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结构图,把刚才讲的内容串起来。

APDU结构总览 APDU(应用协议数据单元) APCI(应用协议控制信息) ASDU(应用服务数据单元) 启动字符 0x68 APDU长度 1字节 控制域 4字节 I帧(信息帧) S帧(监视帧) U帧(未编号帧) 数据单元标识 类型/原因/地址 信息体 地址+数值+品质 类型标识 可变结构 传送原因 公共地址 对象地址 信息元素 品质描述 APCI字段 ASDU字段 帧类型

3.6 实战中的APDU解析

说了这么多理论,咱们来点实际的。假设你抓到一个报文:

68 0E 00 00 00 00 09 03 03 00 01 00 00 00 01 40

我来带你一步步解析:

  1. 0x68:启动字符,确认是APDU
  2. 0x0E:APDU长度=14,后面有14个字节
  3. 00 00 00 00:控制域,全是0,说明是I帧,发送序号和接收序号都是0
  4. 0x09:类型标识=9,遥测报文
  5. 0x03:可变结构限定词,表示有3个数据
  6. 03 00:传送原因=3,突发上传
  7. 01 00:公共地址=1,设备1号
  8. 00 00 00:信息对象地址=0,第一个测点
  9. 01 40:信息元素,数值=0x4001(具体含义看协议映射)

你看,是不是很简单?我在储能站调试时,每天都要看几十个这样的报文。刚开始觉得眼花,后来习惯了,一眼就能看出问题。

我的习惯:解析APDU时,先看控制域确定帧类型,再看ASDU的类型标识确定数据内容。这样不会乱。另外,我建议用Wireshark的IEC104插件,它能自动解析,省很多事。

3.7 避坑指南

最后,分享几个我踩过的坑:

  • APDU长度算错:我曾经写程序时,把启动字符和长度字段也算进去了,结果从站一直报错。记住,长度字段只算后面的字节。
  • 控制域字节序:IEC104是大端序,但有些设备是小端序。我遇到过设备发过来的控制域是反的,解析出来序号全乱。嗯,这个要特别注意。
  • ASDU的公共地址:在储能站中,一个主站可能管理几十个从站。公共地址一定要配对,否则数据会串。我见过一个项目,两个电池簇的地址配反了,遥测数据全乱套。

好了,APDU结构就讲到这里。记住这个“信封+信纸”的模型,后面学报文交互就轻松多了。


专注资料整理