固件版本管理
固件版本管理
本节介绍固件版本管理的策略和实现方法。系统化的版本管理是 OTA 批量升级的基础。学习完成后,您将能够:
- 设计固件版本号规范
- 在 ESP32 中实现版本校验逻辑
- 通过 Node-RED 管理设备固件版本
- 理解固件兼容性管理策略
在开始本节之前,请确保:
- 理解 OTA 升级流程
- 了解 HTTP OTA 配置
- 了解 Node-RED 的基础功能
Version Numbering
Section titled “Version Numbering”语义化版本号(SemVer)
Section titled “语义化版本号(SemVer)”推荐使用语义化版本号(Semantic Versioning)规范:
主版本号.次版本号.修订号
2.1.3↑ ↑ ↑│ │ └── 修订号: Bug 修复、小优化(向后兼容)│ └──── 次版本号: 新增功能(向后兼容)└────── 主版本号: 不兼容的重大修改ESP32 固件版本示例:
| 版本 | 变更类型 | 示例变更 |
|---|---|---|
| 1.0.0 | 初始版本 | 首个发布固件 |
| 1.1.0 | 功能新增 | 增加 MQTT 心跳监测 |
| 1.2.0 | 功能新增 | 增加传感器校准算法 |
| 2.0.0 | 不兼容修改 | MQTT Topic 结构重设计 |
| 2.0.1 | Bug 修复 | 修复 WiFi 重连 bug |
| 2.1.0 | 功能新增 | 增加远程配置能力 |
固件版本号存储
Section titled “固件版本号存储”在 ESP32 代码中定义当前版本:
#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 → 20100Version Check Implementation
Section titled “Version Check Implementation”MQTT 版本上报
Section titled “MQTT 版本上报”#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); // 保留消息}版本兼容性检查
Section titled “版本兼容性检查”// 兼容性要求#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;}Version Server
Section titled “Version Server”Node-RED 版本管理 Flow
Section titled “Node-RED 版本管理 Flow”[ { "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", "固件版本", "最后在线", "需更新"] }]版本服务器 API
Section titled “版本服务器 API”// 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 重连问题"// ]// }Update Strategy
Section titled “Update Strategy”升级策略对比
Section titled “升级策略对比”| 策略 | 说明 | 适用场景 |
|---|---|---|
| 强制更新 | 发现新版本立即升级 | 安全补丁、紧急修复 |
| 可选更新 | 设备上报版本,用户决定升级时间 | 功能升级、非关键更新 |
| 灰度发布 | 先推送给 10% 设备,稳定后全量 | 大规模部署,风险控制 |
| 按区域分批 | 按设备组逐个推送 | 跨区域部署,避免带宽拥塞 |
| 最低版本强制 | 低于最低版本的强制升级 | 确保设备 API 兼容性 |
Node-RED 灰度发布 Flow
Section titled “Node-RED 灰度发布 Flow”// 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;Firmware Compatibility Management
Section titled “Firmware Compatibility Management”API 兼容性策略
Section titled “API 兼容性策略”| 固件版本 | MQTT Topic 版本 | 兼容的 Node-RED | 备注 |
|---|---|---|---|
| 1.x.x | v1 | v1 | 原始方案 |
| 2.0.x | v2 | v2 | Topic 结构改变 |
| 2.1.x | v2 | v2 | 向后兼容 |
| 3.0.x | v3 | v3 | 重大架构变更 |
兼容性检查清单
Section titled “兼容性检查清单”- MQTT Topic 结构保持一致或增加桥接
- JSON 消息格式兼容
- 传感器驱动接口不变
- 配置参数结构兼容
- 文件系统格式兼容
- 分区表结构兼容
Pre-sales Key Points
Section titled “Pre-sales Key Points”版本管理价值
Section titled “版本管理价值”| 价值 | 说明 | 沟通要点 |
|---|---|---|
| 可控性 | 了解设备固件分布 | ”随时查看所有设备的固件版本” |
| 安全性 | 确保设备及时更新 | ”批量推送安全补丁,降低风险” |
| 可追溯 | 记录更新历史 | ”固件更新有完整日志,可追溯” |
| 兼容性 | 避免版本不匹配 | ”自动检测兼容性,防止升级失败” |
Summary
Section titled “Summary”本节介绍了固件版本管理的策略和实现:
- 版本号规范:语义化版本号(SemVer),主版本.次版本.修订号
- 版本上报:ESP32 通过 MQTT 上报固件版本
- 版本服务器:Node-RED 管理设备版本列表和分发策略
- 升级策略:强制更新、可选更新、灰度发布等
- 兼容性:确保升级前后 API、Topic、数据格式兼容