Skip to content

Commit

Permalink
tem.
Browse files Browse the repository at this point in the history
  • Loading branch information
janiversen committed Feb 25, 2024
1 parent 1b9628e commit 4a8dd9d
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 13 deletions.
17 changes: 9 additions & 8 deletions pymodbus/message/ascii.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class MessageAscii(MessageBase):
r"""Modbus ASCII Frame Controller.
[ Start ][Address ][ Function ][ Data ][ LRC ][ End ]
1c 2c 2c Nc 2c 2c
1c 2c 2c Nc 1c 2c
* data can be 0 - 2x252 chars
* end is "\\r\\n" (Carriage return line feed), however the line feed
Expand All @@ -40,22 +40,23 @@ def decode(self, data: bytes) -> tuple[int, int, int, bytes]:
if (used_len := len(data)) < 10:
Log.debug("Short frame: {} wait for more data", data, ":hex")
return 0, 0, 0, self.EMPTY
if data[0] != int(self.START):
if data[0:1] != self.START:
if (start := data.find(self.START)) != -1:
used_len = start
Log.debug("Garble data before frame: {}, skip until start of frame", data, ":hex")
return used_len, 0, 0, self.EMPTY
if not (used_len := data.find(self.END)):
Log.debug("Incomplete frame: {} wait for more data", data, ":hex")
return 0, 0, 0, self.EMPTY
lrc = int(data[used_len - 2: used_len], 16)
msg = a2b_hex(data[1 : used_len - 2])
if not self.check_LRC(msg, lrc):
Log.debug("LRC wrong in frame: {} skipping", data, ":hex")
return used_len+2, 0, 0, self.EMPTY

dev_id = int(data[1:3], 16)
lrc = int(data[used_len - 2 : used_len], 16)
data = a2b_hex(data[1 : used_len - 2])
if not self.check_LRC(data, lrc):
Log.debug("LRC wrong in frame: {} skipping", data, ":hex")
return used_len+1, 0, 0, self.EMPTY
return used_len+1, dev_id, 0, data
_fc = int(data[3:5], 16).to_bytes(1,'big')
return used_len+2, 0, dev_id, msg

def encode(self, data: bytes, device_id: int, _tid: int) -> bytes:
"""Decode message."""
Expand Down
15 changes: 11 additions & 4 deletions pymodbus/message/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,17 @@ def __init__(self,

def callback_data(self, data: bytes, addr: tuple | None = None) -> int:
"""Handle received data."""
used_len, tid, device_id, data = self.msg_handle.decode(data)
if data:
self.callback_request_response(data, device_id, tid)
return used_len
tot_len = len(data)
start = 0
while True:
used_len, tid, device_id, data = self.msg_handle.decode(data[start:])
if data:
self.callback_request_response(data, device_id, tid)
if not used_len:
return used_len
start += used_len
if start == tot_len:
return tot_len

# --------------------- #
# callbacks and helpers #
Expand Down
30 changes: 29 additions & 1 deletion test/message/test_ascii.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ def test_check_LRC(self):
data = struct.pack(">HHHH", 0x1234, 0x2345, 0x3456, 0x4567)
assert MessageAscii.check_LRC(data, 0x1C)

def test_check_noLRC(self):
"""Test check_LRC."""
data = struct.pack(">HHHH", 0x1234, 0x2345, 0x3456, 0x4567)
assert not MessageAscii.check_LRC(data, 0x0C)

def test_compute_LRC(self):
"""Test compute_LRC."""
data = struct.pack(">HHHH", 0x1234, 0x2345, 0x3456, 0x4567)
Expand All @@ -32,5 +37,28 @@ def test_roundtrip_LRC(self):
assert MessageAscii.compute_LRC(data) == 0x1c
assert MessageAscii.check_LRC(data, 0x1C)

def test_decode(self, frame):
@pytest.mark.parametrize(
("packet", "used_len", "id", "res"),
[
(b":010100010001FC\r\n", 17, 1, b'\x00\x01\x00\x00'),
],
)
def test_decode(self, frame, packet, used_len, id, res):
"""Test decode."""
res_len, tid, dev_id, data = frame.decode(packet)
assert res_len == len(packet)
assert not tid
assert dev_id == id
assert data == res


# OK: b":010100010001FC\r\n"
# OK: b':00010001000AF4\r\n'
# OK: b':01010001000AF3\r\n'
# NO: b':01270001000ACD\r\n'
# OK: b':61620001000AF4\r\n'
# remember:
# -- split packet
# -- double packet
# -- garble data in front
# -- garble data after

0 comments on commit 4a8dd9d

Please sign in to comment.