10
10
import logging
11
11
import time
12
12
import os
13
- from typing import List , Optional , Tuple , Sequence , Union
14
-
15
- import typing
13
+ from typing import List , NamedTuple , Optional , Tuple , Sequence , Union
16
14
17
15
try :
18
16
# Try builtin Python 3 Windows API
31
29
32
30
# Import Modules
33
31
# ==============
34
- from can import BusABC , Message
32
+ from can import BusABC , Message , CanInterfaceNotImplementedError , CanInitializationError
35
33
from can .util import (
36
34
len2dlc ,
37
35
dlc2len ,
38
36
deprecated_args_alias ,
39
37
time_perfcounter_correlation ,
40
38
)
41
- from can .typechecking import CanFilters
39
+ from can .typechecking import AutoDetectedConfig , CanFilters
40
+
42
41
from .exceptions import VectorError
43
42
44
43
# Define Module Logger
45
44
# ====================
46
45
LOG = logging .getLogger (__name__ )
47
46
48
- # Import Vector API module
49
- # ========================
47
+ # Import Vector API modules
48
+ # =========================
49
+ from .exceptions import VectorError , VectorInitializationError , VectorOperationError
50
50
from . import xldefine , xlclass
51
51
52
52
# Import safely Vector API module for Travis tests
@@ -131,14 +131,20 @@ def __init__(
131
131
Bus timing value tseg1 (data)
132
132
:param tseg2_dbr:
133
133
Bus timing value tseg2 (data)
134
+
135
+ :raise can.CanInterfaceNotImplementedError:
136
+ If the current operating system is not supported or the driver could not be loaded.
137
+ :raise can.CanInitializationError:
138
+ If the bus could not be set up.
139
+ This may or may not be a :class:`can.interfaces.vector.VectorInitializationError`.
134
140
"""
135
141
if os .name != "nt" and not kwargs .get ("_testing" , False ):
136
- raise OSError (
142
+ raise CanInterfaceNotImplementedError (
137
143
f'The Vector interface is only supported on Windows, but you are running "{ os .name } "'
138
144
)
139
145
140
146
if xldriver is None :
141
- raise ImportError ("The Vector API has not been loaded" )
147
+ raise CanInterfaceNotImplementedError ("The Vector API has not been loaded" )
142
148
143
149
self .poll_interval = poll_interval
144
150
@@ -176,7 +182,7 @@ def __init__(
176
182
self .channels = channel_index
177
183
else :
178
184
# Is there any better way to raise the error?
179
- raise Exception (
185
+ raise CanInitializationError (
180
186
"None of the configured channels could be found on the specified hardware."
181
187
)
182
188
@@ -201,7 +207,7 @@ def __init__(
201
207
# If hardware is unavailable, this function returns -1.
202
208
# Raise an exception as if the driver
203
209
# would have signalled XL_ERR_HW_NOT_PRESENT.
204
- raise VectorError (
210
+ raise VectorInitializationError (
205
211
xldefine .XL_Status .XL_ERR_HW_NOT_PRESENT ,
206
212
xldefine .XL_Status .XL_ERR_HW_NOT_PRESENT .name ,
207
213
"xlGetChannelIndex" ,
@@ -305,9 +311,9 @@ def __init__(
305
311
xldriver .xlActivateChannel (
306
312
self .port_handle , self .mask , xldefine .XL_BusTypes .XL_BUS_TYPE_CAN , 0
307
313
)
308
- except VectorError :
314
+ except VectorOperationError as error :
309
315
self .shutdown ()
310
- raise
316
+ raise VectorInitializationError . from_generic ( error ) from None
311
317
312
318
# Calculate time offset for absolute timestamps
313
319
offset = xlclass .XLuint64 ()
@@ -316,25 +322,25 @@ def __init__(
316
322
ts , perfcounter = time_perfcounter_correlation ()
317
323
try :
318
324
xldriver .xlGetSyncTime (self .port_handle , offset )
319
- except VectorError :
325
+ except VectorInitializationError :
320
326
xldriver .xlGetChannelTime (self .port_handle , self .mask , offset )
321
327
current_perfcounter = time .perf_counter ()
322
328
now = ts + (current_perfcounter - perfcounter )
323
329
self ._time_offset = now - offset .value * 1e-9
324
330
else :
325
331
try :
326
332
xldriver .xlGetSyncTime (self .port_handle , offset )
327
- except VectorError :
333
+ except VectorInitializationError :
328
334
xldriver .xlGetChannelTime (self .port_handle , self .mask , offset )
329
335
self ._time_offset = time .time () - offset .value * 1e-9
330
336
331
- except VectorError :
337
+ except VectorInitializationError :
332
338
self ._time_offset = 0.0
333
339
334
340
self ._is_filtered = False
335
341
super ().__init__ (channel = channel , can_filters = can_filters , ** kwargs )
336
342
337
- def _apply_filters (self , filters ):
343
+ def _apply_filters (self , filters ) -> None :
338
344
if filters :
339
345
# Only up to one filter per ID type allowed
340
346
if len (filters ) == 1 or (
@@ -352,7 +358,7 @@ def _apply_filters(self, filters):
352
358
if can_filter .get ("extended" )
353
359
else xldefine .XL_AcceptanceFilter .XL_CAN_STD ,
354
360
)
355
- except VectorError as exc :
361
+ except VectorOperationError as exc :
356
362
LOG .warning ("Could not set filters: %s" , exc )
357
363
# go to fallback
358
364
else :
@@ -379,7 +385,7 @@ def _apply_filters(self, filters):
379
385
0x0 ,
380
386
xldefine .XL_AcceptanceFilter .XL_CAN_STD ,
381
387
)
382
- except VectorError as exc :
388
+ except VectorOperationError as exc :
383
389
LOG .warning ("Could not reset filters: %s" , exc )
384
390
385
391
def _recv_internal (
@@ -394,7 +400,7 @@ def _recv_internal(
394
400
else :
395
401
msg = self ._recv_can ()
396
402
397
- except VectorError as exc :
403
+ except VectorOperationError as exc :
398
404
if exc .error_code != xldefine .XL_Status .XL_ERR_QUEUE_IS_EMPTY :
399
405
raise
400
406
else :
@@ -437,7 +443,7 @@ def _recv_canfd(self) -> Optional[Message]:
437
443
timestamp = xl_can_rx_event .timeStamp * 1e-9
438
444
channel = self .index_to_channel .get (xl_can_rx_event .chanIndex )
439
445
440
- msg = Message (
446
+ return Message (
441
447
timestamp = timestamp + self ._time_offset ,
442
448
arbitration_id = msg_id & 0x1FFFFFFF ,
443
449
is_extended_id = bool (
@@ -461,7 +467,6 @@ def _recv_canfd(self) -> Optional[Message]:
461
467
dlc = dlc ,
462
468
data = data_struct .data [:dlc ],
463
469
)
464
- return msg
465
470
466
471
def _recv_can (self ) -> Optional [Message ]:
467
472
xl_event = xlclass .XLevent ()
@@ -478,7 +483,7 @@ def _recv_can(self) -> Optional[Message]:
478
483
timestamp = xl_event .timeStamp * 1e-9
479
484
channel = self .index_to_channel .get (xl_event .chanIndex )
480
485
481
- msg = Message (
486
+ return Message (
482
487
timestamp = timestamp + self ._time_offset ,
483
488
arbitration_id = msg_id & 0x1FFFFFFF ,
484
489
is_extended_id = bool (
@@ -498,7 +503,6 @@ def _recv_can(self) -> Optional[Message]:
498
503
data = xl_event .tagData .msg .data [:dlc ],
499
504
channel = channel ,
500
505
)
501
- return msg
502
506
503
507
def handle_can_event (self , event : xlclass .XLevent ) -> None :
504
508
"""Handle non-message CAN events.
@@ -507,9 +511,7 @@ def handle_can_event(self, event: xlclass.XLevent) -> None:
507
511
when `event.tag` is not `XL_RECEIVE_MSG`. Subclasses can implement this method.
508
512
509
513
:param event: XLevent that could have a `XL_CHIP_STATE`, `XL_TIMER` or `XL_SYNC_PULSE` tag.
510
- :return: None
511
514
"""
512
- pass
513
515
514
516
def handle_canfd_event (self , event : xlclass .XLcanRxEvent ) -> None :
515
517
"""Handle non-message CAN FD events.
@@ -520,27 +522,25 @@ def handle_canfd_event(self, event: xlclass.XLcanRxEvent) -> None:
520
522
521
523
:param event: `XLcanRxEvent` that could have a `XL_CAN_EV_TAG_RX_ERROR`, `XL_CAN_EV_TAG_TX_ERROR`,
522
524
`XL_TIMER` or `XL_CAN_EV_TAG_CHIP_STATE` tag.
523
- :return: None
524
525
"""
525
- pass
526
526
527
- def send (self , msg : Message , timeout : typing . Optional [float ] = None ):
527
+ def send (self , msg : Message , timeout : Optional [float ] = None ):
528
528
self ._send_sequence ([msg ])
529
529
530
- def _send_sequence (self , msgs : typing . Sequence [Message ]) -> int :
530
+ def _send_sequence (self , msgs : Sequence [Message ]) -> int :
531
531
"""Send messages and return number of successful transmissions."""
532
532
if self .fd :
533
533
return self ._send_can_fd_msg_sequence (msgs )
534
534
else :
535
535
return self ._send_can_msg_sequence (msgs )
536
536
537
- def _get_tx_channel_mask (self , msgs : typing . Sequence [Message ]) -> int :
537
+ def _get_tx_channel_mask (self , msgs : Sequence [Message ]) -> int :
538
538
if len (msgs ) == 1 :
539
539
return self .channel_masks .get (msgs [0 ].channel , self .mask )
540
540
else :
541
541
return self .mask
542
542
543
- def _send_can_msg_sequence (self , msgs : typing . Sequence [Message ]) -> int :
543
+ def _send_can_msg_sequence (self , msgs : Sequence [Message ]) -> int :
544
544
"""Send CAN messages and return number of successful transmissions."""
545
545
mask = self ._get_tx_channel_mask (msgs )
546
546
message_count = ctypes .c_uint (len (msgs ))
@@ -571,7 +571,7 @@ def _build_xl_event(msg: Message) -> xlclass.XLevent:
571
571
572
572
return xl_event
573
573
574
- def _send_can_fd_msg_sequence (self , msgs : typing . Sequence [Message ]) -> int :
574
+ def _send_can_fd_msg_sequence (self , msgs : Sequence [Message ]) -> int :
575
575
"""Send CAN FD messages and return number of successful transmissions."""
576
576
mask = self ._get_tx_channel_mask (msgs )
577
577
message_count = len (msgs )
@@ -611,22 +611,22 @@ def _build_xl_can_tx_event(msg: Message) -> xlclass.XLcanTxEvent:
611
611
612
612
return xl_can_tx_event
613
613
614
- def flush_tx_buffer (self ):
614
+ def flush_tx_buffer (self ) -> None :
615
615
xldriver .xlCanFlushTransmitQueue (self .port_handle , self .mask )
616
616
617
- def shutdown (self ):
617
+ def shutdown (self ) -> None :
618
618
xldriver .xlDeactivateChannel (self .port_handle , self .mask )
619
619
xldriver .xlClosePort (self .port_handle )
620
620
xldriver .xlCloseDriver ()
621
621
622
- def reset (self ):
622
+ def reset (self ) -> None :
623
623
xldriver .xlDeactivateChannel (self .port_handle , self .mask )
624
624
xldriver .xlActivateChannel (
625
625
self .port_handle , self .mask , xldefine .XL_BusTypes .XL_BUS_TYPE_CAN , 0
626
626
)
627
627
628
628
@staticmethod
629
- def _detect_available_configs ():
629
+ def _detect_available_configs () -> List [ AutoDetectedConfig ] :
630
630
configs = []
631
631
channel_configs = get_channel_configs ()
632
632
LOG .info ("Found %d channels" , len (channel_configs ))
@@ -663,7 +663,7 @@ def _detect_available_configs():
663
663
def popup_vector_hw_configuration (wait_for_finish : int = 0 ) -> None :
664
664
"""Open vector hardware configuration window.
665
665
666
- :param int wait_for_finish:
666
+ :param wait_for_finish:
667
667
Time to wait for user input in milliseconds.
668
668
"""
669
669
xldriver .xlPopupHwConfig (ctypes .c_char_p (), ctypes .c_uint (wait_for_finish ))
@@ -681,9 +681,9 @@ def get_application_config(
681
681
:return:
682
682
Returns a tuple of the hardware type, the hardware index and the
683
683
hardware channel.
684
- :raises VectorError:
685
- Raises a VectorError when the application name does not exist in
686
- Vector Hardware Configuration .
684
+
685
+ :raises can.interfaces.vector.VectorInitializationError:
686
+ If the application name does not exist in the Vector hardware configuration .
687
687
"""
688
688
hw_type = ctypes .c_uint ()
689
689
hw_index = ctypes .c_uint ()
@@ -732,6 +732,9 @@ def set_application_config(
732
732
hardware type are present.
733
733
:param hw_channel:
734
734
The channel index of the interface.
735
+
736
+ :raises can.interfaces.vector.VectorInitializationError:
737
+ If the application name does not exist in the Vector hardware configuration.
735
738
"""
736
739
xldriver .xlSetApplConfig (
737
740
app_name .encode (),
@@ -757,7 +760,7 @@ def set_timer_rate(self, timer_rate_ms: int) -> None:
757
760
xldriver .xlSetTimerRate (self .port_handle , timer_rate_10us )
758
761
759
762
760
- class VectorChannelConfig (typing . NamedTuple ):
763
+ class VectorChannelConfig (NamedTuple ):
761
764
name : str
762
765
hwType : xldefine .XL_HardwareType
763
766
hwIndex : int
0 commit comments