Files
ln-bi/docs/oneos-mileage-reconciliation-investigation-2026-09-16.md
T
shishengliang 9c13ab6d3b
ci/woodpecker/push/woodpecker Pipeline was successful
fix(energy): use new hydrogen site master data
Use new_hydrogen_site for daily and overview station names and regional aggregation, with empty-name fallback. Include the OneOS mileage reconciliation investigation report.
2026-09-16 11:54:27 +08:00

9.9 KiB
Raw Blame History

OneOS 日里程与累计里程差额排查报告

  • 排查日期:2026-09-16Asia/Shanghai
  • 涉及数据日期:2026-09-11 至 2026-09-15
  • 接收方:OneOS 开放平台及里程计算服务维护人员
  • 状态:已复现;待上游核查计算基准、跨日缺报及协议选源逻辑

1. 问题概述

BI 用户发现:昨日累计总里程减去前日累计总里程,不等于昨日的区间里程;继续向前检查,多日均存在差额。

本次在相同车辆范围、相同协议优先级下复现,并绕过 BI 直接请求 OneOS 单日接口核对异常车辆。上游返回本身就存在相邻日期累计差与日里程不一致的情况,不能仅用 BI 显示取整解释。

已确认的现象:

  1. 某查询日返回的累计里程对应更早日期的报文;后续更新后的累计差跨越多天,与当日日里程不一致。
  2. 同一车辆相邻日期切换 MQTT / GB32960,累计读数发生跳变,且切换后可能选中很早的读数。

尚未确认:日里程的内部计算公式、有效数据判定、跨日补算规则及异常过滤规则。本文不将差额直接认定为漏算里程,也不将累计差直接认定为真实日行驶里程。

2. 查询范围与 BI 计算口径

本次 BI 查询未附加客户、部门、车牌或里程筛选条件,每天返回 916 台车辆。

GET /api/mileage/monitoring
    ?startDate=2026-09-15
    &endDate=2026-09-15
    &sourcePriority=instrument
    &limit=2000

instrument 对应上游协议优先级:

["GB32960", "MQTT"]

BI 当前计算方式:

指标 计算方式
单车累计里程 OneOS totalMileageKm,不以日里程反推
单车单日里程 OneOS dailyMileageKm
单车区间里程 区间内每日 dailyMileageKm 求和
累计总里程 查询范围内车辆的累计里程求和;空值按 0 参与汇总
当日总里程 查询范围内车辆的日里程求和;汇总接口对结果取整

以下对账表使用逐车日里程原始数值求和,保留三位小数,避免整数显示带来的误差。

3. 汇总对账结果

单位:km。定义 差额 = 当天累计总里程 - 前一天累计总里程 - 当天日里程合计

日期 累计总里程 相邻日累计差 当日日里程合计 差额
2026-09-11 48,448,486.800 98,182.208
2026-09-12 48,546,128.300 97,641.500 97,321.774 +319.726
2026-09-13 48,619,784.800 73,656.500 82,322.847 8,666.347
2026-09-14 48,721,190.600 101,405.800 94,242.687 +7,163.113
2026-09-15 48,824,917.800 103,727.200 103,554.604 +172.596

按车牌匹配相邻日期,差额来源分解如下:

日期 两日累计非空且协议相同的车辆数 / 净差额 两日累计非空且协议变化的车辆数 / 净差额 至少一日累计为空的车辆数 / 净差额
09-12 759 / +319.726 0 / 0 157 / 0
09-13 758 / +674.653 1 / 9,341.000 157 / 0
09-14 759 / +7,163.113 0 / 0 157 / 0
09-15 759 / +172.596 0 / 0 157 / 0

本次样本中,空累计值组对差额净贡献为 0;同协议数据也存在明显不一致,不能只修复协议切换问题。

4. 异常样本一:累计读数跨日,日里程未与累计差对齐

以下记录已通过 OneOS 单日接口直接复核,响应均为 HTTP 200、code=SUCCESS,记录状态均为 NORMAL

4.1 粤AGQ83779 月 15 日差额 +70.2 km

查询日期 sourceProtocol totalMileageKm dailyMileageKm dataTime+08:00
2026-09-13 GB32960 14,366.0 6.1 2026-09-13 07:17:27
2026-09-14 GB32960 14,366.0 0 2026-09-13 07:17:27
2026-09-15 GB32960 14,467.4 31.2 2026-09-15 20:57:04
累计差 = 14,467.4 - 14,366.0 = 101.4
差额   = 101.4 - 31.2 = 70.2 km

查询 9 月 14 日时,累计读数仍来自 9 月 13 日。请核查 9 月 15 日日里程的起点读数及其时间,并解释 70.2 km 在日统计中的归属或过滤原因。

4.2 粤AGR68399 月 15 日差额 +38.0 km

查询日期 sourceProtocol totalMileageKm dailyMileageKm dataTime+08:00
2026-09-14 GB32960 45,122.2 0 2026-09-11 11:10:53
2026-09-15 GB32960 45,162.8 2.6 2026-09-15 10:34:02

累计差为 40.6 km,日里程为 2.6 km,差额为 38.0 km。请核查跨多日无新读数后的统计基准及补算策略。

4.3 粤AGP36099 月 14 日差额 +808.7 km

