物联网设备 OTA 升级通道实战:固件签名、灰度发布与 MQTT 升级指令下发
设备装出去之后,固件就不再是代码了,而是负债。
我们这批网关型采集终端在 2023 年底完成了第一轮部署,现场分布在水厂、箱式变电站和几个远端的农业大棚,一共 1200 多台。半年后客户提出一个需求:采集周期从 5 分钟改成 1 分钟,通信协议要换成国标。前三个月我们做了什么?一台一台打电话问客户要设备编号,运维同事带着笔记本和 USB-TTL 出发,一个站点待两天,拆机、断电、烧录、封箱、寄回。一台设备的单次现场升级成本,摊到人天上超过 800 元。这还只是顺利的情况。
真正的麻烦不在成本,在于风险不可控。2024 年 4 月我们尝试过用一段串口脚本批量推送固件,结果同一批固件里有两份是不同分支上编译的,其中一份链接脚本忘了改,一半设备升级后通信参数变成了出厂值。那天晚上 11 点接到现场电话,设备不在线了,但现场没人知道是软件问题还是硬件问题。我们最后靠逐台断电重启才确认有 300 多台处于半死状态。事后复盘,结论很朴素:没有签名的 OTA 通道,本质上是一次没有回滚手段的批量实验。
于是这篇要解决的,是把"改固件"这件事从现场作业,变成一条可以审计、可以分批、可以回退的工程通道。目标设备是已经在上千个现场跑着的 STM32F103C8T6 采集终端,通信用 ESP8266 走 MQTT,云端是自建的 Mosquitto 加 Node.js 调度服务和 PostgreSQL。这套方案的核心是四件事:固件离线签名、设备端双分区与断电保护、云端灰度批次调度、前端可视化推进与失败重推。
需要说明的是,这不是一个"下载器 demo"。下面给出的分区布局、状态机、Topic 约定