为 TCP 服务器寄存器赋值的 pymodbus 语法是什么?

What is the pymodbus syntax to assign values to TCP server registers?

我正在尝试使用 Synchronous Server Example 实现一个简单的同步 TCP 服务器。但是,我不明白文档中的语法解释。该示例包括以下代码块:

store = ModbusSlaveContext(
     di=ModbusSequentialDataBlock(0, [17]*100),
     co=ModbusSequentialDataBlock(0, [17]*100),
     hr=ModbusSequentialDataBlock(0, [17]*100),
     ir=ModbusSequentialDataBlock(0, [17]*100))

context = ModbusServerContext(slaves=store, single=True)

假设我想将 152 的值存储到 Input Register (ir) 地址 30001 并将 276 的值存储到地址 30002?我应该如何修改上面的代码?

来自 Pymodbus 文档。

The datastores only respond to the addresses that they are initialized to Therefore, if you initialize a DataBlock to addresses of 0x00 to 0xFF, a request to 0x100 will respond with an invalid address exception. This is because many devices exhibit this kind of behavior (but not all)::

 block = ModbusSequentialDataBlock(0x00, [0]*0xff)

ModbusSequentialDataBlock 在初始化期间接受两个参数 addressvalue.

address – The starting address
values –  List of values to initialise each address with. 

数据块的总大小取决于 len(values) .

所以看看上面的例子,我们正在尝试创建一个大小为 0xFF 的顺序数据块,每个地址都用值 0 初始化。相似地 在你的例子中,如果你想将 152 的值存储到 'Input Register (ir)' 地址 30001,将 276 的值存储到地址 30002,这就是你必须做的。

store = ModbusSlaveContext(

         di=ModbusSequentialDataBlock(0, [17]*100),
         co=ModbusSequentialDataBlock(0, [17]*100),
         hr=ModbusSequentialDataBlock(0, [17]*100),
         ir=ModbusSequentialDataBlock(0, [152, 276]), zero_mode=True)

context = ModbusServerContext(slaves=store, single=True)

请注意,如果不使用 kwarg zero_mode=Trueread_input_registers 对偏移量 0 的请求将 return 276 而不是 152,这是因为没有 zero_mode=True pymodbus 尝试根据规范的第 4.4 节存储值,因此地址(0-7)将映射到(1-8)。如果您不想使用 zero_mode 然后将数据块初始化为 ir=ModbusSequentialDataBlock(1, [152, 276]).

Suppose I want to store a value of 152 to 'Input Register (ir)' address 30001 and a value of 276 to address 30002? How should I adapt the above code?

下面的代码就是你想要的:

from pymodbus.server.sync import StartTcpServer
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext

import logging
FORMAT = ('%(asctime)-15s %(threadName)-15s'
          ' %(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)


def run_server():
    store = ModbusSlaveContext(
        ir=ModbusSequentialDataBlock(30001, [152, 276]), 
        zero_mode=True
    )
    context = ModbusServerContext(slaves=store, single=True)
    StartTcpServer(context, address=("localhost", 5020))


if __name__ == "__main__":
    run_server()

测试用例:

from pymodbus.client.sync import ModbusTcpClient as ModbusClient

cli = ModbusClient('127.0.0.1', port=5020)
assert cli.connect()
res = cli.read_input_registers(30001, count=2, unit=1)
assert not res.isError()
print(res.registers)

输出:

[152, 276]