查询日期 sourceProtocol totalMileageKm dailyMileageKm dataTime+08:00
2026-09-12 GB32960 48,102.9 1,293.6 2026-09-12 15:08:47
2026-09-13 GB32960 48,102.9 0 2026-09-12 15:08:47
2026-09-14 GB32960 48,981.7 70.1 2026-09-14 23:59:51
2026-09-15 GB32960 50,349.1 1,367.4 2026-09-15 23:59:50

9 月 14 日累计差为 878.8 km,日里程为 70.1 km,差额为 808.7 km;9 月 15 日累计差与日里程则同为 1,367.4 km。该车适合对比正常日期与跨日缺报日期的计算路径。

5. 异常样本二:协议切换导致累计值倒退

车辆:沪A60591F。以下记录也已直接请求上游复核,均返回 NORMAL

查询日期 sourceProtocol totalMileageKm dailyMileageKm dataTime+08:00
2026-09-12 MQTT 51,416 0 2026-09-12 04:53:49
2026-09-13 GB32960 42,075 0 2026-07-16 23:59:59
2026-09-14 GB32960 42,075 0 2026-07-16 23:59:59
2026-09-15 GB32960 42,075 0 2026-07-16 23:59:59
9 月 13 日累计差 = 42,075 - 51,416 = -9,341 km
9 月 13 日日里程 = 0 km

该车单独贡献 −9,341 km,叠加其他同协议车辆 +674.653 km 的差额后,形成当日全量净差额 −8,666.347 km。

请重点核查:

  1. 同一请求优先级下,9 月 12 日采用 MQTT,9 月 13 日为何改用 7 月 16 日的 GB32960 读数?
  2. 协议“有效数据”的定义是否包含数据时间、新鲜度和查询日期边界?
  3. NORMAL 是否仅表示读数数值有效,而不表示查询当日存在有效报文?
  4. 两协议累计读数是否具有同一基准?切换时是否应提供不连续标识?
  5. 请核查该车协议记录对应的 VIN、设备及绑定历史,排除历史绑定变化造成的读数混用。

6. 上游直接复现方法

接口:POST https://open.d.lnoneos.com/api/v1/vehicles/mileage/query

使用已授权的 API Key,通过环境变量注入,不将真实凭证写入报告或日志。

curl --fail-with-body --silent --show-error \
  'https://open.d.lnoneos.com/api/v1/vehicles/mileage/query' \
  -H "Authorization: Bearer ${ONEOS_MILEAGE_API_KEY}" \
  -H 'Content-Type: application/json' \
  --data '{
    "date": "2026-09-15",
    "plateNumbers": ["粤AGQ8377", "粤AGR6839", "粤AGP3609", "沪A60591F"],
    "protocolPriority": ["GB32960", "MQTT"]
  }'

依次将 date 替换为 2026-09-122026-09-132026-09-142026-09-15

逐车对比字段:dateplateNumbervinstatusdailyMileageKmtotalMileageKmsourceProtocoldataTimecalculatedAtupdatedAt

本次直接复核保留了报告中的关键字段,未记录响应 traceId;上游重放时请保存完整响应及 traceId。历史数据如已重算或补报,当前返回值可能与本报告不同,请同时提供重算时间和修改前后结果。

7. 请上游提供的定位结果

7.1 明确字段契约

  • dailyMileageKm:是当天首尾读数差、前日末值到当日末值的差,还是逐报文有效增量之和?是否丢弃跨日增量、异常跳变或负增量?
  • totalMileageKm:是查询日最后读数、截至查询日最近读数,还是其他快照?无当日报文时是否延用历史值?
  • dataTime:具体对应累计读数、日里程终点还是其他时间?
  • 两个里程字段是否保证来自同一协议、同一设备、同一计算快照?
  • 自然日边界是否统一为 Asia/Shanghai 的 00:00:00 至次日 00:00:00
  • 是否承诺相邻日累计差等于日里程;若不承诺,请明确哪些场景不成立及差额如何解释。

7.2 提供样本计算明细

对上述四辆车,请返回:

  1. 各协议参与选源的候选记录、时间及未选中原因。
  2. 日里程计算起止报文的时间、累计读数、设备/VIN 标识。
  3. 有效增量、被过滤增量及过滤原因。
  4. 缺报、补报、跨日增量归属,以及历史重算记录。
  5. 对每个差额给出可核对的数值分解,不能只解释为“统计口径不同”。

8. 修复或口径确认后的验收建议

  1. 使用同一车辆集合和协议配置,重放 9 月 11 至 15 日数据,逐车核对后再核对汇总。
  2. 对连续上报且同协议的正常车辆,若契约约定可对账,应满足累计差与日里程一致;容差按上游实际数值精度明确。
  3. 对跨日缺报车辆,明确跨日增量是否补算、归属哪天,并能解释全部差额。
  4. 对协议切换车辆,避免将不同基准的累计值视为连续可减的序列;提供明确的协议切换和不连续信息。
  5. 对陈旧读数,区分“历史累计值仍有效”和“当日有有效报文”,避免用单一 NORMAL 混淆两者。
  6. 验证单日接口与区间接口对同一车、同一天的日里程、累计值和选源结果一致。
  7. 如修复涉及历史重算,提供重算范围及完成时间;BI 历史接口缓存最长 6 小时,应在刷新后复核。

9. 本次排查边界

  • 已检查 BI 里程映射、日/区间聚合和汇总逻辑,并对异常样本直接调用上游单日接口复核。
  • 尚未访问 OneOS 原始报文、计算服务源码或内部存储,不能确定其内部算法根因。
  • 本次未修改业务代码、未变更里程口径、未触发历史数据重算。