Skip to content

Commit

Permalink
new rtu.
Browse files Browse the repository at this point in the history
  • Loading branch information
janiversen committed Apr 16, 2024
1 parent 3c0e9ed commit 33d9ff4
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 11 deletions.
4 changes: 4 additions & 0 deletions pymodbus/framer/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"""
from __future__ import annotations

from abc import abstractmethod


class FramerBase:
"""Intern base."""
Expand All @@ -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.
Expand All @@ -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.
Expand Down
18 changes: 12 additions & 6 deletions pymodbus/framer/framer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions pymodbus/framer/raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
19 changes: 16 additions & 3 deletions pymodbus/framer/rtu.py
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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:
Expand Down

0 comments on commit 33d9ff4

Please sign in to comment.