1. 解读DLT698.45-2017通信规约--预连接响应

国家电网有限公司企业标准,面向对象的用电信息数据交换协议DLT698.45-2017

为提高用电信息采集系统的业务适应性、采集效率、安全性和数据溯源性,规范用电信息数据交换协议的通信架构、数据链路层、应用层、接口类与对象标识,制定本标准。

首先弄清楚服务器(从站)和客户端(主站)。

主站访问采集终端时,采集终端为服务器,主站为客户机;

主站访问电能表时,电能表为服务器,主站为客户机;

采集终端访问电能表时,电能表为服务器,采集终端为客户机。

帧格式

其中帧格式中有两处校验,帧头校验HCS和帧校验FCS。

**帧头校验HCS:**帧头校验HCS为2字节,是对帧头部分不包含起始字符和HCS本身的所有字节的校验。

**帧校验FCS:**帧校验FCS为2字节,是对整帧不包含起始字符、结束字符和FCS本身的所有字节的校验。

C#为例 private static ushort[] Fcstab = new ushort[256]{            0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,            0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,            0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,            0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,            0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,            0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,            0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,            0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,            0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,            0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,            0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,            0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,            0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,            0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,            0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,            0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,            0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,            0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,            0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,            0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,            0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,            0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,            0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,            0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,            0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,            0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,            0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,            0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,            0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,            0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,            0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,            0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78            };

        static ushort PPPINITFCS16 = 0xffff;


        private static ushort Pppfcs16(ushort fcs, byte[] cp, int len)        {            for (int i = 0; i < len; i++)                 fcs = (ushort)((fcs >> 8) ^ Fcstab[(fcs ^ cp[i]) & 0xff]);             return fcs;        }
        public static string GetFCS16(byte[] cp)        {            ushort trialfcs = Pppfcs16(PPPINITFCS16, cp, cp.Length);            trialfcs ^= 0xffff; /* complement */            string hex = ConvertHelper.TenToHex2(trialfcs & 0x00ff);            hex = hex + " " + ConvertHelper.TenToHex2((trialfcs >> 8) & 0x00ff);            return hex;        }

有了帧格式,我们就不用再通篇细看,根据需要直接构建帧

模拟场景:采集终端(集中器)和上位机交互。中继器(服务器)向客户机(主站)发起预连接请求,主站予以回应。

构建预连接请求帧

根据帧格式可以看出,帧头和帧尾基本是固定格式我们先跳过,先看APDU部分。

应用层数据单元(APDU)包括:

Link-APDU

Client-APDU

Server-APDU

Security-APDU

Link-APDU的数据类型定义如下所示:

/**LINK-APDU∷=CHOICE{  预连接请求   [1]     LINK-Request,  预连接响应   [129]   LINK-Response}**/

LINK-APDU包括预连接请求和预连接响应,正是我们想要的,接着查找预连接请求,ID是1,英文名是LINK-Request。

查看LINK-Request(预连接请求)的数据类型定义

**LINK-Request∷=SEQUENCE{   服务序号-优先级-ACD PIID-ACD   请求类型 ENUMERATED  {     登录 (0),     心跳 (1),     退出登录 (2)  },   心跳周期 long-unsigned,   请求时间 date_time}**//

可以看到,LINK-Request包括服务序号-优先级-ACD、请求类型、心跳周期、请求时间; 这就简单了,一共才四项内容。

  1. 服务序号-优先级-ACD(PIID-ACD)

搜索PIID-ACD可以看到它的数据类型是"unsigned",unsigned是8位正整数,数据范围是0-255,这么说unsigned占1个字节。

接下来搜索PIID-ACD的数据类型定义

bit7(服务优先级)------0:普通优先级,1:高优先级,在应答 APDU

中,其值与请求的 APDU 相同。

bit6(请求访问 ACD)------0:不请求,1:请求。

bit0...bit5(服务序号)------二进制编码表示 0...63,在应答 APDU 中,其值与请求的 APDU 相同。

构建PIID-ACD:0x00,00000000(普通优先级,不请求,服务序号0)

  1. 请求类型

也是占用1个字节,登录(0), 心跳(1), 退出登录(2)

构建请求类型:0x00,登录

  1. 心跳周期

心跳周期单位是秒,类型是"long-unsigned",占16位,也就是2个字节,这里可以设置成60秒。

构建心跳周期:0x00 0x3C

  1. 请求时间

类型是"date_time",占10个字节, 顺序是:

"年、月、日、一周的第几天、时、分、秒、毫秒"

其中年和毫秒占两个字节。

构建完成的LINK-Request十六进制报文

00 00 00 3C 07 E7 0B 1A 07 10 38 13 02 F8

