阅读视图

发现新文章,点击刷新页面。

Python 解析 DLT645 协议数据

作者 obaby

DL/T 645是中国国家电网公司制定的一种用于电能表通信的协议,全称为《多功能电能表通信协议》。该协议主要用于电能表与数据采集终端(如集中器、抄表器等)之间的通信,以实现电能数据的采集、传输和管理。

主要特点

  1. 多功能性:支持多种电能参数的读取和设置,如电压、电流、功率、电能、功率因数等。
  2. 灵活性:支持多种通信方式,如RS-485、红外、无线等。
  3. 安全性:支持数据加密和身份验证,确保数据传输的安全性。
  4. 标准化:符合国家电网公司的标准,便于大规模部署和维护。

协议结构

DL/T 645协议的数据帧结构通常包括以下几个部分:

  1. 帧起始符:标识数据帧的开始,通常为0x68。
  2. 地址域:标识电能表的地址,通常为6字节。
  3. 控制码:标识命令类型,如读取数据、写入数据等。
  4. 数据域:包含具体的命令数据或返回的数据。
  5. 校验码:用于校验数据帧的完整性,通常为1字节。
  6. 帧结束符:标识数据帧的结束,通常为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

❌