news 2026/4/3 6:12:54

IEC104 协议 | 帧格式 / 调试(篇 2)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
IEC104 协议 | 帧格式 / 调试(篇 2)

注:本文为 “ IEC104 协议” 相关合辑。
未整理去重,如有内容异常请看原文。
图片清晰度限于引文原状。


IEC 104 电力规约详细解读 (一) - 报文结构、报文分类、ASDU

张二狗和苗翠花已于 2024-04-23 08:08:13 修改

协议一般规则:

  • 平衡方式传输;也就是说每一个过程的会话,没有规定谁从头发起,双方均可

  • 一般情况下配电主站作为 TCP 的客户端,配电终端作为 TCP 的服务器

  • TCP 的默认端口号是 2404

一、报文结构

APCI 应用规约控制信息;ASDU 应用服务数据单元 (和 101 协议里定义一致);APDU 应用规约数据单元。

  • 启动字符 68H 定义了数据流中的起点

  • APDU 的长度域定义了 APDU 体的长度,它包括 APCI 的四个控制域八位位组和 ASDU。第一个被计数的八位位组是控制域的第一个八位位组,最后一个被计数的八位位组是 ASDU 的最后一个八位位组。ASDU 的最大长度限制在 249 以内,因为 APDU 域的最大长度是 253(APDU 最大值 = 255 减去启动和长度八位位组),控制域的长度是 4 个八位位组。

  • 控制域定义了确保报文不丢失和重复传送的控制信息(也就是发送序列号和接收序列号),报文传输启动 / 停止,以及传输连接的监视等。控制域的计数器机制是根据 ITU-T X.25 标准中推荐的 2.3.2.2.1 至 2.3.2.2.5 来定义的

二、报文分类(APCI)

2.1 S 格式 (Numbered supervisory functions, 编号的监视功能格式)

S 帧格式报文不用来传送信息,只用来确认对方的发送序列号。比如,双方可以按频率发送,比如接收 8 帧 I 帧回答一帧 S 帧,也可以要求接收 1 帧 I 帧就应答 1 帧 S 帧,当然也可以不要求(S 帧内容示例参考例 1)。因为 S 帧回复确认的序列号在 byte3、byte4 两个字节,并且 byte3 的 bit1 位置固定是 0,所以在使用 S 帧回复确认时,只需在接收报文的发送序列号 + 2 就可以(参考例 2)。

举例 1:68 04 01 00 0A 00 (接收序列号 = 5) 举例 2: RECV: 68 FA 6C 67 84 00 0D 1E 03 00 01 00 E8 ... 省略 ... 6C 67 低前高后转换成 0x676C 再右移一位就是 0x33B6 最终发送序列号 10 进制也就是 13238 SEND: 68 04 01 00 6E 67 接受序列号 = 接收报文的发送序列号 + 1 = 13239 = 0x33B7 左移一位 0x676E 再低前高后转换 就是 6E 67 综上得出其实就是在接收来的报文的发送序列号的 byte1 的 bit2 位置上 + 1,也就成了对应 10 进制上 + 2

2.2 U 格式 (Unnumbered control function, 不编号的控制功能格式)

在同一时刻,TESTFR, STOPDT 或 STARTDT 中只有一个功能可以被激活。所以 U 帧格式的控制欲第一个字节就只有 6 种情况,分别是 0x83(TESTER 确认)0x43(TESTER 命令)0x23(STOPDT 确认)0x13(STOPDT 命令)0x0B(START 确认)0x07(START 命令)

举例:68 04 07 00 00 00 START 命令

U 帧和 S 帧是没有 ASDU 的,所以这两种类型的报文长度也就是 6 字节

2.3 I 格式 (Information Transmit Format, 编号的信息传输格式)

遥信、遥测、遥控、遥调、总召、对时等都需要使用 I 格式传送。

举例:后面几篇文章详细说

三、I 格式帧的 ASDU

ASDU(应用服务数据单元),协议原文格式最好去 101 协议去看看,会比较详细。104 和 101 是一样的

  • 类型标识符(1 byte)。解析来区分属于哪个过程。比如 0x01 单点遥信、0x0D 段浮点遥测

  • 可变结构限定词(1byte)。bit0-bit6 :信息对象的个数 bit7: SQ 信息对象地址是否连续,1 代表连续,也就是信息对象 2 的地址就是信息对象 1 的地址 + 1,信息对象 2 无需再给出它的地址;0 代表不连续,每个信息对象都必须给出自己的地址

  • 传送原因(2byte)。

  • ASDU 公共地址。一般是一个变电站一个地址

  • 信息对象

  • 信息对象地址。也就是点表对应的点位,遥测信息也就是测量点标号

  • 信息元素集。对应的值,按照不同的类型标识去解析

  • 时标。CP56Time2a 格式 7byte

  • 限定词。按照报文类型确定有无限定词。总召唤限定词、复位进行限定词、初始化原因、品质描述词、设置命令限定词


