From 0d44f0de1516ae511d484e6db412c29466d8fc17 Mon Sep 17 00:00:00 2001 From: travijuu Date: Thu, 3 Oct 2019 11:31:31 +0300 Subject: [PATCH] Added support for RTU over TCP --- README.md | 1 + modbus_tk/__init__.py | 1 + modbus_tk/hooks.py | 2 ++ modbus_tk/modbus_rtu_over_tcp.py | 38 ++++++++++++++++++++++++++++++++ 4 files changed, 42 insertions(+) create mode 100644 modbus_tk/modbus_rtu_over_tcp.py diff --git a/README.md b/README.md index 2188bc5..78c2a44 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ Features ------------------------------------ * Modbus TCP support for writing masters and slaves * Modbus RTU support for writing masters and slaves (requires pyserial) +* Modbus RTU over TCP support * Can be customized with hook mechanism (simulate errors, timeouts...) * ready-to use simulator with RPC interface * Defines very easily your own memory blocks diff --git a/modbus_tk/__init__.py b/modbus_tk/__init__.py index 504636c..5bcdfe6 100644 --- a/modbus_tk/__init__.py +++ b/modbus_tk/__init__.py @@ -29,6 +29,7 @@ * Vincent Prince * kcl93 * https://github.com/Slasktra +* travijuu Please let us know if your name is missing! diff --git a/modbus_tk/hooks.py b/modbus_tk/hooks.py index 9132b4e..21792e2 100644 --- a/modbus_tk/hooks.py +++ b/modbus_tk/hooks.py @@ -49,6 +49,8 @@ def install_hook(name, fct): modbus_tcp.TcpServer.before_send((server, sock, response)) returns modified response or None modbus_tcp.TcpServer.on_error((server, sock, excpt)) + modbus_rtu_over_tcp.RtuOverTcpMaster.after_recv((master, response)) + modbus.Master.before_send((master, request)) returns modified request or None modbus.Master.after_send((master)) modbus.Master.after_recv((master, response)) returns modified response or None diff --git a/modbus_tk/modbus_rtu_over_tcp.py b/modbus_tk/modbus_rtu_over_tcp.py new file mode 100644 index 0000000..becc866 --- /dev/null +++ b/modbus_tk/modbus_rtu_over_tcp.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" + Modbus TestKit: Implementation of Modbus protocol in python + + (C)2009 - Luc Jean - luc.jean@gmail.com + (C)2009 - Apidev - http://www.apidev.fr + + This is distributed under GNU LGPL license, see license.txt +""" + +from modbus_tk.hooks import call_hooks +from modbus_tk.modbus_rtu import RtuQuery +from modbus_tk.modbus_tcp import TcpMaster +from modbus_tk.utils import to_data + + +class RtuOverTcpMaster(TcpMaster): + """Subclass of TcpMaster. Implements the Modbus RTU over TCP MAC layer""" + + def _recv(self, expected_length=-1): + """Receive the response from the slave""" + response = to_data('') + length = 255 + while len(response) < length: + rcv_byte = self._sock.recv(1) + if rcv_byte: + response += rcv_byte + if expected_length >= 0 and len(response) >= expected_length: + break + retval = call_hooks("modbus_rtu_over_tcp.RtuOverTcpMaster.after_recv", (self, response)) + if retval is not None: + return retval + return response + + def _make_query(self): + """Returns an instance of a Query subclass implementing the modbus RTU protocol""" + return RtuQuery()