Skip to content

Commit 53577ed

Browse files
authored
Change sync ModbusSerialClient to use framer= instead of method=. (#993)
1 parent 5d91882 commit 53577ed

File tree

6 files changed

+38
-58
lines changed

6 files changed

+38
-58
lines changed

examples/client_sync.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@ def setup_sync_client():
7272
elif args.comm == "serial":
7373
client = ModbusSerialClient(
7474
port=args.port, # serial port
75-
method=args.framer, # how to interpret the messages
76-
# TBD framer=FRAMERS[args.framer], # how to interpret the messages
75+
framer=FRAMERS[args.framer], # how to interpret the messages
7776
stopbits=1, # The number of stop bits to use
7877
bytesize=7, # The bytesize of the serial messages
7978
parity="even", # Which kind of parity to use

examples/common/performance.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717

1818
from pymodbus.client.sync import ModbusTcpClient
1919

20-
# from pymodbus.client.sync import ModbusSerialClient
21-
2220
try:
2321
from multiprocessing import Process as mWorker, log_to_stderr
2422
except ImportError:

pymodbus/client/sync.py

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,10 @@
1515
from pymodbus.exceptions import (
1616
ConnectionException,
1717
NotImplementedException,
18-
ParameterException,
1918
)
2019
from pymodbus.factory import ClientDecoder
2120
from pymodbus.transaction import (
2221
DictTransactionManager,
23-
ModbusAsciiFramer,
24-
ModbusBinaryFramer,
2522
ModbusRtuFramer,
2623
ModbusSocketFramer,
2724
ModbusTlsFramer,
@@ -614,16 +611,9 @@ class ModbusSerialClient(
614611
inter_char_timeout = 0
615612
silent_interval = 0
616613

617-
def __init__(self, method="ascii", **kwargs):
614+
def __init__(self, framer=ModbusRtuFramer, **kwargs):
618615
"""Initialize a serial client instance.
619616
620-
The methods to connect are::
621-
622-
- ascii
623-
- rtu
624-
- binary
625-
626-
:param method: The method to use for connection
627617
:param port: The serial port to attach to
628618
:param stopbits: The number of stop bits to use
629619
:param bytesize: The bytesize of the serial messages
@@ -633,10 +623,11 @@ def __init__(self, method="ascii", **kwargs):
633623
:param strict: Use Inter char timeout for baudrates <= 19200 (adhere
634624
to modbus standards)
635625
:param handle_local_echo: Handle local echo of the USB-to-RS485 adaptor
626+
:param framer: The modbus framer to use (default ModbusRtuFramer)
636627
"""
637-
self.method = method
628+
self.framer = framer
638629
self.socket = None
639-
BaseModbusClient.__init__(self, self.__implementation(method, self), **kwargs)
630+
BaseModbusClient.__init__(self, framer(ClientDecoder(), self), **kwargs)
640631

641632
self.port = kwargs.get("port", 0)
642633
self.stopbits = kwargs.get("stopbits", Defaults.Stopbits)
@@ -647,7 +638,7 @@ def __init__(self, method="ascii", **kwargs):
647638
self._strict = kwargs.get("strict", False)
648639
self.last_frame_end = None
649640
self.handle_local_echo = kwargs.get("handle_local_echo", False)
650-
if self.method == "rtu":
641+
if isinstance(self.framer, ModbusRtuFramer):
651642
if self.baudrate > 19200:
652643
self.silent_interval = 1.75 / 1000 # ms
653644
else:
@@ -656,26 +647,6 @@ def __init__(self, method="ascii", **kwargs):
656647
self.silent_interval = 3.5 * self._t0
657648
self.silent_interval = round(self.silent_interval, 6)
658649

659-
@staticmethod
660-
def __implementation(method, client):
661-
"""Return the requested framer.
662-
663-
:method: The serial framer to instantiate
664-
:returns: The requested serial framer
665-
:raises ConnectionException:
666-
:raises ParameterException:
667-
"""
668-
method = method.lower()
669-
if method == "ascii":
670-
return ModbusAsciiFramer(ClientDecoder(), client)
671-
if method == "rtu":
672-
return ModbusRtuFramer(ClientDecoder(), client)
673-
if method == "binary":
674-
return ModbusBinaryFramer(ClientDecoder(), client)
675-
if method == "socket":
676-
return ModbusSocketFramer(ClientDecoder(), client)
677-
raise ParameterException("Invalid framer method requested")
678-
679650
def connect(self):
680651
"""Connect to the modbus serial server.
681652
@@ -692,7 +663,7 @@ def connect(self):
692663
baudrate=self.baudrate,
693664
parity=self.parity,
694665
)
695-
if self.method == "rtu":
666+
if isinstance(self.framer, ModbusRtuFramer):
696667
if self._strict:
697668
self.socket.interCharTimeout = self.inter_char_timeout
698669
self.last_frame_end = None
@@ -802,13 +773,13 @@ def __str__(self):
802773
803774
:returns: The string representation
804775
"""
805-
return f"ModbusSerialClient({self.method} baud[{self.baudrate}])"
776+
return f"ModbusSerialClient({self.framer} baud[{self.baudrate}])"
806777

807778
def __repr__(self):
808779
"""Return string representation."""
809780
return (
810781
f"<{self.__class__.__name__} at {hex(id(self))} socket={self.socket}, "
811-
f"method={self.method}, timeout={self.timeout}>"
782+
f"framer={self.framer}, timeout={self.timeout}>"
812783
)
813784

814785

pymodbus/repl/client/main.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,17 @@
2929
from prompt_toolkit.styles import Style
3030
from pygments.lexers.python import PythonLexer
3131

32-
from pymodbus.framer.rtu_framer import ModbusRtuFramer
3332
from pymodbus.repl.client.completer import CmdCompleter, has_selected_completion
3433
from pymodbus.repl.client.helper import CLIENT_ATTRIBUTES, Result
3534
from pymodbus.repl.client.mclient import ModbusSerialClient, ModbusTcpClient
3635
from pymodbus.version import version
36+
from pymodbus.exceptions import ParameterException
37+
from pymodbus.transaction import (
38+
ModbusAsciiFramer,
39+
ModbusBinaryFramer,
40+
ModbusRtuFramer,
41+
ModbusSocketFramer,
42+
)
3743

3844
click.disable_unicode_literals_warning = True
3945

@@ -403,8 +409,19 @@ def serial( # pylint: disable=too-many-arguments
403409
write_timeout,
404410
):
405411
"""Define serial communication."""
412+
method = method.lower()
413+
if method == "ascii":
414+
framer = ModbusAsciiFramer
415+
elif method == "rtu":
416+
framer = ModbusRtuFramer
417+
elif method == "binary":
418+
framer = ModbusBinaryFramer
419+
elif method == "socket":
420+
framer = ModbusSocketFramer
421+
else:
422+
raise ParameterException("Invalid framer method requested")
406423
client = ModbusSerialClient(
407-
method=method,
424+
framer=framer,
408425
port=port,
409426
baudrate=baudrate,
410427
bytesize=bytesize,

test/test_client_sync.py

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
from pymodbus.exceptions import (
2323
ConnectionException,
2424
NotImplementedException,
25-
ParameterException,
2625
)
2726
from pymodbus.transaction import (
2827
ModbusAsciiFramer,
@@ -524,32 +523,28 @@ class CustomeRequest: # pylint: disable=too-few-public-methods
524523
# -----------------------------------------------------------------------#
525524
# Test Serial Client
526525
# -----------------------------------------------------------------------#
527-
528526
def test_sync_serial_client_instantiation(self):
529527
"""Test sync serial client."""
530528
client = ModbusSerialClient()
531529
self.assertNotEqual(client, None)
532530
self.assertTrue(
533-
isinstance(ModbusSerialClient(method="ascii").framer, ModbusAsciiFramer)
531+
isinstance(ModbusSerialClient(framer=ModbusAsciiFramer).framer, ModbusAsciiFramer)
534532
)
535533
self.assertTrue(
536-
isinstance(ModbusSerialClient(method="rtu").framer, ModbusRtuFramer)
534+
isinstance(ModbusSerialClient(framer=ModbusRtuFramer).framer, ModbusRtuFramer)
537535
)
538536
self.assertTrue(
539-
isinstance(ModbusSerialClient(method="binary").framer, ModbusBinaryFramer)
537+
isinstance(ModbusSerialClient(framer=ModbusBinaryFramer).framer, ModbusBinaryFramer)
540538
)
541539
self.assertTrue(
542-
isinstance(ModbusSerialClient(method="socket").framer, ModbusSocketFramer)
543-
)
544-
self.assertRaises(
545-
ParameterException, lambda: ModbusSerialClient(method="something")
540+
isinstance(ModbusSerialClient(framer=ModbusSocketFramer).framer, ModbusSocketFramer)
546541
)
547542

548543
def test_sync_serial_rtu_client_timeouts(self):
549544
"""Test sync serial rtu."""
550-
client = ModbusSerialClient(method="rtu", baudrate=9600)
545+
client = ModbusSerialClient(framer=ModbusRtuFramer, baudrate=9600)
551546
self.assertEqual(client.silent_interval, round((3.5 * 11 / 9600), 6))
552-
client = ModbusSerialClient(method="rtu", baudrate=38400)
547+
client = ModbusSerialClient(framer=ModbusRtuFramer, baudrate=38400)
553548
self.assertEqual(client.silent_interval, round((1.75 / 1000), 6))
554549

555550
@patch("serial.Serial")
@@ -573,7 +568,7 @@ def test_basic_sync_serial_client(self, mock_serial):
573568
client.close()
574569

575570
# rtu connect/disconnect
576-
rtu_client = ModbusSerialClient(method="rtu", strict=True)
571+
rtu_client = ModbusSerialClient(framer=ModbusRtuFramer, strict=True)
577572
self.assertTrue(rtu_client.connect())
578573
self.assertEqual(
579574
rtu_client.socket.interCharTimeout, rtu_client.inter_char_timeout
@@ -584,7 +579,7 @@ def test_basic_sync_serial_client(self, mock_serial):
584579
client.socket = False
585580
client.close()
586581

587-
self.assertEqual("ModbusSerialClient(ascii baud[19200])", str(client))
582+
self.assertTrue("baud[19200])" in str(client))
588583

589584
def test_serial_client_connect(self):
590585
"""Test the serial client connection method"""
@@ -667,7 +662,7 @@ def test_serial_client_repr(self):
667662
client = ModbusSerialClient()
668663
rep = (
669664
f"<{client.__class__.__name__} at {hex(id(client))} socket={client.socket}, "
670-
f"method={client.method}, timeout={client.timeout}>"
665+
f"framer={client.framer}, timeout={client.timeout}>"
671666
)
672667
self.assertEqual(repr(client), rep)
673668

test/test_device.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
# ---------------------------------------------------------------------------#
1717

1818

19-
class SimpleDataStoreTest(unittest.TestCase): # pylint: disable=too-many-public-methods
19+
class SimpleDataStoreTest(unittest.TestCase):
2020
"""Unittest for the pymodbus.device module."""
2121

2222
# -----------------------------------------------------------------------#

0 commit comments

Comments
 (0)