同步协议 V1.03:双主题发布对齐 + initialize 数据格式修正

vd960DBN:
- heartbeat/sensor/initialize 发布统一走 dld960/{sn}/dev
- dev_initialize_pub 补 model/hard_ver/soft_ver,删 extra_info.version

DBNMQTTool:
- 协议版本号更新至 V1.03
- 协议 Topic 树和模拟页增加 initialize 支持
This commit is contained in:
wangfq
2026-07-10 08:49:28 +08:00
parent 652fc5f938
commit 11d1a96d24
5 changed files with 66 additions and 18 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
""" """
DLD960 IoT MQTT 协议定义 DLD960 IoT MQTT 协议定义
基于《DLD960_IoT_MQTT协议.md》V1.01 基于《DLD960_IoT_MQTT协议.md》V1.03
双主题结构:{sn}/srv(服务器下发)、{sn}/dev(设备上报) 双主题结构:{sn}/srv(服务器下发)、{sn}/dev(设备上报)
消息类型由 JSON `cmd` 字段区分。 消息类型由 JSON `cmd` 字段区分。
""" """
+38
View File
@@ -419,6 +419,21 @@ class MainWindow(QMainWindow):
g2l.addLayout(g2l2) g2l.addLayout(g2l2)
layout.addWidget(g2) layout.addWidget(g2)
# -- initialize --
g_init = QGroupBox("上电初始化 (initialize) — V1.03")
g_init_l = QVBoxLayout(g_init)
self._sim_init = QPlainTextEdit()
self._sim_init.setFont(QFont("Consolas", 10))
self._sim_init.setPlainText(self._sample_initialize_data())
g_init_l.addWidget(self._sim_init)
g_init_l2 = QHBoxLayout()
b_init = QPushButton("发送")
b_init.clicked.connect(self._sim_send_initialize)
g_init_l2.addWidget(b_init)
g_init_l2.addStretch()
g_init_l.addLayout(g_init_l2)
layout.addWidget(g_init)
# -- heartbeat -- # -- heartbeat --
g3 = QGroupBox("心跳上报 (heartbeat)") g3 = QGroupBox("心跳上报 (heartbeat)")
g3l = QVBoxLayout(g3) g3l = QVBoxLayout(g3)
@@ -479,6 +494,24 @@ class MainWindow(QMainWindow):
]} ]}
}, indent=2) }, indent=2)
def _sample_initialize_data(self) -> str:
return json.dumps({
"msg_id": 1,
"cmd": "initialize",
"ts": 1719000000,
"data": {
"dev_serial": "DC045A49718F",
"model": "DLD960",
"hard_ver": "1.0",
"soft_ver": "1.0",
"extra_info": {
"code": "869756049404948",
"csq": "21",
"location": "113.9237976,022.6400375"
}
}
}, indent=2)
def _sample_heartbeat_data(self) -> str: def _sample_heartbeat_data(self) -> str:
return json.dumps({ return json.dumps({
"msg_id": 200, "msg_id": 200,
@@ -509,6 +542,10 @@ class MainWindow(QMainWindow):
sn = self._sim_sn.text() sn = self._sim_sn.text()
self._sim_publish(topic_up(sn), self._sim_event.toPlainText()) self._sim_publish(topic_up(sn), self._sim_event.toPlainText())
def _sim_send_initialize(self):
sn = self._sim_sn.text()
self._sim_publish(topic_up(sn), self._sim_init.toPlainText())
def _sim_send_hb(self): def _sim_send_hb(self):
sn = self._sim_sn.text() sn = self._sim_sn.text()
self._sim_publish(topic_up(sn), self._sim_hb.toPlainText()) self._sim_publish(topic_up(sn), self._sim_hb.toPlainText())
@@ -602,6 +639,7 @@ class MainWindow(QMainWindow):
item = QTreeWidgetItem(dev, [topic_up(sn), "设备发布:loop_data / event_report / heartbeat / 命令响应"]) item = QTreeWidgetItem(dev, [topic_up(sn), "设备发布:loop_data / event_report / heartbeat / 命令响应"])
# 子条目列出 cmd 类型 # 子条目列出 cmd 类型
for cmd_name, desc in [ for cmd_name, desc in [
("initialize", "设备上电初始化 (V1.03)"),
("loop_data", "线圈传感数据上报"), ("loop_data", "线圈传感数据上报"),
("event_report", "事件上报(有车/无车/故障)"), ("event_report", "事件上报(有车/无车/故障)"),
("heartbeat", "设备心跳"), ("heartbeat", "设备心跳"),
+6 -2
View File
@@ -637,11 +637,13 @@ dld960/{dev_serial}/{direction}
"ts": 1719000000, "ts": 1719000000,
"data": { "data": {
"dev_serial":"A1B2C3D4E5F6", "dev_serial":"A1B2C3D4E5F6",
"model": "DLD960",
"hard_ver": "1.0",
"soft_ver": "1.0",
"extra_info": { "extra_info": {
"code": "869756049404948", "code": "869756049404948",
"csq": "21", "csq": "21",
"location": "113.9237976,022.6400375", "location": "113.9237976,022.6400375",
"version": "1.0.1"
} }
} }
} }
@@ -650,10 +652,12 @@ dld960/{dev_serial}/{direction}
| 字段 | 类型 | 说明 | | 字段 | 类型 | 说明 |
|------|------|------| |------|------|------|
| `data.dev_serial` | string | 设备序列码 | | `data.dev_serial` | string | 设备序列码 |
| `data.model` | string | 产品型号 |
| `data.hard_ver` | string | 硬件版本 |
| `data.soft_ver` | string | 固件版本 |
| `data.extra_info.code` | string | 可选,设备代码如IMSI/ICCID | | `data.extra_info.code` | string | 可选,设备代码如IMSI/ICCID |
| `data.extra_info.csq` | string | 可选,当前信号强度 | | `data.extra_info.csq` | string | 可选,当前信号强度 |
| `data.extra_info.location` | string | 可选,经纬度(经度,纬度) | | `data.extra_info.location` | string | 可选,经纬度(经度,纬度) |
| `data.extra_info.version` | string | 版本号 |
## 5.2 线圈传感数据 `loop_data` ## 5.2 线圈传感数据 `loop_data`
@@ -427,12 +427,16 @@ void iot_mqtt_publish_sensor(void) {
snprintf(p, remaining, "]}"); snprintf(p, remaining, "]}");
/* Wrap and publish */ /* Wrap and publish — V1.01 双主题模型: dld960/{sn}/dev */
snprintf(payload, sizeof(payload), snprintf(payload, sizeof(payload),
"{\"msg_id\":%d,\"cmd\":\"loop_data\",\"ts\":%lu,\"data\":%s}", "{\"msg_id\":%d,\"cmd\":\"loop_data\",\"ts\":%lu,\"data\":%s}",
++g_iot_msg_id, mstick() / 1000, data_json); ++g_iot_msg_id, mstick() / 1000, data_json);
mqtt_publish((char *)g_iot_topic.topic_pub, payload, 0); {
char topic[IOT_MQTT_TOPIC_MAX_LEN];
snprintf(topic, sizeof(topic), "dld960/%s/dev", g_iot_dev_serial);
mqtt_publish(topic, payload, 0);
}
done: done:
InitPkgUart(&g_pkg_uart_2); InitPkgUart(&g_pkg_uart_2);
@@ -463,7 +467,7 @@ static void iot_send_heartbeat(void) {
loop_ok[2] ? "true" : "false", loop_ok[3] ? "true" : "false"); loop_ok[2] ? "true" : "false", loop_ok[3] ? "true" : "false");
char topic[IOT_MQTT_TOPIC_MAX_LEN]; char topic[IOT_MQTT_TOPIC_MAX_LEN];
iot_make_topic(topic, sizeof(topic), "dev", "status", NULL); snprintf(topic, sizeof(topic), "dld960/%s/dev", g_iot_dev_serial);
iot_mqtt_publish(topic, payload, strlen(payload), 0); iot_mqtt_publish(topic, payload, strlen(payload), 0);
} }
@@ -177,30 +177,32 @@ void mqtt_publish(char *topic, char *message, int req_qos)
void dev_initialize_pub(void) void dev_initialize_pub(void)
{ {
char *mBuff = (char *)malloc(256); char *mBuff = (char *)malloc(512);
if(mBuff == NULL) if(mBuff == NULL)
{ {
return; return;
} }
memset(mBuff, 0, 256); memset(mBuff, 0, 512);
// V1.03: 上线后发布 initialize,告知服务器设备信息 // V1.03: 上线后发布 initialize,告知服务器设备信息
// 格式: {msg_id, cmd:"initialize", ts, data:{dev_serial, extra_info:{code,csq,location,version}}} // 格式: {msg_id, cmd:"initialize", ts, data:{dev_serial, model, hard_ver, soft_ver, extra_info:{code,csq,location}}}
uint32_t now = (mstick() > 0) ? (uint32_t)(mstick() / 1000) : 0; uint32_t now = (mstick() > 0) ? (uint32_t)(mstick() / 1000) : 0;
char topic[64];
snprintf(topic, sizeof(topic), "dld960/%s/dev", g_dev_number_str);
sprintf((char *)mBuff, sprintf((char *)mBuff,
"{\"msg_id\":%lu,\"cmd\":\"initialize\",\"ts\":%lu," "{\"msg_id\":%lu,\"cmd\":\"initialize\",\"ts\":%lu,"
"\"data\":{\"dev_serial\":\"%s\"," "\"data\":{\"dev_serial\":\"%s\",\"model\":\"%s\","
"\"hard_ver\":\"%s\",\"soft_ver\":\"%s\","
"\"extra_info\":{\"code\":\"%s\",\"csq\":\"%d\"," "\"extra_info\":{\"code\":\"%s\",\"csq\":\"%d\","
"\"location\":\"%s\",\"version\":\"%s\"}}}", "\"location\":\"%s\"}}}",
(unsigned long)++g_msg_id, (unsigned long)now, (unsigned long)++g_iot_msg_id, (unsigned long)now,
g_dev_number_str, g_dev_number_str, PRODUCT_MODEL,
"0", 0, "", FIRMWARE_VER); HARDWARE_VER, FIRMWARE_VER,
"0", 0, "");
PRINT(" PRINT("\nWill publish initialize topic=%s:\n%s\n", topic, mBuff);
\nWill publish initialize_topic:\n%s
\n", mBuff);
mqtt_publish((char *)(g_iot_topic.topic_pub), (char *)mBuff, 0); mqtt_publish(topic, (char *)mBuff, 0);
free(mBuff); free(mBuff);
} }