跳到主要内容

传输、主题与 CRC

支持的传输模式

IoT 中间件安装包

CoreCharge 可以提供可部署的中间件安装包。设备通信使用 MQTT 封装,运营方系统通过 HTTP POST 调用中间件并接收回调。HTTP 业务 API 与本设备协议分别进行版本管理。

一机一密 IoT 接入

每台机柜获得 ProductKeyDeviceNameDeviceSecret。默认主题模板如下:

方向主题
设备订阅/{ProductKey}/{DeviceName}/user/get
设备发布/{ProductKey}/{DeviceName}/user/update

通用 MQTT Broker

运营方提供经批准的 Broker 域名和端口、认证方式以及主题配置。认证可以使用一机一密,也可以为受控设备组使用带权限范围的统一账号。选定配置提供 ProductKeyDeviceName 时,可以沿用上述默认主题模板。

生产配置

本公开网站不会出现 Broker 地址、端口、用户名、密码、设备密钥、Wi-Fi 凭据或真实设备号。这些值不公开,不影响协议本身的完整性。

CRC16/MODBUS 规则

  1. 去掉最外层大括号和最后的 CRC 字段。
  2. 保留指令、全部业务字段以及最后一个业务字段后的逗号,内容必须与发送值完全一致。
  3. 取配置项 PW 的前 6 个字符;不足 6 位时在右侧补 0
  4. 把这 6 位密钥拼接到上一步字符串后。
  5. 对 ASCII 字节执行 CRC-16/MODBUS:初始值 0xFFFF,反射形式多项式 0xA001
  6. 将 16 位结果输出为 4 位大写十六进制字符,高字节在左。

当查询可见字段为 CQ,17000000,0,非生产 PW 为 DEMO00 时:

CRC input: CQ,17000000,0,DEMO00
CRC result: 6F75
Wire frame: {CQ,17000000,0,6F75}

PW 密钥后缀不会出现在传输帧中。

参考实现

export function crc16ModbusAscii(input) {
let crc = 0xffff;
for (const byte of new TextEncoder().encode(input)) {
crc ^= byte;
for (let bit = 0; bit < 8; bit += 1) {
crc = (crc & 1) ? ((crc >>> 1) ^ 0xa001) : (crc >>> 1);
}
}
return (crc & 0xffff).toString(16).toUpperCase().padStart(4, '0');
}

export function protocolCrc(dataWithoutCrc, password) {
const secret = String(password ?? '').slice(0, 6).padEnd(6, '0');
return crc16ModbusAscii(`${dataWithoutCrc},${secret}`);
}

可以下载完整的帧构造与校验代码

接收与重试

  • 设备发送 CN 后,在收到服务端确认前每 60 秒重发一次。
  • 设备发送 DS 后,在收到确认前每 60 秒重发一次。
  • ACCQ 默认库存上报周期为 180 秒。
  • AE 默认扩展上报周期为 600 秒。
  • 对具有幂等要求的租借指令,同一订单 ID 的重复请求必须返回设备缓存的上一次结果。
  • BR 确认必须使用新的消息 ID,不能复用请求 ID。
  • CRC 通过、指令被接受、物理动作成功是三个独立状态。

解析顺序

  1. 定位一个完整的 {...} 帧。
  2. 校验 ASCII 编码和起止字符。
  3. 按英文逗号拆分。
  4. 根据指令与协商的固件配置选择字段模式。
  5. 校验字段数、类型、范围和标识符长度。
  6. 使用已配置的 PW 后缀重新计算 CRC,并进行恒定时间比较。
  7. 应用消息 ID 和订单 ID 的幂等规则。
  8. 处理指令,并分别保存传输、业务和物理结果。