12、车载网络通信与OTA下载:MQTT协议在车端应用、HTTP/HTTPS下载管理、断点续传与分片下载、网络状态监测与策略

车载OTA,说白了就是让车「自己给自己升级」。但车不是手机,它跑在高速上、停在地库里、穿过隧道时信号说断就断。所以网络通信这块,是整个OTA系统的命门。

我做了这么多年车载系统,见过太多「下载到99%断了,又得从头来」的惨案。嗯,今天我们就来聊聊,怎么把这块做稳。

12.1 MQTT协议在车端应用

先说说MQTT。很多人觉得MQTT就是物联网用的轻量级协议,跟车载OTA有什么关系?

关系大了。OTA不只是下载,还有「指令下发」这个环节。云端要告诉车:「嘿,有新版本了,准备下载」。车也要告诉云端:「我准备好了,开始吧」。

这种双向通信,用HTTP轮询?太浪费流量。用长连接?太耗电。MQTT正好合适。

12.1.1 为什么选MQTT

  • 轻量级:报文头只有2字节,对车载模组友好
  • QoS机制:至少一次、恰好一次,保证指令不丢
  • 遗嘱消息:车突然断网,云端能感知
  • 保留消息:车重启后能拿到最新指令

核心思路:MQTT只负责「控制面」,不负责「数据面」。下载大文件还是用HTTP,MQTT只管发指令、报状态。

12.1.2 车端MQTT架构

我个人习惯把车端的MQTT客户端设计成独立服务,不跟下载模块耦合。这样职责清晰,出了问题也好排查。

// 伪代码:车端MQTT客户端初始化
MqttClient client = new MqttClient(brokerUrl, clientId);

// 设置遗嘱消息
client.setWill("vehicle/status", "offline", 2, true);

// 订阅OTA指令主题
client.subscribe("ota/command/#", 1);

// 收到指令回调
client.onMessage((topic, payload) -> {
    if (topic.equals("ota/command/start")) {
        startDownload(payload.getVersion());
    } else if (topic.equals("ota/command/cancel")) {
        cancelDownload();
    }
});

避坑指南:我曾经遇到过车端MQTT重连风暴——车从地库出来,几百台车同时重连,把MQTT Broker打挂了。后来加了指数退避重连策略,问题解决。

12.2 HTTP/HTTPS下载管理

下载这块,HTTP是主力。但车载环境特殊,不能直接用现成的下载库。你得自己管。

12.2.1 下载管理器设计

我建议把下载管理器设计成状态机。每个下载任务都有明确的状态流转:等待→下载中→暂停→完成→失败。

public enum DownloadState {
    PENDING,      // 等待
    DOWNLOADING,  // 下载中
    PAUSED,       // 暂停
    COMPLETED,    // 完成
    FAILED        // 失败
}

为什么要用状态机?因为车端下载随时可能被打断——用户开车走了、进隧道了、电瓶电量低了。状态机能让你在任何时刻恢复下载,不会乱。

12.2.2 HTTPS证书管理

HTTPS在车端有个坑:证书过期。车不像手机能随时联网更新证书,它可能停着几个月不开。

我的做法是:

  • 内置根证书,不依赖系统证书库
  • 支持证书预埋和远程更新
  • 下载前做证书校验,失败时尝试备用证书

注意:千万不要把证书硬编码在代码里。我见过某厂商把证书写在Java代码中,结果证书一换,所有车都得升级APP才能下载。应该把证书放在安全存储区,支持远程推送更新。

12.3 断点续传与分片下载

这是车载OTA最核心的技术点。没有断点续传,OTA就是空中楼阁。

12.3.1 断点续传原理

说白了就是HTTP的Range头。客户端告诉服务器:「我从第1000字节开始下载」。服务器返回206 Partial Content。

// 请求:从第1000字节开始下载
GET /ota/update.zip HTTP/1.1
Range: bytes=1000-

// 响应:返回从1000开始的内容
HTTP/1.1 206 Partial Content
Content-Range: bytes 1000-9999/10000

但光有Range还不够。车端得记住「我下载到哪了」。我建议用本地数据库记录每个分片的下载进度,而不是只记一个总进度。

12.3.2 分片下载策略

分片大小怎么定?我踩过坑后总结的经验:

