3、DoIP车辆发现机制:VIN请求、路由激活、车辆声明报文解析
好,咱们进入DoIP最核心也最有趣的部分——车辆发现机制。
说实话,CAN诊断时代我们基本不考虑“发现”这件事。你拿个诊断仪,OBD口一插,CAN总线上发个请求,ECU就回了。简单粗暴。但DoIP不一样,它跑在以太网上,IP地址是动态分配的,你得先找到车在哪。
我个人习惯把DoIP车辆发现拆成三个关键动作:VIN请求、路由激活、车辆声明报文。这三个动作串起来,就是一辆车从“网络上的一个IP”变成“可诊断的目标”的全过程。
3.1 车辆声明报文:车在喊“我在这”
先讲车辆声明报文,因为它是整个发现机制的起点。
你想想看,一辆支持DoIP的车,它一上电,或者一接入网络,它得让诊断仪知道自己的存在。怎么知道?它主动发一个广播报文,告诉整个网络:“我在这,这是我的VIN,这是我的逻辑地址。”
这个报文就叫车辆声明报文(Vehicle Announcement Message)。
关键点:车辆声明报文是UDP广播,目标端口是UDP 13400。诊断仪不需要先发请求,车自己就会发。
我在项目中遇到过一个问题:某款T-Box在休眠唤醒后,车辆声明报文发得太快,导致诊断仪还没完成网络初始化就收到了,结果丢包。后来我们加了个延迟,上电后等500ms再发,问题就解决了。
车辆声明报文的结构,我列一下关键字段:
| 字段 | 长度 | 说明 |
|---|---|---|
| 源地址 | 2字节 | 车辆自身的逻辑地址(通常是0x0E80) |
| 目标地址 | 2字节 | 广播地址(0x0000) |
| VIN | 17字节 | 车辆识别码,ASCII编码 |
| 逻辑地址 | 2字节 | 车辆网关的DoIP实体逻辑地址 |
| EID | 6字节 | 以太网标识符(通常是MAC地址) |
| GID | 6字节 | 组标识符(可选) |
| 进一步动作标志 | 1字节 | 指示是否需要路由激活 |
嗯,这里要注意:VIN字段是17字节,但有些车厂会填不满,用空格补齐。我见过一个坑——某供应商把VIN填了16字节加一个换行符,结果诊断仪解析时直接报错。所以解析时一定要按ISO 13400规范严格处理。
3.2 VIN请求:诊断仪主动问“你是谁”
车辆声明报文是车主动发的,但诊断仪不一定总能收到。比如车先上电,诊断仪后接入网络,那声明报文可能已经发过了。这时候诊断仪就得主动问。
VIN请求,说白了就是诊断仪发一个UDP请求,问网络上的DoIP实体:“报上你的VIN来。”
我的经验:VIN请求报文的目标端口是UDP 13400,源端口任意。请求本身不带任何负载数据,就是一个DoIP头部,Payload Type设为0x0001(VIN请求)。
车收到VIN请求后,会回复一个VIN响应报文。这个响应报文和车辆声明报文的结构几乎一样,区别在于它是单播的,只发给请求的诊断仪。
我建议你在做测试时,先发一个VIN请求确认车辆在线,再走后续流程。别一上来就发诊断请求,万一车没上线,你等超时都等半天。
3.3 路由激活:建立诊断通道
好,现在诊断仪知道了车的VIN,也知道车的IP和逻辑地址。但能不能直接发诊断请求?不行。
DoIP有一个安全机制——路由激活。说白了,你得先跟车网关打个招呼:“我要开始诊断了,请给我开个通道。”
路由激活的流程是这样的:
- 诊断仪发送路由激活请求到车辆网关(UDP或TCP,取决于实现)
- 车辆网关检查请求中的源逻辑地址是否合法
- 如果合法,网关回复路由激活响应,状态码为0x10(成功)
- 之后,诊断仪和车辆网关之间建立TCP连接,后续诊断走TCP
注意:路由激活请求中必须包含诊断仪的逻辑地址。这个地址需要和OEM协商好,不能乱填。我曾经见过一个测试工程师随便填了个0x0001,结果网关直接拒绝,状态码返回0x02(未知源地址)。
路由激活响应报文的关键字段:
| 字段 | 长度 | 说明 |
|---|---|---|
| 源地址 | 2字节 | 车辆网关的逻辑地址 |
| 目标地址 | 2字节 | 诊断仪的逻辑地址 |
| 状态码 | 1字节 | 0x10成功,其他为失败 |
| 客户端逻辑地址 | 2字节 | 确认的诊断仪地址 |
| 进一步动作标志 | 1字节 | 指示后续是否需要额外认证 |
状态码这块我吃过亏。有一次现场测试,路由激活总是返回0x11(成功但需要进一步认证)。查了半天,发现是网关配置了安全访问策略,必须走完TLS握手才能继续。所以,如果你遇到0x11,别慌,看看是不是需要证书交换。
3.4 三个动作的完整时序
把上面三个动作串起来,一个典型的DoIP车辆发现时序是这样的:
1. 车辆上电 → 发送车辆声明报文(UDP广播)
2. 诊断仪接入网络 → 发送VIN请求(UDP单播)
3. 车辆回复VIN响应(UDP单播)
4. 诊断仪发送路由激活请求(UDP或TCP)
5. 车辆回复路由激活响应(状态码0x10)
6. TCP连接建立 → 开始诊断通信
你可能会问:如果车辆声明报文和VIN请求同时发生怎么办?嗯,实际项目中确实会遇到。我记得有一次在台架上测试,诊断仪和T-Box同时上电,两边几乎同时发了报文。结果诊断仪收到了车辆声明,但VIN请求的响应丢了。后来我们在诊断仪侧加了重传机制,VIN请求超时500ms没收到响应就重发一次,问题就解决了。
3.5 避坑指南
最后,我总结几个实际项目中容易踩的坑:
- UDP广播域问题:车辆声明报文是广播,但如果诊断仪和车辆不在同一个VLAN,广播可能过不去。我曾经在现场排查了一整天,最后发现是交换机隔离了广播域。
- 逻辑地址冲突:多台诊断仪同时连同一辆车时,逻辑地址不能重复。ISO 13400规定每个诊断仪必须有唯一的逻辑地址。
- 路由激活超时:路由激活成功后,如果诊断仪在5秒内没有发起任何诊断请求,网关可能会自动断开连接。这是安全策略,别问我怎么知道的——我被断开过好多次。
- VIN解析:VIN是ASCII编码,但有些实现会用UTF-8或者带BOM。解析时最好按字节处理,别用字符串函数直接转。
好了,DoIP车辆发现机制就讲到这里。说白了,就是车主动喊一声,诊断仪再确认一下,然后双方握个手,通道就开了。下一章咱们聊诊断通信的具体报文格式,那个更有意思。