Python 解析 DLT645 协议数据
2024年10月30日 10:05
DL/T 645是中国国家电网公司制定的一种用于电能表通信的协议,全称为《多功能电能表通信协议》。该协议主要用于电能表与数据采集终端(如集中器、抄表器等)之间的通信,以实现电能数据的采集、传输和管理。
主要特点
- 多功能性:支持多种电能参数的读取和设置,如电压、电流、功率、电能、功率因数等。
- 灵活性:支持多种通信方式,如RS-485、红外、无线等。
- 安全性:支持数据加密和身份验证,确保数据传输的安全性。
- 标准化:符合国家电网公司的标准,便于大规模部署和维护。
协议结构
DL/T 645协议的数据帧结构通常包括以下几个部分:
- 帧起始符:标识数据帧的开始,通常为0x68。
- 地址域:标识电能表的地址,通常为6字节。
- 控制码:标识命令类型,如读取数据、写入数据等。
- 数据域:包含具体的命令数据或返回的数据。
- 校验码:用于校验数据帧的完整性,通常为1字节。
- 帧结束符:标识数据帧的结束,通常为0x16。
常用命令
- 读取数据:用于读取电能表的各种参数,如电压、电流、功率等。
- 写入数据:用于设置电能表的参数,如时间、费率等。
- 广播校时:用于同步电能表的时间。
- 冻结命令:用于冻结电能表的当前数据,便于后续读取。
应用场景
DL/T 645协议广泛应用于智能电网、电力监控系统、远程抄表系统等领域。通过该协议,可以实现电能数据的实时采集、远程监控和自动化管理,提高电力系统的运行效率和管理水平。
数据报文格式:
数据报文解析相对来说并不复杂,所有的数据都是流式,直接按照顺序进行读取即可。不过里面数据的内容,并不需要在此进行数值转换(电力数据需要处理),基本读到什么内容就是什么内容。
例如原始数据:
message = b'hw8\x06(\x15Dh\x00\x02\x01\x1f(\x16'
解析数据可以通过下面的方法:
def process_645_data(message): print('message in hex=', message.hex()) start_pos = message[0:1] # print('start_code = ', start_pos.hex()) hid = message[1:7] # print(hid) # int_value = int.from_bytes(hid,byteorder='little') # 默认使用大端模式 # print(int_value) # int_value = int.from_bytes(hid,byteorder='big') # 默认使用大端模式 # print(int_value) print('hid = ', hid[::-1].hex()) hid_hex = hid[::-1].hex() # print(hid.hex()) data_pos = message[7:8] # print('data_pos = ', data_pos.hex()) control_code = message[8:9] print('control_code = ', control_code.hex()) data_length = message[9:10] print('data_length =', data_length.hex()) data_lenth_int = int.from_bytes(data_length, byteorder='little') data = message[10:10 + data_lenth_int] print('data = ', data) crc_code = message[10 + data_lenth_int:11 + data_lenth_int] # crc_source = message[0:10 + data_lenth_int] # calced_crc = calc_crc(crc_source) # print('calced crc = ', calced_crc) print('crc_code = ', crc_code.hex()) end_pos = message[11 + data_lenth_int:12 + data_lenth_int] # print('end_pos = ', end_pos.hex()) return hid, hid_hex, control_code, data_lenth_int, crc_code, data
接收到的数据解析出来之后不需要再进行转换int.from_bytes(hid,byteorder=’little’) 不管是大端还是小端模式,转出来都是错的,直接将高低位倒序输出即可:hid[::-1].hex()
解析后的数据:
message in hex= 68773806281544680002011f2816 hid = 441528063877 control_code = 00 data_length = 02 data = b'\x01\x1f' crc_code = 28
对于数据上报的内容,例如电量,电报上报数据为下面的报文:
# 电量上报数据 data_msg = b'\x68\x77\x38\x06\x28\x15\x44\x68\x91\x08\x33\x33\x34\x33\x33\x33\x33\x33\x38\x16'
解析数据内容:
data_msg = b'\x68\x77\x38\x06\x28\x15\x44\x68\x91\x08\x33\x33\x34\x33\x33\x33\x33\x33\x38\x16' hid, hid_hex, control_code, data_lenth_int, crc_code, data = process_654_data(data_msg) print(control_code.hex()) print(data.hex()) data_type = data[0:4] data_source = data[4:] process_data_type = bytes(byte - 0x33 for byte in data_type) print(process_data_type[::-1].hex()) process_data_data = bytes(byte - 0x33 for byte in data_source) print(process_data_data[::-1].hex()) print(int(process_data_data[::-1].hex(), 16) / 100)
解析后的数据:
message in hex= 6877380628154468910833333433333333333816 hid = 441528063877 control_code = 91 data_length = 08 data = b'33433333' crc_code = 38 91 3333343333333333 00010000 00000000 0.0
crc 计算方法:
def calc_crc(src): sum = 0 for i in range(len(src)): sum += src[i] crc = sum % 256 return crc
数据解析处理参考:https://blog.csdn.net/m0_37651448/article/details/143100598