网络类型 推荐分片大小 说明
4G/5G 1MB - 4MB 带宽高,分片大点减少请求次数
3G/弱信号 256KB - 512KB 容易断,分片小点减少重传浪费
WiFi 4MB - 8MB 稳定且免费,分片可以大

核心原则:分片大小不是固定的。我建议根据当前网络质量动态调整。信号好就大分片,信号差就小分片。这叫「自适应分片」。

12.3.3 分片校验

每个分片下载完,必须做完整性校验。我一般用MD5或CRC32。为什么?因为传输过程中可能丢包、错位,不校验的话,最后合成出来的文件是坏的。

// 分片下载完成后校验
boolean verifyChunk(String filePath, long offset, int size, String expectedMd5) {
    FileChannel channel = new FileInputStream(filePath).getChannel();
    MappedByteBuffer buffer = channel.map(READ_ONLY, offset, size);
    String actualMd5 = DigestUtils.md5Hex(buffer);
    return actualMd5.equals(expectedMd5);
}

12.4 网络状态监测与策略

网络监测不是简单地看看「有没有网」。你得知道「网好不好」。

12.4.1 网络质量评估

我常用的评估指标:

  • RTT:往返时延,反映网络延迟
  • 丢包率:丢包超过5%,下载基本没法用
  • 带宽估算:通过下载小文件估算当前带宽
  • 信号强度:RSSI值,反映物理层质量
public class NetworkQuality {
    private int rttMs;          // 毫秒
    private float lossRate;     // 0.0 - 1.0
    private long bandwidthBps;  // 比特每秒
    private int signalStrength; // dBm

    public boolean isDownloadable() {
        // 丢包率超过5%就不下载
        if (lossRate > 0.05) return false;
        // 带宽低于100Kbps也不下载
        if (bandwidthBps < 100_000) return false;
        return true;
    }
}

12.4.2 下载策略决策

网络质量不同,策略也不同。我一般这么定:

网络等级 策略
优质(4G/5G,信号满格) 全速下载,大分片,并发3-5个分片
一般(4G,信号中等) 正常下载,中等分片,并发1-2个分片
较差(3G/弱信号) 小分片,单线程下载,频繁暂停检测
极差(几乎断网) 暂停下载,等待网络恢复

避坑指南:我曾经遇到过车在隧道里反复切换网络状态,导致下载任务频繁启停。后来加了「稳定窗口」——网络质量必须持续稳定5秒以上,才切换策略。这招很管用。

12.4.3 网络切换处理

车端网络切换很频繁:4G切WiFi、WiFi切4G、甚至切到3G。每次切换,IP地址都可能变,TCP连接会断。

我的做法是:

  • 监听ConnectivityManager的网络变化广播
  • 网络切换时,暂停当前下载,记录进度
  • 新网络就绪后,用断点续传恢复下载
  • 如果新网络质量更差,调整分片大小和并发数
// 网络切换回调
void onNetworkChanged(Network newNetwork) {
    // 暂停当前下载
    downloadManager.pauseAll();
    
    // 评估新网络质量
    NetworkQuality quality = evaluator.evaluate(newNetwork);
    
    // 根据新网络调整策略
    DownloadStrategy strategy = new DownloadStrategy();
    strategy.setChunkSize(quality.getRecommendedChunkSize());
    strategy.setConcurrency(quality.getRecommendedConcurrency());
    
    // 恢复下载
    downloadManager.resumeAll(strategy);
}

12.5 整体架构图

下面这张图,是我在项目中实际使用的车载OTA网络通信架构。你仔细看,MQTT和HTTP各司其职,网络监测模块贯穿始终。

云端OTA平台 MQTT Broker CDN/HTTP服务器 车端OTA客户端 MQTT客户端 下载管理器 网络监测模块 存储 指令下发/状态上报 分片下载 控制面 消息面 监测面

你看,整个架构分三层:云端负责指令和文件分发,车端负责执行和反馈,网络监测模块像「交通警察」一样,随时调整下载策略。

最后说一句:车载OTA的网络通信,没有银弹。MQTT、HTTP、断点续传、网络监测,每个环节都得做扎实。我在项目中见过太多「看起来很美」的方案,一上路就现原形。嗯,踏踏实实把基础打牢,比什么都强。


公众号:蓝海资料掘金营,微信deep3321