Skip to content

Commit

Permalink
converted processIncomingPacket.
Browse files Browse the repository at this point in the history
  • Loading branch information
janiversen committed Mar 22, 2023
1 parent 2f4ed4a commit 7ed0665
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 27 deletions.
48 changes: 33 additions & 15 deletions pymodbus/framer/rtu_framer.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def __init__(self, decoder, client=None):
self._hsize = 0x01
self._end = b"\x0d\x0a"
self._min_frame_size = 4
self.function_codes = set(self.decoder.lookup) if self.decoder else {}

# ----------------------------------------------------------------------- #
# Private Helper Functions
Expand Down Expand Up @@ -191,6 +192,23 @@ def populateResult(self, result):
result.slave_id = self._header["uid"]
result.transaction_id = self._header["uid"]

def getFrameStart(self, slaves, broadcast, skip_cur_frame):
"""Scan buffer for a relevant frame start."""
start = 1 if skip_cur_frame else 0
if (buf_len := len(self._buffer)) < 4:
return False
for i in range(start, buf_len - 3): # <slave id><function code><crc 2 bytes>
if not broadcast and self._buffer[i] not in slaves:
continue
if self._buffer[i + 1] not in self.function_codes:
continue
if i:
self._buffer = self._buffer[i:] # remove preceding trash.
return True
if buf_len > 3:
self._buffer = self._buffer[-3:]
return False

# ----------------------------------------------------------------------- #
# Public Member Functions
# ----------------------------------------------------------------------- #
Expand All @@ -214,25 +232,25 @@ def processIncomingPacket(self, data, callback, slave, **kwargs):
"""
if not isinstance(slave, (list, tuple)):
slave = [slave]
broadcast = not slave[0]
self.addToFrame(data)
single = kwargs.get("single", False)
while True:
if self.isFrameReady():
if self.checkFrame():
if self._validate_slave_id(slave, single):
self._process(callback)
else:
header_txt = self._header["uid"]
Log.debug("Not a valid slave id - {}, ignoring!!", header_txt)
self.resetFrame()
break
else:
Log.debug("Frame check failed, ignoring!!")
self.resetFrame()
break
else:
skip_cur_frame = False
while self.getFrameStart(slave, broadcast, skip_cur_frame):
skip_cur_frame = True
if not self.isFrameReady():
Log.debug("Frame - [{}] not ready", data)
break
if not self.checkFrame():
Log.debug("Frame check failed, ignoring!!")
self.resetFrame()
break
if not self._validate_slave_id(slave, single):
header_txt = self._header["uid"]
Log.debug("Not a valid slave id - {}, ignoring!!", header_txt)
self.resetFrame()
break
self._process(callback)

def buildPacket(self, message):
"""Create a ready to send modbus packet.
Expand Down
34 changes: 24 additions & 10 deletions test/test_client_multidrop.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,13 @@ def test_big_split_response_frame_from_other_unit(self, framer, callback):
framer.processIncomingPacket(serial_event, callback, self.slaves)
callback.assert_not_called()

@pytest.mark.skip
def test_split_frame(self, framer, callback):
"""Test split frame."""
serial_events = [self.good_frame[:5], self.good_frame[5:]]
for serial_event in serial_events:
framer.processIncomingPacket(serial_event, callback, self.slaves)
callback.assert_called_once()

@pytest.mark.skip
def test_complete_frame_trailing_data_without_unit_id(self, framer, callback):
"""Test trailing data."""
garbage = b"\x05\x04\x03" # Note the garbage doesn't contain our unit id
Expand Down Expand Up @@ -138,13 +136,29 @@ def test_frame_with_trailing_data(self, framer, callback):
# We should not respond in this case for identical reasons as test_wrapped_frame
callback.assert_not_called()

@pytest.mark.skip
def test_getFrameStart(self, framer, callback):
def test_getFrameStart(self, framer):
"""Test getFrameStart."""
framer_ok = b"\x02\x03\x00\x01\x00}\xd4\x18"
framer._buffer = framer_ok + framer_ok
assert framer.getFrameStart(self.slaves, False)
assert framer_ok + framer_ok == framer._buffer
assert framer.getFrameStart(self.slaves, True)
assert framer_ok == framer._buffer
assert not framer.getFrameStart(self.slaves, True)
framer._buffer = framer_ok # pylint: disable=protected-access
assert framer.getFrameStart(self.slaves, False, False)
assert framer_ok == framer._buffer # pylint: disable=protected-access

framer_2ok = framer_ok + framer_ok
framer._buffer = framer_2ok # pylint: disable=protected-access
assert framer.getFrameStart(self.slaves, False, False)
assert framer_2ok == framer._buffer # pylint: disable=protected-access
assert framer.getFrameStart(self.slaves, False, True)
assert framer_ok == framer._buffer # pylint: disable=protected-access

framer._buffer = framer_ok[:2] # pylint: disable=protected-access
assert not framer.getFrameStart(self.slaves, False, False)
assert framer_ok[:2] == framer._buffer # pylint: disable=protected-access

framer._buffer = framer_ok[:3] # pylint: disable=protected-access
assert not framer.getFrameStart(self.slaves, False, False)
assert framer_ok[:3] == framer._buffer # pylint: disable=protected-access

framer_ok = b"\xF0\x03\x00\x01\x00}\xd4\x18"
framer._buffer = framer_ok # pylint: disable=protected-access
assert not framer.getFrameStart(self.slaves, False, False)
assert framer._buffer == framer_ok[-3:] # pylint: disable=protected-access
4 changes: 2 additions & 2 deletions test/test_framers.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,10 @@ def test_populate_result(rtu_framer): # pylint: disable=redefined-outer-name
(
b"\x11\x03\x06\xAE\x41\x56\x52\x43\x40\x49\xAD",
16,
True,
False,
False,
), # incorrect slave id
(b"\x11\x03\x06\xAE\x41\x56\x52\x43\x40\x49\xAD\x11\x03", 17, True, False),
(b"\x11\x03\x06\xAE\x41\x56\x52\x43\x40\x49\xAD\x11\x03", 17, False, True),
# good frame + part of next frame
],
)
Expand Down

0 comments on commit 7ed0665

Please sign in to comment.