pymodbus:从 Modbus 设备读取字符串和多种类型的数据
pymodbus: Issue reading String & multiple type of data from Modbus device
我正在尝试从 Modbus TCP 设备读取 String
(Usecase-1) & multiple type of data in one request
(Usecase-2) 数据,但是失败了正确解码。
系统配置:
Python 3.6.5
Pymodbus: 2.1.0
Platform: Windows 10 64-bit
Modbus TCP 服务器:
import logging
from pymodbus.constants import Endian
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.payload import BinaryPayloadBuilder
from pymodbus.server.sync import StartTcpServer
class ModbusTCPServer(object):
# initialize your data store:
hrBuilder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big)
# Usecase-1
hrBuilder.add_string("abcdefghij")
#Uncomment below three lines for usecase-2
# hrBuilder.add_32bit_float(20.5)
# hrBuilder.add_32bit_int(45)
# hrBuilder.add_bits([1, 0, 0, 0, 0, 0, 0, 0])
hrBlock = ModbusSequentialDataBlock(0, hrBuilder.to_registers() * 100)
store = ModbusSlaveContext(hr=hrBlock, ir=hrBlock, di=hrBlock, co=hrBlock)
slaves = {
1: store,
}
context = ModbusServerContext(slaves=slaves, single=False)
# initialize the server information
identity = ModbusDeviceIdentification()
modbusDeviceAddress = "127.0.0.1"
modbusDevicePort = 501
# run the TCP server
# TCP:
print("Modbus TCP Server started.")
StartTcpServer(context, identity=identity, address=(modbusDeviceAddress, modbusDevicePort))
if __name__ == "__main__":
print("Reading application configurations...")
ModbusTCPServer();
Modbus TCP 客户端:
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.constants import Endian
from pymodbus.compat import iteritems
if __name__ == '__main__':
client = ModbusClient('127.0.0.1', port=501)
client.connect()
result = client.read_holding_registers(0, 5, unit=1)
print("Result : ",result)
decoder = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=Endian.Big, wordorder=Endian.Big)
# Usecase-1
decoded = {
'name': decoder.decode_string(10).decode(),
}
# Usecase-2
# decoded = {
# 'temp': decoder.decode_32bit_float(),
# 'rpm': decoder.decode_32bit_int(),
# 'status': decoder.decode_bits()
#}
for name, value in iteritems(decoded):
print ("%s\t" % name, value)
client.close()
输出用例 1:
Result : ReadRegisterResponse (5)
name cdefghijab
Modbus 客户端应将字符串解码为 abcdefghij
,但它却将其解码为 cdefghijab
。
输出用例 2:
Result : ReadRegisterResponse (5)
temp 0.0
rpm 2949376
status [True, False, False, False, False, False, True, False]
查看上面读取多个寄存器的输出,输出值与输入给定的值不匹配BinaryPayloadBuilder
。
我已经尝试了 byteorder
和 wordorder
的所有组合,但是,它对任何情况都不起作用。
请帮助我理解为什么数据会这样解码?我在编码或解码此数据时是否错过了要添加的内容?
仅供参考: 此解决方案适用于 Pymodbus 1.5.1
版本。最近我升级了版本,但未能按预期工作。
如有任何帮助,我们将不胜感激。
Tl;博士。在 ModbusSlaveContext
.
中使用 zero_mode=True
如果您想将客户端中的寄存器 [0..n]
映射到服务器中的 [0..n]
。默认情况下,pymodbus 服务器将地址 [0..n]
的寄存器读取映射到其内部存储中的寄存器 [1..n]
。这是为了遵守 modbus 规范。引用自 pymodbus 源代码。
#The slave context can also be initialized in zero_mode which means that a
# request to address(0-7) will map to the address (0-7). The default is
# False which is based on section 4.4 of the specification, so address(0-7)
# will map to (1-8)::
因此在您的情况下,您可以将 ModbusSequentialDataBlock
的起始地址设置为 1
或使用 zero_mode=True
.
初始化 ModbusSlaveContext
hrBlock = ModbusSequentialDataBlock(1, hrBuilder.to_registers() * 100)
# Or
store = ModbusSlaveContext(hr=hrBlock, ir=hrBlock, di=hrBlock, co=hrBlock, zero_mode=True)
我正在尝试从 Modbus TCP 设备读取 String
(Usecase-1) & multiple type of data in one request
(Usecase-2) 数据,但是失败了正确解码。
系统配置:
Python 3.6.5
Pymodbus: 2.1.0
Platform: Windows 10 64-bit
Modbus TCP 服务器:
import logging
from pymodbus.constants import Endian
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.payload import BinaryPayloadBuilder
from pymodbus.server.sync import StartTcpServer
class ModbusTCPServer(object):
# initialize your data store:
hrBuilder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big)
# Usecase-1
hrBuilder.add_string("abcdefghij")
#Uncomment below three lines for usecase-2
# hrBuilder.add_32bit_float(20.5)
# hrBuilder.add_32bit_int(45)
# hrBuilder.add_bits([1, 0, 0, 0, 0, 0, 0, 0])
hrBlock = ModbusSequentialDataBlock(0, hrBuilder.to_registers() * 100)
store = ModbusSlaveContext(hr=hrBlock, ir=hrBlock, di=hrBlock, co=hrBlock)
slaves = {
1: store,
}
context = ModbusServerContext(slaves=slaves, single=False)
# initialize the server information
identity = ModbusDeviceIdentification()
modbusDeviceAddress = "127.0.0.1"
modbusDevicePort = 501
# run the TCP server
# TCP:
print("Modbus TCP Server started.")
StartTcpServer(context, identity=identity, address=(modbusDeviceAddress, modbusDevicePort))
if __name__ == "__main__":
print("Reading application configurations...")
ModbusTCPServer();
Modbus TCP 客户端:
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.constants import Endian
from pymodbus.compat import iteritems
if __name__ == '__main__':
client = ModbusClient('127.0.0.1', port=501)
client.connect()
result = client.read_holding_registers(0, 5, unit=1)
print("Result : ",result)
decoder = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=Endian.Big, wordorder=Endian.Big)
# Usecase-1
decoded = {
'name': decoder.decode_string(10).decode(),
}
# Usecase-2
# decoded = {
# 'temp': decoder.decode_32bit_float(),
# 'rpm': decoder.decode_32bit_int(),
# 'status': decoder.decode_bits()
#}
for name, value in iteritems(decoded):
print ("%s\t" % name, value)
client.close()
输出用例 1:
Result : ReadRegisterResponse (5)
name cdefghijab
Modbus 客户端应将字符串解码为 abcdefghij
,但它却将其解码为 cdefghijab
。
输出用例 2:
Result : ReadRegisterResponse (5)
temp 0.0
rpm 2949376
status [True, False, False, False, False, False, True, False]
查看上面读取多个寄存器的输出,输出值与输入给定的值不匹配BinaryPayloadBuilder
。
我已经尝试了 byteorder
和 wordorder
的所有组合,但是,它对任何情况都不起作用。
请帮助我理解为什么数据会这样解码?我在编码或解码此数据时是否错过了要添加的内容?
仅供参考: 此解决方案适用于 Pymodbus 1.5.1
版本。最近我升级了版本,但未能按预期工作。
如有任何帮助,我们将不胜感激。
Tl;博士。在 ModbusSlaveContext
.
zero_mode=True
如果您想将客户端中的寄存器 [0..n]
映射到服务器中的 [0..n]
。默认情况下,pymodbus 服务器将地址 [0..n]
的寄存器读取映射到其内部存储中的寄存器 [1..n]
。这是为了遵守 modbus 规范。引用自 pymodbus 源代码。
#The slave context can also be initialized in zero_mode which means that a # request to address(0-7) will map to the address (0-7). The default is # False which is based on section 4.4 of the specification, so address(0-7) # will map to (1-8)::
因此在您的情况下,您可以将 ModbusSequentialDataBlock
的起始地址设置为 1
或使用 zero_mode=True
.
ModbusSlaveContext
hrBlock = ModbusSequentialDataBlock(1, hrBuilder.to_registers() * 100)
# Or
store = ModbusSlaveContext(hr=hrBlock, ir=hrBlock, di=hrBlock, co=hrBlock, zero_mode=True)