IEC 104 电力规约详细解读 (二) - 总召唤

张二狗和苗翠花 已于 2024-04-23 08:09:51 修改

1 功能简述

总召唤功能是在初始化以后进行,或者是定期进行总召唤,以刷新主站的数据库。总召唤时请求子站传送所有的过程的变量实际值。定期进行总召唤的周期的是一个系统参数,可以是 15 分钟或者更长的时间。

总召唤的内容包括子站的遥信、遥测等信息。这些信息一般在上报的时候会用 SQ=1 的地址连续的报文进行上报,当然也可以不连续,视情况而定。

2 通信过程

  1. 先由主站向子站发送总召唤命令帧

  2. 子站收到后,如果否定,子站会送否定确认,传输结束;如果确认,则子站回送总召唤确认帧

  3. 子站连续地向主站传送数据。包括但不仅限于不带品质描述词的遥测帧、单点遥信帧、远动终端帧

  4. 子站信息传送完毕后,发送总召唤结束帧,总召唤过程结束

注意事项:

  1. 为了让通信双方同步实时数据库,由于中断原因引起的重建链路后的第一次总召唤过程不允许被打断

  2. 对于非中断原因(如手动总召唤)引起的总召唤回答可以被高优先级数据打断;回答总召唤应该使用 SQ=1 压缩格式传输

3 报文结构

4 报文实例解读

这一部分的实例是主站的视角去看,也就是说 SEND 就是主站发送子站接收;RECV 就是子站发送主站接收。

SEND: 68 0E 00 00 00 00 64 01 06 00 01 00 00 00 00 14

  • 启动字符:68H

  • APDU 长度:0EH 14 个字节

  • 控制域四个八位组:00 00 00 00 第一个字节的 bit0 为 0,第三个字节的 bit0 为 0,所以是 I 格式帧,发送序列号 0,接收序列号 0

  • 类型标识:64H CON<100>:= 总召唤命令

  • 可变结构限定词:01H SQ=0 地址不连续 信息元素个数 1, 单个

  • 传送原因:06 00 -0006H <Cause<6>:= 激活

  • ASDU 公共地址:01 00 =0001H 通常为 RTU 地址

  • 第一个信息元素的地址:00 00 00 =000000H

  • 第一个信息元素的值(召唤限定词):14H 固定 20

RECV: 68 0E 00 00 02 00 64 01 07 00 01 00 00 00 00 14

  • 启动字符:68H

  • APDU 长度:0EH 14 个字节

  • 控制域四个八位组:00 00 02 00 第一个字节的 bit0 为 0,第三个字节的 bit0 为 0,所以是 I 格式帧,发送序列号 0,接收序列号 1

  • 类型标识:64H CON<100>:= 总召唤命令

  • 可变结构限定词:01H SQ=0 地址不连续 信息元素个数 1, 单个

  • 传送原因:07 00 -0007H <Cause<7>:= 激活确认

  • ASDU 公共地址:01 00 =0001H 通常为 RTU 地址

  • 第一个信息元素的地址:00 00 00 =000000H

  • 第一个信息元素的值(召唤限定词):14H

RECV: 68 1A 02 00 02 00 03 04 14 00 01 00 01 00 00 01 02 00 00 02 03 00 00 01 04 00 00 02

  • 启动字符:68H

  • APDU 长度:1AH 26 个字节

  • 控制域四个八位组: 02 00 02 00 第一个字节的 bit0 为 0,第三个字节的 bit0 为 0,所以是 I 格式帧,发送序列号 1,接收序列号 1

  • 类型标识:03H CON<3>:= 双点遥信

  • 可变结构限定词:04H SQ=0 地址不连续 信息元素个数 4

  • 传送原因:14 00 -0014H <Cause<20>:= 响应站召唤

  • ASDU 公共地址:01 00 -0001H 通常为 RTU 地址

  • 第一个信息元素的地址:01 00 00 =000001H

  • 第一个信息元素的值:01H 分位

  • 第二个信息元素的地址:02 00 00 =000002H

  • 第二个信息元素的值:02H 合位

  • 第三个信息元素的地址:03 00 00 =000003H

  • 第三个信息元素的值:01H 分位

  • 第四个信息元素的地址:04 00 00 =000004H

  • 第四个信息元素的值:02H 合位

具体双点遥信的报文结构后面在遥信的章节详细说

RECV: 68 2A 04 00 02 00 0D 04 14 00 01 00 01 40 00 00 78 DB 3F 00 02 40 00 00 D8 90 42 00 03 40 00 00 F4 92 42 00 04 40 00 60 50 9A 3F 00

  • 启动字符:68H

  • APDU 长度:2AH 42 个字节

  • 控制域四个八位组: 04 00 02 00 第一个字节的 bit0 为 0,第三个字节的 bit0 为 0,所以是 I 格式帧,发送序列号 2,接收序列号 1

  • 类型标识:0DH CON<13>:= 测量值,短浮点数

  • 可变结构限定词:04H SQ=0 地址不连续 信息元素个数 4

  • 传送原因:14 00 -0014H <Cause<20>:= 响应站召唤

  • ASDU 公共地址:01 00 -0001H 通常为 RTU 地址

  • 第一个信息元素的地址:01 40 00 =004001H =16385 (在 2002 版的协议中规定遥测点位地址范围是 0x4001 ~ 0x5000)

  • 第一个信息元素的值:00 78 DB 3F //Float.intBitsToFloat(0x3fdb7800) =>1.715

  • 第一个信息元素的品质描述词:00H

  • 第二个信息元素的地址:02 40 00 =004002H

  • 第二个信息元素的值:00 D8 90 42 //Float.intBitsToFloat(0x4290d800) =>72.422

  • 第二个信息元素的品质描述词:00H

  • 第三个信息元素的地址:03 40 00 =004003H

  • 第三个信息元素的值:00 F4 92 42 //Float.intBitsToFloat(0x4292f400) =>73.477

  • 第三个信息元素的品质描述词:00H

  • 第四个信息元素的地址:04 40 00 =004004H

  • 第四个信息元素的值:60 50 9A 3F //Float.intBitsToFloat(0x3f9a5060) =>1.206

  • 第四个信息元素的品质描述词:00H

具体短浮点遥测的报文结构后面在遥侧的章节详细说

RECV: 68 0E 06 00 02 00 64 01 0A 00 01 00 00 00 00 14

  • 启动字符:68H

  • APDU 长度:0EH 14 个字节

  • 控制域四个八位组: 06 00 02 00 第一个字节的 bit0 为 0,第三个字节的 bit0 为 0,所以是 I 格式帧,发送序列号 3,接收序列号 1

  • 类型标识:64H CON<100>:= 总召唤命令

  • 可变结构限定词:01H SQ=0 地址不连续 信息元素个数 1 单个

  • 传送原因:0A 00 -000AH <Cause<10>:= 激活终止

  • ASDU 公共地址:01 00 -0001H 通常为 RTU 地址

  • 第一个信息元素的地址:00 00 00

  • 第一个信息元素的值(召唤限定词):14H 固定 20


IEC 104 电力规约详细解读 (三) - 遥信

张二狗和苗翠花已于 2024-04-23 08:11:38 修改

1. 功能简述

遥信,、即状态量,是为了将断路器、隔离开关、中央信号等位置信号上送到监控后台的信息。遥信信息包括:反应电网运行拓扑方式的位置信息。如断路器状态、隔离开关状态;反应一次二次设备工作状况的运行信息,如变压器本体冷却器全停,断路器弹簧未储能等;反应电网异常和一次二次设备异常的事故信息、预告信息等。如差动保护出口,切换继电器同时失磁等

硬遥信和软遥信

  • 硬遥信:测控装置端子排对应的遥信(即有电缆接线的),如断路器、隔离开关信号等。

  • 软遥信:除硬遥信之外的遥信,主要是一些保护事件,如过流段以及自动化嵌入的应用功能模块产生的运行信息。如五防闭锁提示信息等。

全遥信和变位遥信

  • 全遥信:如果没有遥信状态发生变化,测控装置每隔一定周期,定时向监控后台发送本站所有遥信状态信息

  • 变位遥信:当某遥信状态发生改变,测控装置立即向监控后台插入发送变位遥信的信息。后台收到变遥信报文后,与遥信历史库比较后发现不一致,于是提示该遥信状态发生改变

单点遥信、双点遥信

  • 单点遥信:就是用一位表示一个遥信量,比如断路器位置,只采用一个常开辅助接点,值为 1 或 0,用 1 表示合位,0 表示分位

  • 双点遥信:就是用两位表示一个遥信量,需采集动合 / 动断两个辅助接点位置。当动合点值等于 1,且动断点值等于 0,即值为 10,则认为断路器在合位;当动合点值等于 0,且动断点值等于 1,即值为 01,则认为断路器在分位;当两个位置都为 1 或都为 0,则都被认为位置不确定

2. 通信过程

3. 报文结构

遥信报文结构总结起来可以分为三种:

  • 信息对象序列(SQ=0),不带时标的单 / 双点信息遥信报文格式

  • 信息对象序列(SQ=0),带长时标的单 / 双点信息遥信报文格式

  • 单个信息中信息元素序列(SQ=1),不带时标的单 / 双点信息遥信报文格式

按照 DL/T 634.5104-2009 规定,带长时标的单 / 双点信息遥信报文并不存在信息元素序列(SQ=1)的情况

遥信报文的类型标识符 TI 分为 01H(单点信息)03H(双点遥信); 传输原因 COT 分为 03H(突发)05H(被请求)14H(响应站召唤); 遥信对象的地址范围在 2022 版协议中规定为 1H~4000H

4. 报文实例解读

  • 例 1 SQ=0, 不带时标的单点遥信

    68 0E F8 AD 12 05 01 01 03 00 01 00 A6 01 00 01

  • 启动字符:68H

  • APDU 长度:0EH 14 个字节

  • 控制域四个八位组:F8 AD 12 05 第一个字节的 bit0 为 0,第三个字节的 bit0 为 0,所以是 I 格式帧,发送序列号 22268,接收序列号 649

  • 类型标识:01H CON<1>:= 单点信息

  • 可变结构限定词:01H SQ=0 地址不连续 信息元素个数 1, 单个

  • 传送原因:03 00 -0003H <Cause<3>:= 突发

  • ASDU 公共地址:01 00 =0001H 通常为 RTU 地址

  • 第一个信息元素的地址:A6 01 00 =0001A6H = 第 422 点

  • 第一个信息元素的值:01 合位

  • 例 2 SQ=0, 不带时标的双点遥信

    68 0E 04 00 02 00 03 01 03 00 01 00 01 00 00 02

  • 启动字符:68H

  • APDU 长度:0EH 14 个字节

  • 控制域四个八位组:04 00 02 00 第一个字节的 bit0 为 0,第三个字节的 bit0 为 0,所以是 I 格式帧;发送序列号 2,接收序列号 1

  • 类型标识:03H CON<3>:= 双点信息

  • 可变结构限定词:01H SQ=0 地址不连续 信息元素个数 1, 单个

  • 传送原因:03 00 -0003H <Cause<3>:= 突发

  • ASDU 公共地址:01 00 =0001H 通常为 RTU 地址

  • 第一个信息元素的地址:01 00 00 =000001H = 第 1 点

  • 第一个信息元素的值:02 合位

  • 例 3 SQ=1, 不带时标的双点遥信

    68 10 02 00 02 00 03 83 14 00 01 00 01 01 00 02 02 01

  • 启动字符:68H

  • APDU 长度:10H 16 个字节

  • 控制域四个八位组:02 00 02 00 第一个字节的 bit0 为 0,第三个字节的 bit0 为 0,所以是 I 格式帧;发送序列号 1,接收序列号 1

  • 类型标识:03H CON<3>:= 双点信息

  • 可变结构限定词:83H SQ=1 地址连续 信息元素个数 3

  • 传送原因:14 00 -0014H <Cause<20>:= 响应站召唤

  • ASDU 公共地址:01 00 =0001H 通常为 RTU 地址

  • 第一个信息元素的地址:01 01 00 =000101H = 第 257 点

  • 第一个信息元素的值:02 合位 第 257 点

  • 第二个信息元素的值:02 合位 第 258 点

  • 第三个信息元素的值:01 分位 第 259 点


IEC 104 电力规约详细解读 (四) - 遥测

张二狗和苗翠花已于 2024-04-23 08:12:46 修改

1. 功能简述

遥测,顾名思义就是测量值,由从站上报到主站,有标度化,归一化,短浮点三种类型,再根据是否带有品质描述、是否带试标划分为更细的类型。通常推荐使用短浮点数方式上送。遥测信息对象地址范围为 4001H~5000H.

2. 通信过程

3. 报文结构

  • 归一化值。2 字节,最高位 D15 为符号位 0 正数 1 负数;D14~D0 为数据位取值范围 0-32767

  • 短浮点数,4 字节,IEEE STD745 标准定义,不再赘述,如果你是用 Java 开发,可以直接调用 Float.intBitsToFloat(int)

  • 标度化值。

4. 报文实例解读

RECV: 68 12 0E 00 10 00 0D 01 03 00 01 00 02 40 00 00 78 DB 3F 00

  • 启动字符:68H

  • APDU 长度:12H 18 个字节

  • 控制域四个八位组:0E 00 10 00 第一个字节的 bit0 为 0,第三个字节的 bit0 为 0,所以是 I 格式帧,发送序列号 7,接收序列号 8

  • 类型标识:0DH CON<13>:= 带品质描述词的短浮点数

  • 可变结构限定词:01H SQ=0 地址不连续 信息元素个数 1, 单个

  • 传送原因:03 00 -0003H <Cause<3>:= 突发

  • ASDU 公共地址:01 00 =0001H 通常为 RTU 地址

  • 第一个信息元素的地址:02 40 00 =004002H = 第 16836 点

  • 第一个信息元素的值:00 78 DB 3F //Float.intBitsToFloat(0x3fdb7800) =>1.715

  • 第一个信息元素的品质描述词:00 未溢出 / 未被闭锁 / 未被取代 / 当前值 / 有效


