From 6f6e9dde5a88978fdb25dbc9324bcefaabafaa9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Wed, 3 Feb 2021 09:31:56 +0100 Subject: [PATCH 1/3] Convert unknown error codes to a useful exception class. Introduce an UndefinedModbusException class and use it when the lookup in error_code_to_exception_map fails. Previously that would just throw a KeyError with the contained value, so this change makes it more obvious what actually happened. --- umodbus/exceptions.py | 10 ++++++++++ umodbus/functions.py | 8 ++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/umodbus/exceptions.py b/umodbus/exceptions.py index 85a9a56..393c895 100644 --- a/umodbus/exceptions.py +++ b/umodbus/exceptions.py @@ -3,6 +3,16 @@ class ModbusError(Exception): pass +class UndefinedModbusError(ModbusError): + """Catch-all class for non-standard error codes.""" + + def __init__(self, error_code): + self.error_code = error_code + + def __repr__(self): + return 'Non-standard Modbus error code %#02x received.' % self.error_code + + class IllegalFunctionError(ModbusError): """ The function code received in the request is not an allowable action for the server. diff --git a/umodbus/functions.py b/umodbus/functions.py index 4db3cec..d25fb37 100644 --- a/umodbus/functions.py +++ b/umodbus/functions.py @@ -74,7 +74,7 @@ from umodbus import conf, log from umodbus.exceptions import (error_code_to_exception_map, IllegalDataValueError, IllegalFunctionError, - IllegalDataAddressError) + IllegalDataAddressError, UndefinedModbusError) from umodbus.utils import memoize, get_function_code_from_request_pdu # Function related to data access. @@ -115,7 +115,11 @@ def pdu_to_function_code_or_raise_error(resp_pdu): if function_code not in function_code_to_function_map.keys(): error_code = struct.unpack('>B', resp_pdu[1:2])[0] - raise error_code_to_exception_map[error_code] + try: + exception = error_code_to_exception_map[error_code] + raise exception + except KeyError as e: + raise UndefinedModbusError(e) return function_code From 0e156f6298d68ad094ff69d25c79320be68a3e15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Wed, 10 Mar 2021 12:30:50 +0100 Subject: [PATCH 2/3] Fix string representation of UndefinedModbusError. The __repr__() special method is usually called in place of __str__(), but only if the latter is not defined. However the BaseException class already has a __str__() method, so we need to override that specifically. Note that this change doesn't touch the other cases below where the same problem exists. Initialize the error_code field explicitly using the KeyError argument instead of passing in the whole exception object. --- umodbus/exceptions.py | 2 +- umodbus/functions.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/umodbus/exceptions.py b/umodbus/exceptions.py index 393c895..246cac9 100644 --- a/umodbus/exceptions.py +++ b/umodbus/exceptions.py @@ -9,7 +9,7 @@ class UndefinedModbusError(ModbusError): def __init__(self, error_code): self.error_code = error_code - def __repr__(self): + def __str__(self): return 'Non-standard Modbus error code %#02x received.' % self.error_code diff --git a/umodbus/functions.py b/umodbus/functions.py index d25fb37..ed465d2 100644 --- a/umodbus/functions.py +++ b/umodbus/functions.py @@ -119,7 +119,7 @@ def pdu_to_function_code_or_raise_error(resp_pdu): exception = error_code_to_exception_map[error_code] raise exception except KeyError as e: - raise UndefinedModbusError(e) + raise UndefinedModbusError(e.args[0]) return function_code From c3212d6094017aabe6329a52c646cd82f10c41f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Wed, 10 Mar 2021 12:30:50 +0100 Subject: [PATCH 3/3] Fix hex string length in UndefinedModbusError. --- umodbus/exceptions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/umodbus/exceptions.py b/umodbus/exceptions.py index 246cac9..0f6a1cd 100644 --- a/umodbus/exceptions.py +++ b/umodbus/exceptions.py @@ -10,7 +10,7 @@ def __init__(self, error_code): self.error_code = error_code def __str__(self): - return 'Non-standard Modbus error code %#02x received.' % self.error_code + return 'Non-standard Modbus error code %#04x received.' % self.error_code class IllegalFunctionError(ModbusError):