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 诊断仪发现流程:从搜索到连接

诊断仪怎么找到车?流程其实很清晰,我画了一张图帮你理解。

DoIP 诊断仪发现流程 诊断仪发现车辆流程 诊断仪 车辆(DoIP实体) 1. 上电/连接触发 2. 发送 Vehicle Announcement UDP 广播 (端口 13400) 3. 接收声明报文 4. 解析 VIN/EID/GID 5. 发送路由激活请求 TCP 连接 (端口 13400) 6. 响应路由激活 7. 建立诊断逻辑连接 TCP 双向通信 说明:诊断仪也可主动发送“车辆识别请求”广播,车辆收到后立即回复声明报文。

流程其实不复杂,我拆成几步讲:

  1. 车辆上线:车辆上电或网络连接建立,触发 Vehicle Announcement 广播。
  2. 诊断仪监听:诊断仪在 UDP 13400 端口监听,收到声明报文后,解析出 VIN、EID、GID。
  3. 选择目标:诊断仪根据 VIN 或 EID 选择要连接的车辆。如果有多辆车,可以靠 GID 过滤。
  4. 建立 TCP 连接:诊断仪向车辆的 IP 地址发起 TCP 连接,目标端口也是 13400。
  5. 路由激活: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 广播,不保证可靠传输。诊断仪不能完全依赖被动发现,一定要实现主动发现机制作为兜底。