4、DoIP车辆声明与发现机制:VIN/GID/EID的生成规则、车辆声明报文(Vehicle Announcement)的触发条件与周期、诊断仪发现流程。
各位工程师,咱们今天聊点实在的。DoIP 诊断的第一步,说白了就是“找到车”。你拿着诊断仪,连上以太网,怎么知道哪辆车在线上?它的 VIN 是什么?支持哪些诊断功能?这就是车辆声明与发现机制要解决的问题。
我在项目里见过不少同事,上来就调 DoIP 通信,结果发现诊断仪死活连不上车。查了半天,原来是车辆声明报文没发出来,或者 VIN 格式不对。嗯,这些坑咱们今天一个个填上。
4.1 车辆标识的三把钥匙:VIN、EID、GID
DoIP 协议里,车辆用三个标识符来“自我介绍”。我习惯把它们比作身份证、临时工牌和团队编号。
| 标识符 | 全称 | 长度 | 生成规则 | 作用 |
|---|---|---|---|---|
| VIN | 车辆识别码 | 17 字节 | 符合 ISO 3779,由制造商、车型、年份等编码组成 | 全球唯一,车辆“身份证” |
| EID | 实体标识符 | 6 字节 | 通常基于 MAC 地址或芯片唯一序列号生成 | ECU 硬件唯一标识,VIN 未知时使用 |
| GID | 组标识符 | 6 字节 | 由制造商自定义,可关联车型、项目或产线 | 逻辑分组,用于筛选同类车辆 |
关键点:VIN 是最终标识,但车辆在未配置 VIN 时(比如产线末端),必须靠 EID 或 GID 来被发现。我遇到过产线场景,车辆刚下线还没写 VIN,诊断仪就是靠 EID 找到它的。
4.2 车辆声明报文:Vehicle Announcement
车辆声明报文,就是车在网络上“喊一嗓子”:“我在这里!这是我的 VIN/EID/GID!”
4.2.1 报文结构
报文通过 UDP 广播发送,目标端口是 UDP 13400。结构如下:
| 字节偏移 | 字段名 | 长度(字节) | 说明 |
|----------|----------------|------------|------------------------------|
| 0 | 协议版本 | 1 | 当前为 0x02 (ISO 13400-2) |
| 1 | 协议版本反转 | 1 | 0xFD (用于版本校验) |
| 2-3 | 负载类型 | 2 | 0x0004 (车辆声明) |
| 4-7 | 负载长度 | 4 | 后续数据长度 |
| 8-9 | VIN 有效标志 | 2 | 0x0000=无效, 0x0001=有效 |
| 10-11 | 逻辑地址 | 2 | 车辆网关的逻辑地址 |
| 12-17 | EID | 6 | 实体标识符 |
| 18-23 | GID | 6 | 组标识符 |
| 24-40 | VIN | 17 | 车辆识别码(可能全 0) |
| 41-42 | 保留 | 2 | 填充 0x0000 |
我的习惯:调试时先用 Wireshark 抓包,过滤 udp.port == 13400 && doip.payloadtype == 0x0004,一眼就能看到车辆声明报文。如果 VIN 字段全是 0,说明车辆还没配置 VIN,这时候 EID 就是关键。
4.2.2 触发条件与周期
车辆声明报文不是一直发的,它有明确的触发条件。我总结了一下:
- 上电启动:车辆网关或 DoIP 实体上电后,立即发送一次。这是最常见的触发场景。
- 网络连接建立:当车辆检测到物理链路层连接建立(比如插上网线),会触发一次声明。
- VIN 变更:如果 VIN 被重新配置(比如产线刷写),车辆会主动发送一次更新后的声明。
- 周期性重发:默认情况下,车辆声明报文会以 3 秒 为周期重复发送,持续发送 3 次。这是为了应对诊断仪可能错过第一次广播的情况。
注意:周期重发不是无限持续的。ISO 13400 规定,车辆在发送完 3 次声明后,如果没有收到诊断仪的连接请求,就会停止发送,进入静默状态。我曾经遇到一个 bug,车辆只发了一次声明就停了,诊断仪在 3 秒后才上线,结果就找不到车了。解决方案是让车辆在检测到新的诊断仪请求时,重新触发声明。
4.3 诊断仪发现流程:从搜索到连接
诊断仪怎么找到车?流程其实很清晰,我画了一张图帮你理解。
流程其实不复杂,我拆成几步讲:
- 车辆上线:车辆上电或网络连接建立,触发 Vehicle Announcement 广播。
- 诊断仪监听:诊断仪在 UDP 13400 端口监听,收到声明报文后,解析出 VIN、EID、GID。
- 选择目标:诊断仪根据 VIN 或 EID 选择要连接的车辆。如果有多辆车,可以靠 GID 过滤。
- 建立 TCP 连接:诊断仪向车辆的 IP 地址发起 TCP 连接,目标端口也是 13400。
- 路由激活:TCP 连接建立后,诊断仪发送“路由激活请求”,车辆确认后,诊断逻辑连接正式建立。
避坑指南:我曾经遇到一个场景,诊断仪发送了路由激活请求,但车辆没有响应。查了半天,发现是车辆防火墙把 TCP 13400 端口给封了。记住,DoIP 通信需要双向放行 UDP 13400 和 TCP 13400。
4.4 主动发现 vs 被动发现
诊断仪发现车辆有两种模式,我习惯叫“等车喊”和“我去找”。
| 模式 | 触发方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|---|
| 被动发现 | 车辆主动发送 Vehicle Announcement | 产线、维修车间(车辆已上电) | 无需诊断仪主动请求,省流量 | 诊断仪可能错过第一次广播 |
| 主动发现 | 诊断仪发送“车辆识别请求”广播 | 诊断仪后上线、网络中有多辆车 | 诊断仪可随时发起,不依赖车辆周期 | 需要诊断仪主动发送请求 |
我个人建议,实际项目中两种模式都支持。诊断仪先等 3 秒,如果没收到声明,就主动发一次请求。这样最稳妥。
4.5 实战中的常见问题
最后,我分享几个我在项目中踩过的坑:
- VIN 全 0:车辆声明报文里 VIN 字段全是 0,但 EID 有效。这种情况通常发生在产线末端,车辆还没刷写 VIN。诊断仪必须靠 EID 来识别。
- 声明报文丢失:车辆只发了一次声明,诊断仪没收到。解决方案是让诊断仪主动发送“车辆识别请求”,强制车辆回复。
- 多车冲突:同一个网络里有多辆车,诊断仪收到多个声明。这时候靠 VIN 或 GID 过滤,选择你要的那一辆。
- 周期重发次数不足:有些实现只发了 1 次声明就停了,不符合 ISO 13400 的 3 次要求。我建议在测试用例里专门验证这个点。
重要提醒:车辆声明报文是 UDP 广播,不保证可靠传输。诊断仪不能完全依赖被动发现,一定要实现主动发现机制作为兜底。