11 KiB
2026-07-20 日里程与轨迹里程核对
技术结论
沪A01559F 的 2026-07-19 日里程曾因统计恢复延迟缺失,现已从持久化来源证据重建;沪A62013F 的轨迹页展示了累计总里程,但 2026-07-19 没有可信移动证据,0 km 是正确的自然日日里程。统计链路现已支持在仪表累计值停止刷新、但速度和坐标证明车辆实际移动时生成低优先级 GPS 估算候选,同时拒绝静止漂移、长间隔、乱序和不合理跳点。
事件范围
用户在跨自然日后反馈沪A01559F、沪A62013F“今日里程未计算但轨迹回放有里程”。核对按 Asia/Shanghai 自然日执行;由于反馈发生在 2026-07-20 00:00 之后,而车辆最后活动发生在前一日,本次事实窗口固定为 2026-07-19 00:00:00 至 2026-07-20 00:00:00。
“轨迹里程”是轨迹查询窗口内协议总里程差,协议总里程不可用时才使用经过质量过滤的坐标累计;“当日日里程”是同一车辆、协议、来源在上海时区自然日边界上的累计里程差。轨迹卡片中的“累计里程”只是某个点位携带的仪表总值,不等于当日日里程。
生产事实
| 车牌 | VIN | 轨迹事实 | 日里程结果 | 结论 |
|---|---|---|---|---|
| 沪A01559F | LMRKH9AC7R1004120 |
主来源 JT808;2,793 个有效点;协议总里程差 769.1 km | 宇通 809 km、JT808 769.1 km;宇通按来源优先级进入业务统计 | 当日曾存在统计恢复延迟,结果已恢复 |
| 沪A62013F | LMRKH9AC9R1004099 |
宇通 520 个源点、519 个有效点;最高速度 0;轨迹汇总 0 km | 宇通 0 km;累计总里程 24,245 km | 0 km 正确;轨迹点展示的是累计总里程,不得补成正向日里程 |
沪A01559F 的 2026-07-19 最终日里程在 2026-07-20 00:32 恢复。沪A62013F 的宇通总里程事件时间仍为 2026-07-18 16:48,2026-07-19 只有静止位置证据,因此只能保留显式 0 km。
根因与修复
stat-writer 已支持在累计里程缺失时,用有速度证据的相邻 GPS 坐标生成低优先级日里程候选;但累计里程字段存在且持续重复时,流程会提前进入 skipped_same_mileage,没有执行 GPS 累计。这会影响“车辆真实移动、仪表累计值停止刷新”的 GB32960 或宇通来源。
修复后:
- 重复累计里程仍保留为
skipped_same_mileage证据; - GB32960、宇通只有在设备速度大于 0 且坐标有效时才进入 GPS 累计;
- GPS 状态仍按 10 秒节流,并拒绝超过 10 分钟、时间倒序或隐含速度超过 220 km/h 的线段;
- 低于 100 米的累计仅保留为内部状态,不生成业务日里程候选;
- 正向仪表累计里程优先于 GPS 估算,真实仪表值恢复后会自动覆盖估算;
- 静止车辆不会因 GPS 漂移产生虚假里程。
生产发布与回补验证
2026-07-20 02:31 发布 mileage-track-reconcile-20260720023109,9 个数据链路服务全部通过 /readyz,容量巡检最终为 status=ok,Kafka lag、消费重试队列和待处理消息均为 0。
发布后对 2026-07-17 至 2026-07-19 的 GB32960、JT808、YUTONG_MQTT 执行正式回补:
| 验证项 | 结果 |
|---|---|
| 重建并写入的来源聚合 | 3,155 |
| 新增 GB32960 GPS 安全候选 | 2 |
| 新增 JT808 GPS 安全候选 | 66 |
| 新增宇通 GPS 安全候选 | 0 |
| 归一化平台来源 | 1,376 |
回补后,沪A01559F 的 2026-07-19 结果稳定为宇通 809 km、JT808 769.1 km;2026-07-20 在没有新移动证据时按静止结转明确写为 0 km。沪A62013F 的 2026-07-19 仍为宇通 0 km,且没有生成 GPS 估算候选,证明 100 米阈值和速度证据门槛没有把约 12 米的静止定位偏差放大为业务里程。
同日全量诊断没有统计管道故障;另有 2 条与本事件无关的源数据缺口,分别为一台赛格 JT808 车辆和一台宇通车辆未上报可用总里程字段,已由诊断接口持续暴露,不能用猜测值补录。
同类数据审计与补录边界
生产 stats-backfill 对 2026-07-19 全部 19 台有宇通日活动的车辆执行只读扫描,未发现除现有正向仪表里程之外、可由有效移动线段恢复的 GPS 候选。沪A01559F 的结果已经恢复,无需重复改写;沪A62013F 缺少移动证据,禁止补录正数。
后续历史补录继续使用同一条安全规则:只有存在可用移动线段时才生成 gps_coordinate_accumulation 候选,不按累计总里程、位置点数量或页面展示值推断日里程。
2026-07-20 03:44 对当天三协议再次执行全量 dry-run,共重建 448 个来源聚合,识别 5 个可由 JT808 有效移动轨迹恢复的候选;03:48 正式回补写入 449 个来源聚合并归一化 272 个 JT808 平台来源。复核同时发现阈值规则上线前遗留的沪A56988F 0.004 km GPS 候选,因此补充了“低于 100 米遗留候选清理 + 同事务重新投影”能力;后续回补会自动修复同类旧数据,而不是只阻止新漂移值写入。
03:56 新版本 mileage-gps-candidate-reconcile-202607200350 完成清理型正式回补:写入 452 个来源聚合,subthresholdGPSCandidatesFound=1、subthresholdGPSCandidatesDeleted=1。沪A56988F 当天阈值下候选及错误最终投影均已删除;剩余被选中的 GPS 候选最小值为 0.131 km,低于 0.1 km 的选中候选为 0。清理后该车显式暴露为“JT808 当日缺少新鲜总里程字段”的源数据缺口,统计管道缺口仍为 0;系统保留该缺口,不用 4 米静止漂移构造业务里程。
7 月 20 日 05:40 再次复核
针对“轨迹回放有里程、今日里程没有计算”的再次反馈,按 2026-07-20 00:00:00 至 05:40:00 重新核对生产轨迹、实时总里程证据、来源候选和最终日里程:
| 车牌 | 今日轨迹证据 | 今日统计 | 处理结论 |
|---|---|---|---|
| 沪A01559F | 宇通 260 个源点、259 个有效点;最高/平均速度均为 0;坐标区间累计 0 km | 宇通 stationary_carry_forward 0 km;仪表累计总里程 14,097 km 的最新证据仍是 7 月 19 日 21:23:59 |
已有显式 0 km 统计,无可信正向里程可补 |
| 沪A62013F | 今日 0 个源点;7 月 19 日 520 个源点最高速度仍为 0,区间里程 0 km | 7 月 19 日宇通 0 km;累计总里程 24,245 km | 今日没有上报,昨日 0 km 正确,禁止把累计值补成日里程 |
同一时点全量诊断覆盖 480 个活跃“协议 × 车辆”项,pipeline_issue_total=0;仅有 1 个赛格 JT808 项缺少新鲜总里程,属于上游源数据问题,与这两辆车无关。轨迹页点位卡片同步将“累计里程”明确为“累计总里程”,并说明它不是所选时间窗里程或今日里程,避免把点位累计值误读为区间结果。
7 月 20 日 06:34 当天全量回补
再次收到相同车牌反馈后,按当天实时数据重新核对:
- 沪A01559F 今日 260 个源点、259 个有效点,轨迹区间里程、平均速度和最高速度均为 0;宇通日里程已有
stationary_carry_forward0 km。 - 沪A62013F 今日 271 个源点、259 个有效点,轨迹区间里程、平均速度和最高速度均为 0;宇通日里程已有
stationary_carry_forward0 km。 - 沪A01559F 的正向行驶发生在 7 月 19 日,宇通 809 km、JT808 769.1 km 均已存在;沪A62013F 页面上的 24,245 km 是累计总里程,不是当日里程。
随后对 2026-07-20 的 GB32960、JT808、YUTONG_MQTT 执行全量 dry-run 和正式回补。正式运行重建并写入 642 个来源聚合,归一化 319 个 JT808 平台来源,没有宇通或 GB32960 GPS 降级候选,也没有低于 100 米的遗留漂移候选。4 个具备有效移动轨迹、但缺少正向设备累计里程的 JT808 来源按既有安全规则补录:
| 车牌 | VIN | 补录日里程 | 质量原因 |
|---|---|---|---|
| 浙F02268F | LA9HE60A6PBAF4022 |
0.119 km | gps_coordinate_accumulation |
| 沪A60339F | LKLG7C4E8NA774750 |
29.199 km | gps_coordinate_accumulation |
| 沪A69311F | LKLG7C4E8NA774781 |
21.253 km | gps_coordinate_accumulation |
| 沪A66218F | LKLG7C4E9NA774773 |
0.545 km | gps_coordinate_accumulation |
回补后生产诊断覆盖 569 个活跃“协议 × 车辆”项:GB32960 198/198 正常、JT808 324/325 正常、宇通 46/46 正常。唯一剩余项为沪A56988F 的赛格 JT808 当日没有新鲜总里程且缺少可用移动线段,属于明确上游源数据缺口,未构造里程。stat-writer /readyz、容量巡检均成功,三协议 Kafka lag 和重试队列均为 0。
7 月 20 日 06:53 插入事项复核
用户再次以沪A01559F、沪A62013F 为例要求排查“轨迹回放有里程、今日里程未计算”的同类问题。按相同的当天时间窗重新读取生产轨迹 API、最终日里程、来源候选和统计诊断:
- 沪A01559F 的 260 个源点中有 259 个有效点,区间里程、平均速度和最高速度仍均为 0;最终日里程为宇通
stationary_carry_forward0 km,累计总里程为 14,097 km。 - 沪A62013F 的 271 个源点中有 259 个有效点,区间里程、平均速度和最高速度仍均为 0;最终日里程为宇通
stationary_carry_forward0 km,累计总里程为 24,245 km。 - 沪A01559F 的 769.1 km 来自 7 月 19 日 JT808 轨迹窗口;沪A62013F 的 24,245 km 是轨迹点携带的累计总里程。两者都不能作为 7 月 20 日正向日里程补录。
随后再次对 2026-07-20 的三协议执行全量 dry-run 和正式幂等回补。dry-run 重建 667 个来源聚合,正式运行写入 671 个来源聚合、归一化 327 个 JT808 平台来源;正式运行识别 3 个可用的 JT808 GPS 降级聚合,没有低于 100 米的遗留候选。回补后已选中的 JT808 GPS 安全候选包括浙F02268F 0.119 km、浙F09860F 0.303 km、沪A60339F 30.624 km、沪A69311F 21.253 km;粤A05579F 的设备累计里程随后恢复并以 1.2 km 正向仪表差值覆盖 GPS 估算。
全量诊断覆盖 580 个活跃“协议 × 车辆”项,pipeline_issue_total=0:GB32960 204/204 正常、JT808 329/330 正常、宇通 46/46 正常。唯一剩余项仍是沪A56988F 的赛格 JT808 源数据缺口;容量巡检退出码为 0,stat-writer、realtime-api、history-writer 及其 /readyz 均正常。
限制与后续监控
- GPS 估算只在仪表里程缺失或停滞时兜底,不替代 GB32960、宇通仪表里程或 JT808 设备里程。
- 超过 10 分钟的相邻点、时间倒序、隐含速度超过 220 km/h、非正速度的 GB32960/宇通点,以及不足 100 米的累计都不会形成业务候选。
- 每日巡检继续检查
actionable_issue_total、来源候选与最终投影差异、Kafka lag、重试队列和回补任务状态;源头完全不提供里程且没有可信移动线段时,系统必须保留缺口而不是构造数值。