1. IEC104协议结构

APDU:应用规约数据单元
APCI:应用规约控制单元
ASDU:应用服务数据单元

(Tips:

任何复杂的东西都是由简单的东西构成,首先先看协议的整体结构,然后在细化,最后前面理解协议。)

APDU的整体结构如下:

python iec104协议使用 iec104协议接口_python iec104协议使用

2. APCI

2.1启动字符

默认固定为 68H,意思就是只要是IEC104协议就是以68H开头;

2.2 APDU的长度问题

  • 起始一个apdu的总长度不会超过255个字节;
  • 在协议中的第二个字节会记录本apdu的长度,但是这个记录的长度数是除开前面两个字节之外的长读数,比如下面有个单点信息的apdu协议报文:
    68 31 02 00 02 00 01 A4 14 00 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    其中第二个字节31H就是长度转为10进制为49个字节,你可以数下后面肯定是49个字节,如果不是就不是一个apdu协议;

2.3 控制域

  • 控制域主要是有两个功能
  1. 报文的类型(I帧报文、U帧报文或者S帧报文)
  2. 记录收发报文的个数
2.3.1 I帧报文

python iec104协议使用 iec104协议接口_序列号_02

  • I帧报文格式规定控制域1和控制域3的最低位为0;
  • 其他部分用于发送序列号和接收序列号的计数;
    比如:发送计数为 TxCounter 接收计数为RxCounter
    控制域1 = TxCounter & 0xFE
    控制域2 = (TxCounter >> 8) & 0xFF
    控制域3 = RxCounter & 0xFE
    控制域4 = (RxCounter >> 8) & 0xFF
2.3.2 S帧报文

python iec104协议使用 iec104协议接口_序列号_03

  • S帧报文格式规定控制域1的第0位为1,第1位为0和控制域第0位为0;
  • S帧报文的发送序列号都为0
  • S帧只用于APCI中(意思就是S帧的apdu报文只会有apci不会存在asdu),不能用于传输信息,只用给对方信息的确认,比如子站发送8条报文,结束后主站就会给子站发送一个确认帧(S帧),告诉子站我收到了8条报文。
    比如:接收计数为RxCounter
    控制域1 = 0x01
    控制域2 = 0x00
    控制域3 = RxCounter & 0xFE
    控制域4 = (RxCounter >> 8) & 0xFF
2.3.3 U帧报文

python iec104协议使用 iec104协议接口_IEC104_04

  • I帧报文格式规定控制域1和控制域3的最低位为0;
  • 其他部分用于发送序列号和接收序列号的计数;
  • U帧只用于控制,并且只存在APCI中(意思就是U帧的apdu报文只会有apci不会存在asdu);
  • 测试、停止和开启在一个U帧报文中只可能存在其中的一种;
  • 如果用于【开启】则:
    激活第2位为1 第3位0,如下表所示
  • 激活确认第2为0 第3位1,如下表所示

    U帧启动主要是用于 主站连接子站时,主站给子站发送一个U帧启动报文,如下:
    主站发送:68 04 07 00 00 00
    子站回复:68 04 0B 00 00 00
  • 如果用【停止】则:
    激活第4位为1 第5位0,如下表所示

    激活确认第4为0 第5位1,如下表所示

    U帧停止如下:
    主站发送:68 04 13 00 00 00
    子站回复:68 04 23 00 00 00
  • 如果用【测试】则:
    激活第6位为1 第7位0,如下表所示

    激活确认第6为0 第7位1,如下表所示

    比如:子站发送U帧测试(激活),主站收到测试U帧就会回复一个U帧(确认)
    子站发送:68 04 43 00 00 00
    主站发送:68 04 83 00 00 00
    Tips:测试U帧一般用于子站判断主站是否还在连接子站,主站判断子站是否还在运行,保证数据传输的畅通性;
    到此APCI这一块就没啥了,继续下面ASDU的细化;

3. APDU

3.1类型标识

3.1 类型标识:占一个字节,标识出后面的信息体的数据类型
Tips:一个apdu中信息体中的所有数据的类型都是一致的,并且数据类型在类型标识这个位置标识;

  • 类型的分类:
3.1.1监视方向的用户类型
  • Tips: 标度化值和归一化值占2个字节,短浮点数占4个字节
  • 标度化值:类似INT16
  • 标度化值:(转换比较复杂,参考网上的一个公式)取值范围
    通常将大于1的数映射到1以内的空间,通常就是用实际值除以额定值,即得到归一化的小数(只要双方约定好,什么形式的转化无所谓)
  • 短浮点值:类似float
  • Tips:
    一般为从站发送给主站
3.1.2控制方向的用户类型

python iec104协议使用 iec104协议接口_IEC104_05


python iec104协议使用 iec104协议接口_IEC104_06

  • Tips:
    一般为主站发送给从站
3.1.3监视方向的系统类型

