电力系统60870-5-103规约项目开发知识小结——积成电子
前言
最近有一个103规约需要开发,在这个浩大的工程开始之前,先完善一下前辈开发的电力系统规约字段解析工具,它可以选择不同的规约类型,输入对应的规约报文,然后告诉你对应的字段是什么含义,我需要完善积成103规约的解析功能,在完善完这个小工具之后再进行103规约的开发。
下图是我刚开发出的解析通用分类服务的功能:
这个小工具大家如果有需要,可以后台私信我。
复习预编译条件判断
1 | # 空指令,无任何效果 |
在电力系统中有很多协议会用到APDU这个东西,比如101、102、103、104协议都会用到,说白了APDU就是这些协议的整个帧的一个称呼。
在我这次开发的积成103规约中,APDU的长度是控制域的第一个字节到ASDU的最后一个字节的长度。APDU的最大值是253(255减去前两个字节,也就是16进制的0xFD。
通用分类标识序号(GIN)
什么是通用分类服务,分类的是什么服务,有哪些服务需要分类?有什么作用?
是否可以这么理解呢?就是再兼容范围内的我就可以用ASDU来传输,不在兼容范围的我就得用通用分类服务,但有些已经生产的保护设备在硬件方面难以改动,所以整了个专用范围来使这些保护设备可以使用通用分类服务。
通用分类服务可以传输任何数据,一般会有一个数据集,而数据集又包含上图中的四个项目。
通用分类服务用的是ASDU类型标识21和10,其中21表示请求命令,10表示响应命令,那么
监视方向:保护设备到控制系统
控制方向:控制系统到保护设备
103协议和104协议它们接收序号和发送序号的处理是否一致?答案是一致的。
NGD占一个字节,前六位表示数目,第七位表示计数器位(具有相同返回信息标识符(RII)的应用服务数据单元的一位计数器位),计数器位(COUNT)的初始值为零,第八位表示后续状态位,其中若是0 :后面未跟着具有相同返回信息标识符(RII)的应用服务数据单元; 若是1 :后面跟着具有相同返回信息标识符(RII)的应用服务数据单元。
GIN占两个字节,KOD占两个字节,GDD占三个字节,GID占i个字节,i:=数据宽度(DATASIZE)乘以数目(NUMBER)
发送序号和接收序号的首位都是0,是不用的,只用来标识此帧是I帧。发送序号和接收序号都是用7+8=15位来表示,也就是2^15=32768,可以表示32768个序号。
发送序号要和接收序号做比较。
1 | qy.Format("%02X%s启动符\r\n", m_pRxdFm103->bStart, GetSpace(1)); |
这段代码使用了 CString
类的 Format
方法来格式化一个字符串。具体分析如下:
代码解释
1 | qy.Format("%02X%s启动符\r\n", m_pRxdFm103->bStart, GetSpace(1)); |
各部分详解
qy:
qy
是一个CString
对象,用于存储格式化后的字符串。
Format:
Format
是CString
类的一个方法,用于格式化字符串。它的用法类似于标准 C 的sprintf
函数。
“%02X%s启动符\r\n”:
- 这是格式化字符串,其中包含格式说明符:
%02X
:表示一个两位的十六进制数,不足两位时前面补零。%s
:表示一个字符串。启动符
:表示字符串的一部分,固定内容。\r\n
:表示回车换行。
- 这是格式化字符串,其中包含格式说明符:
m_pRxdFm103->bStart:
m_pRxdFm103
是一个指向某个结构体或类实例的指针,bStart
是其中的一个成员变量。bStart
的值将被格式化为两位的十六进制数。
GetSpace(1):
GetSpace(1)
是一个函数调用,返回一个字符串。- 假设
GetSpace
函数返回一个长度为1的空格字符串。
整体作用
这段代码的作用是将 m_pRxdFm103->bStart
变量的值格式化为两位的十六进制数,并与一个由 GetSpace(1)
返回的字符串和固定的 “启动符\r\n” 连接起来,最终结果存储在 qy
对象中。
示例
假设 m_pRxdFm103->bStart
的值为 15(十进制),即 0x0F
(十六进制),且 GetSpace(1)
返回一个空格字符 " "
,那么 qy
的值将会是:
1 | 0F 启动符\r\n |
这是一个常见的字符串格式化操作,用于生成易于阅读和分析的调试信息或日志
1 | //后七个字节是时间,也就是年月日时分秒 |
积成103报文:
68 11 06 00 02 00 06 81 08 00 FF 00 23 45 06 0B 08 08 18
其中23 45 06 0B 08 08 18代表的是时间,而这个报文我们采用如下结构体存放:
1 | typedef struct |
和上面解析时间的代码对照来看的话,Data[0]里面存放的就是23H,Data[1]里存放的就是45H,以此类推Data[6]就是18