diff --git a/API_changes.rst b/API_changes.rst index 2ed0d71688..335ea73a4a 100644 --- a/API_changes.rst +++ b/API_changes.rst @@ -4,6 +4,7 @@ Versions (X.Y.Z) where Z > 0 e.g. 3.0.1 do NOT have API changes! API changes 3.6.0 (future) -------------------------- +- framer= is an enum: pymodbus.Framer, but still accept a framer class API changes 3.5.0 diff --git a/examples/client_custom_msg.py b/examples/client_custom_msg.py index b8c3f403bf..b42f809bd6 100755 --- a/examples/client_custom_msg.py +++ b/examples/client_custom_msg.py @@ -14,14 +14,10 @@ import logging import struct +from pymodbus import Framer from pymodbus.bit_read_message import ReadCoilsRequest from pymodbus.client import AsyncModbusTcpClient as ModbusClient - -# --------------------------------------------------------------------------- # -# import the various server implementations -# --------------------------------------------------------------------------- # from pymodbus.pdu import ModbusExceptions, ModbusRequest, ModbusResponse -from pymodbus.transaction import ModbusSocketFramer # --------------------------------------------------------------------------- # @@ -130,7 +126,7 @@ def __init__(self, address, **kwargs): async def main(host="localhost", port=5020): """Run versions of read coil.""" - with ModbusClient(host=host, port=port, framer=ModbusSocketFramer) as client: + with ModbusClient(host=host, port=port, framer_name=Framer.SOCKET) as client: await client.connect() # new modbus function code. diff --git a/examples/client_performance.py b/examples/client_performance.py index 50a8b1e32d..77f912dd92 100755 --- a/examples/client_performance.py +++ b/examples/client_performance.py @@ -16,8 +16,8 @@ import asyncio import time +from pymodbus import Framer from pymodbus.client import AsyncModbusSerialClient, ModbusSerialClient -from pymodbus.transaction import ModbusRtuFramer LOOP_COUNT = 1000 @@ -29,7 +29,7 @@ def run_sync_client_test(): print("--- Testing sync client v3.4.1") client = ModbusSerialClient( "/dev/ttys007", - framer=ModbusRtuFramer, + framer_name=Framer.RTU, baudrate=9600, ) client.connect() @@ -56,7 +56,7 @@ async def run_async_client_test(): print("--- Testing async client v3.4.1") client = AsyncModbusSerialClient( "/dev/ttys007", - framer=ModbusRtuFramer, + framer_name=Framer.RTU, baudrate=9600, ) await client.connect() diff --git a/pymodbus/__init__.py b/pymodbus/__init__.py index 84a321feec..f52caa7bd0 100644 --- a/pymodbus/__init__.py +++ b/pymodbus/__init__.py @@ -4,11 +4,13 @@ """ __all__ = [ + "Framer", "pymodbus_apply_logging_config", "__version__", "__version_full__", ] +from pymodbus.framer import Framer from pymodbus.logging import pymodbus_apply_logging_config diff --git a/pymodbus/client/base.py b/pymodbus/client/base.py index a00309cd0a..f8eff05b93 100644 --- a/pymodbus/client/base.py +++ b/pymodbus/client/base.py @@ -20,20 +20,20 @@ class ModbusBaseClient(ModbusClientMixin, ModbusProtocol): """**ModbusBaseClient** - **Parameters common to all clients**: - - :param framer: (optional) Modbus Framer class. - :param timeout: (optional) Timeout for a request, in seconds. - :param retries: (optional) Max number of retries per request. - :param retry_on_empty: (optional) Retry on empty response. - :param close_comm_on_error: (optional) Close connection on error. - :param strict: (optional) Strict timing, 1.5 character between requests. - :param broadcast_enable: (optional) True to treat id 0 as broadcast address. - :param reconnect_delay: (optional) Minimum delay in milliseconds before reconnecting. - :param reconnect_delay_max: (optional) Maximum delay in milliseconds before reconnecting. - :param on_reconnect_callback: (optional) Function that will be called just before a reconnection attempt. - :param no_resend_on_retry: (optional) Do not resend request when retrying due to missing response. - :param kwargs: (optional) Experimental parameters. + Optional parameters: + + :param framer: Modbus Framer class. + :param timeout: Timeout for a request, in seconds. + :param retries: Max number of retries per request. + :param retry_on_empty: Retry on empty response. + :param close_comm_on_error: Close connection on error. + :param strict: Strict timing, 1.5 character between requests. + :param broadcast_enable: True to treat id 0 as broadcast address. + :param reconnect_delay: Minimum delay in milliseconds before reconnecting. + :param reconnect_delay_max: Maximum delay in milliseconds before reconnecting. + :param on_reconnect_callback: Function that will be called just before a reconnection attempt. + :param no_resend_on_retry: Do not resend request when retrying due to missing response. + :param kwargs: Experimental parameters. .. tip:: **reconnect_delay** doubles automatically with each unsuccessful connect, from @@ -62,7 +62,7 @@ class _params: def __init__( # pylint: disable=too-many-arguments self, - framer: type[ModbusFramer] = None, + framer_class: type[ModbusFramer] = None, timeout: float = 3, retries: int = 3, retry_on_empty: bool = False, @@ -114,7 +114,7 @@ def __init__( # pylint: disable=too-many-arguments self.slaves: list[int] = [] # Common variables. - self.framer = framer(ClientDecoder(), self) + self.framer = framer_class(ClientDecoder(), self) self.transaction = DictTransactionManager( self, retries=retries, retry_on_empty=retry_on_empty, **kwargs ) diff --git a/pymodbus/client/mixin.py b/pymodbus/client/mixin.py index 64b41b6bb1..f1bd823ee6 100644 --- a/pymodbus/client/mixin.py +++ b/pymodbus/client/mixin.py @@ -1,7 +1,9 @@ """Modbus Client Common.""" +from __future__ import annotations + import struct from enum import Enum -from typing import Any, List, Tuple, Union +from typing import Any import pymodbus.bit_read_message as pdu_bit_read import pymodbus.bit_write_message as pdu_bit_write @@ -381,7 +383,7 @@ def diag_get_comm_event_log(self, **kwargs: Any) -> ModbusResponse: def write_coils( self, address: int, - values: Union[List[bool], bool], + values: list[bool] | bool, slave: int = 0, **kwargs: Any, ) -> ModbusResponse: @@ -398,7 +400,7 @@ def write_coils( ) def write_registers( - self, address: int, values: Union[List[int], int], slave: int = 0, **kwargs: Any + self, address: int, values: list[int] | int, slave: int = 0, **kwargs: Any ) -> ModbusResponse: """Write registers (code 0x10). @@ -423,7 +425,7 @@ def report_slave_id(self, slave: int = 0, **kwargs: Any) -> ModbusResponse: """ return self.execute(pdu_other_msg.ReportSlaveIdRequest(slave, **kwargs)) - def read_file_record(self, records: List[Tuple], **kwargs: Any) -> ModbusResponse: + def read_file_record(self, records: list[tuple], **kwargs: Any) -> ModbusResponse: """Read file record (code 0x14). :param records: List of (Reference type, File number, Record Number, Record Length) @@ -432,7 +434,7 @@ def read_file_record(self, records: List[Tuple], **kwargs: Any) -> ModbusRespons """ return self.execute(pdu_file_msg.ReadFileRecordRequest(records, **kwargs)) - def write_file_record(self, records: List[Tuple], **kwargs: Any) -> ModbusResponse: + def write_file_record(self, records: list[tuple], **kwargs: Any) -> ModbusResponse: """Write file record (code 0x15). :param records: List of (Reference type, File number, Record Number, Record Length) @@ -465,7 +467,7 @@ def readwrite_registers( read_address: int = 0, read_count: int = 0, write_address: int = 0, - values: Union[List[int], int] = 0, + values: list[int] | int = 0, slave: int = 0, **kwargs, ) -> ModbusResponse: @@ -534,8 +536,8 @@ class DATATYPE(Enum): @classmethod def convert_from_registers( - cls, registers: List[int], data_type: DATATYPE - ) -> Union[int, float, str]: + cls, registers: list[int], data_type: DATATYPE + ) -> int | float | str: """Convert registers to int/float/str. :param registers: list of registers received from e.g. read_holding_registers() @@ -558,8 +560,8 @@ def convert_from_registers( @classmethod def convert_to_registers( - cls, value: Union[int, float, str], data_type: DATATYPE - ) -> List[int]: + cls, value: int | float | str, data_type: DATATYPE + ) -> list[int]: """Convert int/float/str to registers (16/32/64 bit). :param value: value to be converted diff --git a/pymodbus/client/serial.py b/pymodbus/client/serial.py index 240b827d44..bcb1a57ad4 100644 --- a/pymodbus/client/serial.py +++ b/pymodbus/client/serial.py @@ -1,14 +1,15 @@ """Modbus client async serial communication.""" +from __future__ import annotations + import asyncio import time from contextlib import suppress from functools import partial -from typing import Any, Type +from typing import Any from pymodbus.client.base import ModbusBaseClient from pymodbus.exceptions import ConnectionException -from pymodbus.framer import ModbusFramer -from pymodbus.framer.rtu_framer import ModbusRtuFramer +from pymodbus.framer import FRAMER_NAME_TO_CLASS, Framer from pymodbus.logging import Log from pymodbus.transport import CommType from pymodbus.utilities import ModbusTransactionState @@ -27,7 +28,6 @@ class AsyncModbusSerialClient(ModbusBaseClient, asyncio.Protocol): Optional parameters: - :param framer: Framer class. :param baudrate: Bits per second. :param bytesize: Number of bits per byte 7-8. :param parity: 'E'ven, 'O'dd or 'N'one @@ -36,6 +36,7 @@ class AsyncModbusSerialClient(ModbusBaseClient, asyncio.Protocol): Common optional parameters: + :param framer: Framer enum name :param timeout: Timeout for a request, in seconds. :param retries: Max number of retries per request. :param retry_on_empty: Retry on empty response. @@ -65,7 +66,7 @@ async def run(): def __init__( self, port: str, - framer: Type[ModbusFramer] = ModbusRtuFramer, + framer: Framer = Framer.RTU, baudrate: int = 19200, bytesize: int = 8, parity: str = "N", @@ -74,9 +75,10 @@ def __init__( ) -> None: """Initialize Asyncio Modbus Serial Client.""" asyncio.Protocol.__init__(self) + framer_class = FRAMER_NAME_TO_CLASS.get(framer, framer) ModbusBaseClient.__init__( self, - framer=framer, + framer_class=framer_class, # type: ignore[arg-type] CommType=CommType.SERIAL, host=port, baudrate=baudrate, @@ -106,7 +108,6 @@ class ModbusSerialClient(ModbusBaseClient): Optional parameters: - :param framer: Framer class. :param baudrate: Bits per second. :param bytesize: Number of bits per byte 7-8. :param parity: 'E'ven, 'O'dd or 'N'one @@ -115,6 +116,7 @@ class ModbusSerialClient(ModbusBaseClient): Common optional parameters: + :param framer: Framer enum name :param timeout: Timeout for a request, in seconds. :param retries: Max number of retries per request. :param retry_on_empty: Retry on empty response. @@ -150,7 +152,7 @@ def run(): def __init__( self, port: str, - framer: Type[ModbusFramer] = ModbusRtuFramer, + framer: Framer = Framer.RTU, baudrate: int = 19200, bytesize: int = 8, parity: str = "N", @@ -160,9 +162,10 @@ def __init__( """Initialize Modbus Serial Client.""" self.transport = None kwargs["use_sync"] = True + framer_class = FRAMER_NAME_TO_CLASS.get(framer, framer) ModbusBaseClient.__init__( self, - framer=framer, + framer_class=framer_class, # type: ignore[arg-type] CommType=CommType.SERIAL, host=port, baudrate=baudrate, @@ -207,10 +210,9 @@ def connect(self): # pylint: disable=invalid-overridden-method baudrate=self.comm_params.baudrate, parity=self.comm_params.parity, ) - if isinstance(self.framer, ModbusRtuFramer): - if self.params.strict: - self.socket.interCharTimeout = self.inter_char_timeout - self.last_frame_end = None + if self.params.strict: + self.socket.interCharTimeout = self.inter_char_timeout + self.last_frame_end = None except serial.SerialException as msg: Log.error("{}", msg) self.close() diff --git a/pymodbus/client/tcp.py b/pymodbus/client/tcp.py index 30347b4e5e..a78737258b 100644 --- a/pymodbus/client/tcp.py +++ b/pymodbus/client/tcp.py @@ -1,14 +1,15 @@ """Modbus client async TCP communication.""" +from __future__ import annotations + import asyncio import select import socket import time -from typing import Any, Tuple, Type +from typing import Any from pymodbus.client.base import ModbusBaseClient from pymodbus.exceptions import ConnectionException -from pymodbus.framer import ModbusFramer -from pymodbus.framer.socket_framer import ModbusSocketFramer +from pymodbus.framer import FRAMER_NAME_TO_CLASS, Framer from pymodbus.logging import Log from pymodbus.transport import CommType from pymodbus.utilities import ModbusTransactionState @@ -24,11 +25,11 @@ class AsyncModbusTcpClient(ModbusBaseClient, asyncio.Protocol): Optional parameters: :param port: Port used for communication - :param framer: Framer class :param source_address: source address of client Common optional parameters: + :param framer: Framer enum name :param timeout: Timeout for a request, in seconds. :param retries: Max number of retries per request. :param retry_on_empty: Retry on empty response. @@ -59,19 +60,20 @@ def __init__( self, host: str, port: int = 502, - framer: Type[ModbusFramer] = ModbusSocketFramer, - source_address: Tuple[str, int] = None, + framer: Framer = Framer.SOCKET, + source_address: tuple[str, int] = None, **kwargs: Any, ) -> None: """Initialize Asyncio Modbus TCP Client.""" asyncio.Protocol.__init__(self) if "CommType" not in kwargs: kwargs["CommType"] = CommType.TCP + framer_class = FRAMER_NAME_TO_CLASS.get(framer, framer) if source_address: kwargs["source_address"] = source_address ModbusBaseClient.__init__( self, - framer=framer, + framer_class=framer_class, # type: ignore[arg-type] host=host, port=port, **kwargs, @@ -103,11 +105,11 @@ class ModbusTcpClient(ModbusBaseClient): Optional parameters: :param port: Port used for communication - :param framer: Framer class :param source_address: source address of client Common optional parameters: + :param framer: Framer enum name :param timeout: Timeout for a request, in seconds. :param retries: Max number of retries per request. :param retry_on_empty: Retry on empty response. @@ -140,16 +142,22 @@ def __init__( self, host: str, port: int = 502, - framer: Type[ModbusFramer] = ModbusSocketFramer, - source_address: Tuple[str, int] = None, + framer: Framer = Framer.SOCKET, + source_address: tuple[str, int] = None, **kwargs: Any, ) -> None: """Initialize Modbus TCP Client.""" if "CommType" not in kwargs: kwargs["CommType"] = CommType.TCP + framer_class = FRAMER_NAME_TO_CLASS.get(framer, framer) kwargs["use_sync"] = True self.transport = None - super().__init__(framer=framer, host=host, port=port, **kwargs) + super().__init__( + framer_class=framer_class, # type: ignore[arg-type] + host=host, + port=port, + **kwargs, + ) self.params.source_address = source_address self.socket = None diff --git a/pymodbus/client/tls.py b/pymodbus/client/tls.py index 81a5d039af..3ad4fad47d 100644 --- a/pymodbus/client/tls.py +++ b/pymodbus/client/tls.py @@ -1,11 +1,12 @@ """Modbus client async TLS communication.""" +from __future__ import annotations + import socket import ssl -from typing import Any, Type +from typing import Any from pymodbus.client.tcp import AsyncModbusTcpClient, ModbusTcpClient -from pymodbus.framer import ModbusFramer -from pymodbus.framer.tls_framer import ModbusTlsFramer +from pymodbus.framer import Framer from pymodbus.logging import Log from pymodbus.transport import CommParams, CommType @@ -20,7 +21,6 @@ class AsyncModbusTlsClient(AsyncModbusTcpClient): Optional parameters: :param port: Port used for communication - :param framer: Framer class :param source_address: Source address of client :param sslctx: SSLContext to use for TLS :param certfile: Cert file path for TLS server request @@ -30,6 +30,7 @@ class AsyncModbusTlsClient(AsyncModbusTcpClient): Common optional parameters: + :param framer: Framer enum name :param timeout: Timeout for a request, in seconds. :param retries: Max number of retries per request. :param retry_on_empty: Retry on empty response. @@ -60,7 +61,7 @@ def __init__( self, host: str, port: int = 802, - framer: Type[ModbusFramer] = ModbusTlsFramer, + framer: Framer = Framer.TLS, sslctx: ssl.SSLContext = None, certfile: str = None, keyfile: str = None, @@ -103,7 +104,6 @@ class ModbusTlsClient(ModbusTcpClient): Optional parameters: :param port: Port used for communication - :param framer: Framer class :param source_address: Source address of client :param sslctx: SSLContext to use for TLS :param certfile: Cert file path for TLS server request @@ -114,6 +114,7 @@ class ModbusTlsClient(ModbusTcpClient): Common optional parameters: + :param framer: Framer enum name :param timeout: Timeout for a request, in seconds. :param retries: Max number of retries per request. :param retry_on_empty: Retry on empty response. @@ -146,7 +147,7 @@ def __init__( self, host: str, port: int = 802, - framer: Type[ModbusFramer] = ModbusTlsFramer, + framer: Framer = Framer.TLS, sslctx: ssl.SSLContext = None, certfile: str = None, keyfile: str = None, diff --git a/pymodbus/client/udp.py b/pymodbus/client/udp.py index 8b60cbd2da..da1ad18d9f 100644 --- a/pymodbus/client/udp.py +++ b/pymodbus/client/udp.py @@ -1,12 +1,13 @@ """Modbus client async UDP communication.""" +from __future__ import annotations + import asyncio import socket -from typing import Any, Tuple, Type +from typing import Any from pymodbus.client.base import ModbusBaseClient from pymodbus.exceptions import ConnectionException -from pymodbus.framer import ModbusFramer -from pymodbus.framer.socket_framer import ModbusSocketFramer +from pymodbus.framer import FRAMER_NAME_TO_CLASS, Framer from pymodbus.logging import Log from pymodbus.transport import CommType @@ -26,11 +27,11 @@ class AsyncModbusUdpClient( Optional parameters: :param port: Port used for communication. - :param framer: Framer class. :param source_address: source address of client, Common optional parameters: + :param framer: Framer enum name :param timeout: Timeout for a request, in seconds. :param retries: Max number of retries per request. :param retry_on_empty: Retry on empty response. @@ -61,15 +62,21 @@ def __init__( self, host: str, port: int = 502, - framer: Type[ModbusFramer] = ModbusSocketFramer, - source_address: Tuple[str, int] = None, + framer: Framer = Framer.SOCKET, + source_address: tuple[str, int] = None, **kwargs: Any, ) -> None: """Initialize Asyncio Modbus UDP Client.""" + framer_class = FRAMER_NAME_TO_CLASS.get(framer, framer) asyncio.DatagramProtocol.__init__(self) asyncio.Protocol.__init__(self) ModbusBaseClient.__init__( - self, framer=framer, CommType=CommType.UDP, host=host, port=port, **kwargs + self, + framer_class=framer_class, # type: ignore[arg-type] + CommType=CommType.UDP, + host=host, + port=port, + **kwargs, ) self.params.source_address = source_address @@ -102,11 +109,11 @@ class ModbusUdpClient(ModbusBaseClient): Optional parameters: :param port: Port used for communication. - :param framer: Framer class. :param source_address: source address of client, Common optional parameters: + :param framer: Framer enum name :param timeout: Timeout for a request, in seconds. :param retries: Max number of retries per request. :param retry_on_empty: Retry on empty response. @@ -139,15 +146,20 @@ def __init__( self, host: str, port: int = 502, - framer: Type[ModbusFramer] = ModbusSocketFramer, - source_address: Tuple[str, int] = None, + framer: Framer = Framer.SOCKET, + source_address: tuple[str, int] = None, **kwargs: Any, ) -> None: """Initialize Modbus UDP Client.""" + framer_class = FRAMER_NAME_TO_CLASS.get(framer, framer) kwargs["use_sync"] = True self.transport = None super().__init__( - framer=framer, port=port, host=host, CommType=CommType.UDP, **kwargs + framer_class=framer_class, # type: ignore[arg-type] + port=port, + host=host, + CommType=CommType.UDP, + **kwargs, ) self.params.source_address = source_address diff --git a/pymodbus/framer/__init__.py b/pymodbus/framer/__init__.py index 94c840e5e4..c2ac109026 100644 --- a/pymodbus/framer/__init__.py +++ b/pymodbus/framer/__init__.py @@ -1,6 +1,7 @@ """Framer""" - __all__ = [ + "Framer", + "FRAMER_NAME_TO_CLASS", "ModbusFramer", "ModbusAsciiFramer", "ModbusBinaryFramer", @@ -9,9 +10,31 @@ "ModbusTlsFramer", ] + +import enum + from pymodbus.framer.ascii_framer import ModbusAsciiFramer from pymodbus.framer.base import ModbusFramer from pymodbus.framer.binary_framer import ModbusBinaryFramer from pymodbus.framer.rtu_framer import ModbusRtuFramer from pymodbus.framer.socket_framer import ModbusSocketFramer from pymodbus.framer.tls_framer import ModbusTlsFramer + + +class Framer(str, enum.Enum): + """These represent the different framers.""" + + ASCII = "ascii" + BINARY = "binary" + RTU = "rtu" + SOCKET = "socket" + TLS = "tls" + + +FRAMER_NAME_TO_CLASS = { + Framer.ASCII: ModbusAsciiFramer, + Framer.BINARY: ModbusBinaryFramer, + Framer.RTU: ModbusRtuFramer, + Framer.SOCKET: ModbusSocketFramer, + Framer.TLS: ModbusTlsFramer, +} diff --git a/pymodbus/server/async_io.py b/pymodbus/server/async_io.py index 29e7f3902e..a5bcb558b7 100644 --- a/pymodbus/server/async_io.py +++ b/pymodbus/server/async_io.py @@ -11,15 +11,9 @@ from pymodbus.device import ModbusControlBlock, ModbusDeviceIdentification from pymodbus.exceptions import NoSuchSlaveException from pymodbus.factory import ServerDecoder -from pymodbus.framer import ModbusFramer +from pymodbus.framer import FRAMER_NAME_TO_CLASS, Framer, ModbusFramer from pymodbus.logging import Log from pymodbus.pdu import ModbusExceptions as merror -from pymodbus.transaction import ( - ModbusAsciiFramer, - ModbusRtuFramer, - ModbusSocketFramer, - ModbusTlsFramer, -) from pymodbus.transport import CommParams, CommType, ModbusProtocol @@ -283,7 +277,8 @@ def __init__( self.handle_local_echo = False if isinstance(identity, ModbusDeviceIdentification): self.control.Identity.update(identity) - self.framer = framer + + self.framer = FRAMER_NAME_TO_CLASS.get(framer, framer) self.serving: asyncio.Future = asyncio.Future() def callback_new_connection(self): @@ -323,7 +318,7 @@ class ModbusTcpServer(ModbusBaseServer): def __init__( self, context, - framer=ModbusSocketFramer, + framer=Framer.SOCKET, identity=None, address=("", 502), ignore_missing_slaves=False, @@ -383,7 +378,7 @@ class ModbusTlsServer(ModbusTcpServer): def __init__( # pylint: disable=too-many-arguments self, context, - framer=ModbusTlsFramer, + framer=Framer.TLS, identity=None, address=("", 502), sslctx=None, @@ -449,7 +444,7 @@ class ModbusUdpServer(ModbusBaseServer): def __init__( self, context, - framer=ModbusSocketFramer, + framer=Framer.SOCKET, identity=None, address=("", 502), ignore_missing_slaves=False, @@ -503,7 +498,7 @@ class ModbusSerialServer(ModbusBaseServer): """ def __init__( - self, context, framer=ModbusRtuFramer, identity=None, **kwargs + self, context, framer=Framer.RTU, identity=None, **kwargs ): # pragma: no cover """Initialize the socket server. @@ -625,7 +620,7 @@ async def StartAsyncTcpServer( # pylint: disable=invalid-name,dangerous-default """ kwargs.pop("host", None) server = ModbusTcpServer( - context, kwargs.pop("framer", ModbusSocketFramer), identity, address, **kwargs + context, kwargs.pop("framer", Framer.SOCKET), identity, address, **kwargs ) await _serverList.run(server, custom_functions) @@ -657,7 +652,7 @@ async def StartAsyncTlsServer( # pylint: disable=invalid-name,dangerous-default kwargs.pop("host", None) server = ModbusTlsServer( context, - kwargs.pop("framer", ModbusTlsFramer), + kwargs.pop("framer", Framer.TLS), identity, address, sslctx, @@ -687,7 +682,7 @@ async def StartAsyncUdpServer( # pylint: disable=invalid-name,dangerous-default """ kwargs.pop("host", None) server = ModbusUdpServer( - context, kwargs.pop("framer", ModbusSocketFramer), identity, address, **kwargs + context, kwargs.pop("framer", Framer.SOCKET), identity, address, **kwargs ) await _serverList.run(server, custom_functions) @@ -707,7 +702,7 @@ async def StartAsyncSerialServer( # pylint: disable=invalid-name,dangerous-defa :param kwargs: The rest """ server = ModbusSerialServer( - context, kwargs.pop("framer", ModbusAsciiFramer), identity=identity, **kwargs + context, kwargs.pop("framer", Framer.RTU), identity=identity, **kwargs ) await _serverList.run(server, custom_functions) diff --git a/pymodbus/server/simulator/http_server.py b/pymodbus/server/simulator/http_server.py index 08c0051932..4ae7c40d17 100644 --- a/pymodbus/server/simulator/http_server.py +++ b/pymodbus/server/simulator/http_server.py @@ -24,13 +24,6 @@ ModbusTlsServer, ModbusUdpServer, ) -from pymodbus.transaction import ( - ModbusAsciiFramer, - ModbusBinaryFramer, - ModbusRtuFramer, - ModbusSocketFramer, - ModbusTlsFramer, -) MAX_FILTER = 1000 @@ -135,13 +128,6 @@ def __init__( "tls": ModbusTlsServer, "udp": ModbusUdpServer, } - framer_class = { - "ascii": ModbusAsciiFramer, - "binary": ModbusBinaryFramer, - "rtu": ModbusRtuFramer, - "socket": ModbusSocketFramer, - "tls": ModbusTlsFramer, - } if custom_actions_module: actions_module = importlib.import_module(custom_actions_module) custom_actions_dict = actions_module.custom_actions_dict @@ -158,7 +144,7 @@ def __init__( ) datastore = ModbusServerContext(slaves=self.datastore_context, single=True) comm = comm_class[server.pop("comm")] - framer = framer_class[server.pop("framer")] + framer = server.pop("framer") if "identity" in server: server["identity"] = ModbusDeviceIdentification( info_name=server["identity"] diff --git a/test/sub_client/test_client.py b/test/sub_client/test_client.py index fadcd4fd62..b5280dbda7 100755 --- a/test/sub_client/test_client.py +++ b/test/sub_client/test_client.py @@ -265,7 +265,7 @@ async def test_client_instanciate( async def test_client_modbusbaseclient(): """Test modbus base client class.""" client = ModbusBaseClient( - framer=ModbusAsciiFramer, + framer_class=ModbusAsciiFramer, host="localhost", port=BASE_PORT + 1, CommType=CommType.TCP, @@ -297,7 +297,7 @@ async def test_client_base_async(): p_close.return_value = asyncio.Future() p_close.return_value.set_result(True) async with ModbusBaseClient( - framer=ModbusAsciiFramer, + framer_class=ModbusAsciiFramer, host="localhost", port=BASE_PORT + 2, CommType=CommType.TCP, @@ -312,7 +312,7 @@ async def test_client_base_async(): @pytest.mark.skip() async def test_client_protocol_receiver(): """Test the client protocol data received""" - base = ModbusBaseClient(framer=ModbusSocketFramer) + base = ModbusBaseClient(framer_class=ModbusSocketFramer) transport = mock.MagicMock() base.connection_made(transport) assert base.transport == transport @@ -334,7 +334,7 @@ async def test_client_protocol_receiver(): @pytest.mark.skip() async def test_client_protocol_response(): """Test the udp client protocol builds responses""" - base = ModbusBaseClient(framer=ModbusSocketFramer) + base = ModbusBaseClient(framer_class=ModbusSocketFramer) response = base._build_response(0x00) # pylint: disable=protected-access excp = response.exception() assert isinstance(excp, ConnectionException) @@ -348,7 +348,7 @@ async def test_client_protocol_response(): async def test_client_protocol_handler(): """Test the client protocol handles responses""" base = ModbusBaseClient( - framer=ModbusAsciiFramer, host="localhost", port=+3, CommType=CommType.TCP + framer_class=ModbusAsciiFramer, host="localhost", port=+3, CommType=CommType.TCP ) transport = mock.MagicMock() base.connection_made(transport=transport) @@ -395,7 +395,7 @@ def close(self): async def test_client_protocol_execute(): """Test the client protocol execute method""" - base = ModbusBaseClient(host="127.0.0.1", framer=ModbusSocketFramer) + base = ModbusBaseClient(host="127.0.0.1", framer_class=ModbusSocketFramer) request = pdu_bit_read.ReadCoilsRequest(1, 1) transport = MockTransport(base, request) base.connection_made(transport=transport) @@ -407,7 +407,9 @@ async def test_client_protocol_execute(): async def test_client_protocol_retry(): """Test the client protocol execute method with retries""" - base = ModbusBaseClient(host="127.0.0.1", framer=ModbusSocketFramer, timeout=0.1) + base = ModbusBaseClient( + host="127.0.0.1", framer_class=ModbusSocketFramer, timeout=0.1 + ) request = pdu_bit_read.ReadCoilsRequest(1, 1) transport = MockTransport(base, request, retries=2) base.connection_made(transport=transport) @@ -421,7 +423,7 @@ async def test_client_protocol_retry(): async def test_client_protocol_timeout(): """Test the client protocol execute method with timeout""" base = ModbusBaseClient( - host="127.0.0.1", framer=ModbusSocketFramer, timeout=0.1, retries=2 + host="127.0.0.1", framer_class=ModbusSocketFramer, timeout=0.1, retries=2 ) # Avoid creating do_reconnect() task base.connection_lost = mock.MagicMock() diff --git a/test/test_framers.py b/test/test_framers.py index 3070f8b126..501d5b5283 100644 --- a/test/test_framers.py +++ b/test/test_framers.py @@ -308,7 +308,7 @@ def test_send_packet(rtu_framer): """Test send packet.""" message = TEST_MESSAGE client = ModbusBaseClient( - framer=ModbusAsciiFramer, + framer_class=ModbusAsciiFramer, host="localhost", port=BASE_PORT + 1, CommType=CommType.TCP,