IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Python 解析 DLT645 协议数据

    obaby发表于 2024-10-30 02:05:20
    love 0

    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



沪ICP备19023445号-2号
友情链接