python iec104协议使用 iec104协议接口_IEC104_07

  • Tips:
    当厂站(从站)短重新上电、初始化参数、重新分配缓存区等情况下,厂站需要给主站发送该类型,而主站收到该类型的APDU包,主站一般会做一次总召唤;
    从站发送给主站
3.1.4控制方向的系统类型

python iec104协议使用 iec104协议接口_IEC104_08

  • Tips:
    一般为主站发送给从站

3.2可变结构限定词

python iec104协议使用 iec104协议接口_数据_09


SQ = 0 :信息对象的地址不连续(意思就是每个信息对象都会一个对象地址)

SQ = 1 : 信息对象的地址连续 (只有第一个信息对象有地址,其他对象的地址就是累加1)

Tips:总召唤时,为了压缩信息传输时间SQ=1;而在从站主动上传变化数据时,因为地址不连续,采用SQ=0;

3.3传送原因

  • 占2个字节
  • T = 0 未试验 ; T = 1 试验 (一般 T= 0)
  • P/N = 0 肯定 ; P/N = 1 否定 (正常为P/N = 0;P/N = 1说明该报文无效)
  • 源发地址:用来记录来时哪个主站的响应数据,一般写 0;
  • 传送原因:(下面提到的上行:[从站发送给主站]、下行:[主站发送给从站])


    红色标记的是一些常用的;其中【6,7,8,9,10】在一些遥控,设定值时用的比较多
    例如:从站发送一个 传送原因为 突发 的报文 ,则传送原因这个2个字节的情况如下:
    突发 = 3

3.4应用服务数据单元公共地址

  • 占2个字节
  • 规定高位字节 0x00
  • 站地址: 1-254 为站地址;255为全局地址;

3.5信息体

3.5.1连续信息传输型
3.5.1.1带绝对时标(遥测)
  • Tips: 时标有三种,但是例外两种基本不用,暂不去说明
  • 其中只有类型为【21】的【归一化测量值】不带品质描述词
  • 说明:连续、带时标的 ASDU数据部分结构如上表分为:
  • 地址编号:第一个信息体数据的地址(只会出现一次)
  • 重复信息体数据+品质描述词 (地址=第一个地址按顺序+1推算出来)
  • 最后以绝对时标结束
3.5.1.2不带绝对时标(遥测)

python iec104协议使用 iec104协议接口_数据_10

  • 说明:连续、不带时标的 ASDU数据部分结构如上表分为:
  • 地址编号:第一个信息体数据的地址(只会出现一次)
  • 重复信息体数据+品质描述词 (地址=第一个地址按顺序+1推算出来)
3.5.1.3带绝对时标(遥信)

python iec104协议使用 iec104协议接口_从站_11

  • Tips:对于遥信,状态量和品质描述词 合在了一个字节中
3.5.1.4不带绝对时标(遥信)

python iec104协议使用 iec104协议接口_python iec104协议使用_12

  • Tips:对于遥信,状态量和品质描述词 合在了一个字节中

3.5.2非连续信息传输型

3.5.2.1带绝对时标(遥测)

python iec104协议使用 iec104协议接口_python iec104协议使用_13

  • 说明: 不连续、带时标的 ASDU数据部分结构如上表分为:
  • 每一个信息体数据都会有一个地址编号
  • 绝对时标结尾
3.5.2.2不带绝对时标(遥测)

python iec104协议使用 iec104协议接口_python iec104协议使用_14

  • 说明: 不连续、带时标的 ASDU数据部分结构如上表分为:
  • 每一个信息体数据都会有一个地址编号
3.5.2.3带绝对时标(遥信)

python iec104协议使用 iec104协议接口_python iec104协议使用_15

3.5.2.4不带绝对时标(遥信)

python iec104协议使用 iec104协议接口_IEC104_16

3.5.3品质描述词

  • 分为 遥信品质描述词 和 遥测品质描述词;
单点信息品质描述词

python iec104协议使用 iec104协议接口_数据_17

  • BL : 封锁标志;BL=0 未被封锁;BL=1 封锁;
  • SB: 取代标志;SB=0 未被取代;SB = 1 被取代;
  • NT:刷新标志;NT=0 刷新成功;NT=1 刷新未成功;
  • IV:有效标志;IV = 0 状态有效;IV = 1 状态无效;
  • RES: 保留位
  • SPI:遥信状态值(0=开;1=合) 【具体的值,占一个bit位】
双点信息品质描述词

python iec104协议使用 iec104协议接口_数据_18

  • BL : 封锁标志;BL=0 未被封锁;BL=1 封锁;
  • SB: 取代标志;SB=0 未被取代;SB = 1 被取代;
  • NT:刷新标志;NT=0 刷新成功;NT=1 刷新未成功;
  • IV:有效标志;IV = 0 状态有效;IV = 1 状态无效;
  • RES: 保留位
  • SPI:遥信状态值(0=不确定状态或中间装填;
  • 1=确定状态的开;
    2=确定状态的合;
    3=不确定状态或中间装填)【具体的值,占2个bit为必然有4个值】
