Skip to content

Commit 7c12169

Browse files
committed
Generate pdu table direct.
1 parent 6f98569 commit 7c12169

File tree

1 file changed

+18
-13
lines changed

1 file changed

+18
-13
lines changed

pymodbus/pdu/decoders.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@ class DecodePDU:
1212

1313
_pdu_class_table: set[tuple[type[ModbusPDU], type[ModbusPDU]]] = set()
1414
_pdu_sub_class_table: set[tuple[type[ModbusPDU], type[ModbusPDU]]] = set()
15+
pdu_table: dict[int, tuple[type[ModbusPDU], type[ModbusPDU]]] = {}
16+
pdu_sub_table: dict[int, dict[int, tuple[type[ModbusPDU], type[ModbusPDU]]]] = {}
17+
1518

1619
def __init__(self, is_server: bool) -> None:
1720
"""Initialize function_tables."""
21+
self.pdu_inx = 0 if is_server else 1
1822
inx = 0 if is_server else 1
1923
self.lookup: dict[int, type[ModbusPDU]] = {cl[inx].function_code: cl[inx] for cl in self._pdu_class_table}
2024
self.sub_lookup: dict[int, dict[int, type[ModbusPDU]]] = {}
@@ -26,29 +30,35 @@ def __init__(self, is_server: bool) -> None:
2630

2731
def lookupPduClass(self, data: bytes) -> type[ModbusPDU] | None:
2832
"""Use `function_code` to determine the class of the PDU."""
29-
func_code = int(data[1])
30-
if func_code & 0x80:
33+
if (func_code := int(data[1])) & 0x80:
3134
return ExceptionResponse
35+
if not (pdu := self.pdu_table.get(func_code, (None, None))[self.pdu_inx]):
36+
return None
37+
3238
if func_code == 0x2B: # mei message, sub_function_code is 1 byte
3339
sub_func_code = int(data[2])
34-
return self.sub_lookup[func_code].get(sub_func_code, None)
35-
if func_code == 0x08: # diag message, sub_function_code is 2 bytes
40+
elif func_code == 0x08: # diag message, sub_function_code is 2 bytes
3641
sub_func_code = int.from_bytes(data[2:4], "big")
37-
return self.sub_lookup[func_code].get(sub_func_code, None)
38-
return self.lookup.get(func_code, None)
42+
else:
43+
return pdu
44+
return self.pdu_sub_table[func_code].get(sub_func_code, (None, None))[self.pdu_inx]
3945

4046
def list_function_codes(self):
4147
"""Return list of function codes."""
42-
return list(self.lookup)
48+
return list(self.pdu_table)
4349

4450
@classmethod
4551
def add_pdu(cls, req: type[ModbusPDU], resp: type[ModbusPDU]):
4652
"""Register request/response."""
53+
cls.pdu_table[req.function_code] = (req, resp)
4754
cls._pdu_class_table.add((req, resp))
4855

4956
@classmethod
5057
def add_sub_pdu(cls, req: type[ModbusPDU], resp: type[ModbusPDU]):
5158
"""Register request/response."""
59+
if req.function_code not in cls.pdu_sub_table:
60+
cls.pdu_sub_table[req.function_code] = {}
61+
cls.pdu_sub_table[req.function_code][req.sub_function_code] = (req, resp)
5262
cls._pdu_sub_class_table.add((req, resp))
5363

5464
def register(self, custom_class: type[ModbusPDU]) -> None:
@@ -60,12 +70,7 @@ def register(self, custom_class: type[ModbusPDU]) -> None:
6070
"`pymodbus.pdu.ModbusPDU` "
6171
)
6272
self.lookup[custom_class.function_code] = custom_class
63-
if custom_class.sub_function_code >= 0:
64-
if custom_class.function_code not in self.sub_lookup:
65-
self.sub_lookup[custom_class.function_code] = {}
66-
self.sub_lookup[custom_class.function_code][
67-
custom_class.sub_function_code
68-
] = custom_class
73+
self.pdu_table[custom_class.function_code] = (custom_class, custom_class)
6974

7075
def decode(self, frame: bytes) -> ModbusPDU | None:
7176
"""Decode a frame."""

0 commit comments

Comments
 (0)