2. DoIP消息结构:DoIP消息头格式、Payload类型详解、路由激活与诊断消息、车辆发现与声明
好,咱们进入正题。DoIP协议说白了就是一套“车联网上的对话规则”。你想想看,诊断仪和ECU之间要通信,总得有个统一的格式吧?不然你说东它听西,那不乱套了。
我个人习惯,在讲任何协议之前,先看它的“信封”长什么样。DoIP的消息结构,核心就是那个固定的消息头。搞懂了它,后面的Payload类型、路由激活、车辆发现,其实都是在这个信封里装不同的信纸而已。
2.1 DoIP消息头格式
先看消息头。DoIP的头部是固定的8个字节,不多不少。我刚开始接触时也觉得奇怪,为什么是8字节?后来发现,这8字节刚好能把“谁发的、发给谁、多长、什么类型”说清楚。
| 字段 | 长度(字节) | 说明 |
|---|---|---|
| 协议版本 | 1 | 当前固定为0x02(ISO 13400-2:2012) |
| 逆协议版本 | 1 | 取反,用于校验,0xFD |
| Payload类型 | 2 | 标识消息用途,比如0x0001是车辆声明 |
| Payload长度 | 4 | 后面跟着的数据总长度,单位字节 |
嗯,这里要注意。逆协议版本这个字段,很多人会忽略。我曾经在项目联调时,发现诊断仪死活收不到ECU的响应。查了半天,原来是ECU发的逆协议版本算错了。说白了,这就是个简单的校验,但少了它,协议栈直接就把包丢了。
2.2 Payload类型详解
消息头里的Payload类型字段,决定了后面跟着的数据是什么。我把它分成三大类,你记牢了:
- 通用DoIP消息(0x0000 - 0x3FFF):包括车辆发现、路由激活、诊断消息等核心功能。
- 诊断消息(0x8001 - 0x8002):UDS诊断请求和响应就走这里。
- 其他扩展类型:比如0x4000用于事件通知,0x6xxx用于安全相关。
举个例子,Payload类型0x0001是“车辆声明消息”。当ECU上电后,它会主动广播这个消息,告诉网络上的诊断仪:“我在这儿,这是我的VIN码和逻辑地址。” 说白了,就是ECU在喊:“我来了,快来连我!”
2.3 路由激活与诊断消息
路由激活,是DoIP里最关键的握手过程。为什么需要它?因为诊断仪和ECU之间,不能上来就发诊断请求。你得先告诉ECU:“我要激活你,给我一个逻辑地址。”
流程是这样的:
- 诊断仪发送路由激活请求(Payload类型0x0005)。
- ECU收到后,检查源地址是否合法。
- 如果合法,ECU返回路由激活响应(Payload类型0x0006),并分配一个逻辑地址。
- 之后,诊断仪就可以用这个逻辑地址发送诊断消息了。
我记得有一次,客户反馈说诊断仪连不上ECU。我抓包一看,路由激活请求发过去了,但ECU返回了0x06(未知源地址)。原来是诊断仪用的源地址和ECU配置的不一致。说白了,就是“门牌号对不上”。
诊断消息本身,Payload类型是0x8001(诊断请求)和0x8002(诊断响应)。数据部分就是标准的UDS报文。比如你要读ECU的DTC,就发一个0x19 0x02的UDS请求,封装在DoIP的Payload里。
2.4 车辆发现与声明
车辆发现,是DoIP里最“热闹”的部分。想象一下,你拿着诊断仪走进停车场,怎么知道哪辆车支持DoIP?靠的就是“车辆发现”机制。
具体流程:
- 车辆声明(0x0001):ECU上电后,主动广播一条消息,包含VIN码、逻辑地址、EID(实体ID)等信息。诊断仪收到后,就知道这辆车在哪儿了。
- 车辆识别请求(0x0002):诊断仪也可以主动发一个广播,问“谁在?” 符合条件的ECU会回复车辆声明。
- 车辆识别响应(0x0003):针对特定VIN或EID的查询,ECU会单播回复。
我个人觉得,车辆声明是最实用的。你想想看,如果每辆车都要诊断仪去轮询,那效率多低。ECU主动广播,诊断仪被动接收,这才是“车联网”该有的样子。
好了,DoIP的消息结构就这些。消息头是骨架,Payload类型是血肉,路由激活和车辆发现是灵魂。搞懂了这些,你就能看懂DoIP的每一帧数据了。下一章,咱们聊聊怎么用Python把这些消息发出去。