最后在报文前加上LINK-Request的ID

01 00 00 00 3C 07 E7 0B 1A 07 10 38 13 02 F8

然后我们再回过头来把帧头和帧尾加上

帧头

  1. 起始字符:68H

  2. 长度域:预留

帧数据长度,是传输帧中不包含起始字符和结束字符的字节数

  1. 控制域

DIR和PRM组合:10(表示服务器发起的上报)

分帧标志:0(完整帧)

扰码标志SC:0(不加扰码)

功能码

功能码只有两种可选,分别是001链路管理和011用户数据,这里用001。

组合在一起,控制域:10000001(0x81)

  1. 地址域

地址域由"服务器地址SA"和"客户端地址CA"组成。

如图所示,服务器地址SA由 1字节地址特征 和 N个字节地址 组成。

地址类型:00(表示单地址)

逻辑地址:00(不知道就先用0,这个逻辑地址应该可以自定义)

地址长度:0011(这里假设地址长度8,占4个字节)

地址:12 23 34 45

组合在一起,服务器地址SA:00000011(03 45 34 23 12)

客户端地址CA:00(不关注客户机地址)

  1. 帧头校验

帧头校验HCS为2字节,是对帧头部分不包含起始字符和HCS本身的所有字节的校验。

6 帧尾

帧校验FCS:xx xx

结束符:16H

最后完整报文如下所示:

68 xx xx 81 03 45 34 23 12 00 01 00 00 00 3C 07 E7 0B 1A 07 10 38 13 02 F8 xx xx 16

构建预连接响应帧

找到预连接响应(LINK-Response)数据类型定义

/**LINK-Response∷=SEQUENCE{   服务序号-优先级 PIID,   结果 Result,   请求时间 date_time,   收到时间 date_time,   响应时间 date_time}**/

如上所示,我们主要看其中的Result,如下是Result的数据类型定义

/**Result∷=bit-string(SIZE(8)){ bit7(时钟可信标志) (0), bit6(保留) (1), bit5(保留) (2), bit4(保留) (3), bit3(保留) (4), bit2(结果) (5), bit1(结果) (6), bit0(结果) (7)}**/

时钟可信标志------用于表示响应方的时钟是否可信,bit7=0:不可信,bit7=1:可信。

bit0...bit2------二进制编码表示结果,0:成功,1:地址重复,2:非法设备,3:容量不足,其它值:保留。

从上面可以看出预连接响应还是挺简单的,不考虑帧头帧尾,构建APDU部分:

预连接响应ID:129(0x81)

PIID(和请求帧一样):0x00,00000000(普通优先级,不请求,服务序号0)

结果Result:0x80,10000000(时钟可信,结果成功)

请求时间:请求帧里面的时间

收到时间,响应时间:注意格式是date_time就行

响应APDU: 81 00 80 (请求时间10字节) (收到时间10)(响应时间10)

响应帧头

起始符:68H

长度域L:预留

控制域C:00000001, 0x01

00(客户机对服务器上报的响应)0(完整APDU)0(保留)0(不加扰码)001(功能码)

地址域A:同请求帧

帧头校验HCS:xx xx

响应帧尾

帧校验FCS:xx xx

结束符:16H

最后完整的响应帧

68 (长度2字节) 01 03 45 34 23 12 00 (帧头校验HCS) 81 00 80 (请求时间10字节) (收到时间10)(响应时间10)(帧校验FCS) 16

相关推荐
热爱跑步的恒川2 小时前
【论文复现】基于图卷积网络的轻量化推荐模型
网络·人工智能·开源·aigc·ai编程
云飞云共享云桌面3 小时前
8位机械工程师如何共享一台图形工作站算力?
linux·服务器·网络
音徽编程5 小时前
Rust异步运行时框架tokio保姆级教程
开发语言·网络·rust
幺零九零零6 小时前
【C++】socket套接字编程
linux·服务器·网络·c++
23zhgjx-NanKon7 小时前
华为eNSP:QinQ
网络·安全·华为
23zhgjx-NanKon7 小时前
华为eNSP:mux-vlan
网络·安全·华为
点点滴滴的记录7 小时前
RPC核心实现原理
网络·网络协议·rpc
Lionhacker8 小时前
网络工程师这个行业可以一直干到退休吗?
网络·数据库·网络安全·黑客·黑客技术
程思扬8 小时前
为什么Uptime+Kuma本地部署与远程使用是网站监控新选择?
linux·服务器·网络·经验分享·后端·网络协议·1024程序员节
ZachOn1y8 小时前
计算机网络:运输层 —— 运输层概述
网络·tcp/ip·计算机网络·运输层