2. DoIP节点发现与路由:车辆声明报文(VAN)、路由激活请求/响应、诊断电源模式、DoIP实体状态机
好,咱们进入第二章。这一章讲的是DoIP通信的“敲门砖”——节点发现和路由激活。说白了,就是你的诊断仪怎么找到车上的ECU,以及怎么跟它建立一条能说话的通道。
我个人习惯把这一章叫做“握手三部曲”。你想想看,两个设备要通信,总得先打个招呼,确认一下身份,再商量好怎么聊吧?DoIP也是这个道理。咱们一步步拆开看。
2.1 车辆声明报文(VAN)——ECU的“自我介绍”
车辆声明报文,英文叫Vehicle Announcement,简称VAN。这是DoIP实体(也就是车上的ECU)上线后干的第一件事。
它什么时候发?
- ECU上电,DoIP协议栈初始化完成
- 网络链路从断开变为连接(比如网线插上了)
- 收到诊断仪的“车辆识别请求”(Vehicle Identification Request)
报文长什么样?
VAN报文是一个UDP广播报文,目标端口是UDP 13400,目标地址是255.255.255.255。它的载荷结构如下:
| 字节偏移 | 字段名 | 长度(字节) | 说明 |
|----------|---------------------|------------|-------------------------------|
| 0 | 协议版本 | 1 | 当前DoIP版本,如0x02 |
| 1 | 反向协议版本 | 1 | 与协议版本相同,用于校验 |
| 2-3 | 载荷类型 | 2 | 0x0004表示车辆声明 |
| 4-7 | 载荷长度 | 4 | 后续数据的长度 |
| 8-11 | VIN(车辆识别码) | 4 | 实际VIN为17字节,这里存前4字节 |
| ... | ... | ... | ... |
嗯,这里要注意:VAN报文里携带的是完整的17字节VIN码、EID(逻辑地址)和GID(组地址)。诊断仪收到后,就能知道车上挂了哪些ECU。
2.2 路由激活请求/响应——建立诊断通道
找到ECU之后,下一步就是激活路由。这一步很关键,它决定了你能不能往ECU发诊断请求。
路由激活请求(Routing Activation Request)
诊断仪发一个TCP报文给ECU,目标端口是13400。报文里包含:
- 源地址:诊断仪的逻辑地址(比如0x0E80)
- 目标地址:目标ECU的逻辑地址(比如0x0001)
- 激活类型:0x01表示“默认路由激活”,0x02表示“带证书的激活”
路由激活响应(Routing Activation Response)
ECU收到请求后,会检查激活类型是否支持。如果没问题,就返回一个响应:
| 字段 | 值示例 | 说明 |
|-------------------|------------|-------------------------------|
| 协议版本 | 0x02 | |
| 反向协议版本 | 0x02 | |
| 载荷类型 | 0x0005 | 路由激活响应 |
| 载荷长度 | 0x00000007 | 后续7字节 |
| 客户端逻辑地址 | 0x0E80 | 诊断仪的地址 |
| 激活类型 | 0x01 | 默认激活 |
| 响应码 | 0x10 | 0x10=成功,0x11=拒绝 |
| 保留 | 0x00 | |
2.3 诊断电源模式——ECU的“清醒状态”
ECU不是随时都能响应诊断的。它有自己的电源模式,说白了就是“清醒”还是“睡觉”。
DoIP协议里定义了四种电源模式:
| 模式编号 | 模式名称 | 说明 |
|---|---|---|
| 0x00 | Not Ready | ECU刚上电,还没准备好 |
| 0x01 | Ready | ECU正常工作,可以响应诊断 |
| 0x02 | Not Ready(休眠中) | ECU处于低功耗模式,不响应诊断 |
| 0x03 | Transition | ECU正在切换模式,暂时不可用 |
你想想看,如果ECU在休眠状态,你发诊断请求过去,它根本不理你。所以,做压力测试前,一定要确认ECU处于Ready模式。
2.4 DoIP实体状态机——ECU的“生命周期”
每个DoIP实体内部都有一个状态机,管理着它的生命周期。这个状态机有以下几个状态:
- 初始化(Initialization):ECU上电,协议栈初始化
- 未激活(Inactive):初始化完成,但还没收到路由激活请求
- 已激活(Active):路由激活成功,可以收发诊断消息
- 休眠(Sleep):ECU进入低功耗模式
- 错误(Error):发生严重错误,需要复位
状态之间的转换条件,我列一下:
- 初始化完成后,自动进入未激活状态
- 收到有效的路由激活请求,进入已激活状态
- 长时间无活动(比如30秒),进入休眠状态
- 收到唤醒报文,从休眠回到未激活状态
- 发生协议错误,进入错误状态,然后自动复位
我个人习惯在压力测试脚本里,先读取ECU的当前状态,确认是Active再发诊断请求。这样可以避免很多不必要的超时。
好了,这一章的内容就这些。节点发现、路由激活、电源模式、状态机——这四个概念是DoIP通信的基础。你把这些搞清楚了,后面的压力测试才能有的放矢。
下一章,咱们聊聊诊断消息的封装和传输,也就是怎么把UDS请求塞进DoIP报文里。到时候见。