You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python读取大端字节序(BIG Endian)数据?Modbus电表场景

问题:如何用PyModbus读取大端字节序并转换为目标电表数值

我正在开发一套监控系统,使用PyModbus读取电表数据。读取寄存器地址后得到字节列表:result_ups.registers = [3468, 204, 0, 2080],希望将其转换为电表显示的数值20434682080。当前代码如下:

from pymodbus.client import ModbusTcpClient
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
import time


client_tcp = ModbusTcpClient('10.123.133.100',port=502)

while True:
    try:
        client_tcp.connect()
        while True:
            result_ups = client_tcp.read_holding_registers(1716,4,units=1,slave=1)
            decoder_ups = BinaryPayloadDecoder.fromRegisters(result_ups.registers,byteorder=Endian.BIG,wordorder=Endian.LITTLE)
            kwh_ups = decoder_ups.decode_32bit_int()
            print(kwh_ups)
            time.sleep(1)
         
    except Exception as e:
        print(e)
        time.sleep(1)

请问如何实现读取大端字节序(BIG Endian)并转换为目标数值?


解决方案

你的核心问题在于:原代码用decode_32bit_int()解析32位整数,但目标数值是64位范围的拼接/BCD格式,且电表采用大端字序存储(高位字在前),需要调整寄存器顺序后再解析。以下是两种可行实现:

方式一:直接按字序拼接(明确映射规则时使用)

如果已确认电表数值由寄存器2(204)、寄存器1(3468)、寄存器4(2080)拼接而成,直接调整顺序后拼接十进制字符串:

from pymodbus.client import ModbusTcpClient
import time

client_tcp = ModbusTcpClient('10.123.133.100', port=502)

while True:
    try:
        client_tcp.connect()
        while True:
            result_ups = client_tcp.read_holding_registers(1716, 4, units=1, slave=1)
            # 按大端字序重新排列寄存器:高位到低位
            reordered_regs = [
                result_ups.registers[1],
                result_ups.registers[0],
                result_ups.registers[3],
                result_ups.registers[2]
            ]
            # 每个寄存器补前导零到4位,拼接后转整数并去除末尾无效零
            kwh_ups = int(''.join(f"{reg:04d}" for reg in reordered_regs).rstrip('0'))
            print(kwh_ups)
            time.sleep(1)
    except Exception as e:
        print(e)
        time.sleep(1)

方式二:解析BCD码(符合电表通用存储规范)

多数电表采用BCD码存储电量,每个16位寄存器对应4位BCD码。按大端字节序解析:

from pymodbus.client import ModbusTcpClient
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
import time

def bcd_to_int(bcd_bytes):
    """将BCD字节数组转换为整数"""
    result = 0
    for byte in bcd_bytes:
        # 拆分字节的高4位和低4位,转换为十进制
        result = result * 100 + ((byte >> 4) & 0x0F) * 10 + (byte & 0x0F)
    return result

client_tcp = ModbusTcpClient('10.123.133.100', port=502)

while True:
    try:
        client_tcp.connect()
        while True:
            result_ups = client_tcp.read_holding_registers(1716, 4, units=1, slave=1)
            # 按大端字序调整寄存器顺序,确保高位在前
            decoder = BinaryPayloadDecoder.fromRegisters(
                [result_ups.registers[1], result_ups.registers[0], result_ups.registers[3], result_ups.registers[2]],
                byteorder=Endian.BIG,
                wordorder=Endian.BIG
            )
            # 读取8字节原始数据
            raw_bytes = decoder.decode_bytes(8)
            # 转换为BCD整数
            kwh_ups = bcd_to_int(raw_bytes)
            print(kwh_ups)
            time.sleep(1)
    except Exception as e:
        print(e)
        time.sleep(1)

关键说明

  • 原代码的decode_32bit_int()仅能处理32位整数,无法匹配目标数值的格式和范围,因此失效。
  • 调整寄存器顺序是因为电表采用大端字序:原始读取的[3468,204]是低位字在前,需反转成[204,3468]作为数值的高位部分,同理[0,2080]反转成[2080,0]作为低位部分。

内容的提问来源于stack exchange,提问作者Joshe Danianta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 23:17:33