4、车辆发现与声明:VIN/GID/EID的声明机制、车辆发现请求与响应、路由激活过程

好,咱们进入第四章。这一章讲的是DoIP通信里最基础、也最容易踩坑的一环——车辆发现与声明。

你想想看,一台诊断仪连上车载以太网,它怎么知道网线上挂着哪些ECU?这些ECU又怎么告诉诊断仪“我在这儿,这是我的VIN”?这就是车辆发现机制要解决的问题。

我个人习惯把这一章拆成三个部分来讲:标识符声明机制车辆发现请求与响应、以及路由激活过程。咱们一个一个来。

4.1 标识符声明机制:VIN、GID、EID

DoIP协议里定义了三种标识符,用来唯一识别车辆或ECU。说白了,就是给车和ECU发“身份证”。

标识符 全称 长度 作用
VIN Vehicle Identification Number 17字节 车辆唯一身份,全球唯一
GID Group Identification 可变(通常2-6字节) 逻辑分组标识,用于组播场景
EID Entity Identification 6字节 ECU硬件唯一标识,通常是MAC地址

VIN的声明:这是最重要的。网关(DoIP实体)在收到车辆发现请求后,必须回复自己的VIN。我在项目中遇到过一个问题——某台车的网关VIN写死了0xFF,结果诊断仪死活发现不了车辆。排查了半天,发现是产线刷写时VIN没写进去。嗯,这里要注意:VIN必须在车辆下线前正确写入,否则后续所有诊断都连不上。

GID的声明:GID用于逻辑分组。比如你同时诊断多台车,可以用GID把它们分成不同批次。我个人习惯在自动化测试脚本里用GID来区分测试车辆和参考车辆,这样不会搞混。

EID的声明:EID是ECU的硬件ID,通常是MAC地址。DoIP协议规定,EID在车辆上电后必须唯一。我曾经遇到过一个奇葩问题——两台ECU的MAC地址一样,结果网络里疯狂冲突。后来发现是供应商烧录时用了同一个MAC池。所以,EID的分配一定要在硬件设计阶段就规划好。

重要提示:VIN、GID、EID的声明报文,都是通过UDP广播或组播发送的。目标端口是UDP 13400。诊断仪监听这个端口,就能收到所有DoIP实体的声明。

4.2 车辆发现请求与响应

车辆发现的过程,说白了就是诊断仪问一句“谁在?”,车回答“我在,这是我的VIN”。

请求报文结构

字节0-1: 协议版本 (0x02)
字节2-3: 负载类型 (0x0001 表示车辆发现请求)
字节4-7: 负载长度 (0x00000000)

注意,车辆发现请求的负载长度为0,因为不需要额外数据。诊断仪只需要发送这个8字节的UDP报文到组播地址(通常是239.192.0.0/16)。

响应报文结构

字节0-1: 协议版本 (0x02)
字节2-3: 负载类型 (0x0004 表示车辆发现响应)
字节4-7: 负载长度 (0x00000015 = 21字节)
字节8-24: VIN (17字节)
字节25-26: 逻辑地址 (2字节)
字节27-32: EID (6字节)
字节33-34: GID (2字节)
字节35: 进一步动作标志 (1字节)
字节36-37: VIN同步状态 (2字节)

你想想看,诊断仪收到这个响应后,就能知道网线上有哪台车、它的VIN是什么、逻辑地址是多少。这样后续的诊断通信才能建立起来。

实战技巧:在自动化测试中,我建议你写一个UDP监听线程,专门捕获车辆发现响应。然后解析VIN,跟测试用例里的预期VIN做比对。如果对不上,直接报错。这样可以提前发现VIN刷写错误。

4.3 路由激活过程

车辆发现只是第一步。真正要开始诊断通信,还得走路由激活。为什么?因为DoIP协议规定,诊断仪必须先激活一条到目标ECU的路由,才能发送诊断请求。

路由激活的过程,其实就是诊断仪告诉网关:“我要跟逻辑地址为0x0E80的ECU通信,请帮我建立路由。”

路由激活请求

字节0-1: 协议版本 (0x02)
字节2-3: 负载类型 (0x0005 表示路由激活请求)
字节4-7: 负载长度 (0x0000000C = 12字节)
字节8-9: 源逻辑地址 (诊断仪的逻辑地址)
字节10-11: 保留 (0x0000)
字节12-13: 目标逻辑地址 (ECU的逻辑地址)
字节14-19: 保留 (0x000000000000)

路由激活响应

字节0-1: 协议版本 (0x02)
字节2-3: 负载类型 (0x0006 表示路由激活响应)
字节4-7: 负载长度 (0x0000000C = 12字节)
字节8-9: 源逻辑地址 (网关的逻辑地址)
字节10: 响应代码 (0x10 表示成功)
字节11: 保留 (0x00)
字节12-13: 目标逻辑地址 (ECU的逻辑地址)
字节14-19: 保留 (0x000000000000)

响应代码是关键。0x10表示成功,0x11表示拒绝(比如诊断仪未授权),0x12表示目标ECU不可达。

避坑指南:我曾经在测试中发现,路由激活请求发出去后,网关一直不回响应。排查了半天,发现是诊断仪的源逻辑地址跟网关配置的白名单不匹配。网关一看“这个地址我不认识”,直接丢弃了请求。所以,路由激活前一定要确认诊断仪的逻辑地址在网关的白名单里。

路由激活成功后,诊断仪就可以通过TCP连接发送诊断请求了。注意,路由激活是基于UDP的,但后续的诊断通信是基于TCP的。这个切换很多人会忽略。

我个人习惯在自动化测试脚本里,把路由激活单独封装成一个函数。每次测试开始前,先调用这个函数激活路由。如果激活失败,直接跳过后续所有测试用例,并记录失败原因。这样可以避免因为路由问题导致大量误报。

好了,这一章的内容就这些。总结一下:

  • VIN、GID、EID是DoIP实体的三种标识符,各有各的用途
  • 车辆发现请求是UDP广播,响应里包含VIN、逻辑地址等信息
  • 路由激活是建立诊断通信的前提,响应代码决定了是否成功

下一章我们会讲诊断通信的具体流程,包括TCP连接的建立和诊断报文的封装。到时候见。