跳转到内容

固件版本管理

固件版本管理

本节介绍固件版本管理的策略和实现方法。系统化的版本管理是 OTA 批量升级的基础。学习完成后,您将能够:

  • 设计固件版本号规范
  • 在 ESP32 中实现版本校验逻辑
  • 通过 Node-RED 管理设备固件版本
  • 理解固件兼容性管理策略

在开始本节之前,请确保:

  • 理解 OTA 升级流程
  • 了解 HTTP OTA 配置
  • 了解 Node-RED 的基础功能

推荐使用语义化版本号(Semantic Versioning)规范:

主版本号.次版本号.修订号
2.1.3
↑ ↑ ↑
│ │ └── 修订号: Bug 修复、小优化(向后兼容)
│ └──── 次版本号: 新增功能(向后兼容)
└────── 主版本号: 不兼容的重大修改

ESP32 固件版本示例

版本变更类型示例变更
1.0.0初始版本首个发布固件
1.1.0功能新增增加 MQTT 心跳监测
1.2.0功能新增增加传感器校准算法
2.0.0不兼容修改MQTT Topic 结构重设计
2.0.1Bug 修复修复 WiFi 重连 bug
2.1.0功能新增增加远程配置能力

在 ESP32 代码中定义当前版本:

version.h
#define FIRMWARE_VERSION_MAJOR 2
#define FIRMWARE_VERSION_MINOR 1
#define FIRMWARE_VERSION_PATCH 0
#define FIRMWARE_VERSION_STR "2.1.0"
#define FIRMWARE_BUILD_DATE __DATE__
#define FIRMWARE_BUILD_TIME __TIME__
// 版本号整数表示(便于比较)
#define FIRMWARE_VERSION_NUM \
(FIRMWARE_VERSION_MAJOR * 10000 + \
FIRMWARE_VERSION_MINOR * 100 + \
FIRMWARE_VERSION_PATCH)
// 2.1.0 → 20100
#include "version.h"
void publishVersionInfo() {
DynamicJsonDocument doc(256);
doc["device_id"] = "esp32_factory_001";
doc["fw_version"] = FIRMWARE_VERSION_STR;
doc["fw_version_num"] = FIRMWARE_VERSION_NUM;
doc["build_date"] = FIRMWARE_BUILD_DATE;
doc["build_time"] = FIRMWARE_BUILD_TIME;
doc["chip_model"] = ESP.getChipModel();
doc["flash_size"] = ESP.getFlashChipSize();
doc["free_heap"] = ESP.getFreeHeap();
char buffer[256];
serializeJson(doc, buffer);
client.publish("esp32/version", buffer, true); // 保留消息
}
// 兼容性要求
#define MIN_COMPATIBLE_VERSION 10000 // 1.0.0
#define RECOMMENDED_VERSION 20100 // 2.1.0
bool checkFirmwareCompatibility(int newVersion) {
// 检查新固件是否与当前硬件兼容
if (newVersion < MIN_COMPATIBLE_VERSION) {
Serial.println("新固件版本太低,不兼容");
return false;
}
// 检查硬件能力是否满足新固件要求
if (newVersion >= 20000) { // 2.0.0+ 需要 PSRAM
if (!psramFound()) {
Serial.println("新固件需要 PSRAM,当前硬件不支持");
return false;
}
}
return true;
}
[
{
"id": "version_mqtt_in",
"type": "mqtt in",
"topic": "esp32/+/version",
"name": "接收版本上报"
},
{
"id": "version_check",
"type": "function",
"func": `
var deviceId = msg.topic.split('/')[1];
var currentVer = msg.payload.fw_version_num;
var latestVer = flow.get('latestFirmwareVersion') || 10000;
msg.deviceId = deviceId;
msg.currentVersion = currentVer;
msg.needsUpdate = currentVer < latestVer;
// 记录到上下文
var devices = flow.get('devices') || {};
devices[deviceId] = {
version: msg.payload.fw_version,
lastSeen: Date.now(),
ip: msg.payload.ip || 'unknown'
};
flow.set('devices', devices);
return msg;
`
},
{
"id": "version_dashboard",
"type": "ui_table",
"name": "设备版本列表",
"columns": ["设备ID", "固件版本", "最后在线", "需更新"]
}
]
// Node-RED HTTP Endpoint: GET /api/firmware/latest
// 返回最新固件信息
msg.url = "http://firmware-server/firmware.json";
// Firmware JSON:
// {
// "latest_version": "2.1.0",
// "minimum_version": "1.0.0",
// "download_url": "http://firmware-server/esp32-v2.1.0.bin",
// "size": 1245184,
// "checksum": "sha256:...",
// "changelog": [
// "新增: 远程配置能力",
// "优化: 降低内存使用",
// "修复: MQTT 重连问题"
// ]
// }
策略说明适用场景
强制更新发现新版本立即升级安全补丁、紧急修复
可选更新设备上报版本,用户决定升级时间功能升级、非关键更新
灰度发布先推送给 10% 设备,稳定后全量大规模部署,风险控制
按区域分批按设备组逐个推送跨区域部署,避免带宽拥塞
最低版本强制低于最低版本的强制升级确保设备 API 兼容性
// Node-RED Function: 灰度发布逻辑
var devices = flow.get('devices') || {};
var totalDevices = Object.keys(devices).length;
var canaryPercent = msg.payload.canaryPercent || 10;
var canaryCount = Math.ceil(totalDevices * canaryPercent / 100);
var updated = 0;
var targets = [];
for (var id in devices) {
if (devices[id].needsUpdate) {
if (updated < canaryCount) {
targets.push(id); // 灰度组
}
updated++;
}
}
msg.targetDevices = targets;
msg.payload = {
action: "ota_update",
firmwareUrl: flow.get('latestFirmwareUrl'),
force: false
};
return msg;
固件版本MQTT Topic 版本兼容的 Node-RED备注
1.x.xv1v1原始方案
2.0.xv2v2Topic 结构改变
2.1.xv2v2向后兼容
3.0.xv3v3重大架构变更
  • MQTT Topic 结构保持一致或增加桥接
  • JSON 消息格式兼容
  • 传感器驱动接口不变
  • 配置参数结构兼容
  • 文件系统格式兼容
  • 分区表结构兼容
价值说明沟通要点
可控性了解设备固件分布”随时查看所有设备的固件版本”
安全性确保设备及时更新”批量推送安全补丁,降低风险”
可追溯记录更新历史”固件更新有完整日志,可追溯”
兼容性避免版本不匹配”自动检测兼容性,防止升级失败”

本节介绍了固件版本管理的策略和实现:

  1. 版本号规范:语义化版本号(SemVer),主版本.次版本.修订号
  2. 版本上报:ESP32 通过 MQTT 上报固件版本
  3. 版本服务器:Node-RED 管理设备版本列表和分发策略
  4. 升级策略:强制更新、可选更新、灰度发布等
  5. 兼容性:确保升级前后 API、Topic、数据格式兼容