34
34
RestartableCyclicTaskABC ,
35
35
LimitedDurationCyclicSendTaskABC ,
36
36
)
37
+ from can .typechecking import CanFilters
37
38
from can .interfaces .socketcan .constants import * # CAN_RAW, CAN_*_FLAG
38
39
from can .interfaces .socketcan .utils import pack_filters , find_available_interfaces
39
40
@@ -593,20 +594,28 @@ def __init__(
593
594
channel : str = "" ,
594
595
receive_own_messages : bool = False ,
595
596
fd : bool = False ,
597
+ can_filters : Optional [CanFilters ] = None ,
596
598
** kwargs ,
597
599
) -> None :
598
- """
600
+ """Creates a new socketcan bus.
601
+
602
+ If setting some socket options fails, an error will be printed but no exception will be thrown.
603
+ This includes enabling:
604
+ - that own messages should be received,
605
+ - CAN-FD frames and
606
+ - error frames.
607
+
599
608
:param channel:
600
- The can interface name with which to create this bus. An example channel
601
- would be 'vcan0' or 'can0'.
609
+ The can interface name with which to create this bus.
610
+ An example channel would be 'vcan0' or 'can0'.
602
611
An empty string '' will receive messages from all channels.
603
612
In that case any sent messages must be explicitly addressed to a
604
613
channel using :attr:`can.Message.channel`.
605
614
:param receive_own_messages:
606
615
If transmitted messages should also be received by this bus.
607
616
:param fd:
608
617
If CAN-FD frames should be supported.
609
- :param list can_filters:
618
+ :param can_filters:
610
619
See :meth:`can.BusABC.set_filters`.
611
620
"""
612
621
self .socket = create_socket ()
@@ -622,53 +631,56 @@ def __init__(
622
631
self .socket .setsockopt (
623
632
SOL_CAN_RAW , CAN_RAW_RECV_OWN_MSGS , 1 if receive_own_messages else 0
624
633
)
625
- except socket .error as e :
626
- log .error ("Could not receive own messages (%s)" , e )
634
+ except socket .error as error :
635
+ log .error ("Could not receive own messages (%s)" , error )
627
636
637
+ # enable CAN-FD frames
628
638
if fd :
629
- # TODO handle errors
630
- self .socket .setsockopt (SOL_CAN_RAW , CAN_RAW_FD_FRAMES , 1 )
639
+ try :
640
+ self .socket .setsockopt (SOL_CAN_RAW , CAN_RAW_FD_FRAMES , 1 )
641
+ except socket .error as error :
642
+ log .error ("Could not enable CAN-FD frames (%s)" , error )
631
643
632
- # Enable error frames
633
- self .socket .setsockopt (SOL_CAN_RAW , CAN_RAW_ERR_FILTER , 0x1FFFFFFF )
644
+ # enable error frames
645
+ try :
646
+ self .socket .setsockopt (SOL_CAN_RAW , CAN_RAW_ERR_FILTER , 0x1FFFFFFF )
647
+ except socket .error as error :
648
+ log .error ("Could not enable error frames (%s)" , error )
634
649
635
650
bind_socket (self .socket , channel )
636
651
kwargs .update ({"receive_own_messages" : receive_own_messages , "fd" : fd })
637
- super ().__init__ (channel = channel , ** kwargs )
652
+ super ().__init__ (channel = channel , can_filters = can_filters , ** kwargs )
638
653
639
654
def shutdown (self ) -> None :
640
655
"""Stops all active periodic tasks and closes the socket."""
641
656
self .stop_all_periodic_tasks ()
642
- for channel in self ._bcm_sockets :
643
- log .debug ("Closing bcm socket for channel {}" .format (channel ))
644
- bcm_socket = self ._bcm_sockets [channel ]
657
+ for channel , bcm_socket in self ._bcm_sockets .items ():
658
+ log .debug ("Closing bcm socket for channel %s" , channel )
645
659
bcm_socket .close ()
646
660
log .debug ("Closing raw can socket" )
647
661
self .socket .close ()
648
662
649
663
def _recv_internal (
650
664
self , timeout : Optional [float ]
651
665
) -> Tuple [Optional [Message ], bool ]:
652
- # get all sockets that are ready (can be a list with a single value
653
- # being self.socket or an empty list if self.socket is not ready)
654
666
try :
655
667
# get all sockets that are ready (can be a list with a single value
656
668
# being self.socket or an empty list if self.socket is not ready)
657
669
ready_receive_sockets , _ , _ = select .select ([self .socket ], [], [], timeout )
658
670
except socket .error as exc :
659
671
# something bad happened (e.g. the interface went down)
660
- raise can .CanError ("Failed to receive: %s" % exc )
672
+ raise can .CanError (f "Failed to receive: { exc } " )
661
673
662
- if ready_receive_sockets : # not empty or True
674
+ if ready_receive_sockets : # not empty
663
675
get_channel = self .channel == ""
664
676
msg = capture_message (self .socket , get_channel )
665
677
if msg and not msg .channel and self .channel :
666
678
# Default to our own channel
667
679
msg .channel = self .channel
668
680
return msg , self ._is_filtered
669
- else :
670
- # socket wasn't readable or timeout occurred
671
- return None , self ._is_filtered
681
+
682
+ # socket wasn't readable or timeout occurred
683
+ return None , self ._is_filtered
672
684
673
685
def send (self , msg : Message , timeout : Optional [float ] = None ) -> None :
674
686
"""Transmit a message to the CAN bus.
@@ -777,13 +789,12 @@ def _get_bcm_socket(self, channel: str) -> socket.socket:
777
789
def _apply_filters (self , filters : Optional [can .typechecking .CanFilters ]) -> None :
778
790
try :
779
791
self .socket .setsockopt (SOL_CAN_RAW , CAN_RAW_FILTER , pack_filters (filters ))
780
- except socket .error as err :
792
+ except socket .error as error :
781
793
# fall back to "software filtering" (= not in kernel)
782
794
self ._is_filtered = False
783
- # TODO Is this serious enough to raise a CanError exception?
784
795
log .error (
785
796
"Setting filters failed; falling back to software filtering (not in kernel): %s" ,
786
- err ,
797
+ error ,
787
798
)
788
799
else :
789
800
self ._is_filtered = True
0 commit comments