- docs/DLD960_IoT_MQTT协议.md: 字段缩写 + 时间单位 5ms→50ms - vd960DBN/iot_mqtt_srv.c: 6字段缩短对齐协议 (level/iscar/freq/diff/sens/cndtn) - vd960DBN/tcp_json_srv.c: gap_ms5/passtime_ms → gap/passtime - vd960DBN/loop_uart_proto.h: 注释 5ms→50ms - DBNMQTTool/main.py: 模拟样本数据字段同步
142 lines
5.1 KiB
Markdown
142 lines
5.1 KiB
Markdown
# DBNMQTTool 开发日志
|
||
|
||
> DLD960 IoT MQTT 桌面工具 | Python 3.11+ | PySide6 | paho-mqtt v2 | 跨平台 (Windows/Linux/macOS)
|
||
>
|
||
> 定位: DLD960 车检器 MQTT 调试工具 — 设备管理、实时数据监控、模拟上报、主题订阅/发布
|
||
|
||
---
|
||
|
||
## 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 引用丢失
|
||
|