Files
vd_960/vd960DBN/docs/devlog.md
T
wangfq 652fc5f938 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
2026-07-09 21:32:39 +08:00

231 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# vd960DBN 开发日志
> MCU: CH32V208 (RISC-V, WCH) | 通信: BLE + ETH (WCHNET) + UART2→Loop MCU | TCP JSON 端口: 5960
>
> 项目定位: DLD960 通信板 — BLE 配网、TCP JSON 协议服务、Loop MCU 串口桥接
---
## 2026-06-26 — TCP JSON 协议框架搭建
### 1. TCP JSON Server 基础实现
- WCHNET TCP listen socket 创建(端口 5960PROTO_TYPE_TCP
- 参考 WCH 官方 EVT/EXAM/ETH/TCPServer 例程
- `g_net_state.flag` 状态机: `ETH_LibInit→1, WCHNET_CreateUdpSocket→2, WCHNET_CreateTcpSocket→3`
- SSC 禁用时 (`NET_SSC_ENABLE=0`) 手动设 `flag=2` 跳过 UDP 初始化
### 2. 鉴权 + 15 条命令
- `pwd_verify` 鉴权,3次错误 → 60s 锁定
- 命令表驱动分发: `dev_info_query`, `ssc_net_set/query`, `iot_net_set/query`, `iot_topic_set/query`, `pwd_set`, `factory_reset`, `device_reset`, `loop_param_set/query`, `loop_version_query`, `loop_factory_init`, `loop_sens_read/write`
- Deferred 响应模式: Loop MCU 命令异步 → `TcpJsonPending` 挂起 → `json_check_pending()` 轮询
### 3. simple_json 解析器修复
- **6 个 bug 修复**: NULL 解引用崩溃(plain values)、缺少 null terminator、buffer unsafe clear、数组支持缺失
- 字符串值提取时**不带引号**(调用方无需手动 strip quotes
### 4. WCHNET TCP 踩坑
| 问题 | 修复 |
|------|------|
| listen socket 与数据 socket 混用 → 收不到数据 | CONNECT 发到 N, RECV/DISCONNECT 发到 N+1 |
| `WCHNET_SocketSend` 在 listen socket 静默失败 | 改用 `g_json_socket_listen + 1` |
| 接收缓冲区与帧缓冲区重叠 → 数据损坏 | 分离 WCHNET 内部 buf + 帧累加 buf |
| `#if NET_SSC_ENABLE` 误包共享函数 | 移出 `mStopIfError`/`GetMacAddr`/`get_ipstr_to_array` |
---
## 2026-06-30 — Loop MCU 串口协议 (0x7F) + 传感器上报
### 1. USART2 Loop MCU 通信
- 波特率 **192000**(文档写 115200,实际硬件 192000
- 0x7F 协议帧解析器: `lup_feed_byte()` 逐字节状态机 + LEN-based 帧边界
- 校验字节站位: `total_len = 5 + LEN`(CMD 已在 LEN 中,勿重复计)
- 命令: `lup_cmd_send()` 发送 → `lup_cmd_check_timeout()` 轮询超时
### 2. 0xC0 传感器数据上报
- Loop MCU 主动推送 0xC0 帧 → `lup_process_frame()` 校验 → 回调 `json_sensor_callback`
- TCP JSON 输出格式: `{"sens_type":"multi_coil","coils":[...]}`
- `g_report_active` 开关控制上报启停
- 0xC0 帧通过回调直接驱动网络上报,不经 `uart_srv` 阻塞
### 3. 0xC0 帧时间量字段
- `misc_type=0``passtime_ms`(通过时间 / 车间距,根据 `car_state` 区分)
- `misc_type=1``cut_amount`(线圈断开次数)
- `misc_type=2``flow_amount`(车流量)
- `misc_type=3``relay_count`(继电器动作次数)
### 4. 协议文档
- `docs/vd960_loop_protocol_v1.0x.md` — 0x7F 帧格式、校验算法、命令参考
- 波特率修正: 115200 → 192000
---
## 2026-07-01 — passtime_ms5 字段改名
`vd960Loop` 侧时间戳从 5ms 改 50ms 后,DBN 侧同步:
- `passtime_ms5``passtime_ms`(字段名去 5 后缀)
- `loop_uart_proto.h/c` 结构体 + 解析 + `tcp_json_srv.c` JSON 字段同步
---
## 2026-07-02~03 — TCP Server 超时自动重启机制
### 1. 三项超时触发条件
| 条件 | 时间 | 处理 |
|------|------|------|
| 无任何连接 | 5min | `do_restart` → 计数重启 |
| 无数据交互 | 5min | `do_restart` → 计数重启 |
| Auth 密码错 3 次 | 立即 | `tcp_json_restart()` 直接重启 |
### 2. 重启计数保护
- 最多连续重启 **3 次**,超过进入 **10 分钟冷却期**
- `CONNECT` 成功时 `restart_count` 清零(正常连接重置计数,不算异常)
- Auth timeout 不消耗计数器(正常运维行为)
### 3. WCHNET 限制 - listen socket 不可关闭重建
**根因**: `WCHNET_SocketClose(listen)` 后端口 5960 仍标记"已占用"`SocketCreat` 返回 `ERR_ISCONN(0x1D)`
**最终方案**: `tcp_json_restart()` 只关数据 socket(N+1) 断开客户端,listen socket 保持不动,仅重置应用层状态。WCHNET 自动处理下一个 CONNECT。
### 4. Auth timeout 死循环修复
原 Auth timeout 手工 `WCHNET_SocketClose` 后未设 `g_json_socket_listen = 0xFF`,下次 poll 条件仍满足 → 无限打印。改用统一的 `do_restart` 路径后修复。
### 5. Auth 3次失败 → 直接重启
去掉 60s Auth timeout 倒计时。改为连接后 3 次鉴权失败(密码错/格式错)即 `tcp_json_restart()`。连接后无交互由 5min 空闲检查覆盖。
---
## 2026-07-06 — MQTT IoT 基础打通
### 背景
在 CH32V208RISC-V, 栈仅 2KB)上实现 MQTT IoT 协议栈,对标 DBN101GA 参考项目。WCHNET TCP MSS=576, Publish 须 ≤500B。
### 1. MQTT 重构对标 DBN101GA
- `iot_mqtt_srv.c` 对标 DBN101GA 参考实现重写
- MQTT socket 复用 `SocketId_TCP`(而非独立 socket
- `iot_connect_broker``SourPort` 参数
- 出厂默认 topic 使用真实设备序列号
### 2. 栈溢出系列修复
| 问题 | 修复 |
|------|------|
| MQTT buffer 在栈上 → 溢出 | 改为 `static` 全局分配 |
| `iot_mqtt_publish_sensor`: `data_json[2KB] + payload[2KB] = 4KB` 远超 2KB 栈 | 减小缓冲区 + static 分配 |
| 缓冲区 2048 → 1024 | 单次交互不超 1KB |
### 3. MQTT CONNECT 延迟发送
**根因**: `MQTT_connect()` 在中断上下文调用 `WCHNET_SocketSend` → 崩溃。
**修复**: CONNECT 包延到 poll 轮询内发送,避免中断内调用网络 API。
### 4. MQTTPacket 初始化修复
`MQTTPacket_connectData_initializer` 是复合字面量,不能用于赋值。改用临时变量中转。
### 5. IoT socket 重复创建 + broker IP 解析修复
- IoT socket 重复创建 → 连接失败,改为复用已有 socket
- broker IP 字符串解析修正
---
## 2026-07-07 — MQTT 协议 V1.01 + 命令分发
### 1. MQTT 主题压缩:多主题 → 双主题
协议从 V1.00 的多 topic`dld960/{sn}/loop_data`, `/event_report`, `/heartbeat`, `/cmd`, `/cfg`…)压缩为 V1.01 双主题:
| 方向 | V1.00 | V1.01 |
|------|-------|-------|
| 设备→平台 | 5+ topics | `dld960/{sn}/dev` |
| 平台→设备 | 5+ topics | `dld960/{sn}/srv` |
### 2. MQTT 命令分发
`manage_mqtt_recv_message()` 实现 V1.01 协议命令分发,支持 `cmd` / `Method` 双格式:`pwd_verify`, `dev_info_query`, `loop_param_set/query`, `loop_version_query`, `loop_factory_init`, `device_reset`, `factory_reset` 等。
### 3. report_config 完整 7 参数
MQTT/TCP `report_config` 支持完整 7 参数配置:`period`, `loop_data`, `event_report`, `heartbeat`, `passtime`, `cut_amount`, `flow_amount`。与 TCP JSON 协议统一。
### 4. MQTT 网络配置
`ssc_net_set` / `iot_net_set` / `iot_topic_set` 三条命令实现,支持通过 MQTT 远程配置设备网络参数和主题。
---
## 2026-07-08 — MQTT 稳定性修复系列
### 1. g_iot_socket 未初始化 → 硬故障重启
`g_iot_socket` 声明为全局变量但未初始化,值为 `0xFF``WCHNET_SocketSend(0xFF)` 直接触发硬件故障重启。
**修复**: 初始化为 `INVALID_SOCKET`
### 2. loop_data JSON 超 MSS 导致 SocketSend 溢出
WCHNET TCP MSS=576,原 `loop_data` JSON 四通道全字段 ~800B → `WCHNET_SocketSend` 溢出崩溃重启。
**修复**: 精简 JSON 字段至 ~400B(单包达标),再**分批发送**(2通道/包 × 2包)。
### 3. iot_mqtt_send() hex dump 循环 → 栈溢出
调试用的 hex dump 循环(65次 `PRINT`)在仅 2KB 栈的 CH32V208 上直接栈溢出重启。
**修复**: 移除 hex dump 循环。
### 4. MQTT 主动上报无数据 + PINGREQ 缺失
`poll_mqtt()` 未正确触发 `MQTT_Yield()``MQTT_Live()`,导致主动上报无数据、PINGREQ 缺失断连。
**修复**: 改用 `net_srv.c` 统一的 `mqtt_publish()` + 修正 `poll_mqtt()` 调度逻辑。
### 5. 传感数据 topic 修正
topic 修正为 V1.01 双主题协议 `dld960/{sn}/dev`(此前遗留旧 topic 格式)。
### 6. 恢复 loop_data 完整字段
精简 JSON 后缺失部分字段(`freq`, `passtime_ms` 等),恢复完整字段并在分批框架内发送。
---
## 修订记录
| 版本 | 时间 | 说明 |
|------|------|------|
| V3.1 | 2026-07-09 | V1.03: 订阅后发 initialize 上线消息; iot_mqtt_srv 订阅改双主题 |
| V3.0 | 2026-07-08 | MQTT 稳定性修复: socket初始化/buffer溢出/分批发送/hex dump/PINGREQ |
| 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.7 | 2026-07-06 | MQTT IoT 基础打通: 对标DBN101GA + 栈溢出修复 + CONNECT延迟发送 |
| V2.6 | 2026-07-06 | IoT 模式配置 bug 修复 |
| V2.5 | 2026-07-03 | tcp_json_restart 只关数据socket, listen保持不动 (WCHNET限制) |
| V2.4 | 2026-07-03 | 去掉 Auth 60s timeout, 改为3次失败即重启 |
| V2.3 | 2026-07-03 | Auth timeout 不计入重启限额, 修复冷却期阻断连接 |
| V2.2 | 2026-07-03 | Auth timeout 死循环打印修复 → goto do_restart |
| V2.1 | 2026-07-03 | TCP Server 自动重启机制 (3条件 + 3次限额 + 10min冷却) |
| V2.0 | 2026-07-01 | passtime_ms5 → passtime_ms 字段改名 |
| V1.5 | 2026-06-30 | 0xC0 传感器上报 + 时间量字段完善 + 协议文档 |
| V1.4 | 2026-06-30 | USART2 Loop MCU 0x7F 协议实现 |
| V1.3 | 2026-06-30 | simple_json 6 bug 修复 |
| V1.2 | 2026-06-30 | WCHNET buffer 分离 + SocketSend listen→data 修正 |
| V1.1 | 2026-06-30 | NET_SSC_ENABLE 隔离 + #if guard 共享函数修复 |
| V1.0 | 2026-06-26 | TCP JSON 协议框架 (鉴权 + 15条命令) |