7
7
from unittest .mock import Mock
8
8
9
9
from can import BusABC , Message
10
+ from ..exceptions import (
11
+ CanInitializationError ,
12
+ CanInterfaceNotImplementedError ,
13
+ error_check ,
14
+ )
10
15
11
16
logger = logging .getLogger (__name__ )
12
17
13
18
try :
14
19
import cantact
15
20
except ImportError :
21
+ cantact = None
16
22
logger .warning (
17
- "The CANtact module is not installed. Install it using `python3 -m pip install cantact`"
23
+ "The CANtact module is not installed. Install it using `python -m pip install cantact`"
18
24
)
19
25
20
26
@@ -25,13 +31,15 @@ class CantactBus(BusABC):
25
31
def _detect_available_configs ():
26
32
try :
27
33
interface = cantact .Interface ()
28
- except (NameError , SystemError ):
29
- # couldn't import cantact, so no configurations are available
34
+ except (NameError , SystemError , AttributeError ):
35
+ logger .debug (
36
+ "Could not import or instantiate cantact, so no configurations are available"
37
+ )
30
38
return []
31
39
32
40
channels = []
33
41
for i in range (0 , interface .channel_count ()):
34
- channels .append ({"interface" : "cantact" , "channel" : "ch:%d" % i })
42
+ channels .append ({"interface" : "cantact" , "channel" : f "ch:{ i } " })
35
43
return channels
36
44
37
45
def __init__ (
@@ -42,7 +50,7 @@ def __init__(
42
50
monitor = False ,
43
51
bit_timing = None ,
44
52
_testing = False ,
45
- ** kwargs
53
+ ** kwargs ,
46
54
):
47
55
"""
48
56
:param int channel:
@@ -58,36 +66,45 @@ def __init__(
58
66
if _testing :
59
67
self .interface = MockInterface ()
60
68
else :
61
- self .interface = cantact .Interface ()
69
+ if cantact is None :
70
+ raise CanInterfaceNotImplementedError (
71
+ "The CANtact module is not installed. Install it using `python -m pip install cantact`"
72
+ )
73
+ with error_check (
74
+ "Cannot create the cantact.Interface" , CanInitializationError
75
+ ):
76
+ self .interface = cantact .Interface ()
62
77
63
78
self .channel = int (channel )
64
- self .channel_info = "CANtact: ch:%s" % channel
65
-
66
- # configure the interface
67
- if bit_timing is None :
68
- # use bitrate
69
- self .interface .set_bitrate (int (channel ), int (bitrate ))
70
- else :
71
- # use custom bit timing
72
- self .interface .set_bit_timing (
73
- int (channel ),
74
- int (bit_timing .brp ),
75
- int (bit_timing .tseg1 ),
76
- int (bit_timing .tseg2 ),
77
- int (bit_timing .sjw ),
78
- )
79
- self .interface .set_enabled (int (channel ), True )
80
- self .interface .set_monitor (int (channel ), monitor )
81
- self .interface .start ()
79
+ self .channel_info = f"CANtact: ch:{ channel } "
80
+
81
+ # Configure the interface
82
+ with error_check ("Cannot setup the cantact.Interface" , CanInitializationError ):
83
+ if bit_timing is None :
84
+ # use bitrate
85
+ self .interface .set_bitrate (int (channel ), int (bitrate ))
86
+ else :
87
+ # use custom bit timing
88
+ self .interface .set_bit_timing (
89
+ int (channel ),
90
+ int (bit_timing .brp ),
91
+ int (bit_timing .tseg1 ),
92
+ int (bit_timing .tseg2 ),
93
+ int (bit_timing .sjw ),
94
+ )
95
+ self .interface .set_enabled (int (channel ), True )
96
+ self .interface .set_monitor (int (channel ), monitor )
97
+ self .interface .start ()
82
98
83
99
super ().__init__ (
84
100
channel = channel , bitrate = bitrate , poll_interval = poll_interval , ** kwargs
85
101
)
86
102
87
103
def _recv_internal (self , timeout ):
88
- frame = self .interface .recv (int (timeout * 1000 ))
104
+ with error_check ("Cannot receive message" ):
105
+ frame = self .interface .recv (int (timeout * 1000 ))
89
106
if frame is None :
90
- # timeout occured
107
+ # timeout occurred
91
108
return None , False
92
109
93
110
msg = Message (
@@ -103,31 +120,33 @@ def _recv_internal(self, timeout):
103
120
return msg , False
104
121
105
122
def send (self , msg , timeout = None ):
106
- self .interface .send (
107
- self .channel ,
108
- msg .arbitration_id ,
109
- bool (msg .is_extended_id ),
110
- bool (msg .is_remote_frame ),
111
- msg .dlc ,
112
- msg .data ,
113
- )
123
+ with error_check ("Cannot send message" ):
124
+ self .interface .send (
125
+ self .channel ,
126
+ msg .arbitration_id ,
127
+ bool (msg .is_extended_id ),
128
+ bool (msg .is_remote_frame ),
129
+ msg .dlc ,
130
+ msg .data ,
131
+ )
114
132
115
133
def shutdown (self ):
116
- self .interface .stop ()
134
+ with error_check ("Cannot shutdown interface" ):
135
+ self .interface .stop ()
117
136
118
137
119
138
def mock_recv (timeout ):
120
139
if timeout > 0 :
121
- frame = {}
122
- frame [ "id" ] = 0x123
123
- frame [ "extended" ] = False
124
- frame [ "timestamp" ] = time .time ()
125
- frame [ "loopback" ] = False
126
- frame [ "rtr" ] = False
127
- frame [ "dlc" ] = 8
128
- frame [ "data" ] = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ]
129
- frame [ "channel" ] = 0
130
- return frame
140
+ return {
141
+ "id" : 0x123 ,
142
+ "extended" : False ,
143
+ "timestamp" : time .time (),
144
+ "loopback" : False ,
145
+ "rtr" : False ,
146
+ "dlc" : 8 ,
147
+ "data" : [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ],
148
+ "channel" : 0 ,
149
+ }
131
150
else :
132
151
# simulate timeout when timeout = 0
133
152
return None
@@ -144,7 +163,6 @@ class MockInterface:
144
163
set_bit_timing = Mock ()
145
164
set_enabled = Mock ()
146
165
set_monitor = Mock ()
147
- start = Mock ()
148
166
stop = Mock ()
149
167
send = Mock ()
150
168
channel_count = Mock (return_value = 1 )
0 commit comments