# 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 创建(端口 5960,PROTO_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 基础打通 ### 背景 在 CH32V208(RISC-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条命令) |