feat: V1.03 initialize 上线消息 — 固件+工具同步
vd960DBN:
- dev_initialize_pub() 改为 V1.03 格式 (msg_id/cmd/ts/data/extra_info)
- iot_mqtt_srv: 订阅改双主题 dld960/{sn}/srv, 响应 topic 改 dev
- SUBACK 后自动发 initialize 告知服务器上线
- net_srv.h: 加 dev_initialize_pub 声明
DBNMQTTool:
- protocol.py: 加 CMD_INITIALIZE
- device_manager: DeviceInfo 加 extra_info, 加 mark_online()
- main.py: 接收 initialize 消息, 自动标记设备上线
- docs: 协议 V1.03 + devlog V3.1
This commit is contained in:
@@ -22,6 +22,7 @@ class DeviceInfo:
|
|||||||
online: bool = False
|
online: bool = False
|
||||||
loop_data: Optional[dict] = None
|
loop_data: Optional[dict] = None
|
||||||
events: list = field(default_factory=list)
|
events: list = field(default_factory=list)
|
||||||
|
extra_info: dict = field(default_factory=dict) # from initialize 消息
|
||||||
|
|
||||||
|
|
||||||
class DeviceManager:
|
class DeviceManager:
|
||||||
@@ -91,6 +92,17 @@ class DeviceManager:
|
|||||||
dev.online = True
|
dev.online = True
|
||||||
self._notify()
|
self._notify()
|
||||||
|
|
||||||
|
def mark_online(self, dev_serial: str, extra_info: Optional[dict] = None):
|
||||||
|
"""V1.03: 设备上线初始化标记"""
|
||||||
|
with self._lock:
|
||||||
|
dev = self.get_or_create(dev_serial)
|
||||||
|
dev.online = True
|
||||||
|
dev.last_seen = datetime.now()
|
||||||
|
if extra_info:
|
||||||
|
dev.extra_info = extra_info
|
||||||
|
dev.soft_ver = extra_info.get("version", dev.soft_ver)
|
||||||
|
self._notify()
|
||||||
|
|
||||||
def set_offline(self):
|
def set_offline(self):
|
||||||
"""标记所有设备离线(断开连接时调用)"""
|
"""标记所有设备离线(断开连接时调用)"""
|
||||||
with self._lock:
|
with self._lock:
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ CMD_REPORT_CONFIG = "report_config"
|
|||||||
CMD_LOOP_DATA = "loop_data"
|
CMD_LOOP_DATA = "loop_data"
|
||||||
CMD_EVENT_REPORT = "event_report"
|
CMD_EVENT_REPORT = "event_report"
|
||||||
CMD_HEARTBEAT = "heartbeat"
|
CMD_HEARTBEAT = "heartbeat"
|
||||||
|
CMD_INITIALIZE = "initialize" # V1.03: 设备上电初始化
|
||||||
|
|
||||||
# 配置类命令 → topic
|
# 配置类命令 → topic
|
||||||
CONFIG_SET_COMMANDS = {CMD_DEV_SERIAL_SET, CMD_SSC_NET_SET, CMD_IOT_NET_SET, CMD_IOT_TOPIC_SET, CMD_LOOP_PARAM_SET}
|
CONFIG_SET_COMMANDS = {CMD_DEV_SERIAL_SET, CMD_SSC_NET_SET, CMD_IOT_NET_SET, CMD_IOT_TOPIC_SET, CMD_LOOP_PARAM_SET}
|
||||||
|
|||||||
+10
-1
@@ -30,7 +30,7 @@ from dbn_mqtt_tool.protocol import (
|
|||||||
CMD_IOT_TOPIC_QUERY, CMD_LOOP_PARAM_QUERY, CMD_REPORT_CONFIG,
|
CMD_IOT_TOPIC_QUERY, CMD_LOOP_PARAM_QUERY, CMD_REPORT_CONFIG,
|
||||||
CMD_SSC_NET_SET, CMD_IOT_NET_SET, CMD_IOT_TOPIC_SET,
|
CMD_SSC_NET_SET, CMD_IOT_NET_SET, CMD_IOT_TOPIC_SET,
|
||||||
CMD_PWD_VERIFY, CMD_PWD_SET, CMD_FACTORY_RESET, CMD_DEVICE_RESET,
|
CMD_PWD_VERIFY, CMD_PWD_SET, CMD_FACTORY_RESET, CMD_DEVICE_RESET,
|
||||||
CMD_LOOP_DATA, CMD_EVENT_REPORT, CMD_HEARTBEAT,
|
CMD_LOOP_DATA, CMD_EVENT_REPORT, CMD_HEARTBEAT, CMD_INITIALIZE,
|
||||||
ERROR_MSGS, FREQ_LEVELS, OUTPUT_MODES, EVENT_TYPES,
|
ERROR_MSGS, FREQ_LEVELS, OUTPUT_MODES, EVENT_TYPES,
|
||||||
data_ssc_net_set, data_iot_net_set, data_iot_topic_set,
|
data_ssc_net_set, data_iot_net_set, data_iot_topic_set,
|
||||||
data_pwd_verify, data_pwd_set, data_report_config,
|
data_pwd_verify, data_pwd_set, data_report_config,
|
||||||
@@ -857,6 +857,15 @@ class MainWindow(QMainWindow):
|
|||||||
self._devmgr.update_heartbeat(dev_serial, data)
|
self._devmgr.update_heartbeat(dev_serial, data)
|
||||||
self._log_recv(topic, payload, f"heartbeat uptime={data.get('uptime', 0)}s")
|
self._log_recv(topic, payload, f"heartbeat uptime={data.get('uptime', 0)}s")
|
||||||
|
|
||||||
|
elif cmd == CMD_INITIALIZE:
|
||||||
|
# V1.03: 设备上线初始化
|
||||||
|
data = payload.get("data", {})
|
||||||
|
dev_sn = data.get("dev_serial", dev_serial)
|
||||||
|
extra = data.get("extra_info", {})
|
||||||
|
self._devmgr.mark_online(dev_sn, extra)
|
||||||
|
self._log_recv(topic, payload, f"initialize sn={dev_sn} ver={extra.get('version','?')}")
|
||||||
|
self._show_json({"online": dev_sn, "info": extra})
|
||||||
|
|
||||||
# 旧协议 / 无 cmd 字段 的消息(如 Initialize)
|
# 旧协议 / 无 cmd 字段 的消息(如 Initialize)
|
||||||
elif "Method" in payload:
|
elif "Method" in payload:
|
||||||
self._log_recv(topic, payload, f"Method={payload.get('Method', '?')}")
|
self._log_recv(topic, payload, f"Method={payload.get('Method', '?')}")
|
||||||
|
|||||||
@@ -279,6 +279,7 @@ void manage_tcp_message(uint8_t socket, uint8_t *buf, uint32_t len);
|
|||||||
void manage_mqtt_recv_message(char * msg, int length);
|
void manage_mqtt_recv_message(char * msg, int length);
|
||||||
void poll_mqtt(void);
|
void poll_mqtt(void);
|
||||||
void mqtt_publish(char *topic, char *message, int req_qos);
|
void mqtt_publish(char *topic, char *message, int req_qos);
|
||||||
|
void dev_initialize_pub(void); // 发布上线 initialize 消息 (V1.03)
|
||||||
|
|
||||||
|
|
||||||
void GetMacAddr(unsigned char *pMAC);
|
void GetMacAddr(unsigned char *pMAC);
|
||||||
|
|||||||
@@ -110,23 +110,17 @@ static int iot_mqtt_send_connect(void) {
|
|||||||
return iot_mqtt_send(buf, (uint16_t)len);
|
return iot_mqtt_send(buf, (uint16_t)len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 发送 MQTT SUBSCRIBE */
|
/* 发送 MQTT SUBSCRIBE — V1.01 双主题协议 */
|
||||||
static int iot_mqtt_send_subscribe(void) {
|
static int iot_mqtt_send_subscribe(void) {
|
||||||
static uint8_t buf[256]; // static: 避免栈溢出
|
static uint8_t buf[256]; // static: 避免栈溢出
|
||||||
int len;
|
int len;
|
||||||
char topic[IOT_MQTT_TOPIC_MAX_LEN];
|
char topic[IOT_MQTT_TOPIC_MAX_LEN];
|
||||||
MQTTString topics[3];
|
MQTTString topics[1];
|
||||||
int qos[3] = {1, 1, 1};
|
int qos[1] = {1};
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
// 订阅服务器下发消息
|
// V1.01: 仅订阅 dld960/{sn}/srv 双主题
|
||||||
iot_make_topic(topic, sizeof(topic), "srv", "config", "set");
|
snprintf(topic, sizeof(topic), "dld960/%s/srv", g_iot_dev_serial);
|
||||||
topics[count].cstring = topic; topics[count].lenstring.len = 0; count++;
|
|
||||||
|
|
||||||
iot_make_topic(topic, sizeof(topic), "srv", "config", "query");
|
|
||||||
topics[count].cstring = topic; topics[count].lenstring.len = 0; count++;
|
|
||||||
|
|
||||||
iot_make_topic(topic, sizeof(topic), "srv", "ctrl", NULL);
|
|
||||||
topics[count].cstring = topic; topics[count].lenstring.len = 0; count++;
|
topics[count].cstring = topic; topics[count].lenstring.len = 0; count++;
|
||||||
|
|
||||||
len = MQTTSerialize_subscribe(buf, sizeof(buf), 0,
|
len = MQTTSerialize_subscribe(buf, sizeof(buf), 0,
|
||||||
@@ -192,9 +186,9 @@ static void iot_handle_publish(const char *topic, uint8_t *payload, int payload_
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 构建响应 topic */
|
/* 构建响应 topic — V1.01 双主题 */
|
||||||
char resp_topic[IOT_MQTT_TOPIC_MAX_LEN];
|
char resp_topic[IOT_MQTT_TOPIC_MAX_LEN];
|
||||||
iot_make_topic(resp_topic, sizeof(resp_topic), "dev", "config", "resp");
|
snprintf(resp_topic, sizeof(resp_topic), "dld960/%s/dev", g_iot_dev_serial);
|
||||||
|
|
||||||
/* 处理命令 — 复用 TCP JSON 的命令逻辑 */
|
/* 处理命令 — 复用 TCP JSON 的命令逻辑 */
|
||||||
/* 目前仅实现基本响应框架, 后续逐步对接 Loop MCU 命令 */
|
/* 目前仅实现基本响应框架, 后续逐步对接 Loop MCU 命令 */
|
||||||
@@ -268,6 +262,9 @@ static void iot_handle_suback(void) {
|
|||||||
PRINT("IOT: ← SUBACK, topics subscribed\n");
|
PRINT("IOT: ← SUBACK, topics subscribed\n");
|
||||||
g_iot_state = IOT_STATE_READY;
|
g_iot_state = IOT_STATE_READY;
|
||||||
_iot_reconnect_backoff = 0; // 连接成功, 重置退避
|
_iot_reconnect_backoff = 0; // 连接成功, 重置退避
|
||||||
|
|
||||||
|
// V1.03: 订阅成功后发布 initialize 告知服务器上线
|
||||||
|
dev_initialize_pub();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 处理收到的 MQTT 数据 */
|
/* 处理收到的 MQTT 数据 */
|
||||||
@@ -386,10 +383,9 @@ void iot_mqtt_publish_sensor(void) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 全通道一次性上报,字段按 DLD960_TCP_JSON协议.md §5.1:
|
/* 全通道一次性上报,字段按 DLD960_IoT_MQTT协议.md §5.2 V1.02:
|
||||||
ch, freq_level, has_car, loop_ok, freq_current, freq_diff,
|
ch, level, iscar, loop_ok, freq, diff, sens, cndtn, misc.{type,value}
|
||||||
sensitivity, condition, misc.type, misc.value
|
注意: mqttBuf 需 ≥ 1024 才能容纳 4 通道全字段封包 (~800 字节) */
|
||||||
注意: mqttBuf 需 ≥ 1024 才能容纳 4 通道全字段封包 (~846 字节) */
|
|
||||||
static char data_json[1024];
|
static char data_json[1024];
|
||||||
static char payload[1400];
|
static char payload[1400];
|
||||||
char *p = data_json;
|
char *p = data_json;
|
||||||
|
|||||||
@@ -184,11 +184,21 @@ void dev_initialize_pub(void)
|
|||||||
}
|
}
|
||||||
memset(mBuff, 0, 256);
|
memset(mBuff, 0, 256);
|
||||||
|
|
||||||
sprintf((char *)mBuff, "{\"Method\":\"Initialize\", \"Device_id\": \"%s\","
|
// V1.03: 上线后发布 initialize,告知服务器设备信息
|
||||||
"\"Extra_Info\":{\"Code\":\"%s\",\"CSQ\":%d, \"Version\":\"%s\"}}", g_dev_number_str, "0", 0, FIRMWARE_VER);
|
// 格式: {msg_id, cmd:"initialize", ts, data:{dev_serial, extra_info:{code,csq,location,version}}}
|
||||||
//mqtt_publish((char *)"gtpc/display/Initialize", gbufSend, 0);
|
uint32_t now = (mstick() > 0) ? (uint32_t)(mstick() / 1000) : 0;
|
||||||
|
sprintf((char *)mBuff,
|
||||||
|
"{\"msg_id\":%lu,\"cmd\":\"initialize\",\"ts\":%lu,"
|
||||||
|
"\"data\":{\"dev_serial\":\"%s\","
|
||||||
|
"\"extra_info\":{\"code\":\"%s\",\"csq\":\"%d\","
|
||||||
|
"\"location\":\"%s\",\"version\":\"%s\"}}}",
|
||||||
|
(unsigned long)++g_msg_id, (unsigned long)now,
|
||||||
|
g_dev_number_str,
|
||||||
|
"0", 0, "", FIRMWARE_VER);
|
||||||
|
|
||||||
PRINT("\r\nWill publish initialize_topic:\n%s\r\n", mBuff);
|
PRINT("
|
||||||
|
\nWill publish initialize_topic:\n%s
|
||||||
|
\n", mBuff);
|
||||||
|
|
||||||
mqtt_publish((char *)(g_iot_topic.topic_pub), (char *)mBuff, 0);
|
mqtt_publish((char *)(g_iot_topic.topic_pub), (char *)mBuff, 0);
|
||||||
|
|
||||||
|
|||||||
@@ -210,6 +210,7 @@ topic 修正为 V1.01 双主题协议 `dld960/{sn}/dev`(此前遗留旧 topic
|
|||||||
|
|
||||||
| 版本 | 时间 | 说明 |
|
| 版本 | 时间 | 说明 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
|
| V3.1 | 2026-07-09 | V1.03: 订阅后发 initialize 上线消息; iot_mqtt_srv 订阅改双主题 |
|
||||||
| V3.0 | 2026-07-08 | MQTT 稳定性修复: socket初始化/buffer溢出/分批发送/hex dump/PINGREQ |
|
| V3.0 | 2026-07-08 | MQTT 稳定性修复: socket初始化/buffer溢出/分批发送/hex dump/PINGREQ |
|
||||||
| V2.9 | 2026-07-07 | MQTT V1.01 双主题协议 + 命令分发 + report_config 7参数 |
|
| V2.9 | 2026-07-07 | MQTT V1.01 双主题协议 + 命令分发 + report_config 7参数 |
|
||||||
| V2.8 | 2026-07-07 | MQTT 网络配置: ssc_net_set / iot_net_set / iot_topic_set |
|
| V2.8 | 2026-07-07 | MQTT 网络配置: ssc_net_set / iot_net_set / iot_topic_set |
|
||||||
|
|||||||
Reference in New Issue
Block a user