实时车辆诊断 CLI:ECU 地址、VIN、固件与通信控制边界

作者:

在

结论:这四个实时诊断 CLI 不是只读日志分析器:它们都经 sendcan 向车辆发送诊断帧,其中 disable_ecu.py 会请求改变 ECU 通信状态。判断结果是「脚本打印」还是「目标 ECU 真的接受」,是两条不同层级的问题——发布成功只表示请求进入了发送链,能否真正上总线还取决于 pandad 与 panda 固件状态。多个工具还会读写 Params、切换 OBD 复用,且没有 finally 恢复。固定快照基线为 c8fb906,本文未执行脚本、连接车辆或发送 CAN。

共同调用链

四个 CLI 都调用 can_comm_callbacks():从 can 读取 CanData,把请求封装为 sendcan Event。后者被 can_send_thread() 接收并交给 panda;能否真正上总线还取决于 pandad 与 panda 固件状态。不能把「脚本打印结果」或「发布成功」直接等同于目标 ECU 接收成功。

入口 请求与输出 本机状态变化
ecu_addrs.py 默认 bus 1、超时 1 秒;生成 256 个 11-bit 和 256 个 29-bit 候选地址,批量发送 tester-present;仅打印响应地址及可选子地址。 删除 FirmwareQueryDone,IsOffroad 写真、等 0.2 秒再写假;依 --no-obd 切换 OBD 复用。
vin.py 默认 bus 1、单次超时 0.1 秒、最多 5 轮;尝试该总线允许的 UDS / OBD 或品牌特例,打印响应地址、bus 和 VIN。 脚本本身不写 Params、不切 OBD 复用;仍向 sendcan 发诊断请求。
fw_versions.py 先查 bus 0/1 的 VIN,再查品牌固件,输出原始版本字节及可能车型;--brand 只缩小固件查询范围。 同样删除 / 改写 Params;VIN 前先请求 OBD 复用,固件请求期间可逐请求切换。
disable_ecu.py 固定在 bus 1 向 Honda Bosch 雷达地址请求扩展会话,再发送通信控制请求;打印布尔值。 不写 Params、不切 OBD 复用;会尝试改变目标 ECU 的收发状态,且没有恢复调用。

OBD 复用与状态位

obd_callback() 在目标模式与 Params 当前值不同时,删除 ObdMultiplexingChanged、写 ObdMultiplexingEnabled,然后无独立期限地阻塞等待确认;pandad 的 updateMultiplexingMode() 在实际切换后写确认。ECU 地址与固件脚本没有恢复先前 Params / OBD 状态的路径。

FirmwareQueryDone 被删除后,pandad 的 fetchCarParams() 会拒绝继续取得车辆参数,直到其他流程重新置位;常规 Car.__init__() 会在车型识别后置位。IsOffroad 的真 / 假写入是脚本行为,不能据此断言 pandad 已同步切换安全模式——其安全模式配置使用 deviceState.started。

工具 是否读写 Params 是否切 OBD 复用 是否恢复原状态
ecu_addrs.py 删除 FirmwareQueryDone,改写 IsOffroad 是(--no-obd 控制) 否(无 finally)
vin.py 否 否 不适用
fw_versions.py 删除 / 改写同 ECU 地址脚本 是(VIN 前与固件期间) 否
disable_ecu.py 否 否 否(改 ECU 收发状态且无恢复调用)

失效与证据边界

  1. --scan 当前不可用。 脚本把 256 组三种地址形状放进 extra={"any": {"debug": extra}},但固件查询按品牌执行 FW_QUERY_CONFIGS[brand];当前归档没有 any 品牌配置。因此 VIN 查询和 Params / OBD 副作用已经发生后,固件地址构建阶段抛 KeyError('any');--brand 也不会消除此额外键。
  2. ECU 清单不是全量证明。 get_all_ecu_addrs() 把 TX 候选集合直接当 RX 白名单;29-bit 响应通常采用交换后的地址,可能被过滤。get_ecu_addrs() 捕获异常后返回已收集的部分集合,timeout 也不能限制阻塞式接收的整个墙钟时间。
  3. VIN 既不验证身份,也不保证隐藏。 get_vin() 对命中地址的结果做少量去填充后直接解码返回,CLI 原文打印 VIN。失败时返回 (-1, -1, "00000000000000000"),不等同于「车辆没有 VIN」;源码另有 is_valid_vin(),此 CLI 没有调用它。
  4. 固件列表可以是部分结果。 固件查询按请求配置与子地址分组,单个请求异常记录后继续;返回版本可能缺 ECU 或缺品牌。候选车型匹配给的是候选集合,不是执行许可。原始固件字节与 VIN 可能包含可识别车辆的信息。
  5. 手动禁用雷达不确认禁用成功。 通用 disable_ecu() 最多重试 10 次,先要求扩展会话的有效应答,再调用 get_data(0) 发送通信控制请求并丢弃返回字典;零超时和空的期望响应前缀不能提供可靠的正响应证据。帮助函数注释明确警告会禁用原车 AEB,脚本没有配套恢复路径。

面向硬件与插件化的接口约束

以下是设计建议,并非当前实现:将前三类查询工具改为只提交有界诊断任务的证据插件,sendcan 与 OBD 复用由唯一诊断代理持有。代理校验点火 / 车速、bus、地址、服务、速率和总时长,记录每次请求与局部响应;--scan 需先修复配置建模,再在隔离台架验证总线负载。通信控制应归入单独的高危能力,需要目标 ECU / 版本白名单、原车 AEB 影响评估、正响应和总线状态回读、持续保活及恢复方案。身份插件只返回带来源和时间戳的 VIN / 固件证据,不提供控制权限;执行权限仍由独立 MCU / panda safety 和车型适配门决定,不能由插件加载或候选车型自动授予。

常见问题

这些 CLI 会向车辆发 CAN 吗?

会。四个工具都经 sendcan 向车辆发送诊断帧,其中 disable_ecu.py 会请求改变目标 ECU 的通信状态。它们不是只读日志分析器;「脚本打印结果」不等同于目标 ECU 接收成功。

运行这些脚本会留下什么状态?

ECU 地址与固件脚本会删除 FirmwareQueryDone,把 IsOffroad 写真、等 0.2 秒再写假,并切换 OBD 复用,且没有恢复先前 Params / OBD 状态的 finally。FirmwareQueryDone 被删后,pandad 会拒绝继续取得车辆参数直到重新置位。

–scan 现在能用吗?

不能。脚本把地址形状放进 extra={"any": ...},但固件查询按品牌执行 FW_QUERY_CONFIGS[brand],当前归档没有 any 品牌配置,固件地址构建阶段会抛 KeyError('any');--brand 也不会消除该额外键。VIN 查询和 Params / OBD 副作用已经发生。

打印 disabled: True 就说明雷达被禁用了?

不能这样认为。通用 disable_ecu() 丢弃查询结果,零超时与空期望响应前缀无法提供可靠的正响应证据;即使底层打印成功,也不等于已证实 ECU 停发、AEB 状态或会话保持。帮助函数注释明确警告会禁用原车 AEB。

延伸阅读

参考资料

  • 项目 02 —— openpilot-research/CAR_LIVE_DIAGNOSTIC_CLI_CONTRACT_DEEP_DIVE.md(取用了四个 CLI 的请求与副作用、失效边界与插件化接口约束分析)。

说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

更新记录

首次发布 2026-10-11 最近核对:2026-10-11

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注