From e75823066492bfc50a9fdb187b9baef01d0c2878 Mon Sep 17 00:00:00 2001 From: Perry Kundert Date: Mon, 2 Dec 2024 08:30:04 -0700 Subject: [PATCH 1/6] Support providing framer type Enum or class --- pymodbus/server/async_io.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pymodbus/server/async_io.py b/pymodbus/server/async_io.py index 79e52a9b3..d9739e0f7 100644 --- a/pymodbus/server/async_io.py +++ b/pymodbus/server/async_io.py @@ -223,8 +223,8 @@ def __init__( self.handle_local_echo = False if isinstance(identity, ModbusDeviceIdentification): self.control.Identity.update(identity) - - self.framer = FRAMER_NAME_TO_CLASS[framer] + # Support mapping of FramerType to a Framer class, or a Framer class + self.framer = FRAMER_NAME_TO_CLASS.get(framer, framer) self.serving: asyncio.Future = asyncio.Future() def callback_new_connection(self): From 902f3a62fe03dcba9f17cd571ea7042724b379ba Mon Sep 17 00:00:00 2001 From: Perry Kundert Date: Wed, 4 Dec 2024 07:33:12 -0700 Subject: [PATCH 2/6] Remove redundancy --- pymodbus/pdu/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pymodbus/pdu/__init__.py b/pymodbus/pdu/__init__.py index 952bd9ade..3d6838e7a 100644 --- a/pymodbus/pdu/__init__.py +++ b/pymodbus/pdu/__init__.py @@ -2,7 +2,6 @@ __all__ = [ "DecodePDU", "ExceptionResponse", - "ExceptionResponse", "FileRecord", "ModbusPDU", ] From 21b50ddf963bfa5ff4fecce78c62b8d5990e9c69 Mon Sep 17 00:00:00 2001 From: Perry Kundert Date: Wed, 4 Dec 2024 08:03:19 -0700 Subject: [PATCH 3/6] Extend support for passing custom Framer classes to client API --- pymodbus/client/base.py | 8 ++++---- pymodbus/server/async_io.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pymodbus/client/base.py b/pymodbus/client/base.py index 1f930d5e3..b677971ae 100644 --- a/pymodbus/client/base.py +++ b/pymodbus/client/base.py @@ -22,7 +22,7 @@ class ModbusBaseClient(ModbusClientMixin[Awaitable[ModbusPDU]]): def __init__( self, - framer: FramerType, + framer: FramerType | type[FramerBase], retries: int, comm_params: CommParams, trace_packet: Callable[[bool, bytes], bytes] | None, @@ -37,7 +37,7 @@ def __init__( self.comm_params = comm_params self.ctx = TransactionManager( comm_params, - (FRAMER_NAME_TO_CLASS[framer])(DecodePDU(False)), + FRAMER_NAME_TO_CLASS.get(framer, framer)(DecodePDU(False)), retries, False, trace_packet, @@ -116,7 +116,7 @@ class ModbusBaseSyncClient(ModbusClientMixin[ModbusPDU]): def __init__( self, - framer: FramerType, + framer: FramerType | type[FramerBase], retries: int, comm_params: CommParams, trace_packet: Callable[[bool, bytes], bytes] | None, @@ -133,7 +133,7 @@ def __init__( self.slaves: list[int] = [] # Common variables. - self.framer: FramerBase = (FRAMER_NAME_TO_CLASS[framer])(DecodePDU(False)) + self.framer: FramerBase = FRAMER_NAME_TO_CLASS.get(framer, framer)(DecodePDU(False)) self.transaction = TransactionManager( self.comm_params, self.framer, diff --git a/pymodbus/server/async_io.py b/pymodbus/server/async_io.py index d9739e0f7..e23b69860 100644 --- a/pymodbus/server/async_io.py +++ b/pymodbus/server/async_io.py @@ -10,7 +10,7 @@ from pymodbus.datastore import ModbusServerContext from pymodbus.device import ModbusControlBlock, ModbusDeviceIdentification from pymodbus.exceptions import NoSuchSlaveException -from pymodbus.framer import FRAMER_NAME_TO_CLASS, FramerType +from pymodbus.framer import FRAMER_NAME_TO_CLASS, FramerType, FramerBase from pymodbus.logging import Log from pymodbus.pdu import DecodePDU, ModbusPDU from pymodbus.pdu.pdu import ExceptionResponse @@ -201,7 +201,7 @@ def __init__( ignore_missing_slaves: bool, broadcast_enable: bool, identity: ModbusDeviceIdentification | None, - framer: FramerType, + framer: FramerType | type[FramerBase], trace_packet: Callable[[bool, bytes], bytes] | None, trace_pdu: Callable[[bool, ModbusPDU], ModbusPDU] | None, trace_connect: Callable[[bool], None] | None, From 2452d0706564f44be37f6bada445e998f385e166 Mon Sep 17 00:00:00 2001 From: Perry Kundert Date: Wed, 4 Dec 2024 08:53:00 -0700 Subject: [PATCH 4/6] Be more careful with type checking for framer --- build/.gitkeep | 0 dist/.gitkeep | 0 pymodbus/client/base.py | 8 ++++++-- pymodbus/server/async_io.py | 14 ++++++++------ 4 files changed, 14 insertions(+), 8 deletions(-) delete mode 100644 build/.gitkeep delete mode 100644 dist/.gitkeep diff --git a/build/.gitkeep b/build/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/dist/.gitkeep b/dist/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/pymodbus/client/base.py b/pymodbus/client/base.py index b677971ae..5481ffbea 100644 --- a/pymodbus/client/base.py +++ b/pymodbus/client/base.py @@ -35,9 +35,11 @@ def __init__( """ ModbusClientMixin.__init__(self) # type: ignore[arg-type] self.comm_params = comm_params + if not isinstance(framer, type) or not issubclass(framer, FramerBase): + framer = FRAMER_NAME_TO_CLASS[FramerType(framer)] self.ctx = TransactionManager( comm_params, - FRAMER_NAME_TO_CLASS.get(framer, framer)(DecodePDU(False)), + framer(DecodePDU(False)), retries, False, trace_packet, @@ -133,7 +135,9 @@ def __init__( self.slaves: list[int] = [] # Common variables. - self.framer: FramerBase = FRAMER_NAME_TO_CLASS.get(framer, framer)(DecodePDU(False)) + if not isinstance(framer, type) or not issubclass(framer, FramerBase): + framer = FRAMER_NAME_TO_CLASS[FramerType(framer)] + self.framer: FramerBase = framer(DecodePDU(False)) self.transaction = TransactionManager( self.comm_params, self.framer, diff --git a/pymodbus/server/async_io.py b/pymodbus/server/async_io.py index e23b69860..22d067d86 100644 --- a/pymodbus/server/async_io.py +++ b/pymodbus/server/async_io.py @@ -10,7 +10,7 @@ from pymodbus.datastore import ModbusServerContext from pymodbus.device import ModbusControlBlock, ModbusDeviceIdentification from pymodbus.exceptions import NoSuchSlaveException -from pymodbus.framer import FRAMER_NAME_TO_CLASS, FramerType, FramerBase +from pymodbus.framer import FRAMER_NAME_TO_CLASS, FramerBase, FramerType from pymodbus.logging import Log from pymodbus.pdu import DecodePDU, ModbusPDU from pymodbus.pdu.pdu import ExceptionResponse @@ -224,7 +224,9 @@ def __init__( if isinstance(identity, ModbusDeviceIdentification): self.control.Identity.update(identity) # Support mapping of FramerType to a Framer class, or a Framer class - self.framer = FRAMER_NAME_TO_CLASS.get(framer, framer) + if not isinstance(framer, type) or not issubclass(framer, FramerBase): + framer = FRAMER_NAME_TO_CLASS[FramerType(framer)] + self.framer = framer self.serving: asyncio.Future = asyncio.Future() def callback_new_connection(self): @@ -273,7 +275,7 @@ def __init__( self, context: ModbusServerContext, *, - framer=FramerType.SOCKET, + framer: FramerType | type[FramerBase] = FramerType.SOCKET, identity: ModbusDeviceIdentification | None = None, address: tuple[str, int] = ("", 502), ignore_missing_slaves: bool = False, @@ -336,7 +338,7 @@ def __init__( # pylint: disable=too-many-arguments self, context: ModbusServerContext, *, - framer=FramerType.TLS, + framer: FramerType | type[FramerBase] = FramerType.TLS, identity: ModbusDeviceIdentification | None = None, address: tuple[str, int] = ("", 502), sslctx=None, @@ -403,7 +405,7 @@ def __init__( self, context: ModbusServerContext, *, - framer=FramerType.SOCKET, + framer: FramerType | type[FramerBase] = FramerType.SOCKET, identity: ModbusDeviceIdentification | None = None, address: tuple[str, int] = ("", 502), ignore_missing_slaves: bool = False, @@ -463,7 +465,7 @@ def __init__( self, context: ModbusServerContext, *, - framer: FramerType = FramerType.RTU, + framer: FramerType | type[FramerBase] = FramerType.RTU, ignore_missing_slaves: bool = False, identity: ModbusDeviceIdentification | None = None, broadcast_enable: bool = False, From 1efab8f687160209c3234e3be7f89b58e0e06a78 Mon Sep 17 00:00:00 2001 From: Perry Kundert Date: Wed, 4 Dec 2024 14:56:32 -0700 Subject: [PATCH 5/6] Restore some accidentally removed .gitkeep files --- build/.gitkeep | 0 dist/.gitkeep | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 build/.gitkeep create mode 100644 dist/.gitkeep diff --git a/build/.gitkeep b/build/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/dist/.gitkeep b/dist/.gitkeep new file mode 100644 index 000000000..e69de29bb From 87535cdd6678b5668344a0428e3134b37a7792f3 Mon Sep 17 00:00:00 2001 From: Perry Kundert Date: Mon, 9 Dec 2024 06:32:16 -0700 Subject: [PATCH 6/6] Don't log error when missing slave ignored --- pymodbus/server/async_io.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pymodbus/server/async_io.py b/pymodbus/server/async_io.py index 22d067d86..35039ea52 100644 --- a/pymodbus/server/async_io.py +++ b/pymodbus/server/async_io.py @@ -166,9 +166,10 @@ async def server_async_execute(self, request, *addr): response = await request.update_datastore(context) except NoSuchSlaveException: - Log.error("requested slave does not exist: {}", request.dev_id) if self.server.ignore_missing_slaves: + Log.debug("ignored slave that does not exist: {}", request.slave_id) return # the client will simply timeout waiting for a response + Log.error("requested slave does not exist: {}", request.slave_id) response = ExceptionResponse(0x00, ExceptionResponse.GATEWAY_NO_RESPONSE) except Exception as exc: # pylint: disable=broad-except Log.error(