feat: 完善Mesh继电器OTA升级闭环
This commit is contained in:
+99
-31
@@ -54,7 +54,7 @@ F1 DD 09 00 0A | SRC_H SRC_L | BUSINESS | 0D 0A
|
||||
JDY-28M完整Mesh帧最大20字节。当前业务帧最大DATA长度为4字节:
|
||||
|
||||
```text
|
||||
BUSINESS = SRC_H SRC_L CMD LEN DATA CRC16_L CRC16_H
|
||||
BUSINESS = SRC_H SRC_L CMD LEN DATA CRC16_H CRC16_L
|
||||
```
|
||||
|
||||
业务帧长度为`6 + LEN`,完整外层发送帧长度为`16 + LEN`,因此`LEN`最大为4。
|
||||
@@ -62,7 +62,7 @@ BUSINESS = SRC_H SRC_L CMD LEN DATA CRC16_L CRC16_H
|
||||
## 2. 业务帧格式
|
||||
|
||||
```text
|
||||
SRC_H SRC_L | CMD | LEN | DATA[0..LEN-1] | CRC16_L CRC16_H
|
||||
SRC_H SRC_L | CMD | LEN | DATA[0..LEN-1] | CRC16_H CRC16_L
|
||||
```
|
||||
|
||||
### 2.1 CRC16规则
|
||||
@@ -74,7 +74,7 @@ SRC_H SRC_L | CMD | LEN | DATA[0..LEN-1] | CRC16_L CRC16_H
|
||||
输入反射:是
|
||||
输出反射:是
|
||||
计算范围:SRC_H、SRC_L、CMD、LEN和DATA
|
||||
发送顺序:CRC低字节在前,高字节在后
|
||||
发送顺序:CRC高字节在前,低字节在后
|
||||
```
|
||||
|
||||
CRC错误时设备直接丢弃整帧,不执行命令,也不返回错误应答。
|
||||
@@ -87,6 +87,11 @@ CRC错误时设备直接丢弃整帧,不执行命令,也不返回错误应
|
||||
应答CMD = 请求CMD | 0x80
|
||||
```
|
||||
|
||||
当请求通过 Mesh 广播地址 `FFFF` 发送时,设备不会立即同时回复。设备会
|
||||
根据本机短地址和系统时间生成约20~170ms、按10ms分档的随机延时,然后向业务帧中的
|
||||
发送方 `SRC_H SRC_L` 单播回复,以降低多个设备同时应答造成的网络拥塞。
|
||||
单播请求仍然直接回复。
|
||||
|
||||
错误应答:
|
||||
|
||||
```text
|
||||
@@ -104,6 +109,54 @@ DATA[0] = 错误码
|
||||
0x06:未知命令
|
||||
```
|
||||
|
||||
## 3.1 `0x07` 设备上线广播
|
||||
|
||||
设备在本次上电完成基础初始化、蓝牙进入可通信状态后,向 Mesh 广播一次:
|
||||
|
||||
```text
|
||||
CMD = 07
|
||||
LEN = 00
|
||||
```
|
||||
|
||||
发送方短地址位于业务帧的 `SRC_H SRC_L` 字段中,因此该命令不需要 DATA,
|
||||
其他设备收到后不回复。主机或其他设备可据此更新在线状态;如果后续长期
|
||||
未收到该设备的上线或业务消息,可以结合应用层超时判断设备是否离线。
|
||||
|
||||
## 3.2 `0x10` 固件版本发现广播
|
||||
|
||||
主机发现服务器存在新固件后,向Mesh广播最新版本和固件长度。该命令只用于
|
||||
设备发现,不会直接启动OTA。
|
||||
|
||||
```text
|
||||
CMD = 10
|
||||
LEN = 04
|
||||
DATA[0] = 最新版本高字节
|
||||
DATA[1] = 最新版本低字节
|
||||
DATA[2] = 固件长度高字节
|
||||
DATA[3] = 固件长度低字节
|
||||
```
|
||||
|
||||
设备收到后比较:
|
||||
|
||||
```text
|
||||
最新版本 > 当前版本:随机延时后回复
|
||||
最新版本 <= 当前版本:静默丢弃,不回复
|
||||
```
|
||||
|
||||
需要升级的设备返回:
|
||||
|
||||
```text
|
||||
CMD = 90
|
||||
LEN = 04
|
||||
DATA[0] = 当前版本高字节
|
||||
DATA[1] = 当前版本低字节
|
||||
DATA[2] = 需要升级的版本高字节
|
||||
DATA[3] = 需要升级的版本低字节
|
||||
```
|
||||
|
||||
设备短地址位于响应业务帧的`SRC_H SRC_L`字段中。主机收到多个`0x90`后,
|
||||
生成待升级设备列表,由人工选择设备,再对选中的短地址执行后续OTA流程。
|
||||
|
||||
## 4. 主机下发的普通命令
|
||||
|
||||
### 4.1 `0x01` 继电器控制
|
||||
@@ -120,7 +173,7 @@ DATA[0] = 01:继电器吸合
|
||||
业务帧结构示例:
|
||||
|
||||
```text
|
||||
SRC_H SRC_L 01 01 01 CRC16_L CRC16_H
|
||||
SRC_H SRC_L 01 01 01 CRC16_H CRC16_L
|
||||
```
|
||||
|
||||
设备执行后返回:
|
||||
@@ -170,14 +223,14 @@ LEN = 00
|
||||
```text
|
||||
CMD = 83
|
||||
LEN = 02
|
||||
DATA[0] = 电流低字节
|
||||
DATA[1] = 电流高字节
|
||||
DATA[0] = 电流高字节
|
||||
DATA[1] = 电流低字节
|
||||
```
|
||||
|
||||
单位为mA,无符号整数,低字节在前。例如实际电流为`1000mA = 0x03E8`:
|
||||
单位为mA,无符号整数,高字节在前。例如实际电流为`1000mA = 0x03E8`:
|
||||
|
||||
```text
|
||||
DATA = E8 03
|
||||
DATA = 03 E8
|
||||
```
|
||||
|
||||
### 4.4 `0x05` 查询设备短地址
|
||||
@@ -211,14 +264,14 @@ DATA = 00 0C
|
||||
```text
|
||||
CMD = 06
|
||||
LEN = 02
|
||||
DATA[0] = 阈值低字节
|
||||
DATA[1] = 阈值高字节
|
||||
DATA[0] = 阈值高字节
|
||||
DATA[1] = 阈值低字节
|
||||
```
|
||||
|
||||
单位为mA,默认值为100mA,设备保存到内部EEPROM。例如设置100mA:
|
||||
|
||||
```text
|
||||
DATA = 64 00
|
||||
DATA = 00 64
|
||||
```
|
||||
|
||||
设备成功返回:
|
||||
@@ -245,8 +298,8 @@ LEN = 00
|
||||
```text
|
||||
CMD = 8E
|
||||
LEN = 02
|
||||
DATA[0] = 版本低字节
|
||||
DATA[1] = 版本高字节
|
||||
DATA[0] = 版本高字节
|
||||
DATA[1] = 版本低字节
|
||||
```
|
||||
|
||||
当前版本在主程序`include/app_config.h`中定义:
|
||||
@@ -303,17 +356,17 @@ DATA[0] = 被确认的故障码或恢复码
|
||||
```text
|
||||
CMD = 08
|
||||
LEN = 04
|
||||
DATA[0] = 固件长度低字节
|
||||
DATA[1] = 固件长度高字节
|
||||
DATA[2] = 版本号低字节
|
||||
DATA[3] = 版本号高字节
|
||||
DATA[0] = 固件长度高字节
|
||||
DATA[1] = 固件长度低字节
|
||||
DATA[2] = 版本号高字节
|
||||
DATA[3] = 版本号低字节
|
||||
```
|
||||
|
||||
设备收到后擦除:
|
||||
|
||||
```text
|
||||
OTA固件区:0x020000~0x02FFFF
|
||||
OTA元数据:0x030000~0x030FFF
|
||||
OTA固件区:0x003000~0x004FFF
|
||||
OTA元数据:0x005000~0x005FFF
|
||||
```
|
||||
|
||||
成功应答:
|
||||
@@ -364,8 +417,8 @@ DATA[2] = 下一期待偏移低字节
|
||||
```text
|
||||
CMD = 0A
|
||||
LEN = 02
|
||||
DATA[0] = 完整固件CRC16低字节
|
||||
DATA[1] = 完整固件CRC16高字节
|
||||
DATA[0] = 完整固件CRC16高字节
|
||||
DATA[1] = 完整固件CRC16低字节
|
||||
```
|
||||
|
||||
CRC16使用CRC-16/MODBUS,计算范围是整个裸二进制固件文件。
|
||||
@@ -390,12 +443,12 @@ LEN = 00
|
||||
设备从W25Q64重新读取完整固件并计算CRC16。校验成功后写入OTA元数据:
|
||||
|
||||
```text
|
||||
0x030000:魔数
|
||||
0x030004:固件长度
|
||||
0x030008:固件版本
|
||||
0x03000A:CRC16
|
||||
0x03000E:镜像有效标志0xA5
|
||||
0x03000F:升级请求0xA5
|
||||
0x005000:魔数
|
||||
0x005004:固件长度
|
||||
0x005008:固件版本
|
||||
0x00500A:CRC16
|
||||
0x00500E:镜像有效标志0xA5
|
||||
0x00500F:升级请求0xA5
|
||||
```
|
||||
|
||||
设备返回:
|
||||
@@ -407,7 +460,10 @@ DATA[0] = 00:校验成功,已提交升级
|
||||
DATA[0] = 01:校验失败
|
||||
```
|
||||
|
||||
之后设备复位,由Bootloader把OTA固件搬运到内部Flash的`0x8800`区域。
|
||||
当`DATA[0]=00`时,设备已经完成外部Flash固件校验并写入升级元数据。
|
||||
设备会先发送`0x8B`应答,随后自动触发MCU复位,由Bootloader把OTA固件
|
||||
搬运到内部Flash的`0x8800`区域。`0x8B`不代表Bootloader已经搬运完成,
|
||||
主机必须继续等待设备重新启动后主动上报的`0x0D`。
|
||||
|
||||
### 7.5 `0x0C` 取消OTA
|
||||
|
||||
@@ -437,14 +493,24 @@ DATA[0] = 00:取消成功
|
||||
发送完整CRC16:0A
|
||||
请求校验提交:0B
|
||||
等待校验结果:8B
|
||||
设备复位并升级
|
||||
设备发送8B后自动复位并升级
|
||||
主程序启动后主动上报升级结果:0D
|
||||
主机确认升级结果:8D
|
||||
```
|
||||
|
||||
主机等待最终升级结果的建议规则:
|
||||
|
||||
```text
|
||||
收到 0x8B=00 后,继续等待 0x0D,默认超时时间为20秒;
|
||||
收到 0x0D 且 DATA[0]=0x01:升级成功;
|
||||
收到 0x0D 且 DATA[0]不是0x01:升级失败;
|
||||
超过20秒没有收到0x0D:升级失败;
|
||||
收到升级结果后,主机向该设备短地址发送0x8D确认。
|
||||
```
|
||||
|
||||
## 8. OTA升级结果上报
|
||||
|
||||
设备启动后从`0x030010`读取升级结果,蓝牙初始化成功后主动广播:
|
||||
设备启动后从`0x005010`读取升级结果,蓝牙初始化成功后主动广播:
|
||||
|
||||
```text
|
||||
CMD = 0D
|
||||
@@ -472,4 +538,6 @@ LEN = 01
|
||||
DATA[0] = 对应的升级结果码
|
||||
```
|
||||
|
||||
设备收到确认后清除`0x030010`。
|
||||
设备收到确认后清除`0x005010`。
|
||||
如果主机没有发送`0x8D`,设备不会清除结果记录,后续启动时可能再次上报,
|
||||
便于主机发现升级结果确认丢失。
|
||||
|
||||
Reference in New Issue
Block a user