代码之家  ›  专栏  ›  技术社区  ›  Benyamin Jafari

在modbustcp reading中第二次尝试获得结果的原因是什么?

  •  0
  • Benyamin Jafari  · 技术社区  · 6 年前

    有时,当我第一次从modbus设备读取数据时,会立即得到错误响应,但当我再次尝试时,这个响应是预期的结果。

    这是第一次出现的错误消息:

    pymodbus.exceptions.ModbusIOException(pymodbus.exceptions.InvalidMessageReceivedException('Incomplete message received, expected at least 8 bytes (0 received)'), 3)
    

    以下是ipython控制台中的简化代码片段:

    In [1]: from pymodbus.client.sync import ModbusTcpClient
    In [2]: cli = ModbusTcpClient('192.168.1.152', port=502)
    In [3]: cli.connect()
    Out[3]: True
    In [4]: req = cli.read_holding_registers(0x1e, 2, unit=21)  # First try.
    In [5]: req.isError()
    Out[5]: True
    In [6]: req
    Out[6]: pymodbus.exceptions.ModbusIOException(pymodbus.exceptions.InvalidMessageReceivedException('Incomplete message received, expected at least 8 bytes (0 received)'), 3)
    In [7]: req = cli.read_holding_registers(0x1e, 2, unit=21)  # Second try.
    In [8]: req.isError()
    Out[8]: False
    In [9]: req.registers  # As expected.
    Out[9]: [16091, 15697]
    

    原因是什么?


    [更新]:

    我激活modbus从机/服务器日志:

    import logging
    from pymodbus.client.sync import ModbusTcpClient as ModbusClient
    
    logging.basicConfig()
    log = logging.getLogger()
    log.setLevel(logging.DEBUG)
    
    client = ModbusClient('192.168.1.152', port=502)
    client.connect() 
    
    print('First Try: ')
    res = client.read_holding_registers(0x1e, 2, unit=21)
    print('isError = {}'.format(res.isError()))
    
    print('Second Try: ')
    res = client.read_holding_registers(0x1e, 2, unit=21)
    print('isError = {}'.format(res.isError()))
    
    client.close() 
    

    出:

    First Try: 
    DEBUG:pymodbus.transaction:Current transaction state - IDLE
    DEBUG:pymodbus.transaction:Running transaction 1
    DEBUG:pymodbus.transaction:SEND: 0x0 0x1 0x0 0x0 0x0 0x6 0x15 0x3 0x0 0x1e 0x0 0x2
    DEBUG:pymodbus.client.sync:New Transaction state 'SENDING'
    DEBUG:pymodbus.transaction:Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
    DEBUG:pymodbus.transaction:Transaction failed. (Modbus Error: [Invalid Message] Incomplete message received, expected at least 8 bytes (0 received)) 
    DEBUG:pymodbus.framer.socket_framer:Processing: 
    DEBUG:pymodbus.transaction:Getting transaction 1
    DEBUG:pymodbus.transaction:Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
    isError = True
    Second Try: 
    DEBUG:pymodbus.transaction:Current transaction state - TRANSACTION_COMPLETE
    DEBUG:pymodbus.transaction:Running transaction 2
    DEBUG:pymodbus.transaction:SEND: 0x0 0x2 0x0 0x0 0x0 0x6 0x15 0x3 0x0 0x1e 0x0 0x2
    DEBUG:pymodbus.client.sync:New Transaction state 'SENDING'
    DEBUG:pymodbus.transaction:Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
    DEBUG:pymodbus.transaction:Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
    DEBUG:pymodbus.transaction:RECV: 0x0 0x2 0x0 0x0 0x0 0x7 0x15 0x3 0x4 0x3f 0x99 0x8 0xe8
    DEBUG:pymodbus.framer.socket_framer:Processing: 0x0 0x2 0x0 0x0 0x0 0x7 0x15 0x3 0x4 0x3f 0x99 0x8 0xe8
    DEBUG:pymodbus.factory:Factory Response[ReadHoldingRegistersResponse: 3]
    DEBUG:pymodbus.transaction:Adding transaction 2
    DEBUG:pymodbus.transaction:Getting transaction 2
    DEBUG:pymodbus.transaction:Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
    isError = False
    

    如你所见,在第一次尝试中我得到了一个错误,但在第二次尝试中我得到了一个好的结果。

    1 回复  |  直到 6 年前
        1
  •  0
  •   RDorsch    6 年前

    我对Keba热泵控制器也有同样的问题。正如其他人提到的,我的问题是通过将超时时间增加到10秒来解决的,在您的示例中

    client=modbusclient('192.168.1.152',端口=502,超时=10)

    10秒对我来说有一定的差距,我在wireshark中观察到的时间总是在5秒左右。从第二个请求开始,响应总是很容易在几秒钟内到达。

    我的热泵供应商给出的原因是控制器内存不足,而modbus服务器只在第一次收到连接请求时启动。

    @pymodbus开发人员:我建议将default.timeout增加到10秒。