Skip to content

Commit e2f3b39

Browse files
authored
Simplify response rejection. (#2657)
1 parent d37bbe9 commit e2f3b39

25 files changed

+191
-169
lines changed

examples/message_parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def decode(self, message):
8080
print(f"{decoder.decoder.__class__.__name__}")
8181
print("-" * 80)
8282
try:
83-
_, pdu = decoder.processIncomingFrame(message)
83+
_, pdu = decoder.handleFrame(message, 0, 0)
8484
self.report(pdu)
8585
except Exception: # pylint: disable=broad-except
8686
self.check_errors(decoder, message)

pymodbus/client/serial.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ def send(self, request: bytes, addr: tuple | None = None) -> int:
270270
if waitingbytes := self._in_waiting():
271271
result = self.socket.read(waitingbytes)
272272
Log.warning("Cleanup recv buffer before send: {}", result, ":hex")
273-
if (size := self.socket.write(request)) is None:
273+
if (size := self.socket.write(request)) is None: # pragma: no cover
274274
size = 0
275275
return size
276276
return 0

pymodbus/client/tcp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ def recv(self, size: int | None) -> bytes:
259259
return self._handle_abrupt_socket_close(
260260
size, data, time.time() - time_
261261
)
262-
except SSLWantReadError:
262+
except SSLWantReadError: # pragma: no cover
263263
continue
264264
data.append(recv_data)
265265
data_length += len(recv_data)

pymodbus/constants.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,6 @@ class DeviceInformation(int, enum.Enum):
112112
EXTENDED = 0x03
113113
SPECIFIC = 0x04
114114

115-
def __str__(self):
116-
"""Override to force int representation for enum members."""
117-
return str(int(self))
118-
119115

120116
class MoreData(int, enum.Enum):
121117
"""Represents the more follows condition.

pymodbus/exceptions.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
__all__ = [
77
"ConnectionException",
8-
"InvalidMessageReceivedException",
98
"MessageRegisterException",
109
"ModbusIOException",
1110
"NoSuchIdException",
@@ -95,18 +94,6 @@ def __init__(self, string=""):
9594
ModbusException.__init__(self, message)
9695

9796

98-
class InvalidMessageReceivedException(ModbusException):
99-
"""Error resulting from invalid response received or decoded."""
100-
101-
def __init__(self, string=""):
102-
"""Initialize the exception.
103-
104-
:param string: The message to append to the error
105-
"""
106-
message = f"[Invalid Message] {string}"
107-
ModbusException.__init__(self, message)
108-
109-
11097
class MessageRegisterException(ModbusException):
11198
"""Error resulting from failing to register a custom message request/response."""
11299

pymodbus/framer/base.py

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -63,40 +63,29 @@ def buildFrame(self, message: ModbusPDU) -> bytes:
6363
frame = self.encode(data, message.dev_id, message.transaction_id)
6464
return frame
6565

66-
def processIncomingFrame(self, data: bytes) -> tuple[int, ModbusPDU | None]:
67-
"""Process new packet pattern.
68-
69-
This takes in a new request packet, adds it to the current
70-
packet stream, and performs framing on it. That is, checks
71-
for complete messages, and once found, will process all that
72-
exist.
73-
"""
66+
def handleFrame(self, data: bytes, exp_devid: int, exp_tid: int) -> tuple[int, ModbusPDU | None]:
67+
"""Process incoming data."""
7468
used_len = 0
7569
while True:
76-
data_len, pdu = self._processIncomingFrame(data[used_len:])
70+
if used_len >= len(data):
71+
return used_len, None
72+
Log.debug("Processing: {}", data, ":hex")
73+
data_len, dev_id, tid, frame_data = self.decode(data)
7774
used_len += data_len
78-
if not data_len:
75+
if not data_len or not frame_data:
7976
return used_len, None
80-
if pdu:
81-
return used_len, pdu
82-
83-
def _processIncomingFrame(self, data: bytes) -> tuple[int, ModbusPDU | None]:
84-
"""Process new packet pattern.
85-
86-
This takes in a new request packet, adds it to the current
87-
packet stream, and performs framing on it. That is, checks
88-
for complete messages, and once found, will process all that
89-
exist.
90-
"""
91-
Log.debug("Processing: {}", data, ":hex")
92-
if not data:
93-
return 0, None
94-
used_len, dev_id, tid, frame_data = self.decode(data)
95-
if not frame_data:
96-
return used_len, None
97-
if (result := self.decoder.decode(frame_data)) is None:
98-
raise ModbusIOException("Unable to decode request")
99-
result.dev_id = dev_id
100-
result.transaction_id = tid
101-
Log.debug("Frame advanced, resetting header!!")
102-
return used_len, result
77+
if exp_devid and dev_id != exp_devid:
78+
Log.error(
79+
f"ERROR: request ask for id={exp_devid} but got id={dev_id}, Skipping."
80+
)
81+
continue
82+
if exp_tid and tid and tid != exp_tid:
83+
Log.error(
84+
f"ERROR: request ask for transaction_id={exp_tid} but got id={tid}, Skipping."
85+
)
86+
continue
87+
if (pdu := self.decoder.decode(frame_data)) is None:
88+
raise ModbusIOException("Unable to decode request")
89+
pdu.dev_id = dev_id
90+
pdu.transaction_id = tid
91+
return used_len, pdu

pymodbus/logging.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def build_msg(cls, txt, *args):
8383
string_args.append(hexlify_packets(args[i]))
8484
elif args[i + 1] == ":str":
8585
string_args.append(str(args[i]))
86-
elif args[i + 1] == ":b2a":
86+
else: # args[i + 1] == ":b2a":
8787
string_args.append(b2a_hex(args[i]))
8888
skip = True
8989
else:
@@ -117,5 +117,4 @@ def error(cls, txt, *args):
117117
@classmethod
118118
def critical(cls, txt, *args):
119119
"""Log critical messages."""
120-
if cls._logger.isEnabledFor(logging.CRITICAL):
121-
cls._logger.critical(cls.build_msg(txt, *args), stacklevel=2)
120+
cls._logger.critical(cls.build_msg(txt, *args), stacklevel=2)

pymodbus/pdu/bit_message.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ async def update_datastore(self, context: ModbusDeviceContext) -> ModbusPDU:
3838
values = await context.async_getValues(
3939
self.function_code, self.address, self.count
4040
)
41-
if isinstance(values, int):
42-
return ExceptionResponse(self.function_code, values)
4341
response_class = (ReadCoilsResponse if self.function_code == 1 else ReadDiscreteInputsResponse)
4442
return response_class(dev_id=self.dev_id, transaction_id=self.transaction_id, bits=cast(list[bool], values))
4543

@@ -98,9 +96,6 @@ async def update_datastore(self, context: ModbusDeviceContext) -> ModbusPDU:
9896
if (rc := await context.async_setValues(self.function_code, self.address, self.bits)):
9997
return ExceptionResponse(self.function_code, rc)
10098
values = await context.async_getValues(self.function_code, self.address, 1)
101-
if isinstance(values, int):
102-
return ExceptionResponse(self.function_code, values)
103-
10499
return WriteSingleCoilResponse(address=self.address, bits=cast(list[bool], values), dev_id=self.dev_id, transaction_id=self.transaction_id)
105100

106101
def get_response_pdu_size(self) -> int:

pymodbus/pdu/device.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
# pylint: disable=missing-type-doc
1919
from collections import OrderedDict
2020

21-
from pymodbus.constants import INTERNAL_ERROR, DeviceInformation
21+
from pymodbus.constants import DeviceInformation
2222
from pymodbus.pdu.events import ModbusEvent
2323
from pymodbus.utilities import dict_property
2424

@@ -293,11 +293,6 @@ def __gets(cls, identity, object_ids): # pylint: disable=unused-private-member
293293
"""
294294
return {oid: identity[oid] for oid in object_ids if identity[oid]}
295295

296-
def __init__(self):
297-
"""Prohibit objects."""
298-
raise RuntimeError(INTERNAL_ERROR)
299-
300-
301296
# ---------------------------------------------------------------------------#
302297
# Counters Handler
303298
# ---------------------------------------------------------------------------#
@@ -562,8 +557,7 @@ def setDiagnostic(self, mapping):
562557
:param mapping: Dictionary of key:value pairs to set
563558
"""
564559
for entry in iter(mapping.items()):
565-
if entry[0] >= 0 and entry[0] < len(self._diagnostic):
566-
self._diagnostic[entry[0]] = bool(entry[1])
560+
self._diagnostic[entry[0]] = bool(entry[1])
567561

568562
def getDiagnostic(self, bit):
569563
"""Get the value in the diagnostic register.

pymodbus/pdu/register_message.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from __future__ import annotations
33

44
import struct
5+
from collections.abc import Sequence
56
from typing import cast
67

78
from pymodbus.datastore import ModbusDeviceContext
@@ -37,8 +38,6 @@ async def update_datastore(self, context: ModbusDeviceContext) -> ModbusPDU:
3738
values = await context.async_getValues(
3839
self.function_code, self.address, self.count
3940
)
40-
if isinstance(values, int):
41-
return ExceptionResponse(self.function_code, values)
4241
response_class = (ReadHoldingRegistersResponse if self.function_code == 3 else ReadInputRegistersResponse)
4342
return response_class(registers=cast(list[int], values), dev_id=self.dev_id, transaction_id=self.transaction_id)
4443

@@ -147,8 +146,6 @@ async def update_datastore(self, context: ModbusDeviceContext) -> ModbusPDU:
147146
registers = await context.async_getValues(
148147
self.function_code, self.read_address, self.read_count
149148
)
150-
if isinstance(registers, int):
151-
return ExceptionResponse(self.function_code, registers)
152149
return ReadWriteMultipleRegistersResponse(registers=cast(list[int], registers), dev_id=self.dev_id, transaction_id=self.transaction_id)
153150

154151
def get_response_pdu_size(self) -> int:
@@ -194,8 +191,6 @@ async def update_datastore(self, context: ModbusDeviceContext) -> ModbusPDU:
194191
if rc:
195192
return ExceptionResponse(self.function_code, rc)
196193
values = await context.async_getValues(self.function_code, self.address, 1)
197-
if isinstance(values, int):
198-
return ExceptionResponse(self.function_code, values)
199194
return WriteSingleRegisterResponse(address=self.address, registers=cast(list[int], values))
200195

201196
def get_response_pdu_size(self) -> int:
@@ -288,9 +283,7 @@ async def update_datastore(self, context: ModbusDeviceContext) -> ModbusPDU:
288283
if not 0x0000 <= self.or_mask <= 0xFFFF:
289284
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_VALUE)
290285
values = await context.async_getValues(self.function_code, self.address, 1)
291-
if isinstance(values, int):
292-
return ExceptionResponse(self.function_code, values)
293-
values = (values[0] & self.and_mask) | (self.or_mask & ~self.and_mask)
286+
values = (cast(Sequence[int | bool], values)[0] & self.and_mask) | (self.or_mask & ~self.and_mask)
294287
rc = await context.async_setValues(
295288
self.function_code, self.address, cast(list[int], [values])
296289
)

0 commit comments

Comments
 (0)