IEC 104 电力规约详细解读 (五) - 遥控

张二狗和苗翠花已于 2024-07-17 11:47:35 修改

1. 功能简述

遥控命令用来实现对一个可操作设备状态的改变。在配电自动化中,包括单点命令和双点命令。通常,单点命令用于控制单点信息对象;双点命令用于控制双点信息对象。

2. 通信过程

主站下发遥控选择命令,子站进行遥控选择返校,若成功则回答遥控选择成功报文,若失败则回答失败报文。主站下发取消遥控命令或者遥控执行命令行。字站予以确认。子站皆以报文的镜像确认。

3. 报文结构

4. 报文实例解读

SEND:68 0E 06 00 0A 00 2D 01 06 00 01 00 02 60 00 81

  • 启动字符:68H

  • APDU 长度:0EH 14 个字节

  • 控制域四个八位组:06 00 0A 00

  • 类型标识:2DH CON<45>:= 单点遥控

  • 可变结构限定词:01H SQ=0 地址不连续 信息元素个数 1, 单个

  • 传送原因:06 00 -0006H Cause<6>:= 激活

  • ASDU 公共地址:01 00 =0001H 通常为 RTU 地址

  • 第一个信息元素的地址:02 60 00 =006002H 点号 24578

  • 第一个信息元素的值:81H 遥控选择 控合

RECV:68 0E 0A 00 06 00 2D 01 07 00 01 00 02 60 00 81

  • 启动字符:68H

  • APDU 长度:0EH 14 个字节

  • 控制域四个八位组:0A 00 06 00

  • 类型标识:2DH CON<45>:= 单点遥控

  • 可变结构限定词:01H SQ=0 地址不连续 信息元素个数 1, 单个

  • 传送原因:07 00 -0007H Cause<7>:= 激活确认

  • ASDU 公共地址:01 00 =0001H 通常为 RTU 地址

  • 第一个信息元素的地址:02 60 00 =006002H 点号 24578

  • 第一个信息元素的值:81H 遥控选择 控合

SEND:68 0E 08 00 0C 00 2D 01 06 00 01 00 02 60 00 01

  • 启动字符:68H

  • APDU 长度:0EH 14 个字节

  • 控制域四个八位组:08 00 0C 00

  • 类型标识:2DH CON<45>:= 单点遥控

  • 可变结构限定词:01H SQ=0 地址不连续 信息元素个数 1, 单个

  • 传送原因:06 00 -0006H Cause<6>:= 激活

  • ASDU 公共地址:01 00 =0001H 通常为 RTU 地址

  • 第一个信息元素的地址:02 60 00 =006002H 点号 24578

  • 第一个信息元素的值:01H 遥控执行 控合

RECV:68 0E 0C 00 08 00 2D 01 07 00 01 00 02 60 00 01

  • 启动字符:68H

  • APDU 长度:0EH 14 个字节

  • 控制域四个八位组:08 00 0C 00

  • 类型标识:2DH CON<45>:= 单点遥控

  • 可变结构限定词:01H SQ=0 地址不连续 信息元素个数 1, 单个

  • 传送原因:07 00 -0006H Cause<7>:= 激活确认

  • ASDU 公共地址:01 00 =0001H 通常为 RTU 地址

  • 第一个信息元素的地址:02 60 00 =006002H 点号 24578

  • 第一个信息元素的值:01H 遥控执行 控合

RECV:68 0E 0E 00 08 00 2D 01 0A 00 01 00 02 60 00 01

  • 启动字符:68H

  • APDU 长度:0EH 14 个字节

  • 控制域四个八位组:0E 00 08 00

  • 类型标识:2DH CON<45>:= 单点遥控

  • 可变结构限定词:01H SQ=0 地址不连续 信息元素个数 1, 单个

  • 传送原因:0A 00 -000AH Cause<10>:= 激活结束

  • ASDU 公共地址:01 00 =0001H 通常为 RTU 地址

  • 第一个信息元素的地址:02 60 00 =006002H 点号 24578

  • 第一个信息元素的值:01H 遥控执行 控合


IEC 104 电力规约详细解读 (六) - Java 解析开发要点

张二狗和苗翠花已于 2024-04-22 19:38:52 修改

1. 前言

最近在研究广东电网的 101 与 104 规约,也就是 DL/T634.5101-2002 和 DL/T634.5104-2009。因为要做一个规约解析的软件(基于 Android 平台的),刚开始接触的也是一头雾水,因为没有接触过这方面的知识,所以就在网上搜索各种技术帖,大神经验什么的。

后来在网上找到了一个软件–IEC8705 (报文翻译工具).exe,这个可以解析一些 101(平衡式)的实例,效果图贴一下。

