结论:canlab-zn6 的「只读」不是一个 UI 设计选择,而是四层各自独立的关:固件跑控制器 listen-only 并持续拉住收发器的 silent 引脚、wire protocol 里根本没有发帧命令、Host 只在 decode-only 门面后面用 can_decode、 contributing scope 直接把写诊断与 ECU 仿真列为不接受。它的价值恰恰在于这套自限——看懂这四层,就知道为什么它是稳妥的上车第一步,也知道它当前拿不到什么。
四层只读约束分别拦住了什么
大多数「只读工具」只在应用层藏了一个按钮。这份 Rust 工具链把约束下沉到了四个不同层次,每一层的失效模式都不一样,因此值得逐层拆开看。
| 层次 | 机制 | 拦住的动作 | 残余风险 |
|---|---|---|---|
| 固件 | 控制器 listen-only 模式,并持续把收发器硬件 silent 输入保持在有效状态 | ESP32-S3 / ESP32-C6 板卡自发帧 | 依赖电气连接正确,官方要求接车前用电表验证 silent 引脚 |
| 协议 | 主机 CLI、Web 应用、SocketCAN 适配器、wire protocol、MCP server 均无任意发送命令 | 来自上位机的单帧注入 | 与本工具同栈协作时才成立;换成其他 CAN stack 自行接入则不受此约束 |
| 解码 | Host 通过 decode-only 门面调用 can_decode,其编码方法不暴露给采集、诊断、固件、Web 服务与 MCP |
构造并编码报文的能力 | 无;但若有人 fork 后改动门面,需重新审计 |
| 社区 | 贡献指南明确不接受增加在车控制、刷写、写诊断或 ECU 仿真的改动 | 通过 PR 把写能力带进来 | fork 版本不受此约束 |
这四层里真正悬而未决的是第二层的物理版本落差:受保护的状态机与 Wokwi 诊断仿真器都已就位,但实体板卡的诊断发送仍处于关闭状态,要等板级的 ARM 与 fail-silent 电气测试完成。也就是说,当前 S3 与 C6 的实体发布包是采集专用(capture-only),诊断只能通过 Linux 上的 receive-only SocketCAN 之外的路径得到 仿真,不能指望在真车上读 Mode 21。
值得把这句警告当回事:作者在文档里明确写了这不是车规产品,而是实验性研究设备。把它接上一台日常代步车之前,先读完安全边界那一章并用电表验证 silent 引脚,是唯一负责任的顺序。
为什么自动变速箱的 DBC 是空的
这份工具的 ZN6 DBC 定义被拆成 common / manual / automatic 三层 profile,每层显式声明它叠加哪些 DBC 文件、以及是否加载 candidate 条目。空文件是有意保留的一种状态。
| 层/文件 | 内容 | 是否加载 | 证据状态 |
|---|---|---|---|
zn6_gen1_common.dbc |
已发布信号,基于 MIT 授权的 FT86 Gen1 map 与 RaceChrono 映射 | 三个 profile 共同底层 | published,含测试向量 |
zn6_gen1_mt.dbc |
手动挡专有部分 | 由 MT profile 叠加加载 | published |
zn6_gen1_at.dbc |
自动挡专有部分 | 由 AT profile 叠加加载 | 目前为空,刻意不出表 |
zn6_gen1_at_inventory.toml |
仅登记存在性与标称速率,不断言任何位布局 | 独立引用,来源为 Toyobaru CAN ID map | 6 个 ID:328/329/330 均 100 Hz、872 为 20 Hz、977 为 8 Hz、1218 为 1 Hz |
evidence.toml |
13 条逐信号证据,含来源 URL、车型变体、观测量与测试向量 | 始终随定义引用 | 12 条 published + 1 条 candidate |
AT DBC 空着不是因为没人做,而是源于一条明确写进文档的原则:看起来合理却是编造出来的字段,比明确标注「未知」更糟。因此 include_candidates 默认 false,candidate 级别的条目(例如 ID 865 那个未经验证的三位挡位字段)不会被加载,除非显式要求。
这套结构的直接推论是:evidence.toml 里的每一行都带车型变体限定,比如车门与尾箱的标志位分配只在右舵车上验证过、安全带只有驾驶员侧测过而乘客侧行为未知。把 published 当成「全变体通用」而不加甄别地套用,左舵车的车门信号就会错位。
九个诊断查询的参数与限速
诊断目录是整套工具里最容易被低估的部分:它把每个请求的预算写死了,包括超时与轮询上限,而不是靠调用方自觉。
| 查询 | service / 参数 | 解码方式 | timeout / max_hz | 置信度 |
|---|---|---|---|---|
| 车速 | 1 / PID 13 | linear_u8,offset 2,factor 1.0 | 250 ms / 2.0 Hz | published |
| 发动机转速 | 1 / PID 12 | linear_u16_be,factor 0.25 | 250 ms / 2.0 Hz | published |
| 冷却液温度 | 1 / PID 5 | linear_u8,bias −40 | 250 ms | published |
| 节气门位置 | 1 / PID 17 | linear_u8,factor 0.3921568627 | 250 ms / 2.0 Hz | published |
| 控制模块电压 | 1 / PID 66 | linear_u16_be,factor 0.001 | 250 ms / 1.0 Hz | published |
| VIN | 9 / PID 2 | ascii,offset 3,length 17 | 750 ms / 0.2 Hz | published |
| 存储故障码 | 3 / 无参数 | trouble_codes,offset 1 | 750 ms / 0.2 Hz | published |
| 机油温度 | 33(Mode 21)/ PID 1 | linear_u8,bias −40 | 400 ms / 1.0 Hz | candidate,opt_in |
| 变速箱油温裸值 | 33(Mode 21)/ PID 130 | raw,offset 2 | 400 ms / 1.0 Hz | candidate,opt_in |
请求 ID 统一为 2016、响应为 2024,即 0x7E0 / 0x7E8 这一对标准 OBD 地址。真正的判别价值在中间两列:四个 PID 用 250 ms 超时、400 ms 给 Mode 21,而 VIN 与故障码给到 750 ms 并把轮询压到 0.2 Hz。这个分配隐含一个判断—— identification 类请求慢且贵,只能偶尔问;物理量类请求便宜,但也不能无上限。自己做轮询调度时,这份表是最省事的初始值。
另外两个 Toyota Mode 21 查询都带 opt_in = true 且标记 candidate。它们的 expected_prefix 是十进制的 [97, 1] 与 [97, 130],正响应前缀落在 Mode 21 的规则内;但把 raw 类型的 ATT 温度直接做成仪表读数是不合适的,它连缩放系数都没有。
常见问题
这套工具能在实车上发送 CAN 帧吗?
不能。固件跑控制器 listen-only 模式并保持收发器 silent 引脚有效,主机 CLI、Web 应用、SocketCAN 适配器、wire protocol 与 MCP server 都没有任意发送命令,且 Host 只用 can_decode 的解码面。当前 S3/C6 实体发布包是采集专用,实体诊断发送要等板级 ARM 与 fail-silent 电气测试。
为什么自动挡的 DBC 文件是空的?
这是一个刻意的选择。作者认为看起来合理却是编造的字段比明确标注未知更危险,因此 zn6_gen1_at_inventory.toml 只登记自动挡报文的存在性与标称速率(328/329/330 为 100 Hz、872 为 20 Hz、977 为 8 Hz、1218 为 1 Hz),不断言位布局;真正的信号定义要等到有可辩护的定义与测试向量再进 DBC。
candidate 级别的信号默认会参与解码吗?
不会。三个 profile 的 include_candidates 都是 false,Candidate 条目需要显式请求才加载。目前 evidence.toml 的 13 条里只有 1 条是 candidate——ID 865 那个未经验证的三位挡位字段,其余 12 条为 published。
贡献一份新的信号定义需要提供什么?
来源、车型变体、观测记录与测试向量,四项缺一不可。并且面向在车控制、刷写、写诊断或 ECU 仿真的改动明确不在接收范围内——这条贡献禁令与前述四层只读约束是一致的。
延伸阅读
- UDS 诊断工具为什么不能随手调:只读、会话与写 ECU 的分权设计 —— 为什么「只读」要在四个层次分别落地
- OBD-II PID 入门:车速 0x0D 为什么是整数 —— PID 13 与 PID 12 的解码差异从这里补起
- 84% 的 PID 没有公开证据:OBD 私有协议解析的现实边界 —— 为什么 Mode 21 查询只能是 candidate
- 2022 GR86 / BRZ 的 CAN 数据地图:ASC 与 DCM 口 —— 同为 FT86 平台的公开地图,可对照 ID 划分
参考资料
- 项目 01 ——
public-can-dbc-datasets/additional/dimitri-canlab-zn6/README.md(read-first 定位、ESP32-S3/C6 与 TJA1051T/3 收发器、listen-only 与 silent 引脚、无任意发送命令、capture-only 实体发布、诊断 TX 待测试、capture 的四种输入源、Rust 1.96 与 2024 edition、MIT OR Apache-2.0) - 项目 01 ——
public-can-dbc-datasets/additional/dimitri-canlab-zn6/docs/definitions.md(common/manual/automatic 三层 profile、candidate 不默认加载、AT 清单仅登记存在与速率、AT DBC 保持为空的原则、Host 只用 decode-only 门面) - 项目 01 ——
public-can-dbc-datasets/additional/dimitri-canlab-zn6/definitions/zn6_gen1_at_inventory.toml、definitions/evidence.toml、definitions/diagnostics.toml(6 个 AT ID 与标称速率、13 条证据的置信分布、9 个诊断查询的 service、参数、解码器、timeout_ms 与 max_hz)
免责声明
本文所述工具行为、定义分层与诊断参数均来自公开开源仓库的说明与配置文件,属社区研究产物,未经实车独立验证,也不代表车辆制造商的官方数据。该项目自我定位为实验性研究设备而非车规产品。涉及在用车接入的操作请以官方资料与实际测量为准。
更新记录
- 2026-10-14 初稿
发表回复