三端唯一契约:嵌入式固件 / Windows GUI / 云端都以此文件为准。 契约变更只能由主代理发起,三端同步更新。modbus-rs 里的旧版已冻结,不再作为依据。 2026-10-01 从 modbus-rs 同步为 v1。
版本注记:v1.2(2026-11-02):新增 firmware_update 升级命令动作(网关 OTA,见第四节)。v1.1(2026-10-02,三端联调修复批)变更记录: - telemetry 精简版键定义收紧:只认
r{N}键(见第二节),F407/H743 固件统一改发此形状; - status 必备字段定稿device_id/online/version,上线 retained、遗嘱 offline retained(见第三节); - cmd_ack 键名定稿message(不是msg),未知命令回执文案与 ping 回执内容写死(见第四、五节); - 新增第八节 CONNECT 约定(username{tenant}/{device}、password=设备 token、遗嘱); - 第七节实现状态按 2026-10-02 实况刷新。
Windows GUI(产品版)、嵌入式设备、采集器、云端统一讲这一种话。 GUI 不碰工业协议,只经 MQTT 跟设备通信——这是地基。
v1/tenants/{tenant}/devices/{device}/telemetry 设备 → 云/GUI:遥测数据
v1/tenants/{tenant}/devices/{device}/status 设备 → 云/GUI:在线状态
v1/tenants/{tenant}/devices/{device}/cmd 云/GUI → 设备:下行命令(QoS 1)
v1/tenants/{tenant}/devices/{device}/cmd_ack 设备 → 云/GUI:命令回执
{tenant} 租户 ID,{device} 设备 ID(只允许字母数字、-、_)。v1/tenants/+/devices/+/status(retained,上线即得设备列表)、
v1/tenants/+/devices/+/cmd_ack、v1/tenants/+/devices/+/telemetry。cmd topic,QoS 1。完整版(采集器 / 资源充足的设备):
{
"customer": "c1",
"tenant_id": "t1",
"device_id": "dev001",
"timestamp": 1759270000000,
"source": "monitor",
"points": [
{"area": "holding", "address": 0, "data_type": "u16", "value": 123, "quality": "good"}
]
}
timestamp:毫秒 unix 时间戳。source:monitor(实时监控)/ poll(轮询采集)等。points[].area:coil / discrete / holding / input。points[].quality:good / bad / stale。精简版(F407 / H743 等 no_std 嵌入式,手工拼 JSON,v1.1 定稿的唯一精简形状):
{"unit": 1, "v": 3, "r0": 123, "r1": 456}
unit(Modbus 站号,必填)、v(点表配置版本号,选填)、r{N}(第 N 个寄存器值,N 从 0 起连续编号,无符号十进制)。r{N} 键解析精简版(映射为 holding 区地址 N、u16);不带 r{N} 键、也不带 points 的载荷视为解析失败,云端必须打 WARN 并计数,不许静默丢弃。timestamp 由 Broker/云端按到达时间补。v:固件当前点表配置版本号(整数,选带);GUI 收到后与本地点表 Version 比对,不一致时提示用户“固件点表版本与本地不一致”。points 按完整版走,否则按精简版走。{"device_id": "dev001", "timestamp": 1759270000000, "online": true, "version": "0.3.0"}
device_id、online(布尔)、version(固件/采集器版本号字符串)。可选:timestamp(毫秒)、serial_no、fw_version、hw_model 等扩展字段,解析方必须忽略不认识的字段。online: true(retained,QoS 1),异常断开靠 MQTT 遗嘱发 online: false(同话题,retained,QoS 1,载荷形状同上、只改 online 与可选字段)。{"cmd_id": "c-001", "action": "ping", "params": {}}
cmd_id:发送方生成,回执时原样带回(用于配对)。ping → 存活探测,回 {"device_id": …}。get_status → 设备状态(uptime、信号/链路健康、发件箱积压)。get_config / set_config {base_version, config}(乐观锁,热生效/需重启分类回告)set_poll_interval {source, interval_ms}、set_point_enabled {source, point, enabled}write_points {points: [{area, address, value, data_type}]} → 写下游设备寄存器/线圈
(网关型设备经 Modbus 写透传);回执逐点 ok 或错误原因trigger_scan {source}、restartfirmware_update {version, pkg_url, key_package}(网关 OTA 升级命令:version=目标版本号字符串;pkg_url=共用包文件下载地址;key_package=80 字节包密钥包的 hex(临时公钥 32 + 包装后包密钥 48);设备按 GWPK v3 解包密钥、解固件、验签后安装,回执按第五节,失败时 message 写原因){"cmd_id": "c-001", "ok": true, "message": "", "data": {"uptime_s": 3600}}
ok:是否执行成功;失败时 message 写人类可读原因(中文),data 可空。键名定稿 message(不是 msg)。ping 回执 data 必须含 {"device_id": "…"}。ok: false, message: "未知命令: xxx"(xxx 为收到的动作名),不许悄悄丢弃。| 方向 | QoS | retained |
|---|---|---|
| telemetry | 0(量大,丢一两条无妨) | 否 |
| status 上线 | 1 | 是(GUI 上线即得设备列表) |
| cmd | 1 | 否 |
| cmd_ack | 1 | 否 |
modbus-mqtt:完整实现(含命令全集)。regs 数组形状双向兼容解码。r{N} 形状;cmd 已实现 ping / get_status / get_config / set_config / 规则类命令,未知命令按第五节回执;status 带 online/version 并 retained 发布,CONNECT 带遗嘱(见第八节)。均未真机验证。MB,unit,r0,r1,不走 MQTT(无网口),由上位机串口桥接或转 MQTT。设备连接 Broker 时:
client_id = 设备 ID({device})。username = {tenant}/{device}(租户与设备以 / 分隔,与云端 ACL 的预期一致)。password = 设备 token(一机一证,注册时签发)。{"device_id":"…","online":false,"version":"…"},QoS 1,retained。GUI 用户连接 Broker 时(凭证由云端登录响应下发,见 rest-api.md 第一节):
username = {tenant}/{username},password = 登录返回的临时 MQTT 凭证(短期、可吊销、过期自动换)。