pymodbus support for Modbus RTU over TCP

3,853 views
Skip to first unread message

StephenL

unread,
Jul 22, 2011, 10:21:07 AM7/22/11
to pymodbus
Hi, all. For a particular type of Modbus device we need to support,
rather than supporting Modbus TCP directly it supports Modbus RTU over
TCP. For some Modbus GUI clients (such as the SimplyModbus client),
this is an option.

Is this type of Modbus interface something that can be handled with
pymodbus?

Thanks,
Stephen

Albert Brandl

unread,
Jul 25, 2011, 3:39:20 AM7/25/11
to pymo...@googlegroups.com
Hi!

On Fri, Jul 22, 2011 at 07:21:07AM -0700, StephenL wrote:
> Hi, all. For a particular type of Modbus device we need to support,
> rather than supporting Modbus TCP directly it supports Modbus RTU over
> TCP. For some Modbus GUI clients (such as the SimplyModbus client),
> this is an option.

The kind of frames handled by a client are defined at initialization time with
the "framer" parameter. Here is a code fragment that initializes a Modbus TCP
client with an RTU framer:

from pymodbus import factory, transaction
from pymodbus.client import async

decoder = factory.ClientDecoder()
framer = transaction.ModbusRtuFramer(decoder)
client_protocol = async.ModbusClientProtocol(framer)

I haven't been able to test if this actually works - please use it as basis for
your own experiments ;-). If it does work, please report back to the list; it would
be good to know that the flexibility of the framework allows to handle such
"exotic" cases, too.

Best regards,

Albert
--
Albert Brandl
Weiermayer Solutions GmbH | Abteistra�e 12, A-4813 Altm�nster
phone: +43 (0) 720 70 30 14 | fax: +43 (0) 7612 20 3 56
web: http://www.weiermayer.com

StephenL

unread,
Jul 25, 2011, 9:13:09 AM7/25/11
to pymodbus
On Jul 25, 3:39 am, Albert Brandl <albert.bra...@weiermayer.com>
wrote:
> The kind of frames handled by a client are defined at initialization time with
> the "framer" parameter. Here is a code fragment that initializes a Modbus TCP
> client with an RTU framer:
>
> from pymodbus import factory, transaction
> from pymodbus.client import async
>
> decoder = factory.ClientDecoder()
> framer = transaction.ModbusRtuFramer(decoder)
> client_protocol = async.ModbusClientProtocol(framer)

