Serial forwarder example

461 views
Skip to first unread message

JoshR

unread,
Jan 5, 2018, 9:27:22 AM1/5/18
to pymodbus
Hi All,

I'm hoping someone might have a working example of the serial forwarder?

I've been trying to get it working from this:

Been reading a few threads, but nothing has jumped out at me. I'm trying to connect a serial (RTU) PLC and interact via TCP through the serial forwarder.


This is my server/forwarder config:

from pymodbus.server.sync import StartTcpServer as StartServer
from pymodbus.client.sync import ModbusSerialClient as ModbusSerialClient

from pymodbus.datastore.remote import RemoteSlaveContext
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext

# --------------------------------------------------------------------------- # 
# configure the service logging
# --------------------------------------------------------------------------- # 
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)


def run_serial_forwarder():
    # ----------------------------------------------------------------------- #
    # initialize the datastore(serial client)
    # ----------------------------------------------------------------------- #
    client = ModbusSerialClient(method='rtu', port='COM5')
    store = RemoteSlaveContext(client)
    context = ModbusServerContext(slaves=store, single=True)

    # ----------------------------------------------------------------------- #
    # run the server you want
    # ----------------------------------------------------------------------- #
    StartServer(context)


if __name__ == "__main__":
    run_serial_forwarder()


This is the client config trying to query over TCP:
#!/usr/bin/env python
 
from pymodbus.client.sync import ModbusTcpClient as ModbusTCPClient
#from pymodbus.client.sync import ModbusUdpClient as ModbusClient
#from pymodbus.client.sync import ModbusSerialClient as ModbusClient

# --------------------------------------------------------------------------- # 
# configure the client logging
# --------------------------------------------------------------------------- # 
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)

def run_sync_client():
    # ------------------------------------------------------------------------# 
    client = ModbusTCPClient('127.0.0.1', port=502, timeout=10)
    # client = ModbusClient(method='ascii', port='/dev/pts/2', timeout=1)
    #client = ModbusClient(method='rtu', port='COM5', timeout=1)
    client.connect()
    # ----------------------------------------------------------------------- #
    log.debug("Reading Holding Registers")
    rr = client.read_holding_registers(0, 8, unit=0x01)
    print("Echoing result", rr.registers)
    # ----------------------------------------------------------------------- #
    client.close()


if __name__ == "__main__":
    run_sync_client()


It drops my PLC serial connection, so then I have to reconnect it.

If I query directly with the serial RTU client, I have no issues:
#!/usr/bin/env python
 
#from pymodbus.client.sync import ModbusTcpClient as ModbusTCPClient
#from pymodbus.client.sync import ModbusUdpClient as ModbusClient
from pymodbus.client.sync import ModbusSerialClient as ModbusClient

# --------------------------------------------------------------------------- # 
# configure the client logging
# --------------------------------------------------------------------------- # 
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)

def run_sync_client():
    # ------------------------------------------------------------------------# 
    #client = ModbusTCPClient('127.0.0.1', port=502, timeout=10)
    # client = ModbusClient(method='ascii', port='/dev/pts/2', timeout=1)
    client = ModbusClient(method='rtu', port='COM5', timeout=10)
    client.connect()
    # ----------------------------------------------------------------------- #
    log.debug("Reading Holding Registers")
    rr = client.read_holding_registers(0, 8, unit=0x01)
    print("Echoing result", rr.registers)
    # ----------------------------------------------------------------------- #
    client.close()


if __name__ == "__main__":
    run_sync_client()


Cheers,
Josh

JoshR

unread,
Jan 5, 2018, 9:49:58 AM1/5/18
to pymodbus
Interestingly, I wanted to compare the difference to see what was being sent over serial when I used the RTU script vs when I used the serial forwarder.
I ran up a virtual serial port, and sent both scripts. When I just use the RTU client script, I get "D" with a line break in my virtual com port. When I use the serial forwarder, I get "E" with no line break.

JoshR

unread,
Jan 7, 2018, 12:50:44 AM1/7/18
to pymodbus
For anyone else looking to bridge Modbus serial RTU to TCP, I spent a bit of time and couldn't get the pymodbus example serial forwarder working. Ended up installing the project here:

Had the PLC bridged and running over TCP in ~10 minutes. Using pymodbus as the client to send modbus TCP commands works perfectly :)

Cheers!
Josh


On Saturday, January 6, 2018 at 12:27:22 AM UTC+10, JoshR wrote:

AaronT

unread,
May 24, 2018, 1:51:50 PM5/24/18
to pymodbus
I am using pymodbus version 1.2 and was able to get the serial forwarder example to work with the following hack.

Instead of this:
if __name__ == '__main__':
    run_serial_forwarder
()

I do this:
import pymodbus.constants
if __name__ == '__main__':
    pymodbus
.constants.Defaults.UnitId = 0x0A
    run_serial_forwarder
()


I guess the Modbus ID is not getting passed from the TCP server to the Serial Client. So the Serial Client is using the default modbus id of 0 (which I don't even think is a valid ID). This just over rides the default id to the id of my modbus device (dec 10, hex 0x0a). 

Of course this hack won't work if you have more than one modbus device on that serial segment.

-Aaron

Abbad Zafar

unread,
Aug 11, 2020, 7:29:02 AM8/11/20
to pymodbus
JoshR or anyone has been able to pull this off. I am in same situation as JoshR. Able to get holding register data through simple RTU read. But cant get data through Forwarder/TCP.

Sanjay KV

unread,
Aug 12, 2020, 9:33:14 PM8/12/20
to pymo...@googlegroups.com
If you are working with real device, make sure you are explicitly initializing the b remote slave context with the unit I'd.

`context = RemoteSlaveContext(
.., unit=<unit-id-of-slave>)`

The default is 0 which works fine with simulated slaves but would be considered as a broadcast address with the real devices generally and no response would be returned back.

ಮಂಗಳ, ಆಗ 11, 2020 16:59 ದಿನಾಂಕದಂದು Abbad Zafar <abbad...@gmail.com> ಅವರು ಬರೆದಿದ್ದಾರೆ:
--
You received this message because you are subscribed to the Google Groups "pymodbus" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pymodbus+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pymodbus/5b419a46-6fc4-417a-a8fb-9ca40a7c2f35n%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages