3. APDU结构详解:启动字符、APDU长度、控制域类型(I帧/S帧/U帧)、ASDU结构
好,咱们今天来啃一块硬骨头——APDU结构。说实话,我刚接触IEC104时,看到这一堆帧类型、控制域、ASDU,头都大了。但后来我发现,只要搞懂APDU这个“信封”是怎么封装的,后面所有报文解析都一通百通。
APDU的全称是Application Protocol Data Unit,应用协议数据单元。你可以把它想象成一个快递包裹。这个包裹有固定的封装格式,里面装的是我们要传输的数据。
APDU = APCI(应用协议控制信息)+ ASDU(应用服务数据单元)
APCI是信封,ASDU是信纸。没有信封,信纸寄不出去;没有信纸,信封就是空的。
3.1 启动字符:0x68,一个字节定乾坤
每个APDU的第一个字节,固定是0x68。为什么是0x68?这是IEC标准定的,咱们记住就行。
我在项目中遇到过一个问题:有个新同事抓包分析,发现报文开头是0x68,但后面解析总出错。我过去一看,原来他把0x68当成了数据内容,没意识到这是启动字符。嗯,这里要注意——启动字符就是报文的“身份证”,看到0x68,你就知道一个APDU开始了。
小技巧:抓包时,如果看到连续多个0x68,说明有多个APDU连续发送。每个0x68都是一个新报文的开始。
3.2 APDU长度:别小看这一个字节
启动字符后面紧跟着APDU长度字段,也是1个字节。它表示从启动字符之后到APDU结束的总字节数。
说白了,这个长度值 = APCI剩余部分 + ASDU的总长度。注意,它不包括启动字符本身和长度字段自己。
| 字段 | 字节数 | 说明 |
|---|---|---|
| 启动字符 | 1 | 固定0x68 |
| APDU长度 | 1 | 后续字节数(不含前2字节) |
| 控制域 | 4 | I帧/S帧/U帧标识 |
| ASDU | 可变 | 实际数据内容 |
举个例子:如果APDU长度是0x0A(10),那意味着从控制域开始到ASDU结束,一共10个字节。控制域占4个,ASDU就是6个字节。
注意:APDU长度最大是0xFF(255),但实际中很少超过200。因为IEC104底层是TCP,报文太长会影响实时性。我在储能站调试时,遥测报文一般就30-50字节,够用了。
3.3 控制域类型:I帧、S帧、U帧,三兄弟各司其职
控制域占4个字节,它决定了这个APDU是干什么用的。IEC104定义了三种帧类型,我习惯叫它们“三兄弟”。
3.3.1 I帧(信息传输帧)
I帧是干活的主力。它携带ASDU,用来传输遥测、遥信、遥控等实际数据。I帧的控制域里有两个关键数字:发送序号和接收序号。
- 发送序号(N(S)):我发了多少帧出去
- 接收序号(N(R)):我收到了多少帧
你想想看,这两个序号就像快递单号。我发一个I帧,告诉你“这是我发的第5个包裹”,同时告诉你“你的第3个包裹我收到了”。这样双方都知道对方的状态,不会丢包。
我曾经在储能站调试时,发现遥测数据偶尔会跳变。抓包一看,原来是I帧的发送序号乱了,从站收到了重复的帧。嗯,这就是典型的序号管理问题。
3.3.2 S帧(监视帧)
S帧不携带ASDU,它只做一件事:确认收到。S帧的控制域里只有接收序号,没有发送序号。
说白了,S帧就是“我收到了,你放心”的信号。它不传数据,所以报文很短,只有6个字节(启动字符+长度+4字节控制域)。
实战经验:在储能站中,如果主站和从站之间网络延迟大,S帧会频繁出现。因为从站收到I帧后,需要尽快回复确认,否则主站会超时重发。我建议S帧的回复时间不要超过100ms。
3.3.3 U帧(未编号帧)
U帧是“特殊任务”帧,用于建立连接、测试链路、关闭连接。它没有序号,只有三个功能位:
- STARTDT:启动数据传输
- STOPDT:停止数据传输
- TESTFR:测试链路是否正常
U帧也不带ASDU,长度和S帧一样,6个字节。我记得有一次,储能站和调度中心通信中断,我发了一个TESTFR帧过去,对方没回复。嗯,那就是链路断了,直接排查网络吧。
3.4 ASDU结构:数据到底长什么样
ASDU是APDU的核心,所有实际数据都在这里。ASDU的结构比较复杂,我拆开来讲。
3.4.1 数据单元标识
ASDU的开头是数据单元标识,包含:
- 类型标识:1个字节,告诉你是遥测(0x09)、遥信(0x01)、遥控(0x2D)还是其他
- 可变结构限定词:1个字节,表示数据个数和排列方式
- 传送原因:2个字节,说明为什么发这个数据(周期上传、突发变化、总召唤等)
- 公共地址:2个字节,标识是哪个设备发的
举个例子,遥测报文的类型标识是0x09,传送原因是0x03(突发上传)。我在储能站调试时,经常看到遥测数据是周期上传(传送原因0x01),但电池温度突变时会变成突发上传(0x03)。
3.4.2 信息体
信息体是ASDU的“正文”,包含具体的数据值。每个信息体由信息对象地址、信息元素、品质描述符(可选)组成。
| 字段 | 字节数 | 说明 |
|---|---|---|
| 信息对象地址 | 3 | 标识哪个测点(如电池电压、SOC) |
| 信息元素 | 可变 | 实际数值(如电压值、开关状态) |
| 品质描述符 | 1 | 数据是否有效、是否被取代等 |
品质描述符这个字段,很多人会忽略。但我吃过亏——有一次遥测数据看起来正常,但品质描述符显示“无效”,说明传感器已经坏了。如果不检查这个字段,你会被假数据骗了。
3.5 一张图看懂APDU
下面我用SVG画一张APDU结构图,把刚才讲的内容串起来。
3.6 实战中的APDU解析
说了这么多理论,咱们来点实际的。假设你抓到一个报文:
68 0E 00 00 00 00 09 03 03 00 01 00 00 00 01 40
我来带你一步步解析:
- 0x68:启动字符,确认是APDU
- 0x0E:APDU长度=14,后面有14个字节
- 00 00 00 00:控制域,全是0,说明是I帧,发送序号和接收序号都是0
- 0x09:类型标识=9,遥测报文
- 0x03:可变结构限定词,表示有3个数据
- 03 00:传送原因=3,突发上传
- 01 00:公共地址=1,设备1号
- 00 00 00:信息对象地址=0,第一个测点
- 01 40:信息元素,数值=0x4001(具体含义看协议映射)
你看,是不是很简单?我在储能站调试时,每天都要看几十个这样的报文。刚开始觉得眼花,后来习惯了,一眼就能看出问题。
我的习惯:解析APDU时,先看控制域确定帧类型,再看ASDU的类型标识确定数据内容。这样不会乱。另外,我建议用Wireshark的IEC104插件,它能自动解析,省很多事。
3.7 避坑指南
最后,分享几个我踩过的坑:
- APDU长度算错:我曾经写程序时,把启动字符和长度字段也算进去了,结果从站一直报错。记住,长度字段只算后面的字节。
- 控制域字节序:IEC104是大端序,但有些设备是小端序。我遇到过设备发过来的控制域是反的,解析出来序号全乱。嗯,这个要特别注意。
- ASDU的公共地址:在储能站中,一个主站可能管理几十个从站。公共地址一定要配对,否则数据会串。我见过一个项目,两个电池簇的地址配反了,遥测数据全乱套。
好了,APDU结构就讲到这里。记住这个“信封+信纸”的模型,后面学报文交互就轻松多了。