首页 > 解决方案 > pymodbus 如何通过真实的串行端口测试我的串行 RTU 服务器

问题描述

我尝试为我的 pymodbus RTU 服务器编写一个 pytest,我想将 32 位浮点编码值写入服务器并将其与服务器自己的寄存器读取方法进行比较。服务器看起来像这样:

class ModbusRTUServer:
    P_target_address = 0x33
    def __init__(self, port, timeout, baudrate):
        self.thread = None
        self.port = port
        self.timeout = timeout
        self.baudrate = baudrate
        self.block = ModbusSequentialDataBlock.create()
        self.store = ModbusSlaveContext(hr=self.block, ir=self.block)
        self.context = ModbusServerContext(slaves=self.store)
        self.P_target = 0

    def _run_server_threaded(self):
        StartSerialServer(
            self.context,
            framer=ModbusRtuFramer,
            port=self.port,
            timeout=self.timeout,
            baudrate=self.baudrate,
        )
        l.debug("StartSerialServer() ended.")

    def run_server(self):
        self.thread = Thread(target = self._run_server_threaded)
        self.thread.start()

    def stop_server(self):
        StopServer()

    def get_P_target_float32(self):
        return BinaryPayloadDecoder.fromRegisters(
            self.block.getValues(ModbusRTUServer.P_target_address, 2), 
            byteorder=Endian.Big, wordorder=Endian.Big
        ).decode_32bit_float()

这是测试,它不起作用:

@patch("twisted.internet.serialport.SerialPort")
def test_modbus_rtu_server_get_P_target_float32_should_be_big_endian_encoded(mock_sp) -> None:
    with patch('twisted.internet.reactor') as mock_reactor:
        m, s = os.openpty()

        server = ModbusRTUServer(os.ttyname(s), test_server_timeout, test_server_baudrate)
        server.run_server()
        assert mock_reactor.run.call_count == 1

        val_f = -3.33
        builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big)
        builder.add_32bit_float(val_f)
        print(builder.to_registers()) # [49237, 7864]

        client = ModbusSerialClient(method='rtu', baudrate=test_server_baudrate, timeout = test_server_timeout, port=os.ttyname(m))
        client.connect()
        assert client.is_socket_open() == True

        client.write_registers(ModbusRTUServer.P_target_address, builder.to_registers())
        assert server.get_P_target_float32() >= val_f - 0.01
        assert server.get_P_target_float32() <= val_f + 0.01

这些是我最终得到的日志消息:

>           assert server.get_P_target_float32() <= val_f + 0.01
E           assert 4.775518667735688e-39 <= (-3.33 + 0.01)
E            +  where 4.775518667735688e-39 = <bound method ModbusRTUServer.get_P_target_float32 of <smc.ModbusRTUServer object at 0x7f2353f78d60>>()
E            +    where <bound method ModbusRTUServer.get_P_target_float32 of <smc.ModbusRTUServer object at 0x7f2353f78d60>> = <smc.ModbusRTUServer object at 0x7f2353f78d60>.get_P_target_float32

tests/test_modbus.py:47: AssertionError
-------------------------------------------------------------------------------------------------------- Captured log call --------------------------------------------------------------------------------------------------------
INFO     pymodbus.server.asynchronous:asynchronous.py:327 Starting Modbus Serial Server on /dev/pts/12
DEBUG    pymodbus.server.asynchronous:asynchronous.py:223 Running in spawned thread
DEBUG    pymodbus.payload:payload.py:125 [49237, 7864]
DEBUG    pymodbus.payload:payload.py:125 [49237, 7864]
DEBUG    pymodbus.transaction:transaction.py:139 Current transaction state - IDLE
DEBUG    pymodbus.transaction:transaction.py:144 Running transaction 1
DEBUG    pymodbus.transaction:transaction.py:273 SEND: 0x0 0x10 0x0 0x33 0x0 0x2 0x4 0xc0 0x55 0x1e 0xb8 0x91 0x90
DEBUG    pymodbus.client.sync:sync.py:76 New Transaction state 'SENDING'
DEBUG    pymodbus.transaction:transaction.py:287 Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
DEBUG    pymodbus.transaction:transaction.py:303 Transaction failed. (Modbus Error: [Invalid Message] No response received, expected at least 2 bytes (0 received)) 
DEBUG    pymodbus.framer.rtu_framer:rtu_framer.py:240 Frame - [b''] not ready
DEBUG    pymodbus.transaction:transaction.py:465 Getting transaction 0
DEBUG    pymodbus.transaction:transaction.py:224 Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
DEBUG    pymodbus.payload:payload.py:312 [52, 52]
DEBUG    pymodbus.payload:payload.py:368 [b'\x004', b'\x004']
DEBUG    pymodbus.payload:payload.py:312 [52, 52]
DEBUG    pymodbus.payload:payload.py:368 [b'\x004', b'\x004']

当我在连接到另一个 raspi 的真实串行端口上运行此服务器并在那里启动相同的客户端示例时,一切正常。

我在所有示例和测试中进行了搜索,但没有找到解决此问题的方法或如何通过真实串行端口进行此类测试的示例。非常感谢任何帮助!

标签: pythonpytestpymodbuspytest-mock

解决方案


推荐阅读