3.5.3.2遥测品质描述词

python iec104协议使用 iec104协议接口_IEC104_19

  • BL : 封锁标志;BL=0 未被封锁;BL=1 封锁;
  • SB: 取代标志;SB=0 未被取代;SB = 1 被取代;
  • NT:刷新标志;NT=0 刷新成功;NT=1 刷新未成功;
  • IV:有效标志;IV = 0 状态有效;IV = 1 状态无效; (tips:如何无效说明该遥测数据无效)
  • RES: 保留位;
  • OV:溢出标志;OV=0 未溢出;OV=1 遥测超出量程,发生溢出

3.5.4绝对时标

python iec104协议使用 iec104协议接口_数据_20

  • IV : IV = 0 时标有效;IV=1时标无效;
  • RES:保留位

3.5.5遥控和设定值

单点遥控

python iec104协议使用 iec104协议接口_序列号_21

  • 单点遥控信息
  • S/E = 0 遥控执行命令;S/E=1 遥控选择命令;
  • QU = 0 被控占内部确定遥控输出方式,不有控制站选择;
  • 1 短脉冲方式输出
    2 长脉冲方式输出
    3 持续脉冲方式输出
    其他值没有定义
  • RES :保留位
  • SCS : 设置值; 0 = 控开 ;1 = 控合
双点遥控

python iec104协议使用 iec104协议接口_IEC104_22

  • 单点遥控信息
  • S/E = 0 遥控执行命令;S/E=1 遥控选择命令;
  • QU = 0 被控占内部确定遥控输出方式,不有控制站选择;
  • 1 短脉冲方式输出
    2 长脉冲方式输出
    3 持续脉冲方式输出
    其他值没有定义
  • DCS; 0 无效控制
    1 控分
    2 控合
    3 无效控制
    Tips:一个从站系统单点和双点只能存在一种
设定值(遥测)
  • Tips:除了类型编号: 136 存在多点设定外,其他都是单个信息体设置值
  • QOS:设定命令限定词
  • S/E : 0 设定执行;1 设定选择;
  • 设定命令限定词: 基本就是 0 ,因为其他并没有定义;

4.过程描述

  1. 建立tcp连接;
  2. 主站给从站发送启动帧;报文:68 04 07 00 00 00
  3. 从站收到启动帧,给主站发送启动确认帧;报文:68 04 0B 00 00 00
  4. 主站给从站发送总召唤;报文:68 0E 00 00 00 00 64 01 06 00 01 00 00 00 00 14
  5. 从站收到主站的总召唤命令,给主站发送总召唤确认;
    报文:68 0E 00 00 02 00 64 01 07 00 01 00 00 00 00 14
  6. 从站上传遥信,遥测,电度等I帧信息帧,发送完毕从站发送总召唤结束帧;
  7. 主站收到从站发送的结束帧,会回复一个S帧的确认帧;
  8. 进入下一个周期(其中如何数据有变化,从站需要主动上报)

5.用到的参数解释

python iec104协议使用 iec104协议接口_数据_23

Tips:其中 t3>t1>t2

python iec104协议使用 iec104协议接口_序列号_24

默认端口:2404;

//超时机制
    int t1_calc; // 用于计数
    int t1;    //  发送或者测试APDU的超时
    // 从站端启动U格式测试过程后等待U格式测试应答的超时时间(超时处理:断开连接)
    // 启动条件:发送U测试帧
    // 关闭条件:接收U测试帧

    int t2_calc; // 用于计数
    int t2;    //  无数据报文t2<t1确认的超时
    //	1)	以突发的传送原因向主站(客户)端上送了变化信息
    //	2)	或以激活结束的传送原因向主站(客户)端上送了总召唤/电度召唤结束后
    //	等待主站(客户)端回S格式的超时时间,若超过此时间还没有收到,就主动关闭TCP连接
    //  处理完I格式帧后开始计时(置0),接收到S帧置0
    //  启动条件:发送完所有I帧
    //  关闭条件:收到S/I帧

    int t3_calc; // 用于计数
    int t3;    //  长期闲置t3>t1状态下发送测试帧的超时
    // T3:当RTU(服务器)端和主站(客户)端之间没有实际的数据交换时,任何一端启动U格式测试过程的最大间隔时间(超时处理:发送U测)
    // 启动条件:建立连接
    // 关闭条件:断开连接

    int K;  // 发送序号和接收序号之间的最大差值   【发送方在发送K个I报文还未收到确认就应该关闭数据传送 默认值为12;从站使用】
    int W;  // 【接收方最迟收到W个I就必须要回复确认帧 默认值为8;主站使用,这里不使用】
    // W 不能够超过 K 的2/3

    QTimer *timer1;     // 发送或者测试APDU的计时器
    QTimer *timer2;     // 无数据报文确认的计时器
    QTimer *timer3;     // 发送测试帧的计时器

希望能帮到你