但有些还是解析不了,并且在网上也找不到他的源码,所以就很苦恼。也找到一些 C++ 的源码,但是由于技术有限,我看不懂。下面就和大家来看看我写的这个简单的 Java 语言的规约解析。先贴一下效果图(我就在控制台简单演示一下,没有做可视化界面)。

GitHub 地址:https://github.com/mujave/iec

2. Java 版效果图

3. 规约详细解释

先看一下我总结的关于规约解析的几个图

101 的规约总结

104 规约总结

具体的 104 协议解释也可以参考 https://blog.csdn.net/wojiuguowei/article/details/79413142

4. 名词解释

这里所说的名词解释,并不是对一些名词的定义的解释,因为这不是我的专业领域,下面我主要针对报文所代表的名词在代码里怎样解释(解析)说一下。

控制域(平衡式)

在报文解析中,我就是按照图里面的取值方法对对应的字节进行取值,然后进行逻辑判断,将结果加到解析结果里面,由于后四位所代表的平衡链路功能码在这里是固定的,所以可以采取枚举或者反射(常量) 的方式进行解析

地址域(以 104 的信息体地址为例)

在规约中地址才用的低前高后(低位在前高位在后)的规则

例如:68 10 08 00 02 00 09 01 03 00 01 00 01 40 00 2B 02 00(黄色部分为信息体地址)

所以 这个信息体的地址为 01 40 00 >0x004001=16385

时标 CP56Time2a

解析代码如下

/** * 时标CP56Time2a解析 * * @param b 时标CP56Time2a(长度为7 的int数组) * @return 解析结果 */ public static String TimeScale(int b[]) { StringBuilder result = new StringBuilder(); int year = b[6] & 0x7F; int month = b[5] & 0x0F; int day = b[4] & 0x1F; int week = (b[4] & 0xE0) / 32; int hour = b[3] & 0x1F; int minute = b[2] & 0x3F; int second = (b[1] << 8) + b[0]; result.append("时标CP56Time2a:20"); result.append(year).append("-"); result.append(String.format("%02d", month)).append("-"); result.append(String.format("%02d", day)).append(","); result.append(hour).append(":").append(minute).append(":"); result.append(second / 1000 + "." + second % 1000).append("\n"); return result.toString(); }

遥测量的解析

在 101 的遥测中定义到有三种类型的值,分别是归一化值,标度值,短浮点数,具体的定义大家可以参考 “电力 101/104 规约中遥测量类型转换”,下面我说一下在 Java 中怎么解析这三种类型的值。直接上代码了。

