AED设备OTA升级流程设计(云端管理系统)
系统架构说明:
本系统由 门户(Portal) 和 CODEC 两个微服务组成。
- CODEC 使用私有协议通过 TCP(基于 Netty)与 AED 设备通信;
- CODEC 接收到设备信息后,将其封装为 JSON 格式,通过 MQTT 中间件发送给 Portal;
- Portal 负责固件管理、状态存储、用户交互及与对象存储(如阿里云 OSS)的对接。
OTA 升级核心要求:
- 每台设备可能包含多个固件文件,且必须按指定顺序升级;
- 所有固件分片必须由 设备端主动发起拉取请求;
- 设备在拉取分片或完成安装后,必须立即反馈结果给 CODEC;
- 支持 4G 物联网弱网环境,需具备断点续传、CRC 校验、错峰请求等能力;
- CODEC 不直接访问对象存储(如阿里云 OSS),所有固件分片由 Portal 代理获取。
一、数据模型设计
1. 固件元信息(FirmwareMeta)
| 字段 | 说明 |
|---|---|
firmwareId | 固件唯一ID |
deviceModel | 适配的设备型号 |
hardwareVersion | 适配的硬件版本 |
fileOrder | 升级顺序(从1开始) |
fileName | 文件名(如 boot.bin) |
fileVersion | 文件版本号 |
fileSize | 文件总大小(字节) |
crc32 | 整个文件的 CRC32 校验值 |
totalChunks | 总分片数 |
chunkSize | 单个分片大小(建议 4KB) |
管理员上传固件包时,Portal 解析并持久化上述信息,并将原始文件上传至阿里云 OSS。
2. 设备升级状态(DeviceUpgradeState)
| 字段 | 说明 |
|---|---|
deviceId | 设备唯一标识 |
currentFileOrder | 当前正在处理的文件序号(初始为0) |
targetFileName | 当前目标文件名 |
downloadedChunks | 已成功下载的分片索引列表(如 [0,1,2]) |
status | 状态:IDLE / WAITING_META / DOWNLOADING / VERIFYING / UPGRADING / SUCCESS / FAILED |
二、OTA 升级完整流程(按文件粒度)
阶段 1:设备上报 + 服务端匹配升级包(触发)
- 设备上电,与 CODEC 建立 TCP 连接。
- 设备主动上报自身文件信息列表,包括:
deviceModelhardwareVersion- 当前各文件的
fileName、fileVersion、fileIndex等
- CODEC 接收并解析设备上报数据。
- CODEC 向 Portal 发起内部请求(HTTP/gRPC),携带设备信息:
{ "deviceId": "AED-12345", "deviceModel": "AED-X200", "hwVersion": "V1.2", "currentFiles": [ { "name": "boot.bin", "version": "1.0.0" }, { "name": "app.bin", "version": "2.1.3" } ] } - Portal 查询固件库:
- 根据
deviceModel + hwVersion匹配预定义的升级策略; - 比对
currentFiles,确定是否有新版本可升级; - 若有,按
fileOrder顺序选出下一个待升级文件。
- 根据
- Portal 返回该文件的 meta 信息给 CODEC(仅返回一个文件)。
- CODEC 通过私有 TCP 协议将 meta 下发给设备。
- 设备收到 meta 后:
- 缓存目标文件信息(
fileName,totalChunks,crc32等); - 启动错峰定时器(例如随机延迟 5~30 分钟,避免集中请求);
- 立即向 CODEC 上报
OTA_META_ACK,确认接收。
- 缓存目标文件信息(
✅ 此时设备进入“等待拉取”状态,但不立即请求分片。
阶段 2:设备主动拉取分片(循环)
设备在错峰时间到达后,开始逐片拉取。
- 设备向 CODEC 发送分片请求:
{ "cmd": "req_chunk", "fileOrder": 1, "chunkIndex": 5 } - CODEC 收到请求后:
- 向 Portal 发起内部 API 请求,携带
deviceId、fileOrder和chunkIndex; - Portal 接收请求后,从阿里云 OSS 读取对应的固件文件分片;
- Portal 将该分片的字节数组返回给 CODEC;
- CODEC 通过 TCP 私有协议将分片数据下发给设备:
{ "cmd": "chunk_data", "fileOrder": 1, "chunkIndex": 5, "data": "base64...", "isLast": false }
- 向 Portal 发起内部 API 请求,携带
- 设备收到分片后:
- 本地暂存;
- 立即向 CODEC 上报接收结果:
{ "cmd": "ack_chunk", "fileOrder": 1, "chunkIndex": 5, "success": true } - 若校验失败(如长度错误、超时),上报
success: false。
- CODEC 收到 ACK 后:
- 更新设备状态,记录已成功接收的 chunk;
- 若所有 chunks 已收齐,通知设备进入校验阶段。
⚠️ 关键原则:
- 所有分片请求均由设备发起;
- 每次拉取后必须立即反馈,便于服务端追踪进度;
- CODEC 不直接访问 OSS,所有分片由 Portal 代理获取,确保权限集中、安全可控;
- 失败时设备可指数退避重试,服务端不主动重推。
阶段 3:文件校验、安装与结果上报
- 设备收齐所有分片后:
- 拼接完整文件;
- 计算 CRC32,与 meta 中的
crc32比对; - 若一致,执行安装(可能需重启);
- 安装完成后,立即向 CODEC 上报升级结果:
{ "cmd": "upgrade_result", "fileOrder": 1, "result": "SUCCESS" }
- CODEC 收到结果后:
- 若
SUCCESS:- 更新设备
currentFileOrder += 1; - 若存在下一个文件(
fileOrder + 1),则 重复阶段 1(向 Portal 查询下一个文件 meta); - 若无后续文件,标记设备 OTA 成功。
- 更新设备
- 若
FAILED:- 记录失败原因;
- 终止后续文件升级(因顺序依赖);
- 可触发告警通知管理员。
- 若
三、关键机制保障
| 机制 | 说明 |
|---|---|
| 设备主动拉取 | 所有 req_chunk 由设备发起,适应 4G 弱网(设备在信号好时拉取) |
| 实时反馈闭环 | 每个 chunk 和每个文件安装后必须上报结果,服务端才能推进状态 |
| 顺序控制 | 必须完成 fileOrder = N 才能开始 N+1 |
| 断点续传 | 设备记录已下载 chunks,只请求缺失部分 |
| 幂等性 | 重复请求同一 chunk 应返回相同数据 |
| 错峰请求 | 避免大量设备同时拉取造成网络拥塞 |
| CRC 校验 | 确保固件完整性,防止弱网传输损坏 |
| 存储访问隔离 | CODEC 无权直连 OSS,所有文件访问经 Portal 代理,提升安全性 |
四、异常处理策略
| 场景 | 处理方式 |
|---|---|
| 设备离线 | CODEC 缓存 meta,待设备重连后重新下发 |
| 分片请求失败 | 设备自动重试(带退避),服务端不干预 |
| CRC 校验失败 | 丢弃文件,上报失败,可人工介入或自动重试整个文件 |
| 升级卡住(超时) | Portal 设置全局超时(如 72 小时),自动标记失败并告警 |
| 网络中断 | 设备下次上线时继续未完成的升级(基于 downloadedChunks 状态) |
| Portal-OSS 访问异常 | CODEC 收到 Portal 错误响应后,向设备返回错误码,设备可重试 |
五、通信消息示例(简化)
// 设备上报当前文件
{ "cmd": "report_files", "model": "AED-X200", "hwVer": "V1.2", "files": [...] }
// CODEC 向 Portal 查询升级包
→ POST /api/v1/ota/check-upgrade { deviceId, model, hwVer, files }
// Portal 返回 meta
← { "fileOrder": 1, "fileName": "boot.bin", "totalChunks": 100, "crc32": "a1b2c3d4" }
// CODEC 下发 meta 到设备
{ "cmd": "ota_meta", "fileOrder": 1, "fileName": "boot.bin", "totalChunks": 100, "crc32": "a1b2c3d4" }
// 设备 ACK meta
{ "cmd": "ota_meta_ack", "fileOrder": 1, "success": true }
// 设备请求分片
{ "cmd": "req_chunk", "fileOrder": 1, "chunkIndex": 5 }
// CODEC → Portal 请求分片
→ GET /api/v1/ota/chunk?fileOrder=1&chunkIndex=5
// Portal 从 OSS 获取后返回分片
← [binary data or base64]
// CODEC 返回分片给设备
{ "cmd": "chunk_data", "fileOrder": 1, "chunkIndex": 5, "data": "...", "isLast": false }
// 设备 ACK 分片
{ "cmd": "ack_chunk", "fileOrder": 1, "chunkIndex": 5, "success": true }
// 设备上报文件升级结果
{ "cmd": "upgrade_result", "fileOrder": 1, "result": "SUCCESS" }
六、总结
本设计严格遵循以下原则:
- ✅ 设备驱动:升级由设备上电上报触发;
- ✅ 服务端响应式:Portal 仅在被查询时返回 meta 或分片;
- ✅ 设备主动拉取:所有分片由设备发起请求;
- ✅ 实时反馈闭环:每一步操作均有 ACK 机制;
- ✅ 顺序与完整性保障:多文件按序升级,CRC 校验确保安全;
- ✅ 弱网友好:错峰、断点续传、重试机制支持 4G 物联网场景;
- ✅ 安全架构:CODEC 不直连 OSS,所有文件访问由 Portal 代理,权限集中管理。
该方案可安全、可靠、可扩展地支撑 AED 设备的远程固件升级需求。