Files
vd_960/docs/ROADMAP.md
T
wangfq 70e44e6241 docs(roadmap): 补充脱机日志子系统 + 日志导出管理 + 远程OTA路线细化
- P1.2 脱机日志: W25Qxx 分区规划(参数/事件流/快照流/OTA暂存),
  事件流必录清单, 快照流同频落盘挂 iot_sensor_ingest 同源出口,
  无RTC时间戳方案(boot_seq+mstick+时钟锚点)
- P1.3 导出与管理: MQTT断网补报/命令分页拉取/BLE小程序读取
  三通道, log_stat/log_clear(鉴权+审计自记录)
- P1.4 远程OTA: 先走现网MQTT+复用ISP透传底层(与BLE OTA同构);
  Loop先存后刷+断点续传+回滚, 继电器安全底线;
  DBN自身远程OTA三路线比选(过渡态=仍走BLE最稳妥)
- 风险表新增: 无RTC时间戳、日志写与总线争用
2026-07-17 18:57:13 +08:00

199 lines
14 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.
# vd960 (DLD960) 开发计划 — V1.0.0 之后
> 制定日期:2026-07-17 · 基线:整机 V1.0.02026-07-16 发布)
> 原则:先稳固、再上云、后算法深化;任何涉及继电器输出的改动,防砸车逻辑优先。
---
## 0. 现状基线
| 项 | 状态 |
|----|------|
| 整机版本 | V1.0.0(首发),Loop/DBN 固件 1.0 配套 |
| 协议 | Loop 串口 V1.05 / TTL 串口 V1.01 / TCP JSON V1.01 / IoT MQTT V1.05 |
| 在途改动(未提交) | BLE 透传路径重构:`usart_biz.c` 0x7F→0x8F 帧改走 `set_response_tran_to_notify()`,原 `_report_flag` 保留机制移除 |
| 已知约束 | 无 RTC(依赖平台下发 ts);CH32V208 栈紧张;Loop/DBN 固件禁止混刷 |
---
## P0 — 发布后稳固(目标 V1.1.0,约 2~4 周)
### P0.1 BLE 透传路径重构收尾 🔴(在途)
当前工作区改动把 0xC0 传感帧的 BLE 转发从"置 flag 延迟消费"改为"立即 notify"。收尾必须核对三件事:
1. **帧消费方真值表**0xC0 帧现在有 **三个消费方**TCP JSON 回调 / MQTT `iot_sensor_ingest` / BLE notify)。2026-07-15 的"陈旧快照 34 秒"事故根因就是消费路径数据源分裂——BLE 加入后必须重画一张"谁消费、谁清理(InitPkgUart"的真值表,确保:
- 每条路径都能拿到帧(同源汇聚不漏帧);
- 帧最终一定被清理(无滞留 → 无假"新帧");
- BLE ACS 分支改 Magic 为 0x8F 后,MQTT/TCP 路径若还要读同一缓冲,读到的是被改过的帧头(**待确认是否有影响**)。
2. `set_response_tran_to_notify()` 新增返回值的语义与调用方检查。
3. 板上验证:BLE 小程序连上时,TCP/MQTT 上报不受影响;BLE 断开后无帧泄漏。
### P0.2 代码 TODO 清剿
| 位置 | 问题 | 优先级 |
|------|------|--------|
| `iot_mqtt_srv.c:753` | `loop_ok[i] = 1` 硬编码,未取 Loop MCU 真实线圈状态 → 平台看到的线圈健康度是假的 | 🔴 高 |
| `net_srv.c:528` | MQTT 接收长度未做溢出防护(`len-received` 越界风险)| 🔴 高 |
| `storage.c:494`DBN | Flash_Model 读失败无停机/降级保护 | 中 |
| `net_srv.c:1225` | 序列号修改命令未实现 | 中 |
| `dbn_ble_srv.c:870` | ACS timeout `min→ms` 换算待确认(当前 ×60×100,疑似按 10ms tick,需对时钟源) | 中 |
| `main.c`Loop)多处 | "不整个设备复位,只复位蓝牙以外部分"——历史注释,评估后关闭或立项 | 低 |
### P0.3 回归验证清单(配合 vd_test_fixture 工装)
- [ ] 长车双线圈场景复测:car_leave 事件后**下一条** loop_data 的 iscar 必须已翻 false(同源验证)
- [ ] event_report 断网入队 → 重连补报闭环;5s 超时重发 ×3 后的放弃行为
- [ ] 时钟同步:校准前 ts=上电秒数的平台侧兼容;mstick 49.7 天回绕仿真(gcc 隔离单测)
- [ ] MQTT 稳定性:>512B 帧、PINGREQ 保活、broker 主动踢线后的重连节奏
- [ ] 拨码/灵敏度/hold_time/relay_delay 全参数配置读写一致性(BLE 链路 + MQTT 链路交叉验证)
**P0 出口条件**:以上全绿 → 两侧 `FIRMWARE_VER` 升 1.1 → 整机 tag v1.1.0。
---
## P1 — 传感数据上云闭环(目标 V1.2.x,约 1~2 月,与 edc_server 平台侧并行)
这是你"传感数据云 + 业务平台"目标的主线,设备侧固件已基本就绪,重心在平台侧消费。
### P1.1 平台侧对接(edc_server
- **event_report 消费契约**:平台先落库、后 ACK(code=0)——严禁先 ACK 后落库(设备出队后事件不可再生)
- **loop_data 落库 + 可视化**variation 有符号曲线(正=车/裕量,负=基线污染——免费的诊断维度)、频率漂移趋势图;锯齿波形态识别(5s 基线阶跃是正常形态,别当故障)
- **流量/占用 API**:基于 car_enter/car_leave 事件 + 通过时间/车间距(50ms 单位)产出分通道流量计数、占用率、平均通过时间
- **设备台账**initialize 上线登记、心跳离线判定(阈值=心跳间隔×3)、report_config 远程下发界面
### P1.2 脱机日志子系统 🆕(W25Qxx SPI NOR
**硬件底子**DBN 外挂 W25QxxSPI1,驱动支持 Q80~Q128,**板上型号待确认**——容量决定快照保留时长)。参数区只占头部 <1KB,其余全部可规划。
**分区规划(建议,按 W25Q64/8MB 算)**
| 分区 | 容量 | 用途 |
|------|------|------|
| 参数区 | 64KB0x000000 起,现用 <1KB | 现有配置,留余量 |
| 事件日志区 | 256KB | 环形,关键事件流,不被快照冲掉 |
| 传感快照区 | ~6MB | 环形,0xC0 帧原样落盘 |
| OTA 镜像暂存区 | 512KB | Loop 固件(64KB×2 版本回滚)+ 预留 DBN 镜像 |
**两条日志流分开存**
1. **事件流(必录,低速率)**car_enter/car_leave(含时间量)、线圈断线/恢复、继电器动作、上电/复位(含复位原因)、MQTT/TCP 连接与断开、event_report ACK 超时/重发/放弃、配置变更(含来源:BLE/MQTT/TCP)、灵敏度换档、**时钟同步锚点**、固件升级开始/结果、日志清除操作(审计自记录)
2. **快照流(环形可覆盖)**:0xC0 帧二进制原样 + 头部(序号/boot_seq/mstick),~64B/条,**记录节奏与网络上报同频**(空闲按 interval、活动 300ms、car 沿立即)——直接挂在 `iot_sensor_ingest()` 同源出口,天然与上报一致
**容量预算**W25Q64):6MB 快照区 ≈ 9.8 万条;快档 300ms 连续压满也能存 ~8 小时,实际车流场景(空闲 30s + 过车突发)可保留**数周**。W25Q80(1MB)则只有 ~1.1 万条,**所以先确认板上焊的哪颗**。
**⚠ 无 RTC 的时间戳设计(最容易踩的坑)**:断电后 mstick 归零,纯 Unix 时间戳不可行。方案:每条记录带 `(boot_seq, mstick)`;每次时钟同步成功时写一条**时间锚点事件**boot_seq ↔ unix_ts 映射);导出时由平台/小程序用锚点回算绝对时间。从未同步过的 boot 段只有相对时间——协议文档里要写明这个语义。
**磨损与 RAM**:环形顺序写天然磨损均衡(4KB sector 顺序擦除,W25Q 10 万次擦写寿命无忧);**复用现有 `SPI_FLASH_BUF[4096]`,不新增大缓冲**CH32V208 SRAM 紧张的教训)。
### P1.3 日志导出与管理 🆕
**导出通道(三条,统一按序号分页,不按时间——时间不可靠)**
| 通道 | 机制 | 说明 |
|------|------|------|
| MQTT 自动补报 | 断网期间事件流落盘,重连后按序号续传 | 现有 16 深 RAM 队列扩展为 flash-backed,溢出转日志区;与 event_report ACK 闭环衔接 |
| MQTT/TCP 命令拉取 | `log_query {stream, start_seq, count}` 分页 | 复用现有 cmd 分发框架;注意 Publish≤500B 分批(MSS=576 教训) |
| BLE 小程序读取 | 复用 0x8F 通道新增日志读命令 | BLE MTU 分包(20~244B),小程序侧分页 UI |
**管理命令**
- `log_stat`:各流的序号区间、条数、容量占用
- `log_clear {stream}`:**需鉴权**;分流清除;清除动作本身写入事件流(审计——谁在什么时候清了日志)
- 自动管理:环形覆盖为常态,无需人工干预;满不停写
### P1.4 远程 OTA 🆕(路线已定:先走现网 MQTT,底层复用 ISP 透传)
**关键认知**BLE 给 Loop MCU 升级 = "镜像经手机流式送到 CH32V208 → ISP 串口透传刷写"。远程 OTA 只是把"送镜像"的传输层从 BLE 换成 MQTT,**ISP 透传底层完全复用**——且 Loop MCU 的 OTA 根本不需要 CH32V208 做 A/B 分区,镜像只是路过。
**分两档,难度和节奏完全不同:**
**① Loop MCU (AT32F421) 远程 OTA —— v1.2.x 落地**
采用**先存后刷**(优于流式直透):
1. 平台 MQTT 分片下发(每片带 offset+CRC,≤500B/片,支持断点续传)→ 写入 W25Qxx 暂存区
2. 全镜像 CRC 校验通过后,才启动 ISP 透传本地刷写(复用 BLE OTA 的透传状态机)
3. 抗网络抖动:下载阶段断网无所谓,续传即可;刷写阶段纯本地,窗口短
4. 暂存区保留上一版镜像 → 支持回滚重刷
**安全底线(会车产品,升级失败=继电器行为不可控)**
- 升级窗口检查:有车压线圈时告警/延迟启动——**待定策略**
- ISP 期间 Loop MCU 停止检测,继电器处于什么状态?(复位后 GPIO 默认态应为断开=常开安全侧,**待板上验证**)
- 刷写失败自动重试 ×3,仍失败 → event_report 告警 + 保持 ISP 可重入(AT32 ISP bootloader 兜底,不会真砖)
- 升级开始/结果写入事件日志
**② DBN (CH32V208) 自身远程 OTA —— 方案评审先行,落地后置**
难点:128KB Flash 装不下 APP 双分区;现有 BLE OTA 走 WCH "OnlyUpdateApp" IAP 框架(bootloader 固定只认 BLE)。候选路线:
- (a) 镜像下到 W25Qxx 暂存 + 校验 → 改 bootloader 支持从外部 Flash 搬运(**动 bootloader 风险高**,刷坏只能拆壳烧录)
- (b) RAM 驻留搬运代码自刷写(掉电=砖,不推荐)
- (c) 维持现状:DBN 升级仍走 BLE(现场人员),只有 Loop 支持远程——**最稳妥的过渡态**
先出方案评审文档比选,v1.2.x 期间不阻塞 ①。
**③ 4G 通道下的 OTA**4G 模组(TTL 对接 UART1)跑 MQTT 后,①②的分片下载协议原样复用——传输层无关是这套设计的出发点。注意 4G 流量成本:64KB 镜像 + 重传开销可忽略,但快照流补报要设流量上限。
### P1.5 设备侧其他补强
- **loop_data 增补字段**(若 P1.1 分析需要):如 Origin 绝对值上报,便于平台重建基线轨迹——走协议 V1.06 流程,两侧同版本配套
- **DBNMQTTool** 同步:日志拉取/OTA 分片下发的模拟与断言(工具先行,固件后到)
### P1.6 4G 上云通道(UART1 RFU 启用,可后置到 P3
- 模组选型(Cat.1 足够:EC800 系列/Air780 级别),AT 透传 vs 模组内置 MQTT 两条路线对比
- 网口 MQTT 与 4G MQTT 复用同一 `iot_mqtt_srv` 状态机,仅换传输层——架构上先留接口
---
## P2 — 检测算法深化(Loop 侧,目标 V2.x,约 2~3 月)
### P2.1 抗变频器/电磁干扰 🎯(你的长期主目标)
1. **先取证再动手**:用工装+现场采集受扰线圈的 CAPVD 原始序列(10ms 粒度),确认干扰形态(周期性拍频 / 白噪 / 突发脉冲)——**待现场验证**
2. **频点错开**:4 路线圈两级调频电容(33nF/10nF)已有硬件基础,上电自检各路振荡频率,间距不足时自动切档,抑制相邻串扰
3. **算法层**:现有 IIR+斜率限幅+进入确认对突发脉冲已有基础免疫;针对周期性拍频评估陷波/中值预滤(注意 10ms tick 下的计算预算)
4. 产出:抗干扰测试报告(干扰源型号、距离、频谱、误检率前后对比)
### P2.2 双线圈测速 + 车型粗分类
- 利用现有 misc 时间量(通过时间/车间距,50ms 单位)+ 已知线圈间距 → 速度估计
- 信号长度(占用时间×速度)→ 车长 → 粗分类(小车/大车/拖挂)
- 拖挂车"半截车"识别:单通道内 variation 双峰形态检测——直接服务会车防砸
- 输出通道:event_report 新增 speed/class 字段(协议升版)
### P2.3 方向判别
- 线圈 1→2 与 2→1 的触发时序 → 方向语义,供会车/双向流量使用
- Loop 侧输出还是平台侧算:**倾向 Loop 侧**(时序精度 50ms 内,平台侧受上报调度抖动影响)
---
## P3 — 会车控制与融合(依赖 P1/P2 产出)
- **会车控制逻辑平台侧先行**:基于多台 DLD960 的 event_report(有 ACK 闭环,可靠交付)做单通道红绿灯会车状态机;业务逻辑只认 event_reportloop_data 仅做展示——两通道职责不混
- **异常分支优先设计**:设备离线(心跳超时)→ 会车灯降级策略;继电器粘连检测(relay_count 与命令数比对);车辆长时间停留(hold_time 超时全通道重启的平台侧感知)
- **单机版会车评估**:DLD960 四通道 + 继电器本地联动能否覆盖小型场景(无平台依赖,可靠性更高)——出对比方案:纯平台 / 纯单机 / 混合
- **雷达/相机融合接口预留**:扩展 UART1 或网口接入目标列表,融合仲裁放平台侧
---
## 版本映射与节奏
| 版本 | 内容 | 前置 |
|------|------|------|
| v1.1.0 | P0 全部(BLE 收尾 + TODO 清剿 + 回归全绿) | — |
| v1.2.x | P1 设备侧(脱机日志 + Loop 远程 OTA + 协议 V1.06 | edc_server 对接联调;W25Q 型号确认 |
| v2.0.0 | P2 算法深化(抗干扰 + 测速分类 + 方向) | 现场干扰数据采集 |
| v2.x | P3 会车控制 | P1 平台 + P2 方向判别 |
## 风险与待现场验证
| # | 风险 | 应对 |
|---|------|------|
| 1 | BLE 重构改动帧消费时序,复发"不同源"类 bug | P0.1 真值表 + 长车复测强制过 |
| 2 | 变频器干扰形态未知,算法方案可能推倒重来 | 先采数据后设计,不拍脑袋 |
| 3 | DBN 自身远程 OTA 无安全落点(128KB 无 A/B、bootloader 只认 BLE | 过渡态:DBN 走 BLE、Loop 走远程;bootloader 改造单独评审 |
| 4 | 协议再升版(V1.06)又是双侧死绑定 | 沿用 Len 字节区分格式的兼容方案,发布走配套矩阵 |
| 5 | 无 RTC,脱机日志绝对时间不可靠 | boot_seq+mstick+时钟锚点回算;协议明示"未同步段仅相对时间" |
| 6 | 日志高频写与 MQTT/BLE 共抢主循环与 SPI 总线 | 快照落盘按 page 缓写、擦除放空闲窗口;实测不达标就降快照档频率 |