3

I have a python script which can handle Modbus transactions using the pymodbus library. For troubleshooting purposes I would like to print the raw bytes sent and received to the device, preferably in hex format.

Here is simplified code, see the comments at the bottom for an example of what I would like to get. I used a TCP client but would like it to work on a ModbusSerialClient too.

from pymodbus.client.sync import ModbusTcpClient

ipAddress = '10.130.14.174'
registerToRead = 3000

client = ModbusTcpClient(ipAddress, port=502)
connection = client.connect()

response = client.read_holding_registers(registerToRead, 1, unit=1)

print(response.registers)

# Would like to get something like:
# OUT: [00h] [00h] [00h] [00h] [00h] [06h] [01h] [03h] [0Bh] [B8h] [00h] [01h] 
# IN : [00h] [00h] [00h] [00h] [00h] [05h] [01h] [03h] [02h] [00h] [FFh] 

I tried response.encode() but that only returned b'\x02\x00\xff'

J. Murray
  • 1,460
  • 11
  • 19
Dave1551
  • 323
  • 2
  • 13
  • I was looking at the same thing. It is very strange that we don't have access to the raw bytes read. It looks like that some point the raw bytes are decoded by this function https://github.com/pymodbus-dev/pymodbus/blob/7f994edf26ec33ef00cfacec17e809881713a667/pymodbus/register_read_message.py#L84 – kaptan Jan 31 '23 at 23:17

1 Answers1

2

To get the raw frames you just need to run the request in debug mode.

That would be something like this:

from pymodbus.client.sync import ModbusTcpClient
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)

ipAddress = '10.130.14.174'
registerToRead = 3000

client = ModbusTcpClient(ipAddress, port=502)
connection = client.connect()

response = client.read_holding_registers(registerToRead, 1, unit=1)

If you are running this code from the Python console now you should see something similar to this:

2019-10-08 13:10:42,872 MainThread      DEBUG    transaction    :111      Current transaction state - TRANSACTION_COMPLETE
2019-10-08 13:10:42,872 MainThread      DEBUG    transaction    :116      Running transaction 3
2019-10-08 13:10:42,872 MainThread      DEBUG    transaction    :215      SEND: 0x0 0x3 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0x1 0x0 0x1
2019-10-08 13:10:42,872 MainThread      DEBUG    sync           :73       New Transaction state 'SENDING'
2019-10-08 13:10:42,872 MainThread      DEBUG    transaction    :224      Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
2019-10-08 13:10:42,873 MainThread      DEBUG    transaction    :300      Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
2019-10-08 13:10:42,873 MainThread      DEBUG    transaction    :229      RECV: 0x0 0x3 0x0 0x0 0x0 0x5 0x1 0x3 0x2 0x0 0x14
2019-10-08 13:10:42,873 MainThread      DEBUG    socket_framer  :147      Processing: 0x0 0x3 0x0 0x0 0x0 0x5 0x1 0x3 0x2 0x0 0x14
2019-10-08 13:10:42,873 MainThread      DEBUG    factory        :266      Factory Response[ReadHoldingRegistersResponse: 3]
2019-10-08 13:10:42,873 MainThread      DEBUG    transaction    :379      Adding transaction 3
2019-10-08 13:10:42,873 MainThread      DEBUG    transaction    :390      Getting transaction 3
2019-10-08 13:10:42,873 MainThread      DEBUG    transaction    :189      Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
>>> 

If you want more details or you need to process more than a couple of frames I would advise to install Wireshark which is very powerful. If you need to do the same with Modbus over serial you can try SerialPCAP.

EDIT: This is probably something you don't need at the moment but in case you don't have access to either side of a Modbus serial link you can tap on the bus or use a software sniffer as I explained here, here and here.

For Modbus TCP, I'm not aware of any easy technique to monitor traffic with Wireshark if you don't have access to either side of the link or to the network switch.

Marcos G.
  • 3,371
  • 2
  • 8
  • 16