You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm using the Modbus server for testing our client implementation.
As part of our client code, it tests the server for a few baud rates. As a consequence of this, some bad messages are sent with a specified interval between them.
After some debugging, I figured out that the RTU Framer is storing the last received frame indefinitely. As a consequence the next frame which was good was added to the last bad frame and then throws altogether because it cannot parse.
See the framer code below.
According to Modbus serial implementation guide (section 2.5.1.1 MODBUS Message RTU Framing): "If a silent interval of more than 1.5 character times occurs between two characters, the message frame is declared incomplete and
should be discarded by the receiver."
Character time is based on the baud rate, and it seems that the RTU Framer doesn't handle silence between charchters at all.
Code and Logs
Some logs, the second message is good and appended to the previous:
It's all here basically, 'addToFrame' just append the buffer and 'isFrameReady' returns false if the buffer is smaller than the expected function code, and in this case just log 'not ready' and returns.
defprocessIncomingPacket(
self, data, callback, unit, **kwargs
): # pylint: disable=arguments-differ"""Process new packet pattern. This takes in a new request packet, adds it to the current packet stream, and performs framing on it. That is, checks for complete messages, and once found, will process all that exist. This handles the case when we read N + 1 or 1 // N messages at a time instead of 1. The processed and decoded messages are pushed to the callback function to process and send. :param data: The new packet data :param callback: The function to send results to :param unit: Process if unit id matches, ignore otherwise (could be a list of unit ids (server) or single unit id(client/server) :param kwargs: """ifnotisinstance(unit, (list, tuple)):
unit= [unit]
self.addToFrame(data)
single=kwargs.get("single", False)
whileTrue:
ifself.isFrameReady():
ifself.checkFrame():
ifself._validate_unit_id(unit, single):
self._process(callback)
else:
header_txt=self._header["uid"]
txt=f"Not a valid unit id - {header_txt}, ignoring!!"_logger.debug(txt)
self.resetFrame()
breakelse:
_logger.debug("Frame check failed, ignoring!!")
self.resetFrame()
breakelse:
txt=f"Frame - [{data}] not ready"_logger.debug(txt)
break
Suggestion
Add logic to 'addToFrame' checking the last time a buffer was added (stored as a member variable), and if the interval is bigger than expected (according to the baud rate), reset previous buffer and set the buffer to the received one.
The text was updated successfully, but these errors were encountered:
Versions
Pymodbus Specific
Description
I'm using the Modbus server for testing our client implementation.
As part of our client code, it tests the server for a few baud rates. As a consequence of this, some bad messages are sent with a specified interval between them.
After some debugging, I figured out that the RTU Framer is storing the last received frame indefinitely. As a consequence the next frame which was good was added to the last bad frame and then throws altogether because it cannot parse.
See the framer code below.
According to Modbus serial implementation guide (section 2.5.1.1 MODBUS Message RTU Framing):
"If a silent interval of more than 1.5 character times occurs between two characters, the message frame is declared incomplete and
should be discarded by the receiver."
Character time is based on the baud rate, and it seems that the RTU Framer doesn't handle silence between charchters at all.
Code and Logs
Some logs, the second message is good and appended to the previous:
It's all here basically, 'addToFrame' just append the buffer and 'isFrameReady' returns false if the buffer is smaller than the expected function code, and in this case just log 'not ready' and returns.
Suggestion
Add logic to 'addToFrame' checking the last time a buffer was added (stored as a member variable), and if the interval is bigger than expected (according to the baud rate), reset previous buffer and set the buffer to the received one.
The text was updated successfully, but these errors were encountered: