标签: UDS

  • Nissan Leaf ZE0:LBC 块数据与只读遥测

    结论:Nissan Leaf(ZE0,2011–2012)最反直觉的一点是:它不实现标准 OBD-II PID——连发送 `0100` 都返回 NO DATA。要读电池,必须用 UDS 服务 0x21 向 LBC(锂电池控制器)索取整块数据(如 39 字节一组的电流、电压、SOC、容量)。同时 Car-CAN 上还有一批被动广播帧(档位、转向灯、里程、车门等)可直接监听。源文档的架构默认只读,从不发送会改变车辆状态的指令。以下所有结论仅限源文档记录的这一台车。

    车辆与适用范围

    本文数据来自第三方开源项目为 Nissan Leaf 开发的只读遥测仪表盘。项目通过 ELM327 适配器读取标准与非标准数据,并用离线回放、模拟与 MQTT 等多种无车模式做测试,源码中带有大量离线测试用例。

    项 内容
    车型 Nissan Leaf(ZE0 世代)
    年款 2011–2012
    接入方式 ELM327(BLE 或 USB);源文档另记录自 2026-10-03 起用 CANable 2 接入 Car-CAN
    采集跨度 两个车辆 profile:Leaf 版 18 项 / 61 个信号 / 33 条历史列;另一台对照车为纯标准 Mode 01(19 项 / 20 个信号)
    适用范围 仅限源文档记录的这台 Leaf;年份、电池版本与固件差异都可能改变可用数据块

    总线与寻址

    这辆车的读取要分两条路走:一条是主动的 UDS 块数据读取,另一条是被动的广播帧监听。两者的传输参数完全不同。

    项 内容
    Car-CAN 500 kbit/s;11 位标准帧;引脚 6 / 14
    EV-CAN 引脚 13 / 12;源文档要求强制只监听
    适配器参数 `ATSP6`(ISO 15765-4,11 位 500 kbit/s)
    UDS 寻址 向 LBC 请求用 `ATSH 79B`,接收用 `ATCRA 7BB`;读取服务为 0x21
    被动监听 必须关闭自动格式化(`ATCAF0`)才能拿到原始帧
    标准 OBD-II 本车不实现标准 PID,发送 `0100` 返回 NO DATA
    实测吞吐 CANable 2 在 Car-CAN 上约 1,692 帧/秒、49 个 ID、0 错误帧

    已解码信号

    下表从源文档的信号清单中抽取。项目的置信度分三档:verified(已确认)、static(静态常量)、tentative(暂定),本文按源文档标注保留。

    信号 位置(ID / DID / 字节) 解码 证据
    高压电流 LBC 数据块 01 s32 ÷ 1024 A verified
    电池包电压 LBC 数据块 01 u16 ÷ 100 V verified
    12 V 电压 LBC 数据块 01 u16 ÷ 1024 V verified
    绝缘电阻 LBC 数据块 01 kΩ verified
    SOC(荷电状态) LBC 数据块 01 u24 ÷ 10000 % verified
    可用容量 LBC 数据块 01 u24 ÷ 10000 Ah verified
    单体电压 LBC 数据块 02 96 × u16,单位 mV,量程 3000–4200 mV verified
    电流(第二通道) LBC 数据块 05 16 位回绕:±32 A 之外按 64 A 折叠 verified(2026-09-03 定案)
    档位 Car-CAN 0x421 枚举 verified
    转向灯 Car-CAN 0x358 位标志 verified
    整车里程 Car-CAN 0x5C5 — verified
    车门 / 锁 / 灯 Car-CAN 0x60D 位标志 verified
    车速 Car-CAN 0x284 — verified
    续航 Car-CAN 0x5A9 — verified

    读取方法与注意事项

    第一条是「不按标准 OBD 走」。多数车用 Mode 01 就能读到车速、转速等,但本车不实现标准 PID:`0100`(查询支持哪些 PID)返回 NO DATA。因此不能指望通用的 OBD 诊断 App 直接读出电池信息,必须走 UDS 服务 0x21 向 LBC 请求数据块。

    第二条是块数据的规模与时序。LBC 的第一个数据块约 39 字节,包含电流、电压、SOC、容量等多个字段;单体电压块则是 96 个 16 位值(对应电池单体),量程约 3000–4200 mV。源文档实测在 CANable 2 上,Car-CAN 约 1,692 帧/秒、49 个 ID、零错误帧,一次完整的 96 节电芯读取约 351 毫秒——这给出了「块读取能不能满足刷新需求」的量化参考。

    第三条是回绕陷阱。数据块 05 的电流是 16 位字段:当真实电流超出 ±32 A 时,读数会按 64 A 折叠回绕。也就是说,读到一个看似很低的电流,可能其实是对应的大电流。源文档在 2026-09-03 把这一行为定案。

    证据等级与边界

    源文档的置信度分三档:verified 表示已在实车或离线回放中确认;static 表示该字段在该车上恒为常量;tentative 表示暂定。表中所列以 verified 为主,原样保留标注。此外项目还保留一台对照车的纯标准 Mode 01 profile,用来区分「Leaf 特有的非标准读取」与「通用 OBD 路径」。

    安全边界方面,源文档明确记录了这套工具会发送与不会发送的内容:只发送 UDS 服务 0x21(只读)、标准 Mode 01/03/07,以及适配器自身的监听模式;从不发送会清除或改写 ECU 的指令。EV-CAN 上强制只监听。这一设计把「读车」与「改车」彻底分开。

    适用范围上必须强调:以上数据块布局、字段刻度与广播 ID 都限定在这一台 2011–2012 年的 ZE0 上。不同年份、不同电池容量版本(如 24/30/40 kWh)的 Leaf,其数据块与可用 PID 都可能不同,跨车使用前必须重新核对。

    常见问题

    为什么普通的 OBD 诊断 App 读不到这辆车的电池?

    因为本车不实现标准 OBD-II PID,发送 `0100` 会返回 NO DATA。通用 App 依赖标准 PID,自然读不到。要读电池必须用 UDS 服务 0x21 向 LBC(用 `ATSH 79B`、`ATCRA 7BB`)索取数据块。

    为什么读到的电流有时明显偏小?

    因为数据块 05 的电流是 16 位字段,真实值超出 ±32 A 时会按 64 A 折叠回绕。看到的低值可能对应实际的大电流,需要按回绕规则还原。源文档在 2026-09-03 确认了这一行为。

    被动监听需要什么特殊设置?

    源文档要求关闭自动格式化(`ATCAF0`),否则适配器会把原始帧「翻译」成标准格式,丢失块数据所需的信息。EV-CAN 上则强制只监听。整轮循环在实测硬件上约 0.58 秒完成。

    这套读取方式安全吗?

    源文档的设计是只读:只发送服务 0x21、标准 Mode 01/03/07 与监听模式,从不发送清除或改写指令,EV-CAN 强制只监听。即便如此,任何实车操作仍应自行复核并遵守当地法规。

    延伸阅读

    参考资料

    • 项目 08 —— public-can-dbc-datasets/additional/davidkarnowski-leaf-ze0/README.md(本项目车型档案主来源:只读架构、profile 与安全边界)
    • 项目 08 —— public-can-dbc-datasets/additional/davidkarnowski-leaf-ze0/docs/SIGNALS.md(数据块字段、置信度分级与广播帧表)
    • 项目 08 —— public-can-dbc-datasets/additional/davidkarnowski-leaf-ze0/docs/CAN_TRANSPORT.md(适配器参数与实测吞吐)

    说明:本文整理自第三方开源项目的公开文档,仅代表该文档所记录的单个车辆样本,不代表同型号全系车型。CAN 与诊断操作存在风险,任何实车操作前请自行复核并遵守当地法规。

    更新记录

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

  • VinFast VF8/VF9 诊断档案:7 个 CAN 矩阵与 UDS

    结论:这份档案记录的是 VinFast VF8 / VF9 的诊断侧资料:一个基于 OpenXC 或 ELM327、通过 UDS(ISO 14229)读写故障码的桌面工具,以及七份 CAN 网络矩阵(合计约 1,027 条报文、8,684 条信号)与九份信号转发路由表。要点是两条:诊断 CAN 总线为 500 kbit/s,而 VF8 的多数子系统是藏在 XGW 网关之后的 CAN 节点,必须按逻辑地址寻址、由网关转发;读取故障码在默认会话常可用,但清除故障码往往需要安全访问(0x27)。需要提醒的是,工具里随附的逻辑地址是占位符、不是官方地址。

    车辆与适用范围

    源文档是一个面向 VinFast VF8/VF9 的诊断应用仓库。它把「固件反推得到的事实」与「一次实车观测」分开陈述,这个分层在下文原样保留。

    项 内容
    车型 VinFast VF8 / VF9(BEV)
    年款 / 市场版本 实车观测为 2024 款美规 VF8;VF9 的适配性源文档未确认
    ECU / 改装状态 原车;通过 OpenXC 车辆接口或 ELM327 适配器接入诊断总线
    采集跨度 源文档给出一次实车观测;其余为固件与矩阵文档
    适用范围 仅限源文档记录的 2024 美规 VF8 观测;七份 DBC 与实车捕捉的对应关系未被独立验证

    总线与寻址

    VF8 的诊断总线比特率在出厂脚本里写死为 500 kbit/s。部分子系统位于 XGW 网关之后,需要按逻辑地址寻址、由网关把请求路由到对应 CAN 网络。工具另支持 MS-CAN 的 125 kbit/s 与 250 kbit/s 两档,物理拨档需与所选总线一致。

    项 内容
    物理层 OpenXC 车辆接口(USB 或蓝牙 SPP)或 ELM327 v1.5(USB/蓝牙串口)
    链路层 / 比特率 诊断 CAN 500 kbit/s;MS-CAN 支持 125 kbit/s(ELM 协议 B)与 250 kbit/s
    寻址方式 逻辑地址寻址,网关转发到 CAN;CAN ID 映射默认为 请求 = 0x700 + (addr & 0xFF)、响应 = 请求 + 0x08
    CAN FD 源文档未提及
    地址默认值 测试端源地址默认 0x0E80;功能地址默认 0xE400(占位符,须按实车设置)

    已解码信号

    下表把源文档的固件事实、路由表条目与实车观测分开列,逐条注明证据来源。涉及安全访问的条目只说明「存在该会话要求」与「密钥来源」,不展开任何算法或密钥细节。

    条目 位置(ID / 服务 / DID) 含义 证据
    诊断 CAN 比特率 — 500 kbit/s(出厂脚本设定) 固件事实(init-can.sh)
    读取故障码 UDS 0x19 / 0x02 读取 DTC,默认会话通常可用 README「Features」
    清除故障码 UDS 0x14 会先进入扩展会话,需确认;常需安全访问 README「Features / Realistic expectations」
    诊断会话控制 UDS 0x10 默认/扩展会话切换,配合 TesterPresent 保活 README「Session & security」
    安全访问 UDS 0x27(seed / key) 密钥为「每 ECU / 每安全等级」的机密,不在固件明文,须取自本车 README「Realistic expectations」
    读取身份 / VIN UDS 0x22 / DID F190 读 VIN 等身份信息 README「Per-ECU actions」
    例程结果(只请求不启动) UDS 0x31 03 FFFF 只请求例程结果,绝不启动例程 README「Safe ECU capability research」
    归还 I/O 控制 UDS 0x2F FFFF 00 把 I/O 控制权交回 ECU README「Safe ECU capability research」
    诊断会话计数 UDS 0x19 01 FF 报告故障码数量 README「Safe ECU capability research」
    BCM 诊断响应信号 Diag_CAN 0x601 ← Body_CAN 0x601 车身控制模块诊断响应数据 路由表 ToDiag_v10.7.5.csv
    MHU 诊断响应信号 Diag_CAN 0x604 ← Info_CAN 0x604 车机模块诊断响应数据 路由表 ToDiag_v10.7.5.csv
    AMP 诊断响应信号 Diag_CAN 0x605 ← Info_CAN 0x605 功放模块诊断响应数据 路由表 ToDiag_v10.7.5.csv
    ACM 诊断响应信号 Diag_CAN 0x608 ← Body_CAN 0x608 音响/空调模块诊断响应数据 路由表 ToDiag_v10.7.5.csv
    XGW 隧道候选 0x682(Info-CAN 隧道路径) 首选隧道 ID,仍是候选,未获实车匹配响应 实车观测
    OBD 物理回退 0x7E0 标准 OBD 物理回退地址,同为候选 实车观测

    读取方法与注意事项

    源文档把「安全的能力指纹」做成了默认动作:对已确认可达的 ECU,只发六条只读/归还类服务——0x3E 00(TesterPresent)、0x19 01 FF(报告 DTC 计数)、0x22 F190(读 VIN/身份)、0x31 03 FFFF(只请求例程结果)、0x2F FFFF 00(归还 I/O 控制)、0x83 01(读扩展时序上限)。结果区分「肯定响应」「识别到服务但返回否定码」「明确的服务不支持 0x11」「无响应」四种,每行记录 ECU 地址、会话、请求/响应字节与否定码。这一工作流刻意排除了复位、清除 DTC、写入、安全访问与文件传输等服务。

    实车那一侧的观察需要谨慎解读:在参考的 2024 美规 VF8 上,用 OpenXC 发出 diagnostic_request(总线 1、ID 0x682、UDS 0x22 F190),主机侧确认收到了指令,但 3 秒内没有收到 diagnostic_response。源文档据此只说「电脑到车辆接口的链路工作正常」,并明确这不能证明车辆接口的 CAN 发送、物理 OBD 网络、XGW 唤醒状态,也不能证明 0x682 在连接口可达;超时不等于某个 ECU 不存在。

    关于安全访问,源文档的结论是:密钥不在固件中以明文存在,而是每 ECU、每安全等级各自持有的机密,必须从本车自身的配置数据中取得。源文档未提供任何绕过安全访问的方法,且不建议尝试。

    证据等级与边界

    证据分三层,源文档自己就分开了。固件事实(诊断总线 500 kbit/s、各 UDS 服务的存在)来自对车载 TBOX 根文件系统的反推,可核对。路由表条目(0x601/0x604/0x605/0x608 等)来自随附的九份转发 CSV,是信号转发参考数据,不构成执行器或写流程。实车观测只有一次,且只证明链路连通。

    三处不能外推。第一,源文档明说原始适配器帧不标识自己属于哪个网络,因此为某一帧选用某个 DBC 是一种「解码假设」,不是检测出的总线身份。第二,实车观测既未证明 VF9 装配、也未证明全部网络访问路径,不能把 VF8 的观察推广到 VF9 或其他年款。第三,矩阵文档的 1,027 条报文与 8,684 条信号与实车捕捉的对应关系未被独立验证,且来源说明指出这些矩阵的原始出处与再分发授权均未声明。

    常见问题

    VF8 的故障码能免密清除吗?

    通常不能。源文档指出读取 DTC 在默认会话往往可用,但清除往往需要安全访问(0x27)。密钥不在固件明文里,须从本车自身的配置数据取得;源文档未提供绕过方法,且不建议尝试。

    工具里内置的逻辑地址能直接用吗?

    不能。源文档明确这些 VinFast 逻辑地址是占位符、非官方地址,须用「探测 ECU 地址」逐个试出真正响应的地址后再配置。

    七份 DBC 是按什么划分的?

    按网络划分,分别对应信息、车身、诊断、动力、底盘、电池与一条 ASU 私有车身总线。由于原始帧不携带网络标识,为某帧选用某个 DBC 属于解码假设;路由 CSV 是信号转发参考,不定义执行器或写流程。

    那次实车观测说明了什么?

    只说明电脑到车辆接口的链路可用。3 秒内没有响应不能证明车辆接口的 CAN 发送、物理 OBD 网络或 XGW 唤醒状态,也不能证明 0x682 在连接口可达;超时不等于 ECU 不存在。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/cmarshall108-vinfast-vf8-vf9/README.md(本项目车型档案主来源:UDS 工具说明、固件事实与实车观测)。
    • 项目 01 —— public-can-dbc-datasets/additional/cmarshall108-vinfast-vf8-vf9/SOURCE.md(七份 CAN 矩阵与路由表的规模、校验值,以及「未独立验证」的边界声明)。
    • 项目 01 —— public-can-dbc-datasets/additional/cmarshall108-vinfast-vf8-vf9/assets/can/routing/ToDiag_v10.7.5.csv(诊断网络信号转发条目示例)。

    说明:本文整理自第三方开源项目的公开文档,仅代表该文档所记录的单个车辆样本,不代表同型号全系车型。CAN 与诊断操作存在风险,任何实车操作前请自行复核并遵守当地法规。

    更新记录

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

  • Toyota 接口:能力参数怎么算,雷达静默事务又证明了什么

    结论:Toyota 车型接口把能力参数构建与雷达静默事务分成两件不同的事:前者在 _get_params() 里派生安全参数、转向模式与纵向能力,后者由 init() 通过 UDS 0x28 通信控制向总线 0 地址 0x750 发请求。源文档指出 disable_ecu() 的返回值只反映「本函数的请求路径判定」,而 Toyota.init() 丢弃该返回值、card.controls_update() 在 CI.init() 返回后直接设置 ControlsReady——这是一个确认状态缺口,但不等于任何具体车辆 ECU 实际未静默。本文为静态追踪,没有车辆、台架、UDS 抓包或回放结果。

    参数生成的先后次序

    get_car() 在指纹和固件识别后,把 alpha_long_allowed、is_release 传给车型 get_params(),再实例化接口。基类 CarInterfaceBase.get_params() 先装配平台质量、轴距、转向比和静态 flags,再调用 Toyota _get_params(),随后增加标准载荷并计算惯量和轮胎刚度。末尾的质量、惯量和轮胎刚度计算依赖 Toyota 已设置的 centerToFront 等值,所以单独调用 _get_params() 或只复制 values.py 的标志,不能重建最终 CarParams。

    Toyota safety model 固定为 toyota,safetyParam 先装载该车型 EPS_SCALE,再按动力 DBC、SecOC、角度控制和原车纵向模式叠加标志;ToyotaSafetyFlags 从第 9 位起定义,低字节留给 EPS 比例。换 DBC 或线束地址时,必须同步核对 MCU hook 的解析/白名单,不能把 CarParams 能力位看成安全策略的唯一实现。

    参数分支 取值 边界
    角度车型 steerControlType=angle、启用 LTA 标志、延迟 0.18 秒、steerLimitTimer=0.8 秒 与扭矩车型的标定不同
    其他车型 扭矩横向标定、默认延迟 0.12 秒、0.4 秒限制 按车型逐项核对
    旧 Prius 特例 非指定 EPS 版本时 0.25 秒延迟、0.2 度死区;另一不支持版本标 dashcamOnly 固件列表为空或未命中时不能推断该特例已验证
    混动标志 固件列表中存在 Ecu.hybrid;TSS2 混动纵向执行器延迟 0.05 秒 按固件列表判定
    BSM 能力 TSS2 且动力 fingerprint 中存在 0x3F6 不由所有静态配置直接推断
    radarUnavailable 仅测试该车型 DBC 映射是否包含 Bus.radar 不是运行时雷达在线/健康检测

    注意 TSS2 且 RADAR_ACC 的平台配置还会移除雷达 DBC,因此「未提供雷达解析器」与「已经成功静默雷达 ECU」是两个不同状态。get_pid_accel_limits() 按 CarControllerParams 给出加速度最小/最大值,函数签名中的当前/巡航车速并没有用于动态调整。

    纵向能力决策

    纵向能力由源码布尔表达式决定,不是对全部平台的实车适用性声明:

    输入条件 参数结果 运行含义
    TSS2 且非 RADAR_ACC 默认 openpilotLongitudinalControl=True 相机侧 ACC 路径,源码不调用 Toyota 雷达静默请求
    RADAR_ACC 且 alpha_long=True 加 DISABLE_RADAR,允许自控纵向;alphaLongitudinalAvailable=True 需走 ECU 通信控制
    RADAR_ACC 且 alpha_long=False 不加 DISABLE_RADAR,原车纵向;safety 加 STOCK_LONGITUDINAL 不应发自控加速候选
    非 TSS2 / 其他组合 由 DISABLE_RADAR 是否设置决定 逐平台核对

    autoResumeSng 在 Toyota 分支直接设为 openpilotLongitudinalControl。最低启用速度由 stop-and-go 能力选择 -1 或 19 mph 换算值;TSS2 加 RAISED_ACCEL_LIMIT 时,控制参数上限从 1.5 提升到 2.0 m/s²。发布版 SecOC 车型 dashcamOnly=is_release;card 若判为被动,会把 safety 配置改为 noOutput——这是上线许可门,不是 SecOC 密钥校验。

    雷达静默事务:证明了什么、没证明什么

    Toyota init() 仅在 DISABLE_RADAR 时调用 disable_ecu(),目标为总线 0、地址 0x750、子地址 0xF;默认请求是 UDS 0x28 的「使能接收/禁用发送」,作用于正常消息。disable_ecu() 最多尝试 10 次,每次先要求扩展会话 0x10 0x03 的 0x50 0x03 前缀响应,再发送通信控制请求。该函数自身注释明确警告此操作会禁用 AEB,应把原车主动安全能力变化纳入车型准入,而非当作普通功能开关。

    关键缺口在于:通信控制阶段把期望响应前缀设置为空字节串,调用 query.get_data(0),却丢弃该调用的返回字典;只要前置扩展会话查询产生条目且通信控制调用没有抛异常,disable_ecu() 就记录「ecu disabled」并返回真。get_data() 对非空响应使用 startswith(expected_response),空前缀无法鉴别 UDS 正响应内容。加之 Toyota.init() 丢弃 disable_ecu() 返回值,card.controls_update() 在 CI.init() 返回后直接设置 ControlsReady,即便诊断静默请求返回假,也没有从这条返回链阻断就绪。

    控制器在 DISABLE_RADAR 时按 20 帧节拍发送 tester-present 候选,但该帧生成并不证明 ECU 进入目标会话,也不证明会话保持或 AEB 真实状态。Toyota.deinit() 定义了相反的「使能接收/使能发送」请求,复用同一路径;但在本快照的运行链检索中未找到它的调用,因此不能把函数存在视为正常退出一定恢复 ECU。

    硬件与插件重构边界

    车型能力插件应产出期望配置而非宣称已经完成 ECU 改写,至少包含车型/固件/DBC 身份、纵向权限、AEB 影响、safety 模式及版本摘要。受信任诊断服务独占 UDS 写权限,把「请求接受」「正响应校验」「目标 ECU 读回/总线行为确认」「tester-present 存活」「恢复结果」设为独立状态;不满足确认条件时不得授予需要静默雷达的纵向执行能力。这一建议比当前源码多了安全门,属于拟议重构,不是现有实现描述。

    验证路径上,可先在无车环境用 alpha_long、RADAR_ACC、SecOC 发布版、不同 Prius EPS 固件和 0x3F6 指纹构造参数矩阵,再用模拟 ISO-TP 正/负响应、无响应及超时检查请求与回执,最后在隔离台架核对 ECU 静默、AEB/FCW、重启与恢复时序。

    常见问题

    disable_ecu() 返回真,是否说明雷达 ECU 已被静默?

    不代表。源文档指出该返回值只反映「本函数的请求路径判定」:通信控制阶段把期望响应前缀设为空字节串并丢弃返回字典,只要前置扩展会话查询产生条目且调用没有抛异常就返回真;get_data() 的 startswith 对空前缀无法鉴别正响应内容。因此这是确认状态缺口,不能断言具体车辆 ECU 的实际状态。

    radarUnavailable 是不是在检测雷达是否在线?

    不是。radarUnavailable 仅测试该车型 DBC 映射是否包含 Bus.radar,不是运行时雷达在线或健康检测;而 DISABLE_RADAR 反映的是参数层是否要发起诊断静默请求。源文档明确「未提供雷达解析器」与「已经成功静默雷达 ECU」是两个不同状态。

    为什么单独调用 _get_params() 复现不了最终 CarParams?

    因为基类 get_params() 先装配平台质量、轴距、转向比和静态 flags,再调用 Toyota _get_params(),末尾的质量、惯量和轮胎刚度计算依赖 Toyota 已设置的 centerToFront 等值。所以只复制 values.py 的标志或单独调用 _get_params(),都不能重建最终结果。

    两种 EPS 固件的 Prius 为什么处理不同?

    因为源码把旧 Prius 由 EPS 固件字节作例外:非指定版本时设 0.25 秒延迟和 0.2 度死区;明确识别到另一不支持的 EPS 版本时标记 dashcamOnly。源文档同时说明,固件列表为空或版本未命中时,不能据此推断该特例得到验证。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/TOYOTA_INTERFACE_CAPABILITY_RADAR_DISABLE_DEEP_DIVE.md(取用了参数生成次序、纵向能力决策表、雷达静默事务的确认状态缺口与插件重构边界)。
    • 项目 02 —— openpilot-research/CAR_PROTOCOL_IMPLEMENTATIONS.md(仅用于确认 Toyota 品牌目录与启动识别门的总体位置)。

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

    更新记录

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

  • Ram ProMaster 2022:三总线与 19 个 UDS 模块

    结论:Ram ProMaster(2022 款,3.6 L Pentastar 配 ZF 948TE 变速箱)是典型的「三总线 + 安全网关」结构:C-CAN / HS-CAN(500 kbit/s,引脚 6/14)、B-CAN / CAN IHS(125 kbit/s,引脚 3/11)、CAN CH(500 kbit/s,引脚 12/13)三条总线速率与用途各不相同,OBD 口后面还有 SGW 安全网关。车速与整车里程在两条不同总线上各有来源,且源文档记录了两者不一致的验证结果。以下所有结论仅限源文档记录的这一台车。

    车辆与适用范围

    本文数据来自第三方开源项目对一台 2022 款 Ram ProMaster 的总线映射与信号分析。项目先用双通道适配器分别接入不同总线,再通过 UDS 读取模块内的数据块,并对同一物理量在不同总线上的表现做交叉验证。

    项 内容
    车型 Ram ProMaster,2022 款
    动力总成 3.6 L Pentastar 发动机(PCM);ZF 948TE 变速箱(TCM)
    采集硬件 双通道 USBCANFD 适配器,两路分别映射到不同总线(源文档记录了通道与总线的对应关系)
    采集跨度 多次行车与静态采集,涵盖车速、里程、挡位与机油寿命等验证
    适用范围 仅限源文档记录的这一台车;不同年款或不同配置的总线拓扑与 UDS 地址都可能不同

    总线与寻址

    这辆车的接入难点在于「多条总线、多个速率,且后面有网关」。只有先确定每个物理接口对应哪条总线,后续的波形才有意义。

    项 内容
    C-CAN / HS-CAN 500 kbit/s,OBD-II 引脚 6 / 14;OBD 口后面存在 SGW(安全网关)
    B-CAN / CAN IHS 125 kbit/s,OBD-II 引脚 3 / 11
    CAN CH 500 kbit/s,OBD-II 引脚 12 / 13
    诊断寻址 29 位 ISO-TP 物理寻址,形如 18DAxxF1;源文档记录了 19 个模块的地址
    网关 SGW 位于 OBD 口之后;源文档中部分内部总线需要物理接入方式才能观察到,本文不复述具体做法,也不建议尝试

    已解码信号

    下表从源文档的行车分析与离线验证记录中抽取。项目对每一条都注明了验证方式(载体验证、相关系数或读取值),本文原样保留;被否决的条目也一并列出,以说明边界。

    信号 位置(ID / DID / 字节) 解码 证据
    车速 C-CAN 0x101 B0:B2 speed_raw = ((B0 & 0x01) << 11) | (B1 << 3) | (B2 >> 5) 已确认(轮速载体验证)
    车速(第二来源) C-CAN 0x0EE 约等于 8 × speed_raw 已确认(相关 r=0.9999919)
    输出轴转速 0x1F7 rpm 标定记录
    涡轮转速 0x1F7 rpm 标定记录
    整车里程 0x760(从位 8 起的 17 位大端) km 标定记录
    整车里程(ICS) B-CAN,UDS 服务 22 / DID 0x2001 u24 大端 × 0.1 km 已确认(与 0x760 交叉对照)
    机油寿命 PCM,UDS 服务 22 / DID 0x2185 百分比读数 已确认(读取值显示 82%)
    帧校验 0x101 B7 CRC-8 / SAE-J1850 标定记录
    变速箱挡位(候选) 0x1F4 内的 nibble 枚举 被否决(源文档否定该位置)

    读取方法与注意事项

    第一条是「先认总线,再看信号」。三条总线的速率分别是 500、125、500 kbit/s,若适配器接错引脚或用错速率,会直接抓不到帧。源文档为此专门记录了双通道适配器的角色映射,把每一路固定到指定总线。

    第二条是同一物理量的多来源问题。车速在 C-CAN 的 0x101 与 0x0EE 上都有表现(后者约为前者的 8 倍,相关系数 0.9999919),整车里程同时在 0x760 与 B-CAN 的 ICS 数据块里出现(后者由 UDS 服务 22 读 DID 0x2001 得到,u24 大端 × 0.1 km)。使用前应确定以哪一路为准,并核对两路是否一致。

    第三条是负向结果同样重要。源文档明确指出,CAN CH 上的七个高速 ID 都没有通过轮速载体验证——也就是说它们看起来像车速信号,但不能被证实。类似地,0x1F4 里被怀疑是挡位的那个 nibble 已被否决。这些「证伪」结论能避免后续误用。

    证据等级与边界

    源文档的验证手段主要有两类:一类用「轮速载体」做参照,把候选信号与已知的轮速做一致性比对;另一类用 UDS 读取模块自身的数据块(如机油寿命、ICS 里程)作为可信基准。通过比对的标为已确认,未通过的明确记为被否决,处于中间状态的则作为候选保留。

    关于网关,需要格外谨慎:OBD 口后的 SGW 会限制可观察范围,源文档记录的部分内部总线访问方式涉及对车辆网络的物理改动,本文不复述具体做法,也不建议尝试——这类改动有损坏车辆网络的风险,且可能不符合当地法规。

    边界上必须强调:以上总线拓扑、UDS 地址与信号刻度都限定在这一台 2022 款 ProMaster 上。不同年款、不同市场版本的模块地址、总线划分与信号位置都可能变化,跨车使用前必须重新验证。

    常见问题

    为什么这辆车要在三条总线上分别接线?

    因为三条总线的速率与用途不同:C-CAN / HS-CAN 是 500 kbit/s(引脚 6/14),B-CAN / CAN IHS 是 125 kbit/s(引脚 3/11),CAN CH 是 500 kbit/s(引脚 12/13)。用单一速率接单一引脚只能看到其中一部分数据,必须按总线分别接入并设置正确速率。

    车速信号有两个来源,该信哪个?

    0x101 与 0x0EE 上的车速高度相关(r=0.9999919,后者约为前者的 8 倍)。理论上两者一致即可互换使用,但源文档并未就此给出统一建议,使用前应自行在本车上核对两路是否始终一致,并确定以哪一路为准。

    被否决的信号还有参考价值吗?

    有。被否决说明「某位置不是挡位」这类边界已被排除,能避免后来者重复踩坑。源文档同时记录了「CAN CH 上七个高速 ID 均未通过轮速载体验证」这样的负向结论,同样缩小了搜索空间。

    这些 UDS 地址能直接用于别的 ProMaster 吗?

    不能。源文档记录的 19 个模块地址限定在这一台车上,不同年款或市场版本的模块地址可能不同。换车使用前必须重新枚举并复核。

    延伸阅读

    参考资料

    • 项目 05 —— public-can-dbc-datasets/additional/jakeiwen-promaster-2022/docs/bus-map.md(本项目车型档案主来源:三总线映射与 UDS 模块地址表)
    • 项目 05 —— public-can-dbc-datasets/additional/jakeiwen-promaster-2022/findings/2026-07-19_ccan_drive_signal_analysis.md(C-CAN 车速信号与 CRC 分析)
    • 项目 05 —— public-can-dbc-datasets/additional/jakeiwen-promaster-2022/findings/2026-09-22_gear_and_oil_life_offline.md(挡位否决与机油寿命读取)

    说明:本文整理自第三方开源项目的公开文档,仅代表该文档所记录的单个车辆样本,不代表同型号全系车型。CAN 与诊断操作存在风险,任何实车操作前请自行复核并遵守当地法规。

    更新记录

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

  • ECU 探测与 ISO-TP:在场、固件候选与可执行是三件事

    结论:诊断链上的三个结论必须严格分开——「探测到响应」「解析到固件」「车型可执行」是三件不同的事。tester present 收到单帧响应只说明该地址在场,返回固件候选只说明查询有结果,二者都不构成车型可执行的许可。此外 get_ecu_addrs() 的 timeout 是循环条件而非硬墙钟上界,0x78 的 pending 判断只看第三个字节、是宽松的超时延长条件而非已认证的 UDS pending 状态。本文为固定源码快照 c8fb906 的静态阅读,未连接 CAN 设备、未发送任何诊断请求。

    发现链路:从在场探测到品牌排序

    make_tester_present_msg() 生成 0x3e 0x00 服务请求,诊断 RX 地址由 get_rx_addr_for_tx_addr() 按 11-bit 偏移或 29-bit 地址字节交换计算。get_ecu_addrs() 先排空接收,再批量发送 tester present,在时间窗口内收集允许的响应地址与总线。

    函数/组件 输入与实际行为 输出边界
    get_present_ecus() 从各品牌 FwQueryConfig 取 ECU 地址,按 OBD 复用模式分组;无子地址并行、有子地址逐个查询 返回已响应的 (rx_addr, subaddr, bus) 集合;未响应不等于 ECU 不存在
    get_ecu_addrs() 排空接收、批量发 tester present,在时间窗口内收集允许的响应地址/总线 异常被记录后返回已收集的局部集合,不是全有或全无事务
    _is_tester_present_response() 验证短单帧格式;接受 SID 0x7e 正响应或 0x7f 0x3e 负响应 「ECU 在场」不表示该 ECU 接受诊断会话或会返回固件
    get_brand_ecu_matches() 将探测地址与各品牌预期 RX 地址比较 只作查询顺序启发;实现明确未比较 bus
    get_fw_versions_ordered() 按已命中 ECU 数与比例排序,仅查询有命中的品牌,单一固件候选即停止 不是全品牌全 ECU 的完整清单;早停可由 fuzzy 单一候选触发

    这里有两个容易被忽略的边界。其一,get_ecu_addrs() 的 timeout 是循环条件,而 can_recv(wait_for_one=True) 可阻塞,因此该值不是整个扫描过程的硬墙钟上界;经 card 的回调使用时订阅端设置了 timeout=20。其二,OBD 复用切换由参数写入及 pandad 确认构成,回调内没有独立握手超时。

    独立开发工具 get_all_ecu_addrs() 枚举 11-bit 与 29-bit 发送地址,但直接把 queries 复用为 responses:11-bit 枚举覆盖整个 0x700..0x7ff 范围,29-bit 通常需要交换后的 RX 地址。因此按代码推导,该工具的 29-bit 响应多数不会通过白名单,并非可靠的完整 ECU 清单;生产用的 get_present_ecus() 是单独计算预期 RX 地址的另一条路径。

    ISO-TP 查询状态机

    IsoTpParallelQuery 把 TX 地址映射成预期 RX 地址,按总线与地址过滤,子地址再逐条筛选;get_data() 用每地址计数器校验多阶段请求的响应前缀,最终只返回成功完成的 (tx_addr, subaddr) -> payload。VIN 的功能寻址先发广播请求,随后由物理寻址的 ISO-TP 对象接收/发流控;固件查询通常用物理地址。

    层 职责 边界
    CanClient 按 bus/RX 地址过滤,处理子地址和发送节拍 只对匹配地址的帧做后续处理
    IsoTpMessage 单帧、多帧、连续帧序号及流控;固件查询设为非阻塞接收、10 ms separation time 发送与接收错误可被上层记录并使对应地址结束
    get_data() 每地址计数器校验多阶段响应前缀 只返回成功完成的结果,部分成功不返回
    pending 分支 响应第三字节为 0x78 时延长该地址等待 只看第三字节,不先要求完整负响应前缀,属宽松条件

    正常多帧进展会刷新单地址截止时间;响应的第三字节为 0x78 时走 pending 分支并延长等待。关键在于 pending 判断仅按第三字节,不先要求完整负响应前缀 0x7f ... 0x78,所以它是宽松的超时延长条件,而非已认证的 UDS pending 状态。另外 total_timeout=60 也在循环尾检查,不能约束本次阻塞式 can_recv() 的耗时。

    固件数据契约

    get_fw_versions() 为每个成功响应创建 CarFw,记录 ECU 类型、固件字节、TX/RX 地址、请求、品牌、bus、OBD 复用模式及 logging。请求配置允许白名单、特殊 RX offset、子地址,以及需记录但不参与指纹匹配的 ECU。个别查询异常被捕获并继续,因此返回值可以是部分固件清单。build_fw_dict() 丢弃 logging 响应;匹配函数用地址/子地址与固件版本来判定,而不是把 CarFw 中的 bus 和响应地址都作为唯一身份校验条件。

    自制硬件与插件边界

    以下是改造建议,不是现有运行时的保证。应将 ECU 探测器、VIN 解码器、固件查询器拆成可替换的证据提供者,但对外只暴露受限的诊断代理;插件不得直接持有原始 sendcan 发布权限。诊断代理应对 bus、地址、服务 ID、速率、总时长、同时请求数和点火/行车状态实施硬限制,物理网关/MCU 独立保留 CAN 输出安全门。状态建模上,应把正/负响应、部分超时、未查询、OBD 模式切换失败分成不同状态,不以空集合或空固件列表直接推断「该车型不受支持」;每条证据应附采集时间、硬件拓扑和本次启动标识,缓存或早停结果不得自动获得执行许可。

    常见问题

    收到 tester present 响应就说明 ECU 支持诊断吗?

    不说明。_is_tester_present_response() 只验证短单帧格式并接受 0x7e 正响应或 0x7f 0x3e 负响应。「ECU 在场」不表示它接受诊断会话或会返回固件。

    0x78 的 pending 判断是标准 UDS pending 吗?

    不是。pending 分支仅按第三个字节是否为 0x78 判断,不先要求完整的负响应前缀,因此它是宽松的超时延长条件,而非已认证的 UDS pending 状态。

    get_fw_versions_ordered() 会返回全部 ECU 固件吗?

    不会。它按已命中 ECU 数与比例排序,只查询有命中的品牌,并在拿到单一固件候选时即停止,因此返回的是候选子集而非全品牌全 ECU 的完整清单。

    为什么 get_all_ecu_addrs() 的 29-bit 结果不可靠?

    因为它把 queries 直接复用为 responses,而 29-bit 通常需要交换后的 RX 地址,多数响应不会通过白名单。可靠路径是单独计算预期 RX 地址的 get_present_ecus()。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/ECU_DIAGNOSTIC_TRANSPORT_DEEP_DIVE.md(取用了 ECU 发现链、ISO-TP 查询状态机、固件数据契约、插件边界与离线探针结论)。
    • 项目 02 —— openpilot-research/CAR_MESSAGES_FIELD_CONTRACT_DEEP_DIVE.md(仅用于确认诊断结果进入车型识别与安全配置的衔接位置)。

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

    更新记录

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

  • Hyundai 接口的 CAN FD 判别、能力位与 ECU 静默恢复边界

    结论:Hyundai 车型接口的能力位是软件决策,不等于目标 ECU 已按请求改变状态。接口按指纹与固件把平台分成 CAN FD 与经典 CAN 两条判别路径,再由相机总线上是否出现 0x50 或 0x110 决定 LKA 还是 LFA 转向,并据此交换 A-CAN / E-CAN;纵向 ECU 静默只在「自控纵向且非相机 SCC」路径发起,且通用 disable_ecu() 的返回布尔值没有在 Hyundai init() 中被汇总,card 在其返回后直接写 ControlsReady。固定快照基线为 c8fb906,未执行 UDS 请求或实车验证。

    入口与函数链

    CarInterfaceBase.get_params() 先装载平台规格和静态 flags,再调用 Hyundai _get_params(),最后计算车辆惯量与轮胎刚度。Hyundai _get_params() 负责分 CAN FD / 经典 CAN,由指纹与固件推导动态标志、纵向能力和 safety 配置。HyundaiFlags 记录车型 / 检测特征,HyundaiSafetyFlags 编码给 MCU 的控制策略,二者不可互换。

    组件 职责
    CarInterfaceBase.get_params() 先装载平台规格与静态 flags,再调用 Hyundai _get_params(),最后算惯量与轮胎刚度。
    CarInterface._get_params() 分 CAN FD / 经典 CAN,由指纹与固件推导动态标志、纵向能力与 safety 配置。
    CanBus.__init__() / CanBusBase.__init__() LKA / LFA 使 A-CAN / E-CAN 互换;安全配置数量决定四路总线偏移。
    CarInterface.init() / deinit() 条件性发 UDS 通信控制禁发 / 恢复请求。
    disable_ecu() 先进入扩展会话,再请求通信控制;返回布尔值,但上层 Hyundai 接口未消费。
    card.controls_update() 首次进入控制时调用接口 init(),其返回后写 ControlsReady。

    CAN FD:相机地址驱动的分支

    _get_params() 先由 CanBus(None, fingerprint).CAM 找相机总线;该总线上出现 0x50 或 0x110 时判为 LKA 转向,否则判为 LFA。随后 CanBus(None, fingerprint, lka_steering) 重新计算 A-CAN / E-CAN:LKA 平台与 LFA 平台交换两条总线。

    CanBusBase 在指纹阶段按非空 bus 最大编号推导四路偏移;运行阶段 CanBus(CP) 则按 safetyConfigs 数量算偏移。因此识别出的拓扑必须与实际 panda / 线束配置一致,不能由车型名称单独推断 E-CAN 号。CAN FD 的 0x1ba、0xFA、0x1cf、0x130、0x40 等地址参与 BSM、混动、备用按钮和档位报文推断。

    LKA 平台若相机有 0x110,再加 ALT LKA 标志;非 LKA 平台在没有 CANFD_RADAR_SCC 静态标志时,推导相机 SCC。CANFD_NO_RADAR_DISABLE 会关掉实验纵向可用性;LKA 平台若 car_fw 未列出 ADAS ECU,也会关掉。这些是保守能力判据,但空固件列表与「已证明车辆无 ADAS ECU」不能画等号。CAN FD 默认以 hyundaiCanfd 作为执行 safety;若推导出的 E-CAN 编号至少为 4,则在安全配置列表前插入一个 noOutput,由后一个配置承载 Hyundai safety 参数。

    经典 CAN、共同能力与雷达状态

    经典 CAN 在动力总线 0 / 相机总线 2 上按地址判断 BSM、LFA 图标、FCA 报文及 LDA 按钮。LEGACY 平台选 hyundaiLegacy safety,因为旧报文缺计数 / 校验;其他经典平台选 hyundai,相机 SCC 再追加相应 safety 参数。LEGACY 或 UNSUPPORTED_LONGITUDINAL 会使实验纵向不可用。

    两条路径共同设置 0.1 秒转向执行延迟、0.4 秒限制计时器、扭矩标定,以及 ALT_LIMITS / ALT_LIMITS_2 安全标志;后者还使车型 dashcamOnly。特定平台型号另改延迟或设 dashcamOnly。

    概念 边界说明
    openpilotLongitudinalControl 等于 alpha_long and alphaLongitudinalAvailable,pcmCruise 取其反值;只有真正启用时才给 MCU 设 LONG。
    radarUnavailable 仅在 CAN 指纹 bus 1 有雷达起始地址且平台 DBC 提供 Bus.radar 时为假;不是实时雷达在线或诊断静默结果。
    被动回退 card 可因开关关闭、无控制器或 dashcamOnly 把接口设为被动并把安全模式改为 noOutput。
    动力类型 EV / HEV / FCEV 映射为安全参数,但不改变上述能力判定层级。

    车型参数里的 LONG 不是最终上路授权:card 仍可能把接口设为被动并把安全模式改为 noOutput。

    ECU 静默与恢复的实际边界

    CarInterface.init() 仅在自控纵向且非相机 SCC 路径静默纵向 ECU:经典 CAN 及普通 CAN FD 目标为 0x7d0,LKA 转向 CAN FD 改为 E-CAN 的 0x730。默认通信控制请求带 UDS 0x28 的 suppress-positive-response 位;它表示请求 ECU 不发送正响应,不是已经收到确认。若 CANFD_ENABLE_BLINKERS 置位,接口另对 0x7b1 发独立请求;该 flag 在本快照的静态平台项中未见设置。

    通用 disable_ecu() 先要求扩展会话的有效前缀响应,随后以空期望前缀调用通信控制查询并丢弃查询结果;只要后者没有抛异常,就可记录成功。因此其返回真也不等于已验证 0x28 正响应或实际 ECU 停发。Hyundai init() 又没有返回 / 汇总这个布尔值;card 在它返回后直接写 ControlsReady。这是一条源码确认的状态回执缺口,不是对特定车辆雷达或 ADAS ECU 实际行为的断言。

    deinit() 构造启用收发请求并复用 init() 的条件与地址。在本快照的主运行链未检出 CI.deinit() 调用,所以不能说正常退出一定主动恢复 ECU。控制器每 100 帧的 tester-present 也仅在自控纵向、非 CAN FD 相机 SCC 时形成。禁用雷达可能使原车 AEB 不可用,必须逐硬件架构独立验证。

    面向新硬件与插件化的接口建议

    车型插件只应给出期望能力、指纹 / 固件证据、DBC 和拓扑;受信任 ECU 管理服务独占诊断写权限,并单独报告请求已发送、预期正响应或可观测行为、持续存活和恢复结果。不同车型的相机 SCC 与雷达 / ADAS ECU 静默对原车 AEB 的影响,不得合并为一个通用开关。非上车验证矩阵应覆盖 LKA / LFA、相机 / 雷达 SCC、双 panda 总线偏移、备用按钮 / 档位、缺失 ADAS 固件、CANFD_NO_RADAR_DISABLE、负 UDS 响应、超时、掉电恢复及 AEB / FCW。

    常见问题

    为什么不能用车型名直接推断 E-CAN 号?

    因为 E-CAN 号由拓扑推导:指纹阶段 CanBusBase 按非空 bus 最大编号算四路偏移,运行阶段 CanBus(CP) 按 safetyConfigs 数量算偏移;而 LKA 与 LFA 平台会交换 A-CAN / E-CAN。识别出的拓扑必须与实际 panda / 线束配置一致。

    车型参数里 LONG 为真就代表能上纵向控制吗?

    不代表。只有 openpilotLongitudinalControl(即 alpha_long and alphaLongitudinalAvailable)真正启用时才给 MCU 设 LONG;card 还可能因开关关闭、无控制器或 dashcamOnly 把接口设为被动并把安全模式改为 noOutput。

    接口静默雷达 ECU 成功了吗?

    无法从返回值判断。默认请求带 UDS 0x28 suppress-positive-response 位,只是让 ECU 不回正响应;disable_ecu() 丢弃查询结果,返回真也不等于已验证 0x28 正响应或 ECU 实际停发。Hyundai init() 更没有汇总该布尔值。

    退出时会自动恢复被静默的 ECU 吗?

    不能这样假设。deinit() 会构造恢复请求并复用 init() 的条件与地址,但在本快照的主运行链未检出 CI.deinit() 调用。恢复是否发生需按具体运行路径与硬件架构单独验证。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/HYUNDAI_INTERFACE_CAPABILITY_ECU_LIFECYCLE_DEEP_DIVE.md(取用了 CAN FD / 经典 CAN 判别、能力位推导、ECU 静默与恢复边界分析)。

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

    更新记录

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

  • Tesla Model3 CAN 仿真档案:67 条报文与 5 个锚点信号

    结论:这份「车型 CAN 数据档案」的对象是 Tesla Model3 的一台 CANoe / CAPL 仿真工程,不是一台真实车辆:它用三份逆向得来的 DBC(Battery / Thermal / Drive)和一条「电池异常 → 热管理响应 → 扭矩降额」的因果链,在总线上造出约 67 条报文、其中 8 条为核心周期报文。总线为 500 kBaud 经典 CAN、11 位标准帧,另叠加一条 Ethernet / DoIP 诊断通道,CAN 侧用标准 ISO-TP(CanTp)承载 UDS。关键结论——例如硬切断后扭矩以 kHardCutoffTau=0.4s 衰减、集中式架构下 bmsContactorState 稳定在 80.500s——全部来自仿真,不能当作实车测量,也不能外推到其他 Model3 车或年款。

    车辆与适用范围

    源文档是一套围绕仿真节点搭建的工程:三个业务 ECU(Battery / Thermal / Drive)实现核心因果链,一个独立的 SafetyMonitor 节点只监听总线,外加测试驱动与 DoIP 网关/以太网诊断。以下范围只对应这套仿真的内部设定。

    项 内容
    车型 Tesla Model3(仿真建模对象,非实车采集)
    年款 / 市场版本 源文档未确认;DBC 名称仅区分 Battery / Drive / Thermal 三个域
    ECU / 改装状态 仿真态:Battery_ECU、ThermalCtrl_ECU、DriveInverter_ECU、SafetyMonitor_ECU 四个 CAPL 节点
    采集跨度 约 121.5 分钟的四阶段自动化场景(Phase0 正常基线 / Phase1 冷被动 / Phase2 热被动软限 / Phase3 热主动硬切断)
    适用范围 仅限该仿真工程产出的 .asc 日志与其下游分析;不代表真实 Model3 的任何总线行为

    总线与寻址

    总线侧为经典 CAN,叠加以太网诊断扩展。源文档给出的寻址与帧格式信息如下;需要注意,DBC 本身是逆向产物,其对报文周期的标注并不完整。

    项 内容
    物理层 / 比特率 CAN 500 kBaud;另设一条 Ethernet 通道(DoIP / OSEK_TP 节点层 DLL)
    寻址 / 帧格式 经典 CAN;总线负载按 CAN 2.0A 标准帧 47 位开销计算,即 11 位标识符
    CAN FD 源文档未使用 CAN FD;诊断走 CAN 侧 ISO-TP(CanTp)与以太网 DoIP
    报文规模 三份 DBC 去重后共 67 条报文;CAPL 仿真实际周期发送 8 条核心报文
    周期标注完整性 67 条中 45 条没有 GenMsgCycleTime,为原始逆向 DBC 的数据缺口

    已解码信号

    下表抽取源文档中最有代表性的条目。位置一列尽量保留源文档的 ID 与消息名写法;「证据」一列注明来自 DBC、CAPL 设定还是分析脚本的输出口径。凡源文档标注为「未完全根因」或「数据缺口」的,均原样保留。

    信号 位置(ID / 字节域) 解码 证据
    BMSmaxPackTemperature Battery 域锚点信号 电池包最高温度,跨域因果链的温度锚点 anchor_signals.csv;Phase0 拟合归一化
    BMS_maxDischargePower ID252BMS_powerAvailable(十进制 594) 最大放电功率,驱动域软限跟踪的输入 DBC;CAPL 设定
    VCFRONT_coolantFlowBatActual Thermal 域锚点信号 电池冷却液实际流量 anchor_signals.csv
    CMP_speedRPM ID227CMP_state 压缩机转速档位;三级压缩机转速状态机 CAPL 设定;故障注入用例
    DIR_torqueCommand Drive 域锚点信号 驱动扭矩指令;硬切断后按指数衰减到近零 anchor_signals.csv;kHardCutoffTau=0.4s
    BMS_contactorState Battery 域广播 接触器状态;==1 时 Thermal 冻结全部热信号 CAPL 设定;SafetyMonitor Rule 1/5
    ID312BMSthermal 广播 ID312BMSthermal(十进制 786) 电池热报文;被抑制即触发 SafetyMonitor 通信超时 CAPL 设定;故障注入用例
    gFlowRequest Simulink 信号链(1000 ms 周期) 流量请求;延迟/量化行为最高约 1.92s Simulink 验证;已调查未完全根因
    gCompressorRPM Simulink Drive 分支 随机游走驱动的压缩机转速 Stateflow;随机序列复现问题见边界
    gTorqueCommand Simulink Drive 分支 随机游走驱动的扭矩指令 Stateflow;同上
    targetPower(稳态) Simulink 两架构对照 稳态目标功率,两架构均为 40.0000 Verify_key_metrics.m 校验
    HardCutoff.Opening 时长 状态机(Battery_ECU) 硬切断 OPENING→OPEN 过渡,精确 200ms CAPL 设定;Simulink 复核
    UDS 0x22 ReadDataByIdentifier Battery_ECU 诊断栈 5 个 DID,含两个由其他 ECU 拥有的网关式 DID(被动缓存) CAPL;UDS_DiagnosticsTest 14 个检查点
    UDS 0x19 / 0x14 与 0x7F Battery_ECU 诊断栈 读/清 DTC(子功能 0x02/0x04);7 种否定响应场景 CAPL;Freeze Frame 用例

    读取方法与注意事项

    解析链以 cantools 为基础。源文档明确:默认采用流式解析以适配大日志,小于 200 MB 时才用 --in-memory;解码后的长表可再重采样到 100ms 均匀网格,但真实逐帧时间戳只在长表里,做周期核验必须用长表而非重采样结果。引用因果滞后结论时,源文档要求只引用 causal_lag_analysis_HIGH_CONFIDENCE_ONLY.csv。

    数据完整性有专门的检查脚本,给出三种判定:CLEAN(可直接使用)、ISOLATED, LIKELY OK(不超过 5 个孤立点,建议抽查)、CORRUPTED(存在大段连续异常,不可直接使用)。源文档建议在 LSTM 训练或引用因果滞后结论之前先跑这一检查,用于识别已知的 CAPL/CANoe 信号解码缺陷是否复现。

    异常检测模块有一处容易踩的坑:训练与评估的 --val-fraction、--block-size、--seed 必须完全一致,否则 Phase0 基线会落在模型已训练过的窗口上,静默低估基线误差。归一化只在 Phase0 上拟合,以避免把异常期统计量泄漏进「正常」基线。总线负载侧,长表须先按 (timestamp_s, frame_id) 去重,否则到达帧会被按信号重复计数,严重高估发送频率。

    时延分析脚本不接收命令行参数,输入文件名固定为 CAN.asc 与 Eth.asc;它以两个文件各自的时间戳相减来定义时延,而不是信任 UDP 载荷内的 Timestamp 字段(后者存在约 0.5ms 的整毫秒截断偏置)。匹配采用精确 RawValue 相等、平分时取最近在前的策略,源文档明确这是尽力而为、不保证唯一的匹配。

    证据等级与边界

    本档案的全部信号都是仿真观测,没有任何实车旁证。DBC 是逆向结果,45/67 条报文缺少周期标注,因此总线负载只能给出「未填充下界」与「+20% 填充上界」两个口径,30%/50% 也只是业界经验阈值、非强制标准。Simulink 侧两架构对照给出确定性结论:集中式架构的 bmsContactorState 在 11 次重复仿真中稳定到达 80.500s(零方差),分布式架构则落在 0–110ms、10ms 栅格的延迟窗内,且在受控变量测试下确认延迟来自接收域自身采样节拍。

    已知缺陷必须原样保留。其一,Battery_ECU.can 内部使用了两个互不同步的 100ms 定时器,CAPL 不定义其相对触发顺序,在窄时序巧合下会令 SafetyMonitor 的 Rule 1 在模拟上电复位后短暂重触发,源文档将其记为未修复的开放问题(低优先级、影响面窄),根因已分析但未获得带时间戳的证据确认。其二,Simulink 中 Stateflow 的随机游走函数在独立 sim() 调用间复现同一随机序列,机制未定位,只影响随机游走驱动信号,不影响上述确定性结论。其三,1000ms 周期的 gFlowRequest 链出现最高约 1.92s 的延迟/量化,与其余信号的 0–110ms 模式不一致,已调查但未完全根因、被降级搁置。

    不能外推的部分:本文所有数值限定在这套仿真的设定与日志;40.0000、200ms、80.500s 等均属工程参数,不构成对任何真实 Model3 的描述。源文档未提供对车辆安全机制的绕过方法,且不建议尝试;本文只讨论仿真工程的公开文档。

    常见问题

    这是不是一台真实 Model3 的数据?

    不是。它是 CANoe/CAPL 仿真工程:三个业务 ECU 加一个独立监听节点,用逆向 DBC 复现「电池异常 → 热响应 → 扭矩降额」的因果链。所有信号与节拍都来自仿真设定,源文档未包含任何实车采集。

    为什么 67 条报文里只有 8 条能算总线负载?

    因为逆向 DBC 中 45 条报文没有 GenMsgCycleTime,且核心 8 条里还有两条在 DBC 里根本没有周期。源文档的做法是以 CAPL 的 setTimer() 调用作为周期的唯一真实来源,并逐行标注对应的 CAPL 源码位置以便追溯。

    引用因果滞后结论时要注意什么?

    源文档要求只引用 HIGH_CONFIDENCE_ONLY 的结果文件,并在引用前先跑数据完整性检查以排除已知的解码缺陷;LSTM 训练/评估的 val-fraction、block-size、seed 必须一致,否则基线会被静默低估。峰值与时长在本数据集中还存在部分混淆。

    SafetyMonitor 的 Rule 1 为什么会误触发?

    因为 Battery_ECU.can 内部两个不同步的 100ms 定时器相对顺序未定义,在窄时序巧合下会在模拟上电复位后短暂重触发。源文档标记为开放且未修复,根因已分析但未经带时间戳的证据确认,影响面窄。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/model3-can-simulation/README.md(本项目车型档案主来源:节点与因果链、DBC 与锚点信号、总线负载、时延分析与 Simulink 对照)。

    说明:本文整理自第三方开源项目的公开文档,仅代表该文档所记录的单个车辆样本,不代表同型号全系车型。CAN 与诊断操作存在风险,任何实车操作前请自行复核并遵守当地法规。

    更新记录

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

  • Honda Civic FL5:25 个 DID 与 109 个 CAN 信号

    结论:Honda Civic FL5 的数据特征与多数车相反:OBD 口后面存在网关,且总线上几乎抓不到周期性广播帧——必须用 UDS 服务 22(ReadDataByIdentifier)主动向四个模块索取 DID,才能读到 25 个 DID、109 个信号。正因为如此,DBC 不适合做这辆车的主格式。以下所有结论仅限源文档记录的这一台车与其固件版本,不代表同型号其他车辆。

    车辆与适用范围

    本文数据来自第三方开源项目对一台 Honda Civic FL5 的诊断数据整理。项目以 UDS 服务 22 的读取结果为基础,按模块组织成 DID 与信号清单,并对每条信号标注了证据等级。

    项 内容
    车型 Honda Civic FL5
    年款 / 市场版本 源文档未确认
    ECU / 模块 共 4 个:0x10 ECM、0x28 VSA、0x30 EPS、0x60 仪表(组合仪表)
    采集跨度 数据集 25 个 DID、109 个信号;源文档记录版本 1.0.1
    适用范围 仅限源文档记录的这一台车与其固件;DID 布局与信号刻度不保证适用于其他年款或市场版本

    总线与寻址

    这辆车是经典 CAN 加主动诊断读取的典型:总线上没有可供解析的周期广播流,价值的全部来源是「问—答」。因此寻址方式、传输层时序与请求节奏比 DBC 更重要。

    项 内容
    物理层 / 速率 经典 CAN 2.0B,500 kbit/s,无 CAN FD
    接入点 标准 OBD-II(J1962)引脚 6 / 14
    网关 OBD 口后存在网关;源文档实测总线上为零周期性广播帧
    诊断寻址 29 位 ISO 15765 物理寻址:请求 18DA<目标>F1,应答 18DAF1<目标>,诊断仪地址固定为 F1;功能广播为 18DB33F1
    传输层 ISO-TP(ISO 15765-2):首帧宣告长度,随后连续帧,接收方回 30 00 00 流控帧;数据区 54–63 字节,填充 0xAA
    11 位寻址 在 7E0 / 7E8 上发标准 Mode 01 无应答

    已解码信号

    下表从源文档的信号清单中抽取最具代表性的条目。项目的置信度分为「已确认(研究级)」「中」「低-候选」三档,表中原样保留该标注;标为「中」的条目表示解码方向明确但仍缺独立旁证。

    信号 位置(ID / DID / 字节) 解码 证据
    ENGINE_RPM(发动机转速) DID 0x2610 B6:B8 raw × 0.25 rpm 已确认(研究级)
    MAP_ABS(绝对进气压力) DID 0x2610 B9:B11 raw × 0.0078125 kPa 已确认(研究级)
    ECT(冷却液温度) DID 0x2610 B11 raw − 40 ℃ 已确认(研究级)
    VEHICLE_SPEED(车速) DID 0x2610 B18 raw km/h 已确认(研究级)
    OIL_PRESSURE(机油压力) DID 0x2610 B44:B46 raw kPa 已确认(研究级)
    OIL_TEMP_MODEL(机油温度模型) DID 0x268F B15 raw − 40 ℃ 已确认(研究级);源文档标注该信号在公开资料中无先例
    BRAKE_PRESSURE(制动压力) DID 0x4005 B7:B9 raw − 25 bar 已确认(研究级)
    STEER_ANGLE(方向盘转角) DID 0x48BD B11:B13 s16 × 0.1° 已确认(研究级)
    WHEEL_SPEED_FL / FR / RL / RR DID 0x48C4 B23:B31 raw × 0.01 km/h 已确认(研究级)
    STEER_MODE(转向模式) DID 0x48AC B1 枚举 中
    FUEL_LEVEL(燃油液位) DID 0x7029 B12:B14 raw × 0.01 L 已确认(研究级)
    AMBIENT_TEMP(环境温度) DID 0x7028 B17 raw ℃ 已确认(研究级)

    读取方法与注意事项

    这辆车读数据必须走 UDS 服务 22。请求用 29 位物理寻址发到 18DA<目标>F1,模块在 18DAF1<目标> 上应答;诊断仪地址固定为 F1,功能广播是 18DB33F1。注意 11 位寻址(7E0 / 7E8)上的标准 Mode 01 在本车上没有应答。

    一旦某个 DID 的应答超过单帧容量,就会落到 ISO-TP 分段传输:模块先发一个首帧(形如 10 29 …)宣告总长度,再发若干连续帧,诊断仪需要及时回一个流控帧 30 00 00 授权它继续。源文档特别指出,流控帧如果晚回几毫秒,ECU 会放弃整笔传输——所以「问得到」不等于「收得全」,接收端的流控时机是硬约束。

    工程上还要考虑读取节奏:同一模块上多个 DID 需要轮流询问,模块之间(ECM / VSA / EPS / 仪表)也要分配请求配额,否则在高频轮询时容易触发超时或让 ECU 返回否定应答。源文档记录了若干次安全访问被拒的情形,未提供绕过方法,也不建议尝试。

    证据等级与边界

    项目的证据等级分「已确认(研究级)」「中」「低-候选」三档。已确认条目既有编码依据也有行为或参考交叉验证;「中」表示解码方向明确但缺少独立旁证;「低-候选」则是尚未闭环的猜测。本文抽取的信号以已确认为主,并原样保留了 STEER_MODE 的「中」标注。

    项目文档中有一节专门列出「已推翻的说法」,条目数量在三十条以上——说明这辆车的诊断数据在公开讨论里存在大量误传。阅读时要把「已推翻」与「已确认」严格分开,不要把早期猜测当作结论使用。

    边界上必须强调:25 个 DID 与 109 个信号全部来自这一台车的这一版固件。不同年款、不同市场版本的 DID 编号、字节偏移与刻度都可能变化;同一 DID 在不同固件下含义也未必一致。任何实车读取都应在目标车上逐条复核。

    常见问题

    为什么这辆车用 DBC 解析不出来东西?

    因为源文档实测其总线上没有周期性广播帧,OBD 口后还有网关。DBC 描述的是「谁在什么时刻广播什么布局的帧」,而这辆车的数据要靠 UDS 服务 22 主动索取,表现形式是「问—答」而非广播,所以 DBC 不适合作主格式。

    读一个 DID 需要满足哪些传输层条件?

    用 29 位寻址发请求到 18DA<目标>F1,模块在 18DAF1<目标> 应答;如果应答超过单帧,模块会先发 ISO-TP 首帧宣告长度,诊断仪必须及时回 30 00 00 流控帧。源文档指出流控晚回几毫秒 ECU 就会放弃整笔传输。

    标准差一点的信号还能用吗?

    要按证据等级区分。标为「已确认(研究级)」的可以直接用;标为「中」的(如 STEER_MODE)解码方向明确但缺独立旁证,使用前应自行验证;「低-候选」的不要作为结论。源文档对每一条都保留了原始标注。

    这些 DID 能套用到别的 Civic 上吗?

    不能。源文档的全部结论限定在这一台车与其固件版本上,且明确 DID 编号、字节偏移与刻度都可能随年款或市场版本变化。换车使用前必须重新读取并复核。

    延伸阅读

    参考资料

    • 项目 02 —— public-can-dbc-datasets/additional/caldis-honda-civic-fl5-dids/README.zh-CN.md(本项目车型档案主来源)
    • 项目 02 —— public-can-dbc-datasets/additional/caldis-honda-civic-fl5-dids/CHANGELOG.md(版本与已推翻说法的变更记录)
    • 项目 02 —— public-can-dbc-datasets/additional/caldis-honda-civic-fl5-dids/SOURCE.md(数据集版本与来源说明)

    说明:本文整理自第三方开源项目的公开文档,仅代表该文档所记录的单个车辆样本,不代表同型号全系车型。CAN 与诊断操作存在风险,任何实车操作前请自行复核并遵守当地法规。

    更新记录

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

  • UDS 诊断工具为什么不能随手调:只读、会话与写 ECU 的分权设计

    结论:UDS 诊断客户端只做格式校验,不做权限分级。同一套客户端既提供读取 DTC 这类只读操作,也提供清 DTC、写内存、请求下载等下发原语——它只检查响应 SID 是否正确、DID 是否回显,不判断这个操作该不该被允许。所以「能不能调」必须由宿主层决定,而不是靠客户端。

    一条诊断指令要经过几层

    诊断脚本到 ECU 之间是一条明确的分层链路,每一层各管一段:

    层 职责 与整车其它链路的关系
    诊断脚本 组织请求、打印结果 直接调客户端,不走车况消息回调
    UDS 客户端 服务与子功能编码、正响应校验、负响应解析 面向单个目标 ECU
    请求构造 每次新建传输消息对象并等待应答 会话与超时在此层管理
    ISO-TP 单帧、多帧、连续帧序号与流控 把长报文拆合
    CAN 客户端 按 bus、RX 地址、子地址过滤 决定哪些响应会被看到
    硬件收发 直接调用收发接口 与车辆识别路径不同——识别走并行查询器

    这里有个关键区别:车辆识别走的是另一条并行查询路径,而诊断工具直接拿硬件收发接口。这意味着诊断工具绕过了识别阶段建立的上下文,也意味着它不受识别逻辑的任何约束。

    响应语义里的一个超时缺口

    正响应要求服务 ID 等于「请求 ID 加 0x40」,带子功能时还要校验回显。负响应以 0x7f 开头,解析错误码后抛出异常;而 0x78 表示「响应待定」,代码会继续等待下一轮。

    问题在于:没有跨多次「响应待定」的累计墙钟期限。每次收到待定状态都重设下一轮等待时间,理论上一个持续返回待定的 ECU 可以让调用一直循环下去。单次调用的超时参数,不保证整个请求过程的总时限。

    服务能力清单:哪些只读,哪些有副作用

    把服务按副作用分类,是设计权限边界的前提。客户端本身不做这个分类,但代码里的校验强度能反映风险等级:

    能力类别 代表操作 代码里的校验与副作用
    基本会话 诊断会话控制、会话保持 会发 CAN 请求,不是纯本地查询
    身份与数据读取 按数据标识符读取 除通用校验外还比对返回的 DID;解出的字节仍需按车型解释
    故障码读取 读取 DTC 信息 返回原始内容,注释标明尚未统一解析
    扩展读取 按地址读内存、请求上传 只限制地址/长度字段为 1 到 4 字节,未形成车端权限策略
    安全与通信控制 安全访问、通信控制 只检查种子/密钥参数形状;密钥派生不在此层;通信控制可影响 ECU 报文
    清除与复位 清除诊断信息、ECU 复位 对 ECU 状态有直接影响
    配置与执行 按标识符写数据、写内存、例程控制 按格式编码并检查部分回显,但没有写前写后事务、没有回滚
    数据传输 请求下载、传输数据、请求退出传输 提供刷写原语;字段与块序号校验不等于固件包签名或完整性验证

    四个现成工具入口的实际风险

    仓库里已经带了四个直接调用该客户端的脚本,它们最能说明「只读」这个标签有多不可靠:

    工具 静态调用链 需要注意的点
    读故障码 检查守护进程 → 连接硬件 → 设为诊断模式 → 开扩展会话 → 读 DTC 虽名为读取,仍然切换了 ECU 会话与硬件安全模式;进程名检查不是互斥锁
    清故障码 同样切换会话后执行清除 默认使用功能寻址;清除阶段的超时异常被吞掉,无论地址如何都可能继续打印完成提示——不能据此判断 DTC 已清除
    平台配置写入 读取控制器标识与编码 → 安全访问 → 写配置 → 回读 是实际会修改 ECU 配置的工具;有回读但没有通用事务回滚
    雷达点开启 检查固件版本 → 读配置 → 必要时写入新配置 只在写入之后才检查旧配置是否为预期默认值;异常路径可能先写入再报告中止

    这四个都在本项目的服务端源码里,本文没有运行其中任何一个。「可能继续」「可能先写入」是控制流结论,不代表已对具体车辆复现。

    插件化宿主该怎么划边界

    如果要把诊断能力接入行车软件,下面是建议而非现状:

    1. 按副作用分层授权。只读证据、会话维护、ECU 状态修改、数据传输四类分开授权。即使只读插件也通过单一代理发送,不直接拿到硬件收发对象或报文发布权限。
    2. 写入类限定场景。离车、点火与供电稳定、目标 ECU 与版本白名单、人工审批;请求、回执、旧值和回读结果都要审计留痕。超时或部分响应时状态记为「未知」,不得显示成功。
    3. 代理层实施独立约束。总墙钟期限、速率限制、总线/地址/服务白名单、并发互斥;会话结束与异常退出要有显式恢复流程。
    4. 保留硬件安全链与人工接管边界。工具代码里已有直接切换安全模式和修改 ECU 的入口,所以插件宿主绝不能把「加载成功」当成执行许可。

    常见问题

    只读诊断会改变车辆状态吗?

    会。读取类脚本本身就会切换 ECU 会话、把硬件置为诊断模式,这些都属于状态变更。名称里的「读」只描述返回值的用途,不描述副作用。

    清除故障码返回成功就算清干净了吗?

    不一定。清除阶段的超时异常被吞掉,无论功能寻址还是非功能寻址都可能继续打印完成提示。可靠做法是清除后再显式读取 DTC 回读确认。

    安全访问能替代权限控制吗?

    不能。客户端只检查种子与密钥参数的形状,密钥派生不在这一层。安全访问是 ECU 侧的准入机制,不等于宿主侧的授权机制。

    数据传输做完就等于固件可信吗?

    不等于。传输层的字段与块序号校验只能保证传输结构正确,不能验证固件包签名与完整性。

    延伸阅读

    参考资料

    • 项目 02 —— NAS 谭健强/openpilot-research/UDS_CLIENT_DIAGNOSTIC_TOOLS_DEEP_DIVE.md(UDS 客户端与车端诊断工具,含源码行号索引)
    • 项目 02 —— openpilot-research/ECU_DIAGNOSTIC_TRANSPORT_DEEP_DIVE.md(ECU 启动识别与 ISO-TP 传输)
    • 项目 02 —— openpilot-research/ACTUATION_GATE_CHAIN_DEEP_DIVE.md(执行链门控与失效边界)

    说明:本文为对固定源码快照的静态阅读,未连接车辆、未打开诊断会话、未清除 DTC、未改写任何 ECU。文中标注为建议的内容是重构意见,不是当前实现已有的机制。

    更新记录

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