diff --git a/DBNMQTTool/docs/devlog.md b/DBNMQTTool/docs/devlog.md index 95de3ca..375e35c 100644 --- a/DBNMQTTool/docs/devlog.md +++ b/DBNMQTTool/docs/devlog.md @@ -1,188 +1,206 @@ -# DBNMQTTool 开发日志 - -> DLD960 IoT MQTT 桌面工具 | Python 3.11+ | PySide6 | paho-mqtt v2 | 跨平台 (Windows/Linux/macOS) -> -> 定位: DLD960 车检器 MQTT 调试工具 — 设备管理、实时数据监控、模拟上报、主题订阅/发布 - ---- - -## 2026-08-18 — 脱机日志支持快照流 (stream=snapshot, 协议 V1.07) - -### 变更 - -- **protocol.py**:新增 `STREAM_EVENT` / `STREAM_SNAPSHOT` 常量;`data_log_query` 加 `stream` 参数(快照流显式传 `stream` 字段 + count≤2);新增 `data_log_clear(stream)`(事件流省略 data 兼容老固件);新增 `SNAP_MISC_TYPE_DESC`(time/cut_count/flow_count/relay_count 中文描述) -- **main.py**:脱机日志区加"日志流"选择器(事件日志/传感快照);统计/拉取/清除三按钮按当前流发请求(log_clear 确认框提示阻塞时长 2.8s/45ms);`log_stat`/`log_query` 响应展示区分流——快照记录解析 `channels[]` 逐字段(freq_level/direction/freq_type/sens/cond/loop/car/freq/variation/misc) - -### 验证 - -- protocol 数据构建器断言 6 例全过(事件流不带 stream / 快照流 count≤2 / log_clear 流参数) -- `QT_QPA_PLATFORM=offscreen` 实例化 MainWindow 实测:`log_stat(snapshot)` capacity=48064 展示、`log_query(snapshot)` 2 条快照记录逐字段展示(含负 variation、misc_type 中文)、事件流展示回归无损、空记录边界 -- 依赖:venv + PySide6 + paho-mqtt(`venv/` 已加 .gitignore) - -### 配套 - -- 固件 vd960DBN `log_*` stream=snapshot 分支(同日实现,devlog V4.1) -- 协议文档:TCP JSON V1.03 / IoT MQTT V1.07 - ---- - -## 2026-07-06 (晚) — 模拟上报 + 协议Topic + 自定义Topic `c19e465` - -### 1. 模拟上报 Tab - -- **loop_data / event_report / heartbeat** 三类上报携带独立可编辑 JSON 编辑区 -- **范例填充**:首次切换类型时自动填入协议定义的标准载荷 -- 单次发送 + **周期上报**(QSpinBox 可调间隔) -- 周期开关由 `QPushButton` toggle 控制 - -### 2. 协议Topic Tab - -- 预加载双主题:`dld960/{sn}/srv`(下发)、`dld960/{sn}/dev`(上报) -- QListWidget 展示,双击自动填充到发布区 -- 发布区可编辑 JSON 载荷,一键发布 -- 主题列表受 SN 输入框驱动,实时更新 - -### 3. 自定义Topic Tab - -- 自由输入 topic + JSON 载荷,QoS (0/1/2) 可调 -- **订阅 / 取消订阅**,接收消息实时展示在 QPlainTextEdit -- `#` / `+` 通配符支持,`paho.mqtt.topic_matches_sub` 路由匹配 -- 自定义订阅的消息自动分发到接收区,附带 topic 前缀 - -### 4. 新增依赖 - -- `paho.mqtt.client` 导入新增 `topic_matches_sub` -- UI 控件: QComboBox, QSpinBox, QPlainTextEdit - ---- - -## 2026-07-06 — paho-mqtt v2 回调修复 `213c0dd` - -### 问题 -断开连接时报错: -``` -TypeError: MqttClient._on_disconnect() missing 1 required positional argument: 'reason_code' -``` - -### 根因 -paho-mqtt v2 默认 `callback_api_version=VERSION2`,`on_disconnect` 回调签名为 5 参数 `(client, userdata, flags, reason_code, properties)`,而 v1 为 3 参数 `(client, userdata, rc)`。 - -### 修复 -- `_on_disconnect` 改用 `*args` 兼容 v1/v2 -- `Client` 构造显式指定 `callback_api_version=CallbackAPIVersion.VERSION2` -- `_on_connect` 保持 v2 签名不变 - ---- - -## 2026-07-06 — tkinter → PySide6 迁移 `e1bf3dc` - -### 决策 -放弃 tkinter,改用 PySide6 (Qt for Python),理由: -- 跨平台原生外观 (Fusion 风格) -- Qt 信号/槽机制替代 tkinter 回调,更易维护 -- 组件丰富 (QGroupBox, QSplitter, QTabWidget 等) - -### 改动 -- `main.py` 全量重写为 PySide6 主窗口 -- 布局: QGroupBox 分组 → QSplitter 分栏 → QTabWidget 功能分区 -- `requirements.txt` 新增 `PySide6>=6.6.0` -- tkinter → Qt 映射: `StringVar`→信号/槽, `Listbox`→`QListWidget`, `Text`→`QTextEdit` - ---- - -## 2026-07-06 — 项目初始化 `a2cfe46` - -### 功能 (初始版本, tkinter) -- MQTT Broker 连接管理 -- 设备自动发现 (`dld960/+/dev` 通配符订阅) -- 设备信息查询 + 主题配置 -- 实时线圈数据 / 事件上报 / 心跳 监控 -- 控制命令: 密码验证/设置、出厂初始化、设备复位 - -### 项目结构 -``` -DBNMQTTool/ -├── main.py # 主窗口 (tkinter → 后迁移至 PySide6) -├── dbn_mqtt_tool/ -│ ├── protocol.py # DLD960 IoT MQTT 协议定义 (主题/命令/载荷模板) -│ ├── mqtt_client.py # MQTT 客户端封装 (paho-mqtt v2) -│ └── device_manager.py # 设备发现与状态管理 -└── requirements.txt # paho-mqtt>=2.0.0 + PySide6>=6.6.0 -``` - -### 协议依据 -`DLD960_IoT_MQTT协议.md` V1.00 - ---- - -## 当前状态 - -| 组件 | 状态 | -|------|------| -| MQTT 连接/断开 | ✅ 已实现,v1/v2 兼容 | -| 设备发现 | ✅ 通配符订阅 | -| 实时数据监控 | ✅ loop_data/event_report/heartbeat | -| 控制命令 | ✅ 15 条命令 | -| 模拟上报 | ✅ c19e465 | -| 协议Topic订阅/发布 | ✅ c19e465 | -| 自定义Topic订阅/发布 | ✅ c19e465 | -| 固件联调 | ✅ vd960DBN IoT 模式稳定上报 | - ---- - -## 2026-07-07 — MQTT V1.01 适配 + 稳定性修复 - -### 1. MQTT 协议 V1.01 适配 - -- Topic 从多主题(`/loop_data`, `/event_report`, `/heartbeat`, `/cmd`…)压缩为双主题 `dld960/{sn}/dev`(上报)、`dld960/{sn}/srv`(下发) -- `manage_mqtt_recv_message()` 实现 V1.01 协议命令分发,支持 `cmd`/`Method` 双格式 -- MQTT PUBLISH 接收修复:topic 过滤 + 通配符路由修正 - -### 2. MqttClient 重构:tkinter 回调 → QObject 信号/槽 - -**问题**: `paho.mqtt` C 层回调直接操作 Qt UI 控件 → `RuntimeError: wrapped C/C++ object has been deleted` 崩溃。 - -**修复**: -- `MqttClient` 继承 `QObject`,使用 Qt 信号/槽机制 -- `on_message` → `message_received` 信号 → 主线程 slot 安全更新 UI -- 所有 publish 路径增加通用异常捕获,防止未捕获异常导致静默崩溃 -- 回退 Qt 信号排队方案,改用 `QMetaObject.invokeMethod` + 日志追踪定位阻塞点 - -### 3. DeviceManager 死锁修复 - -`threading.Lock` 在单线程 Qt 事件循环中自锁 → `RLock`。`add_device()` 和 `remove_device()` 同线程互调时 `Lock` 阻塞自身。 - -### 4. UI/UX 改进 - -- **日志增强**: 收发打印 topic + payload 详情,调试信息更直观 -- **查询响应自动回填**: 设备信息查询后自动填充 SN 等输入框 -- **主动上报配置**: `report_config` 面板支持完整 7 参数独立开关 -- `right` 局部变量 → `self._notebook`,修复 tab 引用丢失 - - ---- - -## 2026-08-05 — 脱机事件日志命令支持 (MQTT V1.06) - -配合 vd960DBN 固件 P1.3(commit 1a01316)+ 协议 V1.06,工具新增脱机事件日志面板(参数配置 Tab 底部): - -### 新增命令 - -| 命令 | 按钮 | 说明 | -|------|------|------| -| `log_stat` | 统计 | 日志统计/分页定位: enabled/boot_seq/count/capacity/seq_first/seq_last | -| `log_query` | 拉取日志 | 按全局序号分页拉取, 起始序号 + 条数(1~4) 可调 | -| `log_clear` | 清除日志 | 二次确认弹窗, 审计留痕不可撤销 | - -### 实现要点 - -- `protocol.py`: 新增 `CMD_LOG_*` 常量、`LOG_COMMANDS` 集合、`data_log_query()` 构建器(start_seq≥1 / count 1~4 边界钳制)、`LOG_EVENT_TYPE_DESC` 事件类型中文描述(10 类 + unknown) -- `main.py`: 参数配置 Tab 新增 g6 组(起始序号/条数 spinbox + 三按钮 + 只读显示区 QPlainTextEdit) -- `_on_message` code==0 分支新增 `log_stat`/`log_query`/`log_clear` 响应处理 -- 显示优化: log_query 记录带事件类型中文描述; unix_ts 已同步显示真实时间, 未同步显示 `boot+ts_ms(未同步)` -- 清除日志前 QMessageBox 二次确认(防误触, 与出厂初始化/设备复位同模式) - -### 验证 - -- `py_compile` 四个模块通过 -- protocol 逻辑单测: data_log_query 边界钳制 (0→1, 99→4, 0→1)、命令枚举一致性、build_request 带 data +# DBNMQTTool 开发日志 + +> DLD960 IoT MQTT 桌面工具 | Python 3.11+ | PySide6 | paho-mqtt v2 | 跨平台 (Windows/Linux/macOS) +> +> 定位: DLD960 车检器 MQTT 调试工具 — 设备管理、实时数据监控、模拟上报、主题订阅/发布 + +--- + +## 2026-08-18 — 命令集对齐:禁用固件未实现的 MQTT 命令按钮 + +### 背景 + +实测发现 MQTT 通道 `ssc_net_query` / `iot_net_query` 返回 `code=4 unsupported command`——固件 MQTT 分发只实现 6 条命令,工具按协议文档命令表做了全按钮。 + +### 变更 + +- **固件同步补齐**(vd960DBN V4.2):`ssc_net_query` / `iot_net_query` / `iot_topic_query` 三条查询命令已实现,工具对应查询按钮保持可用 +- **工具禁用**固件仍未实现的命令按钮:`ssc_net_set` / `iot_net_set` / `iot_topic_set` / `pwd_set` / `factory_reset` / `device_reset`(`setEnabled(False)` + tooltip 引导走 TCP JSON/BLE 通道) +- 设备刷新列表移除 `CMD_LOOP_PARAM_QUERY`(固件未实现,刷新时不再报 error) + +### 验证 + +- offscreen 实例化:6 个按钮禁用 + tooltip 正确,查询类/验证密码/report_config/log_* 可用 + +--- + +## 2026-08-18 — 脱机日志支持快照流 (stream=snapshot, 协议 V1.07) + +### 变更 + +- **protocol.py**:新增 `STREAM_EVENT` / `STREAM_SNAPSHOT` 常量;`data_log_query` 加 `stream` 参数(快照流显式传 `stream` 字段 + count≤2);新增 `data_log_clear(stream)`(事件流省略 data 兼容老固件);新增 `SNAP_MISC_TYPE_DESC`(time/cut_count/flow_count/relay_count 中文描述) +- **main.py**:脱机日志区加"日志流"选择器(事件日志/传感快照);统计/拉取/清除三按钮按当前流发请求(log_clear 确认框提示阻塞时长 2.8s/45ms);`log_stat`/`log_query` 响应展示区分流——快照记录解析 `channels[]` 逐字段(freq_level/direction/freq_type/sens/cond/loop/car/freq/variation/misc) + +### 验证 + +- protocol 数据构建器断言 6 例全过(事件流不带 stream / 快照流 count≤2 / log_clear 流参数) +- `QT_QPA_PLATFORM=offscreen` 实例化 MainWindow 实测:`log_stat(snapshot)` capacity=48064 展示、`log_query(snapshot)` 2 条快照记录逐字段展示(含负 variation、misc_type 中文)、事件流展示回归无损、空记录边界 +- 依赖:venv + PySide6 + paho-mqtt(`venv/` 已加 .gitignore) + +### 配套 + +- 固件 vd960DBN `log_*` stream=snapshot 分支(同日实现,devlog V4.1) +- 协议文档:TCP JSON V1.03 / IoT MQTT V1.07 + +--- + +## 2026-07-06 (晚) — 模拟上报 + 协议Topic + 自定义Topic `c19e465` + +### 1. 模拟上报 Tab + +- **loop_data / event_report / heartbeat** 三类上报携带独立可编辑 JSON 编辑区 +- **范例填充**:首次切换类型时自动填入协议定义的标准载荷 +- 单次发送 + **周期上报**(QSpinBox 可调间隔) +- 周期开关由 `QPushButton` toggle 控制 + +### 2. 协议Topic Tab + +- 预加载双主题:`dld960/{sn}/srv`(下发)、`dld960/{sn}/dev`(上报) +- QListWidget 展示,双击自动填充到发布区 +- 发布区可编辑 JSON 载荷,一键发布 +- 主题列表受 SN 输入框驱动,实时更新 + +### 3. 自定义Topic Tab + +- 自由输入 topic + JSON 载荷,QoS (0/1/2) 可调 +- **订阅 / 取消订阅**,接收消息实时展示在 QPlainTextEdit +- `#` / `+` 通配符支持,`paho.mqtt.topic_matches_sub` 路由匹配 +- 自定义订阅的消息自动分发到接收区,附带 topic 前缀 + +### 4. 新增依赖 + +- `paho.mqtt.client` 导入新增 `topic_matches_sub` +- UI 控件: QComboBox, QSpinBox, QPlainTextEdit + +--- + +## 2026-07-06 — paho-mqtt v2 回调修复 `213c0dd` + +### 问题 +断开连接时报错: +``` +TypeError: MqttClient._on_disconnect() missing 1 required positional argument: 'reason_code' +``` + +### 根因 +paho-mqtt v2 默认 `callback_api_version=VERSION2`,`on_disconnect` 回调签名为 5 参数 `(client, userdata, flags, reason_code, properties)`,而 v1 为 3 参数 `(client, userdata, rc)`。 + +### 修复 +- `_on_disconnect` 改用 `*args` 兼容 v1/v2 +- `Client` 构造显式指定 `callback_api_version=CallbackAPIVersion.VERSION2` +- `_on_connect` 保持 v2 签名不变 + +--- + +## 2026-07-06 — tkinter → PySide6 迁移 `e1bf3dc` + +### 决策 +放弃 tkinter,改用 PySide6 (Qt for Python),理由: +- 跨平台原生外观 (Fusion 风格) +- Qt 信号/槽机制替代 tkinter 回调,更易维护 +- 组件丰富 (QGroupBox, QSplitter, QTabWidget 等) + +### 改动 +- `main.py` 全量重写为 PySide6 主窗口 +- 布局: QGroupBox 分组 → QSplitter 分栏 → QTabWidget 功能分区 +- `requirements.txt` 新增 `PySide6>=6.6.0` +- tkinter → Qt 映射: `StringVar`→信号/槽, `Listbox`→`QListWidget`, `Text`→`QTextEdit` + +--- + +## 2026-07-06 — 项目初始化 `a2cfe46` + +### 功能 (初始版本, tkinter) +- MQTT Broker 连接管理 +- 设备自动发现 (`dld960/+/dev` 通配符订阅) +- 设备信息查询 + 主题配置 +- 实时线圈数据 / 事件上报 / 心跳 监控 +- 控制命令: 密码验证/设置、出厂初始化、设备复位 + +### 项目结构 +``` +DBNMQTTool/ +├── main.py # 主窗口 (tkinter → 后迁移至 PySide6) +├── dbn_mqtt_tool/ +│ ├── protocol.py # DLD960 IoT MQTT 协议定义 (主题/命令/载荷模板) +│ ├── mqtt_client.py # MQTT 客户端封装 (paho-mqtt v2) +│ └── device_manager.py # 设备发现与状态管理 +└── requirements.txt # paho-mqtt>=2.0.0 + PySide6>=6.6.0 +``` + +### 协议依据 +`DLD960_IoT_MQTT协议.md` V1.00 + +--- + +## 当前状态 + +| 组件 | 状态 | +|------|------| +| MQTT 连接/断开 | ✅ 已实现,v1/v2 兼容 | +| 设备发现 | ✅ 通配符订阅 | +| 实时数据监控 | ✅ loop_data/event_report/heartbeat | +| 控制命令 | ✅ 15 条命令 | +| 模拟上报 | ✅ c19e465 | +| 协议Topic订阅/发布 | ✅ c19e465 | +| 自定义Topic订阅/发布 | ✅ c19e465 | +| 固件联调 | ✅ vd960DBN IoT 模式稳定上报 | + +--- + +## 2026-07-07 — MQTT V1.01 适配 + 稳定性修复 + +### 1. MQTT 协议 V1.01 适配 + +- Topic 从多主题(`/loop_data`, `/event_report`, `/heartbeat`, `/cmd`…)压缩为双主题 `dld960/{sn}/dev`(上报)、`dld960/{sn}/srv`(下发) +- `manage_mqtt_recv_message()` 实现 V1.01 协议命令分发,支持 `cmd`/`Method` 双格式 +- MQTT PUBLISH 接收修复:topic 过滤 + 通配符路由修正 + +### 2. MqttClient 重构:tkinter 回调 → QObject 信号/槽 + +**问题**: `paho.mqtt` C 层回调直接操作 Qt UI 控件 → `RuntimeError: wrapped C/C++ object has been deleted` 崩溃。 + +**修复**: +- `MqttClient` 继承 `QObject`,使用 Qt 信号/槽机制 +- `on_message` → `message_received` 信号 → 主线程 slot 安全更新 UI +- 所有 publish 路径增加通用异常捕获,防止未捕获异常导致静默崩溃 +- 回退 Qt 信号排队方案,改用 `QMetaObject.invokeMethod` + 日志追踪定位阻塞点 + +### 3. DeviceManager 死锁修复 + +`threading.Lock` 在单线程 Qt 事件循环中自锁 → `RLock`。`add_device()` 和 `remove_device()` 同线程互调时 `Lock` 阻塞自身。 + +### 4. UI/UX 改进 + +- **日志增强**: 收发打印 topic + payload 详情,调试信息更直观 +- **查询响应自动回填**: 设备信息查询后自动填充 SN 等输入框 +- **主动上报配置**: `report_config` 面板支持完整 7 参数独立开关 +- `right` 局部变量 → `self._notebook`,修复 tab 引用丢失 + + +--- + +## 2026-08-05 — 脱机事件日志命令支持 (MQTT V1.06) + +配合 vd960DBN 固件 P1.3(commit 1a01316)+ 协议 V1.06,工具新增脱机事件日志面板(参数配置 Tab 底部): + +### 新增命令 + +| 命令 | 按钮 | 说明 | +|------|------|------| +| `log_stat` | 统计 | 日志统计/分页定位: enabled/boot_seq/count/capacity/seq_first/seq_last | +| `log_query` | 拉取日志 | 按全局序号分页拉取, 起始序号 + 条数(1~4) 可调 | +| `log_clear` | 清除日志 | 二次确认弹窗, 审计留痕不可撤销 | + +### 实现要点 + +- `protocol.py`: 新增 `CMD_LOG_*` 常量、`LOG_COMMANDS` 集合、`data_log_query()` 构建器(start_seq≥1 / count 1~4 边界钳制)、`LOG_EVENT_TYPE_DESC` 事件类型中文描述(10 类 + unknown) +- `main.py`: 参数配置 Tab 新增 g6 组(起始序号/条数 spinbox + 三按钮 + 只读显示区 QPlainTextEdit) +- `_on_message` code==0 分支新增 `log_stat`/`log_query`/`log_clear` 响应处理 +- 显示优化: log_query 记录带事件类型中文描述; unix_ts 已同步显示真实时间, 未同步显示 `boot+ts_ms(未同步)` +- 清除日志前 QMessageBox 二次确认(防误触, 与出厂初始化/设备复位同模式) + +### 验证 + +- `py_compile` 四个模块通过 +- protocol 逻辑单测: data_log_query 边界钳制 (0→1, 99→4, 0→1)、命令枚举一致性、build_request 带 data diff --git a/DBNMQTTool/main.py b/DBNMQTTool/main.py index 6b06bb3..d698213 100644 --- a/DBNMQTTool/main.py +++ b/DBNMQTTool/main.py @@ -196,6 +196,8 @@ class MainWindow(QMainWindow): b1.clicked.connect(self._query_ssc_net) b2 = QPushButton("设置") b2.clicked.connect(self._set_ssc_net) + b2.setEnabled(False) + b2.setToolTip("MQTT 固件暂未实现 ssc_net_set,请用 TCP JSON 或蓝牙通道配置") btn_row.addWidget(b1) btn_row.addWidget(b2) btn_row.addStretch() @@ -224,6 +226,8 @@ class MainWindow(QMainWindow): b3.clicked.connect(self._query_iot_net) b4 = QPushButton("设置") b4.clicked.connect(self._set_iot_net) + b4.setEnabled(False) + b4.setToolTip("MQTT 固件暂未实现 iot_net_set,请用 TCP JSON 或蓝牙通道配置") btn_row2.addWidget(b3) btn_row2.addWidget(b4) btn_row2.addStretch() @@ -251,6 +255,8 @@ class MainWindow(QMainWindow): b5.clicked.connect(self._query_iot_topic) b6 = QPushButton("设置") b6.clicked.connect(self._set_iot_topic) + b6.setEnabled(False) + b6.setToolTip("MQTT 固件暂未实现 iot_topic_set,请用 TCP JSON 或蓝牙通道配置") btn_row3.addWidget(b5) btn_row3.addWidget(b6) btn_row3.addStretch() @@ -278,6 +284,9 @@ class MainWindow(QMainWindow): ]: btn = QPushButton(label) btn.clicked.connect(slot) + if label != "验证密码": + btn.setEnabled(False) + btn.setToolTip(f"MQTT 固件暂未实现 {label},请用 TCP JSON 或蓝牙通道") btn_row4.addWidget(btn) btn_row4.addStretch() g4_layout.addLayout(btn_row4, 1, 0, 1, 4) @@ -1018,7 +1027,7 @@ class MainWindow(QMainWindow): if not sn: return for cmd in [CMD_DEV_INFO_QUERY, CMD_SSC_NET_QUERY, CMD_IOT_NET_QUERY, - CMD_IOT_TOPIC_QUERY, CMD_LOOP_PARAM_QUERY]: + CMD_IOT_TOPIC_QUERY]: try: self._mqtt.send_command(sn, cmd) except Exception: diff --git a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c index a0b9bab..081c561 100644 --- a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c +++ b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c @@ -671,6 +671,56 @@ static void iot_handle_publish(const char *topic, uint8_t *payload, int payload_ msg_id, dev_time_now()); iot_mqtt_publish(resp_topic, resp, strlen(resp), 1); + } else if (strcmp(cmd_str, "ssc_net_query") == 0) { + /* SSC 网络配置查询 (只读全局, 协议 V1.02) */ + char resp[400]; + snprintf(resp, sizeof(resp), + "{\"msg_id\":%lu,\"cmd\":\"ssc_net_query\"," + "\"ts\":%lu,\"code\":0,\"msg\":\"success\"," + "\"data\":{\"dev_ip\":\"%d.%d.%d.%d\",\"subnet_mask\":\"%d.%d.%d.%d\"," + "\"route_ip\":\"%d.%d.%d.%d\",\"lssc_ip\":\"%d.%d.%d.%d\"," + "\"dns\":\"%d.%d.%d.%d\",\"port\":%d}}", + msg_id, dev_time_now(), + local_net_cfg.lip[0], local_net_cfg.lip[1], local_net_cfg.lip[2], local_net_cfg.lip[3], + local_net_cfg.sub[0], local_net_cfg.sub[1], local_net_cfg.sub[2], local_net_cfg.sub[3], + local_net_cfg.gw[0], local_net_cfg.gw[1], local_net_cfg.gw[2], local_net_cfg.gw[3], + net_center_info.lssc_ip[0], net_center_info.lssc_ip[1], + net_center_info.lssc_ip[2], net_center_info.lssc_ip[3], + local_net_cfg.dns[0], local_net_cfg.dns[1], local_net_cfg.dns[2], local_net_cfg.dns[3], + net_center_info.tcp_port); + iot_mqtt_publish(resp_topic, resp, strlen(resp), 1); + PRINT("IOT: ssc_net_query dev_ip=%d.%d.%d.%d\n", + local_net_cfg.lip[0], local_net_cfg.lip[1], local_net_cfg.lip[2], local_net_cfg.lip[3]); + + } else if (strcmp(cmd_str, "iot_net_query") == 0) { + /* IoT 网络配置查询 (只读全局) */ + char resp[400]; + snprintf(resp, sizeof(resp), + "{\"msg_id\":%lu,\"cmd\":\"iot_net_query\"," + "\"ts\":%lu,\"code\":0,\"msg\":\"success\"," + "\"data\":{\"host\":\"%s\",\"port\":%d,\"client_id\":\"%s\"," + "\"username\":\"%s\",\"password\":\"%s\"}}", + msg_id, dev_time_now(), + iot_net_info.remote_addr, iot_net_info.mqtt_port, + iot_net_info.client_id, iot_net_info.username, iot_net_info.password); + iot_mqtt_publish(resp_topic, resp, strlen(resp), 1); + PRINT("IOT: iot_net_query host=%s port=%d\n", + iot_net_info.remote_addr, iot_net_info.mqtt_port); + + } else if (strcmp(cmd_str, "iot_topic_query") == 0) { + /* IoT Topic 配置查询 (只读全局) */ + char resp[300]; + snprintf(resp, sizeof(resp), + "{\"msg_id\":%lu,\"cmd\":\"iot_topic_query\"," + "\"ts\":%lu,\"code\":0,\"msg\":\"success\"," + "\"data\":{\"client_id_enable\":%s,\"topic_pub\":\"%s\",\"topic_sub\":\"%s\"}}", + msg_id, dev_time_now(), + g_iot_topic.clientid_enable ? "true" : "false", + g_iot_topic.topic_pub, g_iot_topic.topic_sub); + iot_mqtt_publish(resp_topic, resp, strlen(resp), 1); + PRINT("IOT: iot_topic_query pub=%s sub=%s\n", + g_iot_topic.topic_pub, g_iot_topic.topic_sub); + } else { // 暂不支持的命令, 返回错误 char resp[256]; diff --git a/vd960DBN/docs/devlog.md b/vd960DBN/docs/devlog.md index 17b0570..1f584b7 100644 --- a/vd960DBN/docs/devlog.md +++ b/vd960DBN/docs/devlog.md @@ -4,6 +4,34 @@ > > 项目定位: DLD960 通信板 — BLE 配网、TCP JSON 协议服务、Loop MCU 串口桥接 +## 2026-08-18 — MQTT 命令集补齐:ssc_net_query / iot_net_query / iot_topic_query + +### 背景 + +DBNMQTTool 实测发现 MQTT 通道 `ssc_net_query` / `iot_net_query` 返回 `code=4 unsupported command`。根因:MQTT 协议文档命令表声明 14 条 srv→dev 命令,固件 `manage_mqtt_recv_message` 只实现 6 条(dev_info_query / report_config / pwd_verify / event_report ACK / log_*),注释即"目前仅实现基本响应框架"。查询类命令缺口本次补齐。 + +### 变更 + +| 命令 | 数据源 | 说明 | +|------|--------|------| +| `ssc_net_query` | `local_net_cfg` + `net_center_info` | dev_ip/subnet_mask/route_ip/lssc_ip/dns/port 组包,与 TCP JSON §4.5 一致 | +| `iot_net_query` | `iot_net_info` | host/port/client_id/username/password,与 TCP JSON §4.7 一致 | +| `iot_topic_query` | `g_iot_topic` | client_id_enable/topic_pub/topic_sub,与 TCP JSON §4.9 一致 | + +三条均为**只读全局变量组包**,低风险;插入点:log_clear 分支后、unsupported else 前。 + +### 仍未实现(协议声明但固件缺,工具已禁用对应按钮) + +`ssc_net_set` / `iot_net_set` / `iot_topic_set` / `pwd_set` / `factory_reset` / `device_reset` / `dev_serial_set` / `loop_param_query` / `loop_param_set`——设置类涉及写 Flash/设备重启,loop_param 需 UART 透传异步机制,留待后续(工具侧已禁用按钮 + tooltip 引导走 TCP/BLE)。 + +### 验证 + +- check_c_balance OK;全局变量可见性确认(net_srv.h extern) +- DBNMQTTool offscreen:6 个未实现按钮禁用 + tooltip,查询类可用 +- 待板级:MRS 编译 + 真机 MQTT `ssc_net_query` / `iot_net_query` / `iot_topic_query` + +--- + ## 2026-08-18 — TCP/MQTT 脱机日志快照流支持(协议 V1.03/V1.07 落地) ### 背景 @@ -1307,6 +1335,7 @@ TCP 超时要等 ~2 分钟才触发 `SINT_STAT_TIM_OUT`, | 版本 | 时间 | 说明 | |------|------|------| +| V4.2 | 2026-08-18 | MQTT 命令集补齐: ssc_net_query/iot_net_query/iot_topic_query 只读组包 (协议 V1.02 对齐), 工具禁用未实现按钮 | | V4.1 | 2026-08-18 | TCP/MQTT 脱机日志快照流: log_stat/log_query/log_clear 支持 stream=snapshot (协议 V1.03/V1.07), snap_rec_to_json 序列化, 事件流 count=0 按上限 | | V4.0 | 2026-08-10 | BLE 脱机日志接口: OFFLOG_STAT/QUERY/CLEAR (0x25/0x26/0x27), 32B OfflogEvt 二进制直传, 缓冲扩容 132B, 隔离测试 7 例 + 协议文档 V1.00 | | V3.9 | 2026-08-05 | offlog 协议导出命令分发: log_stat/log_query/log_clear 落地 MQTT V1.06 + TCP JSON V1.02 (seq_first/seq_last 计算、idx 映射、OFFLOG_MAX_QUERY_RECORDS=4、log_clear 阻塞~2.8s) |