publicclassMain{publicstaticvoidmain(String[]args){Telemetrytelemetry=newTelemetry();System.out.println(telemetry.Bytes2Float_NVA(0xa4,0x6a));// 报文数据的为A4 6A(低位在前,高位在后) ,为0x6AA4System.out.println(telemetry.Bytes2Float_SVA(0xa4,0x6a));// 报文数据的为A4 6A(低位在前,高位在后) ,为0x6AA4System.out.println(telemetry.Bytes2Float_IEEE754("3e0779a6"));//报文数据 A6 79 07 3E = 0x3e0779a6 = 0.1323(IEEE754 短浮点数)http://lostphp.com/hexconvert/}}/** * 遥测量解析 * * @author zhangyu */publicclassTelemetry{/** * 归一化值 */publicstaticfloatBytes2Float_NVA(intlow,inthigh){floatfVal;intnva=(high<<8)+low;// 符号位1位,0为正数,1为负数,后面的为补码表示,// 正数的补码和原码相同不需要转换。对于负数,先取反码再加1得到补码的补码,就是原码了。intsymbol=(high&0x80);//符号位:0表示正数,1表示负数if(symbol==0x80)fVal=-1*(((nva^0xffff)+1)&0x7fff);// (nva ^ 0xffff) + 1 :补码的补码 ,取出后面的15位数据乘上-1得到值elsefVal=nva;returnfVal/32767;//这里的32767值的是一个量纲,一般这个参数是主站和从站商定的}/** * 标度化值 */publicstaticfloatBytes2Float_SVA(intlow,inthigh){floatfVal;intnva=(high<<8)+low;intsymbol=(high&0x80);//0表示正数,1表示负数if(symbol==0x80)fVal=-1*(((nva^0xffff)+1)&0x7fff);elsefVal=nva;returnfVal;}/** * 短浮点数 * * @param data 从低位到高位按顺序 * @return */publicstaticfloatBytes2Float_IEEE754(Stringdata){returnFloat.intBitsToFloat(Integer.valueOf(data,16));}}

对于短浮点数的计算,在 Java 的文档里有这样的说明。

还有一些 ASDU 里的信息体的解析过程代码,有点多,就不一一贴出来了

代码已经发布到 GitHub,需要的伙伴可以直接下载

5.104 规约解析遇到的一些难题

报文类型的区分

101 报文区分定长和变长两种,而 104 规约都是变长的报文。但是对于 104 来说,其控制域决定了 104 报文分别属于三种类型(I 帧 S 帧 U 帧)。所以在解析 104 到控制域的时候,是在解析 104 的第一个难题。我先说一下我自己的区分逻辑。

  • 我是用控制域的第一字节去和 3 做位运算(因为和 3 做位运算就可以得到第一字节的 D1/D0 两位),从上面的图中我们可以看到,结果如果是 1 的话就是 S 格式,如果是 3 的话就是 U 格式,其他 的结果就是 I 格式的报文。

  • 第二种方式是我在和一个网友交谈中得到的,他是运用奇数或者偶数来区分的,这里我列一个表格 ,这样的话如果第一个字节是偶数就是 I 帧,否则判断第三字节是 0 就是 U 帧。这样也可以区分报文的类型

但是我认为还是做位运算效率会更高,计算奇偶性还需要用到 % 这样的运算。

类型第一字节第二字节第三字节第四字节
S 帧奇(1)0
I 帧
U 帧000

位运算的运用

在解析规约的时候,我一般都是运用的位运算 (&),这样既可以提高程序的效率,也有助于理解。首先在规约的定义中有很多的一个字节中的不同位代表一个含义,这种时候就运用到了位运算,这样就可以直接将对应位的值提取出来,例如那可变结构限定词这个字节来举个例子。最高位的 D7 代表的是信息元素地址的连续性,其中 0 不连续 1 连续,所以我们只需要拿这个字节和 128 (0x80) 做位运算就可以得到 D7 这一位,如果结果是 10000000 就说明是 1 连续。这个地方更直观一点的判断方法就是 ((B&0x80)>>7)==1? 连续:不连续。

###时标的解析

首先时标这里一共有 7 个字节,下面对这几个字节的含义以及解析方法做一下解释:

  • 年 (byte 7): 这里只有后面的 7 位有效,但是第 8 位填充的是 0,所以这一个字节直接转换形成 int 就可以了。

  • 月 (byte 6): 同上

  • 小时 (byte 4): 同上

  • 分钟 (byte 3): 同上

  • 日 (byte 5 [bit 1~5]): 第五字节的后 5 位表示的是日,byte5 & 0x1F 就可以得到 (0x1F = 0001 1111), 例如第五字节是 87 (87 = 0x57 = 0101 0111),其中 010 指的是星期,10111 指的是 day。这里使用 87 & 0x1F 就可以得到 23。使用 87 & 0xE0 就可以得到 64,然后再用这个结果除以 32 就可以得到结果,如果说除以 32 不太理解的话,也可以用结果右移运算 64>>5 也可以得到结果 。

  • 毫秒 (byte 1 and byte 2): 这个地方首先是低前高后的问题 (这个为题不太明白的可以先翻一下下面的第四个问题),( byte 2 << 8 ) + byte 1 ,这个地方我用一个表格说明一下 (例如第一字节是 6E,第二字节是 2A)。

/** * 时标CP56Time2a解析 */publicstaticStringTimeScale(intb[]){Stringstr="";intyear=b[6]&0x7F;intmonth=b[5]&0x0F;intday=b[4]&0x1F;intweek=(b[4]&0xE0)/32;// int week = (b[4] & 0xE0) >> 5;inthour=b[3]&0x1F;intminute=b[2]&0x3F;intsecond=(b[1]<<8)+b[0];str+="时标CP56Time2a:"+"20"+year+"-"+String.format("%02d",month)+"-"+String.format("%02d",day)+","+hour+":"+minute+":"+second/1000+"."+second%1000;returnstr+"\n";}/** * 时间转16进制字符串 */publicstaticStringdate2HStr(Datedate){Calendarcalendar=Calendar.getInstance();calendar.setTime(date);StringBuilderbuilder=newStringBuilder();StringmilliSecond=String.format("%04X",(calendar.get(Calendar.SECOND)*1000)+calendar.get(Calendar.MILLISECOND));builder.append(milliSecond.substring(2,4));builder.append(milliSecond.substring(0,2));builder.append(String.format("%02X",calendar.get(Calendar.MINUTE)&0x3F));builder.append(String.format("%02X",calendar.get(Calendar.HOUR_OF_DAY)&0x1F));intweek=calendar.get(Calendar.DAY_OF_WEEK);if(week==Calendar.SUNDAY)week=7;elseweek--;builder.append(String.format("%02X",(week<<5)+(calendar.get(Calendar.DAY_OF_MONTH)&0x1F)));builder.append(String.format("%02X",calendar.get(Calendar.MONTH)+1));builder.append(String.format("%02X",calendar.get(Calendar.YEAR)-2000));returnbuilder.toString();}

低前高后的问题

这里讲一下低前高后的问题,拿这个 104 规约的信息对象地址举例。例如 34 12 00 这是原报文的字节,再具体解析的时候我们要把它转成 0x001234=4660,其实这里和上面的毫秒的解析方式一样。


  • IEC104 协议 | 帧格式 / 调试(篇 1)-CSDN博客
    https://blog.csdn.net/u013669912/article/details/144622175
  • IEC104 协议 | 帧格式 / 调试(篇 3)-CSDN博客
    https://blog.csdn.net/u013669912/article/details/155851169

via:

  • IEC 104 电力规约详细解读 (一) - 报文结构、报文分类、ASDU_104 规约详细介绍及报文解析-CSDN 博客
    https://blog.csdn.net/ZhangYu971014/article/details/135889376

  • IEC 104 电力规约详细解读 (二) - 总召唤_iec104 总召唤报文-CSDN 博客
    https://blog.csdn.net/ZhangYu971014/article/details/135983190

  • IEC 104 电力规约详细解读 (三) - 遥信_104xieyi 信息元素值-CSDN 博客
    https://blog.csdn.net/ZhangYu971014/article/details/136072736

  • IEC 104 电力规约详细解读 (四) - 遥测_iec104 规约标准 遥测-CSDN 博客
    https://blog.csdn.net/ZhangYu971014/article/details/136994209

  • IEC 104 电力规约详细解读 (五) - 遥控_104 遥控-CSDN 博客
    https://blog.csdn.net/ZhangYu971014/article/details/138089077

  • IEC 104 电力规约详细解读 (六) - Java 解析开发要点
    https://blog.csdn.net/ZhangYu971014/article/details/79841555

  • IEC 60870-5-104 详细解读_张二狗和苗翠花的博客-CSDN 博客
    https://blog.csdn.net/zhangyu971014/category_12562718.html

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/29 7:56:24

JavaScript学习笔记:4.循环与迭代

JavaScript学习笔记&#xff1a;4.循环与迭代 上一篇咱们搞定了JS的“决策术”和“容错术”&#xff08;控制流与错误处理&#xff09;&#xff0c;这一篇来解锁JS的“高效干活技能”——循环与迭代。如果说条件语句是让JS“会做选择”&#xff0c;那循环就是让JS“会重复做事”…

作者头像 李华
网站建设 2026/4/3 4:46:27

PCI Utilities终极完整实用指南:掌握Linux硬件检测与故障排查

PCI Utilities终极完整实用指南&#xff1a;掌握Linux硬件检测与故障排查 【免费下载链接】pciutils The PCI Utilities 项目地址: https://gitcode.com/gh_mirrors/pc/pciutils PCI Utilities&#xff08;pciutils&#xff09;是Linux系统管理员和硬件开发者必备的工具…

作者头像 李华
网站建设 2026/3/29 20:55:21

15、网络资源访问与远程系统管理指南

网络资源访问与远程系统管理指南 1. IRC聊天 尽管即时通讯兴起,但如今仍有很多人使用互联网中继聊天(IRC)。freenode.net有大量专门支持主要开源软件项目的聊天室。很多人整天登录这些聊天室,只观看他们喜欢的UNIX项目讨论滚动而过,这种行为被称为“潜水”。 xchat客户…

作者头像 李华
网站建设 2026/4/3 1:54:51

Revive Adserver:免费开源的广告管理系统终极指南

在数字营销快速发展的今天&#xff0c;一个高效可靠的广告管理系统对于网站运营者来说至关重要。Revive Adserver作为全球最受欢迎的免费开源广告服务器系统&#xff0c;为各类网站提供专业的广告管理解决方案。无论你是个人博主还是大型媒体公司&#xff0c;都能通过这个强大的…

作者头像 李华
网站建设 2026/3/31 2:16:59

GPT-5.2职场必备神器:如何利用它实现高效工作?

随着职场上任务越来越多、压力越来越大&#xff0c;我们都在寻求更高效的工作方式。特别是如果你还在用传统的方法来做事&#xff0c;可能会感觉有点“吃力不讨好”。别担心&#xff0c;今天我给大家带来了一位超级助手——GPT-5.2&#xff01;它不仅能帮你在工作中省时省力&am…

作者头像 李华
网站建设 2026/4/2 4:18:16

张量的基本运算

张量的基本运算 add() 加 sub(),减 - mul(),乘 * div(),除 / neg() 取负 - add_(), sub_(), mul_(), div_(), neg_() # 功能同上&#xff0c;但会修改原有数据, 功能类似pandas中的inplaceTrue按元素相乘运算 元素级乘法, 对应位置的元素进行相乘 两个张量形状相同 mul()/* …

作者头像 李华