Albert, thank you very much for this help. I might need a little more
guidance about what would follow this instantiation of the Modbus TCP
client with the RTU framer. In the examples, there is a standard
import (abridged from http://code.google.com/p/pymodbus/source/browse/trunk/examples/common/synchronous-client.py)
like this:

from pymodbus.client.sync import ModbusTcpClient as ModbusClient
client = ModbusClient('127.0.0.1')

Given your code above, does one then need to set the ModbusTcpClient
with this client_protocol variable you've established?

Also, SimplyModbus says (http://www.simplymodbus.ca/TCP.htm):
***
Modbus RTU over TCP
Simply put, this is a Modbus RTU message transmitted with a TCP/IP
wrapper and sent over a network instead of serial lines. The Server
does not have a SlaveID since it uses an IP Address instead.
***

Does that correspond with what you were saying about the Modbus TCP
client with the RTU framer in pymodbus?

Thanks again for your help,
Stephen

Albert Brandl

unread,
Aug 11, 2011, 3:22:51 AM8/11/11
to pymo...@googlegroups.com
Hi!

On Mon, Jul 25, 2011 at 06:13:09AM -0700, StephenL wrote:

Sorry for the delay - the last weeks were quite stressful, and this is
not likely to change soon :-(

> from pymodbus.client.sync import ModbusTcpClient as ModbusClient
> client = ModbusClient('127.0.0.1')
>
> Given your code above, does one then need to set the ModbusTcpClient
> with this client_protocol variable you've established?

No, my example used the asynchronous client. In the synchronous version,
the framer to be used is hardcoded (see the __init__ method of the class
ModbusTcpClient in sync.py). If you prefer to use the sync client, you
could create a subclass of ModbusTcpClient and override its __init__
method. Try to replace

BaseModbusClient.__init__(self, ModbusSocketFramer(ClientDecoder()))

with

BaseModbusClient.__init__(self, ModbusRtuFramer(ClientDecoder()))

> Also, SimplyModbus says (http://www.simplymodbus.ca/TCP.htm):
> ***
> Modbus RTU over TCP
> Simply put, this is a Modbus RTU message transmitted with a TCP/IP
> wrapper and sent over a network instead of serial lines. The Server
> does not have a SlaveID since it uses an IP Address instead.
> ***
>
> Does that correspond with what you were saying about the Modbus TCP
> client with the RTU framer in pymodbus?

I think so. But YMMV ;-)

> Thanks again for your help,
> Stephen

You're welcome.

Best regards,

StephenL

unread,
Aug 11, 2011, 11:00:19 PM8/11/11
to pymodbus
Hi, Albert. Thank you very much for being so responsive. As it turned
out, we took a more fundamental approach and reconfigured the meter's
Modbus setup to support Modbus TCP directly (didn't know it was
possible), and pymodbus is working very well reading it. So we will
hold off on our implementation of RTU over TCP.

Albert Brandl

unread,
Aug 12, 2011, 3:08:43 AM8/12/11
to pymo...@googlegroups.com
On Thu, Aug 11, 2011 at 08:00:19PM -0700, StephenL wrote:
> Hi, Albert. Thank you very much for being so responsive. As it turned
> out, we took a more fundamental approach and reconfigured the meter's
> Modbus setup to support Modbus TCP directly

This is certainly better than using a not widely used (and untested)
feature. Nevertheless it was interesting to see that the framework is
extensible enough to support RTU frames sent over TCP...

>... pymodbus is working very well reading it.

Cool. If any questions or problems arise, please ask them on the mailing
list. Just out of curiosity: do you still use the synchronous client, or
the async version?

Ivica

unread,
Dec 16, 2012, 1:05:14 PM12/16/12
to pymo...@googlegroups.com
Hello Albert,

I am also interested in implementing RTU over Ethernet using synchronous client, but am a Python beginner. Could you help me a little bit with "overriding constructor" part?

Galen Collins

unread,
Dec 16, 2012, 1:14:34 PM12/16/12
to pymo...@googlegroups.com
If people are starting to override the frame commonly, I can adapt the code to allow the framer to be passed in so users don't have to override the constructor to do these kind of things.

Bashwork

unread,
Dec 16, 2012, 1:32:10 PM12/16/12
to pymo...@googlegroups.com
Since this is something that has been requested a few times now, I have added the ability to inject the framer of your choice into the synchronous clients (this ability is already available in the asynchronous versions)::

    client = ModbusTcpClient(host="1.1.1.1", framer=ModbusRtuFramer)

I have extensively tested this, so your mileage may vary.  This is contained in github commit: bdbcc512d6e284339f3861b7e63f51209cd40845

Michał Konopacki

unread,
Apr 22, 2015, 3:44:10 PM4/22/15
to pymo...@googlegroups.com
Hi Bashwork!

I's been a long time since last message in this threat, but I would like to share my problem here, for it is a continuation of RTU over TCP thread. I've tried to setup such configuration but I failed. Fot me all code seems as it should be, and nevertheless it throws an error.
My code:
from pymodbus import factory, transaction
from pymodbus.client import sync
from pymodbus.client.sync import ModbusTcpClient as ModbusClient

decoder = factory.ClientDecoder()
rtu_framer = transaction.ModbusRtuFramer(decoder)

client = ModbusClient(host="192.168.0.104", port=502, framer=rtu_framer)

Output:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-1ee1f1a2e5c3> in <module>()
      7 rtu_framer = transaction.ModbusRtuFramer(decoder)
      8 
----> 9 client = ModbusClient(host="192.168.0.104", port=502, framer=rtu_framer)

C:\Users\Dell\Anaconda\lib\site-packages\pymodbus\client\sync.pyc in __init__(self, host, port, framer)
    126         self.port = port
    127         self.socket = None
--> 128         BaseModbusClient.__init__(self, framer(ClientDecoder()))
    129 
    130     def connect(self):

TypeError: 'ModbusRtuFramer' object is not callable

Do you know maybe what I did wrong?

Best Regards,
Michał
Reply all
Reply to author
Forward
0 new messages