diff --git a/pymodbus/framer/base.py b/pymodbus/framer/base.py index 9fa3b083c1..e0c1595f03 100644 --- a/pymodbus/framer/base.py +++ b/pymodbus/framer/base.py @@ -6,6 +6,8 @@ """ from __future__ import annotations +from abc import abstractmethod + class FramerBase: """Intern base.""" @@ -21,6 +23,7 @@ def set_dev_ids(self, _dev_ids: list[int]): def set_fc_calc(self, _fc: int, _msg_size: int, _count_pos: int): """Set/Update function code information.""" + @abstractmethod def decode(self, data: bytes) -> tuple[int, int, int, bytes]: """Decode ADU. @@ -31,6 +34,7 @@ def decode(self, data: bytes) -> tuple[int, int, int, bytes]: modbus request/response (bytes) """ + @abstractmethod def encode(self, pdu: bytes, dev_id: int, tid: int) -> bytes: """Encode ADU. diff --git a/pymodbus/framer/framer.py b/pymodbus/framer/framer.py index f7e891e5d6..0e871a975f 100644 --- a/pymodbus/framer/framer.py +++ b/pymodbus/framer/framer.py @@ -66,13 +66,19 @@ def __init__(self, super().__init__(params, is_server) self.device_ids = device_ids self.broadcast: bool = (0 in device_ids) + self.handle1 = FramerRaw() + self.handle2 = FramerAscii() + self.handle3 = FramerRTU() + self.handle4 = FramerSocket() + self.handle5 = FramerTLS() + self.handle = { - FramerType.RAW: FramerRaw, - FramerType.ASCII: FramerAscii, - FramerType.RTU: FramerRTU, - FramerType.SOCKET: FramerSocket, - FramerType.TLS: FramerTLS, - }[framer_type]() + FramerType.RAW: FramerRaw(), + FramerType.ASCII: FramerAscii(), + FramerType.RTU: FramerRTU(), + FramerType.SOCKET: FramerSocket(), + FramerType.TLS: FramerTLS(), + }[framer_type] def callback_data(self, data: bytes, addr: tuple | None = None) -> int: diff --git a/pymodbus/framer/raw.py b/pymodbus/framer/raw.py index 54a9a0ac1c..96ca1bc2ee 100644 --- a/pymodbus/framer/raw.py +++ b/pymodbus/framer/raw.py @@ -27,6 +27,6 @@ def decode(self, data: bytes) -> tuple[int, int, int, bytes]: tid = int(data[1]) return len(data), dev_id, tid, data[2:] - def encode(self, pdu: bytes, device_id: int, tid: int) -> bytes: + def encode(self, pdu: bytes, dev_id: int, tid: int) -> bytes: """Encode ADU.""" - return device_id.to_bytes(1, 'big') + tid.to_bytes(1, 'big') + pdu + return dev_id.to_bytes(1, 'big') + tid.to_bytes(1, 'big') + pdu diff --git a/pymodbus/framer/rtu.py b/pymodbus/framer/rtu.py index 47ae9be88e..a01a171bf1 100644 --- a/pymodbus/framer/rtu.py +++ b/pymodbus/framer/rtu.py @@ -1,6 +1,8 @@ """Modbus RTU frame implementation.""" from __future__ import annotations +from collections import namedtuple + from pymodbus.framer.base import FramerBase from pymodbus.logging import Log @@ -15,7 +17,7 @@ class FramerRTU(FramerBase): neither when receiving nor when sending. Decoding is a complicated process because the RTU frame does not have a fixed prefix - only suffix, therefore it is nessecary to decode the content (PDU) to get length etc. + only suffix, therefore it is necessary to decode the content (PDU) to get length etc. There are some restraints however that help the detection. @@ -43,16 +45,19 @@ class FramerRTU(FramerBase): - data in frame garbled (wrong CRC) decoding assumes the frame is sound, and if not enters a hunting mode. - The 3.5 byte wait betwen frames is 31ms at 1.200Bps and 1ms at 38.600bps, - so the decoder will wait 50ms for more data if not the transmission is + The 3.5 byte wait 31ms at 1.200Bps and 1ms at 38.600bps, + so the decoder will wait for more data a number of milliseconds, if not the transmission is considered complete """ MIN_SIZE = 5 + FC_LEN = namedtuple("FC_LEN", "req_len req_bytepos resp_len resp_bytepos") + def __init__(self) -> None: """Initialize a ADU instance.""" super().__init__() + self.fc_len: dict[int, FramerRTU.FC_LEN] = {} @classmethod @@ -74,6 +79,14 @@ def generate_crc16_table(cls) -> list[int]: return result crc16_table: list[int] = [0] + + def setup_fc_len(self, _fc: int, + _req_len: int, _req_byte_pos: int, + _resp_len: int, _resp_byte_pos: int + ): + """Define request/response lengths pr function code.""" + return + def decode(self, data: bytes) -> tuple[int, int, int, bytes]: """Decode ADU.""" if (buf_len := len(data)) < self.MIN_SIZE: