第2章:OTA系统架构设计:云端架构、车端架构、通信协议选择(MQTT/HTTP)、差分升级原理

好,我们直接进入正题。上一章聊了OTA为什么重要,这一章我们来拆解它的骨架——系统架构。

很多人一上来就纠结协议选型,或者直接写代码。我个人习惯是,先画一张大图。把云端、车端、管道这三块理清楚,后面才不会翻车。

2.1 云端架构:不只是个文件服务器

云端是OTA的大脑。它要管的事情很多:版本管理、车辆分组、策略下发、升级包生成、日志收集。说白了,它是个业务系统,不是简单的文件存储。

我建议把云端拆成几个核心模块:

  • 版本管理模块:维护每个ECU的固件版本基线。你想想看,一辆车几十个ECU,每个ECU又有不同硬件版本,版本矩阵有多复杂?
  • 车辆管理模块:按车型、区域、VIN范围做升级策略。比如「先给测试车队推,没问题再全量」。
  • 升级包生成模块:负责做差分计算,生成增量包。这个后面细讲。
  • 任务调度模块:控制升级节奏,避免全网同时下载把服务器打爆。
  • 日志与监控模块:收集升级成功/失败数据,方便排查问题。

核心要点:云端架构要支持灰度发布和回滚。我在项目中遇到过,全量推送后才发现某个车型的CAN信号定义不一致,差点导致大批量刷死。从那以后,我坚持所有升级必须走灰度。

2.2 车端架构:谁来做升级的「管家」?

车端架构的关键是选一个OTA Master。它负责跟云端通信、下载包、校验、分发到各个ECU。

常见的方案有两种:

  • 方案A:网关做Master。网关本身有网络连接能力,也连着CAN/FlexRay,天然适合做OTA调度。但网关的算力和存储通常有限,大包下载可能吃力。
  • 方案B:座舱域控制器做Master。座舱域一般有高性能SoC,大存储,Wi-Fi/4G都方便。但要注意,它跟底盘域的安全隔离要做好。

我个人更倾向方案B。为什么?因为座舱域升级失败最多是黑屏,不会影响刹车转向。安全边界更清晰。

车端架构里还有几个关键角色:

  • 下载代理:负责断点续传、校验完整性。我曾经见过一个项目,下载到99%断了,结果没做续传,整包重下,用户体验极差。
  • 升级代理:负责刷写具体ECU。它要处理刷写时序、电源管理、看门狗喂狗。
  • 回滚代理:刷失败了怎么办?得有备份分区或者AB系统切换机制。

避坑指南:我曾经在车端架构里忘了考虑「升级过程中车辆休眠」的问题。结果刷到一半,车进入低功耗模式,CAN通信断了,ECU变砖。后来我们加了一个「升级不休眠」的电源管理策略。

2.3 通信协议选择:MQTT vs HTTP

这是大家问得最多的问题。我直接说结论:控制信令用MQTT,文件下载用HTTP

为什么?

特性 MQTT HTTP
连接方式 长连接,双向推送 短连接,请求-响应
实时性 高,毫秒级推送 低,需要轮询
流量开销 低,头部极小 高,头部大
断点续传 不支持 支持(Range头)
适用场景 升级指令、状态上报 固件包下载

你想想看,云端要通知一万辆车「开始升级」,如果用HTTP轮询,每辆车每隔几秒发一个请求,服务器压力多大?MQTT一条消息推下去,所有订阅的车瞬间收到。

但下载固件包就不一样了。固件包动辄几百MB,HTTP的断点续传、多线程下载、CDN加速都是现成的。MQTT不适合传大文件。

我的建议:MQTT的QoS等级选1(至少一次)。QoS0可能丢消息,QoS2太慢。我在项目中用QoS1配合去重逻辑,效果很好。

2.4 差分升级原理:只传变化的部分

差分升级是OTA的核心技术之一。说白了,就是只传输新旧固件之间的差异部分,而不是整个固件包。

举个例子:旧固件100MB,新固件102MB。如果全量下载,每次都要传102MB。但差分后,可能只有5MB的差异。对于车机流量来说,这省的不是一星半点。

差分算法有很多种,常见的有:

  • bsdiff:基于二进制差分,压缩率高,但计算量大。适合座舱域这种高性能平台。
  • hdiffpatch:针对嵌入式优化,内存占用小。适合MCU类ECU。
  • Google的Courgette:Chrome用的算法,对可执行文件优化特别好。

差分升级的流程是这样的:

  1. 云端拿到新旧两个固件,运行差分算法,生成patch文件。
  2. 车端下载patch文件。
  3. 车端用旧固件 + patch文件,通过反向差分算法,还原出新固件。
  4. 校验新固件的完整性(MD5/SHA256)。
  5. 刷写新固件到目标分区。

注意:差分升级有个前提——车端必须保留旧固件。如果旧固件被删了或者损坏了,差分就玩不转了。所以,我建议车端保留至少两个版本的固件副本。

还有一个坑:差分算法对固件编译的确定性有要求。如果每次编译出来的二进制都不一样(比如时间戳、随机数),差分率会很低。我在项目中就遇到过,同一个代码两次编译,差异率高达30%。后来我们强制开启了编译的确定性模式。

2.5 小结

这一章我们聊了:

  • 云端架构要管版本、车辆、任务、日志,核心是灰度发布。
  • 车端架构选座舱域做Master更安全,别忘了电源管理。
  • 通信协议:MQTT管信令,HTTP管下载,各司其职。
  • 差分升级省流量,但要注意编译确定性和旧固件保留。

下一章,我们会深入OTA的安全设计。嗯,那才是真正让人头疼的地方。