fix(iot_mqtt): loop_data 陈旧快照 — 事件与缓存统一帧摄取 (同源)
现场: 长车离开后 event_report 正确, 但 loop_data 连续 34s/100+ 条 iscar:true 陈旧快照, 且冻结 diff=517 锁死 fast_mode 300ms 刷屏。 根因: 0xC0 帧两条竞争消费路径数据源分裂 — uart_srv→lup回调只喂事件不更新 _cached_sr; Step1 直读才更新缓存, 但赢得竞争概率实测 ~2% → 事件每帧必达而快照冻结, 出现'事件说车走了、快照说车还在'。 修复: - 新增 iot_sensor_ingest(): 事件沿 + _cached_sr 刷新单一入口, 回调与 Step1 两路汇入, 帧竞争不再影响数据新鲜度 - Step1 直读路径补 lup_verify_checksum (此前裸解析未校验)
This commit is contained in:
@@ -6,6 +6,42 @@
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-15 — 🔴 loop_data 陈旧快照: 事件与缓存不同源 (帧竞争)
|
||||
|
||||
### 现象 (现场测试: 长车过双线圈)
|
||||
|
||||
车离开线圈1后, event_report(car_leave ch1 val=97) 正确上报并 ACK; 但随后 loop_data 连续 **34 秒 100+ 条** ch1/ch2 `iscar:true`, 直到 msg_id 141 才恢复正常。
|
||||
|
||||
### 根因: 两条帧消费路径的数据源分裂
|
||||
|
||||
0xC0 帧有两条竞争消费路径 (谁先看到 `g_pkg_uart_2.flag` 谁消费):
|
||||
- **uart_srv → lup_process_frame → lup 回调**: 只喂事件检测 `iot_evt_feed`, **不更新 `_cached_sr`**
|
||||
- **iot_mqtt_publish_sensor Step1 直读**: 事件 + 缓存都更新
|
||||
|
||||
主循环里 uart_srv 先于 publish_sensor 执行, Step1 只能吃到"帧恰好在两调用之间完成"的窄窗口 — **实测命中率 ~1/56 ≈ 2%**。结果:
|
||||
1. 事件路径 (回调) 每帧必达 → car_leave 正确 ✅
|
||||
2. `_cached_sr` 冻结在车压线圈时的旧帧 (freq=61518/diff=517/relay_count, msg 28~140 逐字节一致) ❌
|
||||
3. **陈旧数据自激**: 冻结的 diff=517 > 阈值 → fast_mode 锁死 → 以 300ms 最高频率刷屏错误快照
|
||||
4. 34s 后 Step1 偶然赢一次 → 缓存刷新 → car_edge(陈旧true→新false) 立即档发出 msg 141 恢复
|
||||
|
||||
> 证据: 同期真实 LUP 帧 eval 字节 car_state=0、variation=±个位数、misc_type 0→3 轮转, 与冻结快照完全对不上。
|
||||
|
||||
### 修复
|
||||
|
||||
- 新增 `iot_sensor_ingest()`: 事件沿检测 + 刷新 `_cached_sr`, **单一数据源**;
|
||||
lup 回调与 Step1 直读两路全部汇入 → 帧竞争从此无关紧要
|
||||
- Step1 直读路径补 `lup_verify_checksum` (此前只有 uart_srv 路径过校验, 直读裸解析)
|
||||
|
||||
### 教训 (通用)
|
||||
|
||||
**同一物理量的多个消费者必须同源**。事件说"车走了"、快照说"车还在", 这种自相矛盾一定是数据源分裂 — 排查时先问: 这两个字段是从同一帧解析的吗?
|
||||
|
||||
### 板上验证
|
||||
|
||||
长车复测同场景: car_leave 事件后**下一条** loop_data 的 iscar 必须已翻 false (两者同帧同源); 车走后 diff 回落 → 300ms 快速档应在数秒内退回空闲档, 不再刷屏。
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-15 — loop_data 上报调度升级三档: car_state 沿立即上报
|
||||
|
||||
### 背景
|
||||
|
||||
Reference in New Issue
Block a user