Skip to content

Commit 87effed

Browse files
authored
Specific Exceptions: Adapting systec interface (#1158)
* Improve error handling with existing classes * Format code with black * Correct exception handling at startup * Throw the correct exceptions
1 parent b2a5024 commit 87effed

File tree

5 files changed

+174
-124
lines changed

5 files changed

+174
-124
lines changed

can/interfaces/systec/__init__.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1 @@
1-
"""
2-
"""
3-
41
from can.interfaces.systec.ucanbus import UcanBus

can/interfaces/systec/exceptions.py

Lines changed: 86 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,107 @@
1+
from typing import Dict
2+
3+
from abc import ABC, abstractmethod
4+
15
from .constants import ReturnCode
26
from can import CanError
37

48

5-
class UcanException(CanError):
6-
""" Base class for USB can errors. """
9+
class UcanException(CanError, ABC):
10+
"""Base class for USB can errors."""
711

812
def __init__(self, result, func, arguments):
9-
self.result = result.value
13+
self.result = result
1014
self.func = func
1115
self.arguments = arguments
12-
self.return_msgs = {}
13-
super().__init__()
1416

15-
def __str__(self):
16-
message = self.return_msgs.get(self.result, "unknown")
17-
return f"Function {self.func.__name__} returned {self.result}: {message}"
17+
message = self._error_message_mapping.get(result, "unknown")
18+
super().__init__(
19+
message=f"Function {func.__name__} (called with {arguments}): {message}",
20+
error_code=result.value,
21+
)
22+
23+
@property
24+
@abstractmethod
25+
def _error_message_mapping(self) -> Dict[ReturnCode, str]:
26+
...
1827

1928

2029
class UcanError(UcanException):
21-
""" Exception class for errors from USB-CAN-library. """
30+
"""Exception class for errors from USB-CAN-library."""
2231

23-
def __init__(self, result, func, arguments):
24-
super().__init__(result, func, arguments)
25-
self.return_msgs = {
26-
ReturnCode.ERR_RESOURCE: "could not created a resource (memory, handle, ...)",
27-
ReturnCode.ERR_MAXMODULES: "the maximum number of opened modules is reached",
28-
ReturnCode.ERR_HWINUSE: "the specified module is already in use",
29-
ReturnCode.ERR_ILLVERSION: "the software versions of the module and library are incompatible",
30-
ReturnCode.ERR_ILLHW: "the module with the specified device number is not connected "
31-
"(or used by an other application)",
32-
ReturnCode.ERR_ILLHANDLE: "wrong USB-CAN-Handle handed over to the function",
33-
ReturnCode.ERR_ILLPARAM: "wrong parameter handed over to the function",
34-
ReturnCode.ERR_BUSY: "instruction can not be processed at this time",
35-
ReturnCode.ERR_TIMEOUT: "no answer from module",
36-
ReturnCode.ERR_IOFAILED: "a request to the driver failed",
37-
ReturnCode.ERR_DLL_TXFULL: "a CAN message did not fit into the transmit buffer",
38-
ReturnCode.ERR_MAXINSTANCES: "maximum number of applications is reached",
39-
ReturnCode.ERR_CANNOTINIT: "CAN interface is not yet initialized",
40-
ReturnCode.ERR_DISCONECT: "USB-CANmodul was disconnected",
41-
ReturnCode.ERR_NOHWCLASS: "the needed device class does not exist",
42-
ReturnCode.ERR_ILLCHANNEL: "illegal CAN channel",
43-
ReturnCode.ERR_RESERVED1: "reserved",
44-
ReturnCode.ERR_ILLHWTYPE: "the API function can not be used with this hardware",
45-
}
32+
_ERROR_MESSAGES = {
33+
ReturnCode.ERR_RESOURCE: "could not created a resource (memory, handle, ...)",
34+
ReturnCode.ERR_MAXMODULES: "the maximum number of opened modules is reached",
35+
ReturnCode.ERR_HWINUSE: "the specified module is already in use",
36+
ReturnCode.ERR_ILLVERSION: "the software versions of the module and library are incompatible",
37+
ReturnCode.ERR_ILLHW: "the module with the specified device number is not connected "
38+
"(or used by an other application)",
39+
ReturnCode.ERR_ILLHANDLE: "wrong USB-CAN-Handle handed over to the function",
40+
ReturnCode.ERR_ILLPARAM: "wrong parameter handed over to the function",
41+
ReturnCode.ERR_BUSY: "instruction can not be processed at this time",
42+
ReturnCode.ERR_TIMEOUT: "no answer from module",
43+
ReturnCode.ERR_IOFAILED: "a request to the driver failed",
44+
ReturnCode.ERR_DLL_TXFULL: "a CAN message did not fit into the transmit buffer",
45+
ReturnCode.ERR_MAXINSTANCES: "maximum number of applications is reached",
46+
ReturnCode.ERR_CANNOTINIT: "CAN interface is not yet initialized",
47+
ReturnCode.ERR_DISCONECT: "USB-CANmodul was disconnected",
48+
ReturnCode.ERR_NOHWCLASS: "the needed device class does not exist",
49+
ReturnCode.ERR_ILLCHANNEL: "illegal CAN channel",
50+
ReturnCode.ERR_RESERVED1: "reserved",
51+
ReturnCode.ERR_ILLHWTYPE: "the API function can not be used with this hardware",
52+
}
53+
54+
@property
55+
def _error_message_mapping(self) -> Dict[ReturnCode, str]:
56+
return UcanError._ERROR_MESSAGES
4657

4758

4859
class UcanCmdError(UcanException):
49-
""" Exception class for errors from firmware in USB-CANmodul."""
60+
"""Exception class for errors from firmware in USB-CANmodul."""
5061

51-
def __init__(self, result, func, arguments):
52-
super().__init__(result, func, arguments)
53-
self.return_msgs = {
54-
ReturnCode.ERRCMD_NOTEQU: "the received response does not match to the transmitted command",
55-
ReturnCode.ERRCMD_REGTST: "no access to the CAN controller",
56-
ReturnCode.ERRCMD_ILLCMD: "the module could not interpret the command",
57-
ReturnCode.ERRCMD_EEPROM: "error while reading the EEPROM",
58-
ReturnCode.ERRCMD_RESERVED1: "reserved",
59-
ReturnCode.ERRCMD_RESERVED2: "reserved",
60-
ReturnCode.ERRCMD_RESERVED3: "reserved",
61-
ReturnCode.ERRCMD_ILLBDR: "illegal baud rate value specified in BTR0/BTR1 for systec "
62-
"USB-CANmoduls",
63-
ReturnCode.ERRCMD_NOTINIT: "CAN channel is not initialized",
64-
ReturnCode.ERRCMD_ALREADYINIT: "CAN channel is already initialized",
65-
ReturnCode.ERRCMD_ILLSUBCMD: "illegal sub-command specified",
66-
ReturnCode.ERRCMD_ILLIDX: "illegal index specified (e.g. index for cyclic CAN messages)",
67-
ReturnCode.ERRCMD_RUNNING: "cyclic CAN message(s) can not be defined because transmission of "
68-
"cyclic CAN messages is already running",
69-
}
62+
_ERROR_MESSAGES = {
63+
ReturnCode.ERRCMD_NOTEQU: "the received response does not match to the transmitted command",
64+
ReturnCode.ERRCMD_REGTST: "no access to the CAN controller",
65+
ReturnCode.ERRCMD_ILLCMD: "the module could not interpret the command",
66+
ReturnCode.ERRCMD_EEPROM: "error while reading the EEPROM",
67+
ReturnCode.ERRCMD_RESERVED1: "reserved",
68+
ReturnCode.ERRCMD_RESERVED2: "reserved",
69+
ReturnCode.ERRCMD_RESERVED3: "reserved",
70+
ReturnCode.ERRCMD_ILLBDR: "illegal baud rate value specified in BTR0/BTR1 for systec "
71+
"USB-CANmoduls",
72+
ReturnCode.ERRCMD_NOTINIT: "CAN channel is not initialized",
73+
ReturnCode.ERRCMD_ALREADYINIT: "CAN channel is already initialized",
74+
ReturnCode.ERRCMD_ILLSUBCMD: "illegal sub-command specified",
75+
ReturnCode.ERRCMD_ILLIDX: "illegal index specified (e.g. index for cyclic CAN messages)",
76+
ReturnCode.ERRCMD_RUNNING: "cyclic CAN message(s) can not be defined because transmission of "
77+
"cyclic CAN messages is already running",
78+
}
79+
80+
@property
81+
def _error_message_mapping(self) -> Dict[ReturnCode, str]:
82+
return UcanCmdError._ERROR_MESSAGES
7083

7184

7285
class UcanWarning(UcanException):
73-
""" Exception class for warnings, the function has been executed anyway. """
86+
"""Exception class for warnings, the function has been executed anyway."""
7487

75-
def __init__(self, result, func, arguments):
76-
super().__init__(result, func, arguments)
77-
self.return_msgs = {
78-
ReturnCode.WARN_NODATA: "no CAN messages received",
79-
ReturnCode.WARN_SYS_RXOVERRUN: "overrun in receive buffer of the kernel driver",
80-
ReturnCode.WARN_DLL_RXOVERRUN: "overrun in receive buffer of the USB-CAN-library",
81-
ReturnCode.WARN_RESERVED1: "reserved",
82-
ReturnCode.WARN_RESERVED2: "reserved",
83-
ReturnCode.WARN_FW_TXOVERRUN: "overrun in transmit buffer of the firmware (but this CAN message "
84-
"was successfully stored in buffer of the ibrary)",
85-
ReturnCode.WARN_FW_RXOVERRUN: "overrun in receive buffer of the firmware (but this CAN message "
86-
"was successfully read)",
87-
ReturnCode.WARN_FW_TXMSGLOST: "reserved",
88-
ReturnCode.WARN_NULL_PTR: "pointer is NULL",
89-
ReturnCode.WARN_TXLIMIT: "not all CAN messages could be stored to the transmit buffer in "
90-
"USB-CAN-library",
91-
ReturnCode.WARN_BUSY: "reserved",
92-
}
88+
_ERROR_MESSAGES = {
89+
ReturnCode.WARN_NODATA: "no CAN messages received",
90+
ReturnCode.WARN_SYS_RXOVERRUN: "overrun in receive buffer of the kernel driver",
91+
ReturnCode.WARN_DLL_RXOVERRUN: "overrun in receive buffer of the USB-CAN-library",
92+
ReturnCode.WARN_RESERVED1: "reserved",
93+
ReturnCode.WARN_RESERVED2: "reserved",
94+
ReturnCode.WARN_FW_TXOVERRUN: "overrun in transmit buffer of the firmware (but this CAN message "
95+
"was successfully stored in buffer of the ibrary)",
96+
ReturnCode.WARN_FW_RXOVERRUN: "overrun in receive buffer of the firmware (but this CAN message "
97+
"was successfully read)",
98+
ReturnCode.WARN_FW_TXMSGLOST: "reserved",
99+
ReturnCode.WARN_NULL_PTR: "pointer is NULL",
100+
ReturnCode.WARN_TXLIMIT: "not all CAN messages could be stored to the transmit buffer in "
101+
"USB-CAN-library",
102+
ReturnCode.WARN_BUSY: "reserved",
103+
}
104+
105+
@property
106+
def _error_message_mapping(self) -> Dict[ReturnCode, str]:
107+
return UcanWarning._ERROR_MESSAGES

can/interfaces/systec/ucan.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from ctypes import byref
55
from ctypes import c_wchar_p as LPWSTR
66

7+
from ...exceptions import CanInterfaceNotImplementedError
8+
79
from .constants import *
810
from .structures import *
911
from .exceptions import *
@@ -110,6 +112,7 @@ def check_result(result, func, arguments):
110112
return result
111113

112114

115+
_UCAN_INITIALIZED = False
113116
if os.name != "nt":
114117
log.warning("SYSTEC ucan library does not work on %s platform.", sys.platform)
115118
else:
@@ -310,6 +313,8 @@ def check_result(result, func, arguments):
310313
UcanEnableCyclicCanMsg.argtypes = [Handle, BYTE, DWORD]
311314
UcanEnableCyclicCanMsg.errcheck = check_result
312315

316+
_UCAN_INITIALIZED = True
317+
313318
except Exception as ex:
314319
log.warning("Cannot load SYSTEC ucan library: %s.", ex)
315320

@@ -323,6 +328,11 @@ class UcanServer:
323328
_connect_control_ref = None
324329

325330
def __init__(self):
331+
if not _UCAN_INITIALIZED:
332+
raise CanInterfaceNotImplementedError(
333+
"The interface could not be loaded on the current platform"
334+
)
335+
326336
self._handle = Handle(INVALID_HANDLE)
327337
self._is_initialized = False
328338
self._hw_is_initialized = False

0 commit comments

Comments
 (0)