From b2ec42cfc93a9a7d228e9d22f58fbb6f04f9bef3 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 5 Mar 2023 10:24:14 +0100 Subject: [PATCH 01/32] Implement is_fd property for BusABC and PCANBus --- can/bus.py | 9 +++++++++ can/interfaces/pcan/pcan.py | 14 ++++++++------ test/test_pcan.py | 11 ++++++++--- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/can/bus.py b/can/bus.py index f29b8ea6e..073efa1f4 100644 --- a/can/bus.py +++ b/can/bus.py @@ -48,6 +48,7 @@ class BusABC(metaclass=ABCMeta): def __init__( self, channel: Any, + is_fd: bool = False, can_filters: Optional[can.typechecking.CanFilters] = None, **kwargs: object ): @@ -59,6 +60,9 @@ def __init__( :param channel: The can interface identifier. Expected type is backend dependent. + :param is_fd: + Indicates that this bus supports CAN-FD. + :param can_filters: See :meth:`~can.BusABC.set_filters` for details. @@ -71,6 +75,7 @@ def __init__( :raises ~can.exceptions.CanInitializationError: If the bus cannot be initialized """ + self._is_fd = is_fd self._periodic_tasks: List[_SelfRemovingCyclicTask] = [] self.set_filters(can_filters) @@ -442,6 +447,10 @@ def state(self, new_state: BusState) -> None: """ raise NotImplementedError("Property is not implemented.") + @property + def is_fd(self) -> bool: + return self._is_fd + @staticmethod def _detect_available_configs() -> List[can.typechecking.AutoDetectedConfig]: """Detect all configurations/channels that this interface could diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index 2ed0ff445..9cc0c8ddc 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -247,7 +247,7 @@ def __init__( raise ValueError(err_msg) self.channel_info = str(channel) - self.fd = isinstance(timing, BitTimingFd) if timing else kwargs.get("fd", False) + is_fd = isinstance(timing, BitTimingFd) if timing else kwargs.get("fd", False) hwtype = PCAN_TYPE_ISA ioport = 0x02A0 @@ -271,7 +271,7 @@ def __init__( result = self.m_objPCANBasic.Initialize( self.m_PcanHandle, pcan_bitrate, hwtype, ioport, interrupt ) - elif self.fd: + elif is_fd: if isinstance(timing, BitTimingFd): timing = check_or_adjust_timing_clock( timing, sorted(VALID_PCAN_FD_CLOCKS, reverse=True) @@ -338,7 +338,9 @@ def __init__( if result != PCAN_ERROR_OK: raise PcanCanInitializationError(self._get_formatted_error(result)) - super().__init__(channel=channel, state=state, bitrate=bitrate, **kwargs) + super().__init__( + channel=channel, is_fd=is_fd, state=state, bitrate=bitrate, **kwargs + ) def _find_channel_by_dev_id(self, device_id): """ @@ -484,7 +486,7 @@ def _recv_internal( end_time = time.time() + timeout if timeout is not None else None while True: - if self.fd: + if self.is_fd: result, pcan_msg, pcan_timestamp = self.m_objPCANBasic.ReadFD( self.m_PcanHandle ) @@ -546,7 +548,7 @@ def _recv_internal( error_state_indicator = bool(pcan_msg.MSGTYPE & PCAN_MESSAGE_ESI.value) is_error_frame = bool(pcan_msg.MSGTYPE & PCAN_MESSAGE_ERRFRAME.value) - if self.fd: + if self.is_fd: dlc = dlc2len(pcan_msg.DLC) timestamp = boottimeEpoch + (pcan_timestamp.value / (1000.0 * 1000.0)) else: @@ -592,7 +594,7 @@ def send(self, msg, timeout=None): if msg.error_state_indicator: msgType |= PCAN_MESSAGE_ESI.value - if self.fd: + if self.is_fd: # create a TPCANMsg message structure CANMsg = TPCANMsgFD() diff --git a/test/test_pcan.py b/test/test_pcan.py index aa0988a48..df3b9bd59 100644 --- a/test/test_pcan.py +++ b/test/test_pcan.py @@ -53,8 +53,9 @@ def test_bus_creation(self) -> None: self.bus = can.Bus(interface="pcan") self.assertIsInstance(self.bus, PcanBus) - self.MockPCANBasic.assert_called_once() + self.assertFalse(self.bus.is_fd) + self.MockPCANBasic.assert_called_once() self.mock_pcan.Initialize.assert_called_once() self.mock_pcan.InitializeFD.assert_not_called() @@ -80,6 +81,8 @@ def test_bus_creation_fd(self, clock_param: str, clock_val: int) -> None: ) self.assertIsInstance(self.bus, PcanBus) + self.assertTrue(self.bus.is_fd) + self.MockPCANBasic.assert_called_once() self.mock_pcan.Initialize.assert_not_called() self.mock_pcan.InitializeFD.assert_called_once() @@ -452,10 +455,11 @@ def test_peak_fd_bus_constructor_regression(self): def test_constructor_bit_timing(self): timing = can.BitTiming.from_registers(f_clock=8_000_000, btr0=0x47, btr1=0x2F) - can.Bus(interface="pcan", channel="PCAN_USBBUS1", timing=timing) + bus = can.Bus(interface="pcan", channel="PCAN_USBBUS1", timing=timing) bitrate_arg = self.mock_pcan.Initialize.call_args[0][1] self.assertEqual(bitrate_arg.value, 0x472F) + self.assertFalse(bus.is_fd) def test_constructor_bit_timing_fd(self): timing = can.BitTimingFd( @@ -469,7 +473,8 @@ def test_constructor_bit_timing_fd(self): data_tseg2=6, data_sjw=1, ) - can.Bus(interface="pcan", channel="PCAN_USBBUS1", timing=timing) + bus = can.Bus(interface="pcan", channel="PCAN_USBBUS1", timing=timing) + self.assertTrue(bus.is_fd) bitrate_arg = self.mock_pcan.InitializeFD.call_args[0][-1] From 059f33a5f2d48f7638d814699ea68661beb671fd Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Tue, 7 Mar 2023 21:08:30 +0100 Subject: [PATCH 02/32] Implement enum to represent CAN protocol --- can/__init__.py | 2 +- can/bus.py | 29 +++++++++++++++++++++++------ can/interfaces/pcan/pcan.py | 13 +++++++++---- doc/bus.rst | 4 ++++ test/test_pcan.py | 10 +++++----- 5 files changed, 42 insertions(+), 16 deletions(-) diff --git a/can/__init__.py b/can/__init__.py index d9ff5ffcd..b8c94649e 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -27,7 +27,7 @@ from .util import set_logging_level from .message import Message -from .bus import BusABC, BusState +from .bus import BusABC, BusState, CANProtocol from .thread_safe_bus import ThreadSafeBus from .notifier import Notifier from .interfaces import VALID_INTERFACES diff --git a/can/bus.py b/can/bus.py index 073efa1f4..b0571d043 100644 --- a/can/bus.py +++ b/can/bus.py @@ -27,6 +27,14 @@ class BusState(Enum): ERROR = auto() +class CANProtocol(Enum): + """The CAN protocol type supported by a :class:`can.BusABC` instance""" + + CAN_20 = auto() + CAN_FD = auto() + CAN_XL = auto() + + class BusABC(metaclass=ABCMeta): """The CAN Bus Abstract Base Class that serves as the basis for all concrete interfaces. @@ -48,7 +56,7 @@ class BusABC(metaclass=ABCMeta): def __init__( self, channel: Any, - is_fd: bool = False, + protocol: CANProtocol = CANProtocol.CAN_20, can_filters: Optional[can.typechecking.CanFilters] = None, **kwargs: object ): @@ -60,8 +68,12 @@ def __init__( :param channel: The can interface identifier. Expected type is backend dependent. - :param is_fd: - Indicates that this bus supports CAN-FD. + :param protocol: + The CAN protocol currently used by this bus instance. This value + is determined at initialization time (based on the initialization + parameters or because the bus interface only supports a specific + protocol) and does not change during the lifetime of a bus + instance. :param can_filters: See :meth:`~can.BusABC.set_filters` for details. @@ -75,7 +87,7 @@ def __init__( :raises ~can.exceptions.CanInitializationError: If the bus cannot be initialized """ - self._is_fd = is_fd + self._can_protocol = protocol self._periodic_tasks: List[_SelfRemovingCyclicTask] = [] self.set_filters(can_filters) @@ -448,8 +460,13 @@ def state(self, new_state: BusState) -> None: raise NotImplementedError("Property is not implemented.") @property - def is_fd(self) -> bool: - return self._is_fd + def protocol(self) -> CANProtocol: + """Return the CAN protocol used by this bus instance. + + This value is set at initialization time and does not change + during the lifetime of a bus instance. + """ + return self._can_protocol @staticmethod def _detect_available_configs() -> List[can.typechecking.AutoDetectedConfig]: diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index 9cc0c8ddc..912ca8470 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -12,6 +12,7 @@ from can import ( BusABC, BusState, + CANProtocol, BitTiming, BitTimingFd, Message, @@ -339,7 +340,11 @@ def __init__( raise PcanCanInitializationError(self._get_formatted_error(result)) super().__init__( - channel=channel, is_fd=is_fd, state=state, bitrate=bitrate, **kwargs + channel=channel, + protocol=CANProtocol.CAN_FD if is_fd else CANProtocol.CAN_20, + state=state, + bitrate=bitrate, + **kwargs, ) def _find_channel_by_dev_id(self, device_id): @@ -486,7 +491,7 @@ def _recv_internal( end_time = time.time() + timeout if timeout is not None else None while True: - if self.is_fd: + if self.protocol == CANProtocol.CAN_FD: result, pcan_msg, pcan_timestamp = self.m_objPCANBasic.ReadFD( self.m_PcanHandle ) @@ -548,7 +553,7 @@ def _recv_internal( error_state_indicator = bool(pcan_msg.MSGTYPE & PCAN_MESSAGE_ESI.value) is_error_frame = bool(pcan_msg.MSGTYPE & PCAN_MESSAGE_ERRFRAME.value) - if self.is_fd: + if self.protocol == CANProtocol.CAN_FD: dlc = dlc2len(pcan_msg.DLC) timestamp = boottimeEpoch + (pcan_timestamp.value / (1000.0 * 1000.0)) else: @@ -594,7 +599,7 @@ def send(self, msg, timeout=None): if msg.error_state_indicator: msgType |= PCAN_MESSAGE_ESI.value - if self.is_fd: + if self.protocol == CANProtocol.CAN_FD: # create a TPCANMsg message structure CANMsg = TPCANMsgFD() diff --git a/doc/bus.rst b/doc/bus.rst index 51ed0220b..5e09eec34 100644 --- a/doc/bus.rst +++ b/doc/bus.rst @@ -87,6 +87,10 @@ Bus API :members: :undoc-members: +.. autoclass:: can.bus.CANProtocol + :members: + :undoc-members: + Thread safe bus ''''''''''''''' diff --git a/test/test_pcan.py b/test/test_pcan.py index df3b9bd59..c5af88b31 100644 --- a/test/test_pcan.py +++ b/test/test_pcan.py @@ -11,7 +11,7 @@ from parameterized import parameterized import can -from can.bus import BusState +from can import BusState, CANProtocol from can.exceptions import CanInitializationError from can.interfaces.pcan import PcanBus, PcanError from can.interfaces.pcan.basic import * @@ -53,7 +53,7 @@ def test_bus_creation(self) -> None: self.bus = can.Bus(interface="pcan") self.assertIsInstance(self.bus, PcanBus) - self.assertFalse(self.bus.is_fd) + self.assertEqual(self.bus.protocol, CANProtocol.CAN_20) self.MockPCANBasic.assert_called_once() self.mock_pcan.Initialize.assert_called_once() @@ -81,7 +81,7 @@ def test_bus_creation_fd(self, clock_param: str, clock_val: int) -> None: ) self.assertIsInstance(self.bus, PcanBus) - self.assertTrue(self.bus.is_fd) + self.assertEqual(self.bus.protocol, CANProtocol.CAN_FD) self.MockPCANBasic.assert_called_once() self.mock_pcan.Initialize.assert_not_called() @@ -459,7 +459,7 @@ def test_constructor_bit_timing(self): bitrate_arg = self.mock_pcan.Initialize.call_args[0][1] self.assertEqual(bitrate_arg.value, 0x472F) - self.assertFalse(bus.is_fd) + self.assertEqual(bus.protocol, CANProtocol.CAN_20) def test_constructor_bit_timing_fd(self): timing = can.BitTimingFd( @@ -474,7 +474,7 @@ def test_constructor_bit_timing_fd(self): data_sjw=1, ) bus = can.Bus(interface="pcan", channel="PCAN_USBBUS1", timing=timing) - self.assertTrue(bus.is_fd) + self.assertEqual(bus.protocol, CANProtocol.CAN_FD) bitrate_arg = self.mock_pcan.InitializeFD.call_args[0][-1] From 07defb048332029f3b229a464f2d81e294be9525 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 12 Mar 2023 13:10:41 +0100 Subject: [PATCH 03/32] Implement CANProtocol for VirtualBus --- can/interfaces/virtual.py | 46 ++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/can/interfaces/virtual.py b/can/interfaces/virtual.py index 25b7abfb0..5a56eda31 100644 --- a/can/interfaces/virtual.py +++ b/can/interfaces/virtual.py @@ -16,7 +16,7 @@ from random import randint from can import CanOperationError -from can.bus import BusABC +from can.bus import BusABC, CANProtocol from can.message import Message from can.typechecking import AutoDetectedConfig @@ -34,7 +34,8 @@ class VirtualBus(BusABC): """ - A virtual CAN bus using an internal message queue. It can be used for example for testing. + A virtual CAN bus using an internal message queue. It can be used for + example for testing. In this interface, a channel is an arbitrary object used as an identifier for connected buses. @@ -49,9 +50,11 @@ class VirtualBus(BusABC): if a message is sent to 5 receivers with the timeout set to 1.0. .. warning:: - This interface guarantees reliable delivery and message ordering, but does *not* implement rate - limiting or ID arbitration/prioritization under high loads. Please refer to the section - :ref:`virtual_interfaces_doc` for more information on this and a comparison to alternatives. + This interface guarantees reliable delivery and message ordering, but + does *not* implement rate limiting or ID arbitration/prioritization + under high loads. Please refer to the section + :ref:`virtual_interfaces_doc` for more information on this and a + comparison to alternatives. """ def __init__( @@ -60,10 +63,41 @@ def __init__( receive_own_messages: bool = False, rx_queue_size: int = 0, preserve_timestamps: bool = False, + protocol: CANProtocol = CANProtocol.CAN_20, **kwargs: Any, ) -> None: + """ + The constructed instance has access to the bus identified by the + channel parameter. It is able to see all messages transmitted on the + bus by virtual instances constructed with the same channel identifier. + + :param channel: The channel identifier. This parameter can be an + arbitrary value. The bus instance will be able to see messages + from other virtual bus instances that were created with the same + value. + :param receive_own_messages: If set to True, sent messages will be + reflected back on the input queue. + :param rx_queue_size: The size of the reception queue. The reception + queue stores messages until they are read. If the queue reaches + its capacity, it will start dropping the oldest messages to make + room for new ones. If set to 0, the queue has an infinite capacity. + Be aware that this can cause memory leaks if messages are read + with a lower frequency than they arrive on the bus. + :param preserve_timestamps: If set to True, messages transmitted via + :func:`~can.BusABC.send` will keep the timestamp set in the + :class:`~can.Message` instance. Otherwise, the timestamp value + will be replaced with the current system time. + :param protocol: The protocol implemented by this bus instance. The + value does not affect the operation of the bus instance and can + be set to an arbitrary value for testing purposes. + :param kwargs: Additional keyword arguments passed to the parent + constructor. + """ super().__init__( - channel=channel, receive_own_messages=receive_own_messages, **kwargs + channel=channel, + receive_own_messages=receive_own_messages, + protocol=protocol, + **kwargs, ) # the channel identifier may be an arbitrary object From 26fe9d461ca19bf35b8dcb6d1362bb6f5c392e94 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 12 Mar 2023 13:12:24 +0100 Subject: [PATCH 04/32] Implement CANProtocol for UDPMulticastBus --- can/interfaces/udp_multicast/bus.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/can/interfaces/udp_multicast/bus.py b/can/interfaces/udp_multicast/bus.py index 2ba1205b1..bd162eeac 100644 --- a/can/interfaces/udp_multicast/bus.py +++ b/can/interfaces/udp_multicast/bus.py @@ -3,22 +3,21 @@ import select import socket import struct +from typing import List, Optional, Tuple, Union + +import can +from can import BusABC, CANProtocol +from can.typechecking import AutoDetectedConfig +from .utils import pack_message, unpack_message, check_msgpack_installed try: from fcntl import ioctl except ModuleNotFoundError: # Missing on Windows pass -from typing import List, Optional, Tuple, Union log = logging.getLogger(__name__) -import can -from can import BusABC -from can.typechecking import AutoDetectedConfig - -from .utils import pack_message, unpack_message, check_msgpack_installed - # see socket.getaddrinfo() IPv4_ADDRESS_INFO = Tuple[str, int] # address, port @@ -103,7 +102,9 @@ def __init__( "receiving own messages is not yet implemented" ) - super().__init__(channel, **kwargs) + super().__init__( + channel, **kwargs, protocol=CANProtocol.CAN_FD if fd else CANProtocol.CAN_20 + ) self.is_fd = fd self._multicast = GeneralPurposeUdpMulticastBus(channel, port, hop_limit) From 091572b31e32ff64d1a828502bafbfe586ec81ce Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 12 Mar 2023 13:22:03 +0100 Subject: [PATCH 05/32] Implement CANProtocol for the CANalystIIBus --- can/interfaces/canalystii.py | 17 +++++++++++------ test/test_interface_canalystii.py | 11 +++++++++-- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/can/interfaces/canalystii.py b/can/interfaces/canalystii.py index 7150a60bd..b3dd1553f 100644 --- a/can/interfaces/canalystii.py +++ b/can/interfaces/canalystii.py @@ -1,16 +1,16 @@ import collections -from ctypes import c_ubyte import logging import time +from ctypes import c_ubyte from typing import Any, Dict, Optional, Deque, Sequence, Tuple, Union -from can import BitTiming, BusABC, Message, BitTimingFd -from can.exceptions import CanTimeoutError, CanInitializationError +import canalystii as driver + +from can import BitTiming, BusABC, Message, BitTimingFd, CANProtocol +from can.exceptions import CanTimeoutError from can.typechecking import CanFilters from can.util import deprecated_args_alias, check_or_adjust_timing_clock -import canalystii as driver - logger = logging.getLogger(__name__) @@ -50,7 +50,12 @@ def __init__( If set, software received message queue can only grow to this many messages (for all channels) before older messages are dropped """ - super().__init__(channel=channel, can_filters=can_filters, **kwargs) + super().__init__( + channel=channel, + can_filters=can_filters, + protocol=CANProtocol.CAN_20, + **kwargs, + ) if not (bitrate or timing): raise ValueError("Either bitrate or timing argument is required") diff --git a/test/test_interface_canalystii.py b/test/test_interface_canalystii.py index 4d1d3eb84..aa6064fb2 100755 --- a/test/test_interface_canalystii.py +++ b/test/test_interface_canalystii.py @@ -3,12 +3,12 @@ """ """ -import time import unittest -from unittest.mock import Mock, patch, call from ctypes import c_ubyte +from unittest.mock import patch, call import canalystii as driver # low-level driver module, mock out this layer + import can from can.interfaces.canalystii import CANalystIIBus @@ -22,6 +22,9 @@ def test_initialize_from_constructor(self): with create_mock_device() as mock_device: instance = mock_device.return_value bus = CANalystIIBus(bitrate=1000000) + + self.assertEqual(bus.protocol, can.CANProtocol.CAN_20) + instance.init.assert_has_calls( [ call(0, bitrate=1000000), @@ -34,6 +37,8 @@ def test_initialize_single_channel_only(self): with create_mock_device() as mock_device: instance = mock_device.return_value bus = CANalystIIBus(channel, bitrate=1000000) + + self.assertEqual(bus.protocol, can.CANProtocol.CAN_20) instance.init.assert_called_once_with(channel, bitrate=1000000) def test_initialize_with_timing_registers(self): @@ -43,6 +48,8 @@ def test_initialize_with_timing_registers(self): f_clock=8_000_000, btr0=0x03, btr1=0x6F ) bus = CANalystIIBus(bitrate=None, timing=timing) + self.assertEqual(bus.protocol, can.CANProtocol.CAN_20) + instance.init.assert_has_calls( [ call(0, timing0=0x03, timing1=0x6F), From 56e40d20905691975bdcdb3fd71c0b9e47a8fc88 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 12 Mar 2023 13:29:51 +0100 Subject: [PATCH 06/32] Implement CANProtocol for the slcanBus --- can/interfaces/slcan.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/can/interfaces/slcan.py b/can/interfaces/slcan.py index bcb3121ca..38e1c7033 100644 --- a/can/interfaces/slcan.py +++ b/can/interfaces/slcan.py @@ -2,21 +2,19 @@ Interface for slcan compatible interfaces (win32/linux). """ -from typing import Any, Optional, Tuple - import io -import time import logging +import time +from typing import Any, Optional, Tuple -from can import BusABC, Message +from can import BusABC, Message, CANProtocol +from can import typechecking from ..exceptions import ( CanInterfaceNotImplementedError, CanInitializationError, CanOperationError, error_check, ) -from can import typechecking - logger = logging.getLogger(__name__) @@ -120,7 +118,12 @@ def __init__( self.open() super().__init__( - channel, ttyBaudrate=115200, bitrate=None, rtscts=False, **kwargs + channel, + ttyBaudrate=115200, + bitrate=None, + rtscts=False, + protocol=CANProtocol.CAN_20, + **kwargs, ) def set_bitrate(self, bitrate: int) -> None: From 642e71156972fa314ceed52cc7fb491cdb0a4b68 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 12 Mar 2023 21:25:56 +0100 Subject: [PATCH 07/32] Rename CANProtocol to CanProtocol --- can/__init__.py | 2 +- can/bus.py | 6 +++--- can/interfaces/canalystii.py | 4 ++-- can/interfaces/pcan/pcan.py | 10 +++++----- can/interfaces/slcan.py | 4 ++-- can/interfaces/udp_multicast/bus.py | 4 ++-- can/interfaces/virtual.py | 4 ++-- test/test_interface_canalystii.py | 6 +++--- test/test_pcan.py | 10 +++++----- 9 files changed, 25 insertions(+), 25 deletions(-) diff --git a/can/__init__.py b/can/__init__.py index b8c94649e..de29ae109 100644 --- a/can/__init__.py +++ b/can/__init__.py @@ -27,7 +27,7 @@ from .util import set_logging_level from .message import Message -from .bus import BusABC, BusState, CANProtocol +from .bus import BusABC, BusState, CanProtocol from .thread_safe_bus import ThreadSafeBus from .notifier import Notifier from .interfaces import VALID_INTERFACES diff --git a/can/bus.py b/can/bus.py index b0571d043..c13b76c34 100644 --- a/can/bus.py +++ b/can/bus.py @@ -27,7 +27,7 @@ class BusState(Enum): ERROR = auto() -class CANProtocol(Enum): +class CanProtocol(Enum): """The CAN protocol type supported by a :class:`can.BusABC` instance""" CAN_20 = auto() @@ -56,7 +56,7 @@ class BusABC(metaclass=ABCMeta): def __init__( self, channel: Any, - protocol: CANProtocol = CANProtocol.CAN_20, + protocol: CanProtocol = CanProtocol.CAN_20, can_filters: Optional[can.typechecking.CanFilters] = None, **kwargs: object ): @@ -460,7 +460,7 @@ def state(self, new_state: BusState) -> None: raise NotImplementedError("Property is not implemented.") @property - def protocol(self) -> CANProtocol: + def protocol(self) -> CanProtocol: """Return the CAN protocol used by this bus instance. This value is set at initialization time and does not change diff --git a/can/interfaces/canalystii.py b/can/interfaces/canalystii.py index b3dd1553f..e05764aae 100644 --- a/can/interfaces/canalystii.py +++ b/can/interfaces/canalystii.py @@ -6,7 +6,7 @@ import canalystii as driver -from can import BitTiming, BusABC, Message, BitTimingFd, CANProtocol +from can import BitTiming, BusABC, Message, BitTimingFd, CanProtocol from can.exceptions import CanTimeoutError from can.typechecking import CanFilters from can.util import deprecated_args_alias, check_or_adjust_timing_clock @@ -53,7 +53,7 @@ def __init__( super().__init__( channel=channel, can_filters=can_filters, - protocol=CANProtocol.CAN_20, + protocol=CanProtocol.CAN_20, **kwargs, ) diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index 912ca8470..32d13125a 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -12,7 +12,7 @@ from can import ( BusABC, BusState, - CANProtocol, + CanProtocol, BitTiming, BitTimingFd, Message, @@ -341,7 +341,7 @@ def __init__( super().__init__( channel=channel, - protocol=CANProtocol.CAN_FD if is_fd else CANProtocol.CAN_20, + protocol=CanProtocol.CAN_FD if is_fd else CanProtocol.CAN_20, state=state, bitrate=bitrate, **kwargs, @@ -491,7 +491,7 @@ def _recv_internal( end_time = time.time() + timeout if timeout is not None else None while True: - if self.protocol == CANProtocol.CAN_FD: + if self.protocol == CanProtocol.CAN_FD: result, pcan_msg, pcan_timestamp = self.m_objPCANBasic.ReadFD( self.m_PcanHandle ) @@ -553,7 +553,7 @@ def _recv_internal( error_state_indicator = bool(pcan_msg.MSGTYPE & PCAN_MESSAGE_ESI.value) is_error_frame = bool(pcan_msg.MSGTYPE & PCAN_MESSAGE_ERRFRAME.value) - if self.protocol == CANProtocol.CAN_FD: + if self.protocol == CanProtocol.CAN_FD: dlc = dlc2len(pcan_msg.DLC) timestamp = boottimeEpoch + (pcan_timestamp.value / (1000.0 * 1000.0)) else: @@ -599,7 +599,7 @@ def send(self, msg, timeout=None): if msg.error_state_indicator: msgType |= PCAN_MESSAGE_ESI.value - if self.protocol == CANProtocol.CAN_FD: + if self.protocol == CanProtocol.CAN_FD: # create a TPCANMsg message structure CANMsg = TPCANMsgFD() diff --git a/can/interfaces/slcan.py b/can/interfaces/slcan.py index 38e1c7033..5a40097ad 100644 --- a/can/interfaces/slcan.py +++ b/can/interfaces/slcan.py @@ -7,7 +7,7 @@ import time from typing import Any, Optional, Tuple -from can import BusABC, Message, CANProtocol +from can import BusABC, Message, CanProtocol from can import typechecking from ..exceptions import ( CanInterfaceNotImplementedError, @@ -122,7 +122,7 @@ def __init__( ttyBaudrate=115200, bitrate=None, rtscts=False, - protocol=CANProtocol.CAN_20, + protocol=CanProtocol.CAN_20, **kwargs, ) diff --git a/can/interfaces/udp_multicast/bus.py b/can/interfaces/udp_multicast/bus.py index bd162eeac..f118eee84 100644 --- a/can/interfaces/udp_multicast/bus.py +++ b/can/interfaces/udp_multicast/bus.py @@ -6,7 +6,7 @@ from typing import List, Optional, Tuple, Union import can -from can import BusABC, CANProtocol +from can import BusABC, CanProtocol from can.typechecking import AutoDetectedConfig from .utils import pack_message, unpack_message, check_msgpack_installed @@ -103,7 +103,7 @@ def __init__( ) super().__init__( - channel, **kwargs, protocol=CANProtocol.CAN_FD if fd else CANProtocol.CAN_20 + channel, **kwargs, protocol=CanProtocol.CAN_FD if fd else CanProtocol.CAN_20 ) self.is_fd = fd diff --git a/can/interfaces/virtual.py b/can/interfaces/virtual.py index 5a56eda31..40549abc7 100644 --- a/can/interfaces/virtual.py +++ b/can/interfaces/virtual.py @@ -16,7 +16,7 @@ from random import randint from can import CanOperationError -from can.bus import BusABC, CANProtocol +from can.bus import BusABC, CanProtocol from can.message import Message from can.typechecking import AutoDetectedConfig @@ -63,7 +63,7 @@ def __init__( receive_own_messages: bool = False, rx_queue_size: int = 0, preserve_timestamps: bool = False, - protocol: CANProtocol = CANProtocol.CAN_20, + protocol: CanProtocol = CanProtocol.CAN_20, **kwargs: Any, ) -> None: """ diff --git a/test/test_interface_canalystii.py b/test/test_interface_canalystii.py index aa6064fb2..d669b47a6 100755 --- a/test/test_interface_canalystii.py +++ b/test/test_interface_canalystii.py @@ -23,7 +23,7 @@ def test_initialize_from_constructor(self): instance = mock_device.return_value bus = CANalystIIBus(bitrate=1000000) - self.assertEqual(bus.protocol, can.CANProtocol.CAN_20) + self.assertEqual(bus.protocol, can.CanProtocol.CAN_20) instance.init.assert_has_calls( [ @@ -38,7 +38,7 @@ def test_initialize_single_channel_only(self): instance = mock_device.return_value bus = CANalystIIBus(channel, bitrate=1000000) - self.assertEqual(bus.protocol, can.CANProtocol.CAN_20) + self.assertEqual(bus.protocol, can.CanProtocol.CAN_20) instance.init.assert_called_once_with(channel, bitrate=1000000) def test_initialize_with_timing_registers(self): @@ -48,7 +48,7 @@ def test_initialize_with_timing_registers(self): f_clock=8_000_000, btr0=0x03, btr1=0x6F ) bus = CANalystIIBus(bitrate=None, timing=timing) - self.assertEqual(bus.protocol, can.CANProtocol.CAN_20) + self.assertEqual(bus.protocol, can.CanProtocol.CAN_20) instance.init.assert_has_calls( [ diff --git a/test/test_pcan.py b/test/test_pcan.py index c5af88b31..d99d18a9e 100644 --- a/test/test_pcan.py +++ b/test/test_pcan.py @@ -11,7 +11,7 @@ from parameterized import parameterized import can -from can import BusState, CANProtocol +from can import BusState, CanProtocol from can.exceptions import CanInitializationError from can.interfaces.pcan import PcanBus, PcanError from can.interfaces.pcan.basic import * @@ -53,7 +53,7 @@ def test_bus_creation(self) -> None: self.bus = can.Bus(interface="pcan") self.assertIsInstance(self.bus, PcanBus) - self.assertEqual(self.bus.protocol, CANProtocol.CAN_20) + self.assertEqual(self.bus.protocol, CanProtocol.CAN_20) self.MockPCANBasic.assert_called_once() self.mock_pcan.Initialize.assert_called_once() @@ -81,7 +81,7 @@ def test_bus_creation_fd(self, clock_param: str, clock_val: int) -> None: ) self.assertIsInstance(self.bus, PcanBus) - self.assertEqual(self.bus.protocol, CANProtocol.CAN_FD) + self.assertEqual(self.bus.protocol, CanProtocol.CAN_FD) self.MockPCANBasic.assert_called_once() self.mock_pcan.Initialize.assert_not_called() @@ -459,7 +459,7 @@ def test_constructor_bit_timing(self): bitrate_arg = self.mock_pcan.Initialize.call_args[0][1] self.assertEqual(bitrate_arg.value, 0x472F) - self.assertEqual(bus.protocol, CANProtocol.CAN_20) + self.assertEqual(bus.protocol, CanProtocol.CAN_20) def test_constructor_bit_timing_fd(self): timing = can.BitTimingFd( @@ -474,7 +474,7 @@ def test_constructor_bit_timing_fd(self): data_sjw=1, ) bus = can.Bus(interface="pcan", channel="PCAN_USBBUS1", timing=timing) - self.assertEqual(bus.protocol, CANProtocol.CAN_FD) + self.assertEqual(bus.protocol, CanProtocol.CAN_FD) bitrate_arg = self.mock_pcan.InitializeFD.call_args[0][-1] From c6da1c4d06730302dab9a503e73610a26d39a0ca Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 19 Mar 2023 11:24:32 +0100 Subject: [PATCH 08/32] Reimplement PcanBus.fd attribute as read-only property The property is scheduled for removal in v5.0 --- can/interfaces/pcan/pcan.py | 13 +++++++++++-- test/test_pcan.py | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index 32d13125a..fb9d15991 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -2,9 +2,10 @@ Enable basic CAN over a PCAN USB device. """ import logging +import platform import time +import warnings from datetime import datetime -import platform from typing import Optional, List, Tuple, Union, Any from packaging import version @@ -70,7 +71,6 @@ VALID_PCAN_CAN_CLOCKS, ) - # Set up logging log = logging.getLogger("can.pcan") @@ -658,6 +658,15 @@ def shutdown(self): self.m_objPCANBasic.Uninitialize(self.m_PcanHandle) + @property + def fd(self) -> bool: + warnings.warn( + "The PcanBus.fd property is deprecated and superseded by BusABC.protocol. " + "It is scheduled for removal in version 5.0.", + DeprecationWarning, + ) + return self.protocol == CanProtocol.CAN_FD + @property def state(self): return self._state diff --git a/test/test_pcan.py b/test/test_pcan.py index d99d18a9e..70d50b12b 100644 --- a/test/test_pcan.py +++ b/test/test_pcan.py @@ -54,6 +54,7 @@ def test_bus_creation(self) -> None: self.assertIsInstance(self.bus, PcanBus) self.assertEqual(self.bus.protocol, CanProtocol.CAN_20) + self.assertFalse(self.bus.fd) self.MockPCANBasic.assert_called_once() self.mock_pcan.Initialize.assert_called_once() @@ -82,6 +83,7 @@ def test_bus_creation_fd(self, clock_param: str, clock_val: int) -> None: self.assertIsInstance(self.bus, PcanBus) self.assertEqual(self.bus.protocol, CanProtocol.CAN_FD) + self.assertTrue(self.bus.fd) self.MockPCANBasic.assert_called_once() self.mock_pcan.Initialize.assert_not_called() From da89d3530b378df10a0a477e263637dbdc91f55d Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 19 Mar 2023 11:37:48 +0100 Subject: [PATCH 09/32] Reimplement UdpMulticastBus.is_fd attribute as read-only property The property is superseded by BusABC.protocol and scheduled for removal in version 5.0. --- can/interfaces/udp_multicast/bus.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/can/interfaces/udp_multicast/bus.py b/can/interfaces/udp_multicast/bus.py index f118eee84..b445fd6a1 100644 --- a/can/interfaces/udp_multicast/bus.py +++ b/can/interfaces/udp_multicast/bus.py @@ -3,6 +3,7 @@ import select import socket import struct +import warnings from typing import List, Optional, Tuple, Union import can @@ -103,12 +104,22 @@ def __init__( ) super().__init__( - channel, **kwargs, protocol=CanProtocol.CAN_FD if fd else CanProtocol.CAN_20 + channel, + **kwargs, + protocol=CanProtocol.CAN_FD if fd else CanProtocol.CAN_20, ) - self.is_fd = fd self._multicast = GeneralPurposeUdpMulticastBus(channel, port, hop_limit) + @property + def is_fd(self) -> bool: + warnings.warn( + "The UdpMulticastBus.is_fd property is deprecated and superseded by " + "BusABC.protocol. It is scheduled for removal in version 5.0.", + DeprecationWarning, + ) + return self.protocol == CanProtocol.CAN_FD + def _recv_internal(self, timeout: Optional[float]): result = self._multicast.recv(timeout) if not result: @@ -124,13 +135,13 @@ def _recv_internal(self, timeout: Optional[float]): "could not unpack received message" ) from exception - if not self.is_fd and can_message.is_fd: + if self.protocol != CanProtocol.CAN_FD and can_message.is_fd: return None, False return can_message, False def send(self, msg: can.Message, timeout: Optional[float] = None) -> None: - if not self.is_fd and msg.is_fd: + if self.protocol != CanProtocol.CAN_FD and msg.is_fd: raise can.CanOperationError( "cannot send FD message over bus with CAN FD disabled" ) From 51301fe247c383914ba0be2e80b9c99db3e6dddd Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 19 Mar 2023 11:41:56 +0100 Subject: [PATCH 10/32] Implement CanProtocol for robotellBus --- can/interfaces/robotell.py | 6 +++--- test/test_robotell.py | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/can/interfaces/robotell.py b/can/interfaces/robotell.py index 4d82c1922..23a55d9d7 100644 --- a/can/interfaces/robotell.py +++ b/can/interfaces/robotell.py @@ -3,11 +3,11 @@ """ import io -import time import logging +import time from typing import Optional -from can import BusABC, Message +from can import BusABC, Message, CanProtocol from ..exceptions import CanInterfaceNotImplementedError, CanOperationError logger = logging.getLogger(__name__) @@ -96,7 +96,7 @@ def __init__( ) logger.info("Using device: %s", self.channel_info) - super().__init__(channel=channel, **kwargs) + super().__init__(channel=channel, protocol=CanProtocol.CAN_20, **kwargs) def set_bitrate(self, bitrate): """ diff --git a/test/test_robotell.py b/test/test_robotell.py index 64f4acaf1..f95139917 100644 --- a/test/test_robotell.py +++ b/test/test_robotell.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import unittest + import can @@ -14,6 +15,9 @@ def setUp(self): def tearDown(self): self.bus.shutdown() + def test_protocol(self): + self.assertEqual(self.bus.protocol, can.CanProtocol.CAN_20) + def test_recv_extended(self): self.serial.write( bytearray( From 55e349a4a36adb2683db4626c410e96e97a4ccf3 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 19 Mar 2023 11:46:53 +0100 Subject: [PATCH 11/32] Implement CanProtocol for NicanBus --- can/interfaces/nican.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/can/interfaces/nican.py b/can/interfaces/nican.py index ea13e28e8..f8aabb6f2 100644 --- a/can/interfaces/nican.py +++ b/can/interfaces/nican.py @@ -16,17 +16,18 @@ import ctypes import logging import sys +from typing import Optional, Tuple, Type -from can import BusABC, Message import can.typechecking -from ..exceptions import ( +from can import ( + BusABC, + Message, + CanProtocol, CanError, CanInterfaceNotImplementedError, CanOperationError, CanInitializationError, ) -from typing import Optional, Tuple, Type - logger = logging.getLogger(__name__) @@ -274,6 +275,7 @@ def __init__( can_filters=can_filters, bitrate=bitrate, log_errors=log_errors, + protocol=CanProtocol.CAN_20, **kwargs, ) From 76465e4f7d1a753b922ef3b03b122733d948d07d Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 19 Mar 2023 11:50:32 +0100 Subject: [PATCH 12/32] Implement CanProtocol for IscanBus --- can/interfaces/iscan.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/can/interfaces/iscan.py b/can/interfaces/iscan.py index e76d9d060..7326db8ac 100644 --- a/can/interfaces/iscan.py +++ b/can/interfaces/iscan.py @@ -3,12 +3,14 @@ """ import ctypes -import time import logging +import time from typing import Optional, Tuple, Union -from can import BusABC, Message from can import ( + BusABC, + Message, + CanProtocol, CanError, CanInterfaceNotImplementedError, CanInitializationError, @@ -106,7 +108,11 @@ def __init__( iscan.isCAN_DeviceInitEx(self.channel, self.BAUDRATES[bitrate]) super().__init__( - channel=channel, bitrate=bitrate, poll_interval=poll_interval, **kwargs + channel=channel, + bitrate=bitrate, + poll_interval=poll_interval, + protocol=CanProtocol.CAN_20, + **kwargs, ) def _recv_internal( From cdbfa130f16df09c6528092ef680fa02b980c442 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 19 Mar 2023 11:54:20 +0100 Subject: [PATCH 13/32] Implement CanProtocol for CantactBus --- can/interfaces/cantact.py | 10 +++++++--- test/test_cantact.py | 5 +++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/can/interfaces/cantact.py b/can/interfaces/cantact.py index 20e4d0cb7..3e011de56 100644 --- a/can/interfaces/cantact.py +++ b/can/interfaces/cantact.py @@ -2,12 +2,12 @@ Interface for CANtact devices from Linklayer Labs """ -import time import logging +import time from typing import Optional, Union, Any from unittest.mock import Mock -from can import BusABC, Message, BitTiming, BitTimingFd +from can import BusABC, Message, BitTiming, BitTimingFd, CanProtocol from ..exceptions import ( CanInitializationError, CanInterfaceNotImplementedError, @@ -113,7 +113,11 @@ def __init__( self.interface.start() super().__init__( - channel=channel, bitrate=bitrate, poll_interval=poll_interval, **kwargs + channel=channel, + bitrate=bitrate, + poll_interval=poll_interval, + protocol=CanProtocol.CAN_20, + **kwargs, ) def _recv_internal(self, timeout): diff --git a/test/test_cantact.py b/test/test_cantact.py index 2cc3e479c..f90655ae5 100644 --- a/test/test_cantact.py +++ b/test/test_cantact.py @@ -14,6 +14,8 @@ class CantactTest(unittest.TestCase): def test_bus_creation(self): bus = can.Bus(channel=0, interface="cantact", _testing=True) self.assertIsInstance(bus, cantact.CantactBus) + self.assertEqual(bus.protocol, can.CanProtocol.CAN_20) + cantact.MockInterface.set_bitrate.assert_called() cantact.MockInterface.set_bit_timing.assert_not_called() cantact.MockInterface.set_enabled.assert_called() @@ -25,7 +27,10 @@ def test_bus_creation_bittiming(self): bt = can.BitTiming(f_clock=24_000_000, brp=3, tseg1=13, tseg2=2, sjw=1) bus = can.Bus(channel=0, interface="cantact", timing=bt, _testing=True) + self.assertIsInstance(bus, cantact.CantactBus) + self.assertEqual(bus.protocol, can.CanProtocol.CAN_20) + cantact.MockInterface.set_bitrate.assert_not_called() cantact.MockInterface.set_bit_timing.assert_called() cantact.MockInterface.set_enabled.assert_called() From 9ad3dae0c5697158b464d5450e8b12bca2db4cb6 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 19 Mar 2023 12:03:11 +0100 Subject: [PATCH 14/32] Fix sphinx reference to CanProtocol --- doc/bus.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/bus.rst b/doc/bus.rst index 5e09eec34..822397140 100644 --- a/doc/bus.rst +++ b/doc/bus.rst @@ -87,7 +87,7 @@ Bus API :members: :undoc-members: -.. autoclass:: can.bus.CANProtocol +.. autoclass:: can.bus.CanProtocol :members: :undoc-members: From 652d5ccb62d852618ec3e647993561d460e49f4f Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 19 Mar 2023 12:05:46 +0100 Subject: [PATCH 15/32] Implement CanProtocol for GsUsbBus --- can/interfaces/gs_usb.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/can/interfaces/gs_usb.py b/can/interfaces/gs_usb.py index 185d28acf..5bf37e08c 100644 --- a/can/interfaces/gs_usb.py +++ b/can/interfaces/gs_usb.py @@ -1,15 +1,14 @@ +import logging from typing import Optional, Tuple +import usb +from gs_usb.constants import CAN_ERR_FLAG, CAN_RTR_FLAG, CAN_EFF_FLAG, CAN_MAX_DLC from gs_usb.gs_usb import GsUsb from gs_usb.gs_usb_frame import GsUsbFrame, GS_USB_NONE_ECHO_ID -from gs_usb.constants import CAN_ERR_FLAG, CAN_RTR_FLAG, CAN_EFF_FLAG, CAN_MAX_DLC -import can -import usb -import logging +import can from ..exceptions import CanInitializationError, CanOperationError - logger = logging.getLogger(__name__) @@ -56,7 +55,12 @@ def __init__( self.gs_usb.set_bitrate(bitrate) self.gs_usb.start() - super().__init__(channel=channel, can_filters=can_filters, **kwargs) + super().__init__( + channel=channel, + can_filters=can_filters, + protocol=can.CanProtocol.CAN_20, + **kwargs, + ) def send(self, msg: can.Message, timeout: Optional[float] = None): """Transmit a message to the CAN bus. From a20af3840245988da24b0d6af8206234c330519e Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 19 Mar 2023 12:19:35 +0100 Subject: [PATCH 16/32] Implement CanProtocol for NiXNETcanBus --- can/interfaces/nixnet.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/can/interfaces/nixnet.py b/can/interfaces/nixnet.py index 6c3e63697..fb14f4a68 100644 --- a/can/interfaces/nixnet.py +++ b/can/interfaces/nixnet.py @@ -11,12 +11,13 @@ import logging import os import time +import warnings from queue import SimpleQueue from types import ModuleType from typing import Optional, List, Union, Tuple, Any import can.typechecking -from can import BusABC, Message, BitTiming, BitTimingFd +from can import BusABC, Message, BitTiming, BitTimingFd, CanProtocol from can.exceptions import ( CanInitializationError, CanOperationError, @@ -103,10 +104,10 @@ def __init__( self.poll_interval = poll_interval - self.fd = isinstance(timing, BitTimingFd) if timing else fd + is_fd = isinstance(timing, BitTimingFd) if timing else fd # Set database for the initialization - database_name = ":can_fd_brs:" if self.fd else ":memory:" + database_name = ":can_fd_brs:" if is_fd else ":memory:" try: # We need two sessions for this application, @@ -158,7 +159,7 @@ def __init__( if bitrate: self._interface.baud_rate = bitrate - if self.fd: + if is_fd: # See page 951 of NI-XNET Hardware and Software Manual # to set custom can configuration self._interface.can_fd_baud_rate = fd_bitrate or bitrate @@ -185,9 +186,19 @@ def __init__( channel=channel, can_filters=can_filters, bitrate=bitrate, + protocol=CanProtocol.CAN_FD if is_fd else CanProtocol.CAN_20, **kwargs, ) + @property + def fd(self) -> bool: + warnings.warn( + "The NiXNETcanBus.fd property is deprecated and superseded by " + "BusABC.protocol. It is scheduled for removal in version 5.0.", + DeprecationWarning, + ) + return self.protocol == CanProtocol.CAN_FD + def _recv_internal( self, timeout: Optional[float] ) -> Tuple[Optional[Message], bool]: From d6fabc6d6e12fce2a458f58de7b9907cf1468a32 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 19 Mar 2023 13:34:04 +0100 Subject: [PATCH 17/32] Implement CanProtocol for EtasBus --- can/interfaces/etas/__init__.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/can/interfaces/etas/__init__.py b/can/interfaces/etas/__init__.py index 3a203a50d..5833cf69c 100644 --- a/can/interfaces/etas/__init__.py +++ b/can/interfaces/etas/__init__.py @@ -1,9 +1,7 @@ -import ctypes import time from typing import Dict, List, Optional, Tuple -import can -from ...exceptions import CanInitializationError +import can.typechecking from .boa import * @@ -18,6 +16,12 @@ def __init__( data_bitrate: int = 2000000, **kwargs: object, ): + + super().__init__( + channel=channel, + protocol=can.CanProtocol.CAN_FD if fd else can.CanProtocol.CAN_20, + ) + self.receive_own_messages = receive_own_messages nodeRange = CSI_NodeRange(CSI_NODE_MIN, CSI_NODE_MAX) @@ -289,12 +293,13 @@ def state(self, new_state: can.BusState) -> None: # raise CanOperationError(f"OCI_AdaptCANConfiguration failed with error 0x{ec:X}") raise NotImplementedError("Setting state is not implemented.") + @staticmethod def _detect_available_configs() -> List[can.typechecking.AutoDetectedConfig]: nodeRange = CSI_NodeRange(CSI_NODE_MIN, CSI_NODE_MAX) tree = ctypes.POINTER(CSI_Tree)() CSI_CreateProtocolTree(ctypes.c_char_p(b""), nodeRange, ctypes.byref(tree)) - nodes: Dict[str, str] = [] + nodes: List[Dict[str, str]] = [] def _findNodes(tree, prefix): uri = f"{prefix}/{tree.contents.item.uriName.decode()}" From b2d9f3095df73f6d19ecf81cf407f8f8c8adc4bf Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 19 Mar 2023 19:45:24 +0100 Subject: [PATCH 18/32] Implement CanProtocol for IXXATBus --- can/interfaces/ixxat/canlib.py | 2 ++ can/interfaces/ixxat/canlib_vcinpl.py | 16 ++++++++++------ can/interfaces/ixxat/canlib_vcinpl2.py | 22 ++++++++++++---------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index a20e4f59b..f5a56a797 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -132,6 +132,8 @@ def __init__( **kwargs ) + super().__init__(channel=channel, protocol=self.bus.protocol) + def flush_tx_buffer(self): """Flushes the transmit buffer on the IXXAT""" return self.bus.flush_tx_buffer() diff --git a/can/interfaces/ixxat/canlib_vcinpl.py b/can/interfaces/ixxat/canlib_vcinpl.py index 8304a6dd7..e0230209a 100644 --- a/can/interfaces/ixxat/canlib_vcinpl.py +++ b/can/interfaces/ixxat/canlib_vcinpl.py @@ -15,16 +15,18 @@ import sys from typing import Optional, Callable, Tuple -from can import BusABC, Message -from can.bus import BusState -from can.exceptions import CanInterfaceNotImplementedError, CanInitializationError -from can.broadcastmanager import ( +from can import ( + BusABC, + Message, + BusState, + CanProtocol, + CanInterfaceNotImplementedError, + CanInitializationError, LimitedDurationCyclicSendTaskABC, RestartableCyclicTaskABC, ) from can.ctypesutil import CLibrary, HANDLE, PHANDLE, HRESULT as ctypes_HRESULT from can.util import deprecated_args_alias - from . import constants, structures from .exceptions import * @@ -631,7 +633,9 @@ def __init__( except (VCITimeout, VCIRxQueueEmptyError): break - super().__init__(channel=channel, can_filters=None, **kwargs) + super().__init__( + channel=channel, can_filters=None, protocol=CanProtocol.CAN_20, **kwargs + ) def _inWaiting(self): try: diff --git a/can/interfaces/ixxat/canlib_vcinpl2.py b/can/interfaces/ixxat/canlib_vcinpl2.py index b8ed916dc..8f794fab9 100644 --- a/can/interfaces/ixxat/canlib_vcinpl2.py +++ b/can/interfaces/ixxat/canlib_vcinpl2.py @@ -15,17 +15,17 @@ import sys from typing import Optional, Callable, Tuple -from can import BusABC, Message -from can.exceptions import CanInterfaceNotImplementedError, CanInitializationError -from can.broadcastmanager import ( +from can import ( + BusABC, + Message, + CanProtocol, + CanInterfaceNotImplementedError, + CanInitializationError, LimitedDurationCyclicSendTaskABC, RestartableCyclicTaskABC, ) from can.ctypesutil import CLibrary, HANDLE, PHANDLE, HRESULT as ctypes_HRESULT - -import can.util -from can.util import deprecated_args_alias - +from can.util import deprecated_args_alias, dlc2len, len2dlc from . import constants, structures from .exceptions import * @@ -742,7 +742,9 @@ def __init__( except (VCITimeout, VCIRxQueueEmptyError): break - super().__init__(channel=channel, can_filters=None, **kwargs) + super().__init__( + channel=channel, can_filters=None, protocol=CanProtocol.CAN_FD, **kwargs + ) @staticmethod def _canptb_build(defaults, bitrate, tseg1, tseg2, sjw, ssp): @@ -865,7 +867,7 @@ def _recv_internal(self, timeout): # Timed out / can message type is not DATA return None, True - data_len = can.util.dlc2len(self._message.uMsgInfo.Bits.dlc) + data_len = dlc2len(self._message.uMsgInfo.Bits.dlc) # The _message.dwTime is a 32bit tick value and will overrun, # so expect to see the value restarting from 0 rx_msg = Message( @@ -915,7 +917,7 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None: message.uMsgInfo.Bits.edl = 1 if msg.is_fd else 0 message.dwMsgId = msg.arbitration_id if msg.dlc: # this dlc means number of bytes of payload - message.uMsgInfo.Bits.dlc = can.util.len2dlc(msg.dlc) + message.uMsgInfo.Bits.dlc = len2dlc(msg.dlc) data_len_dif = msg.dlc - len(msg.data) data = msg.data + bytearray( [0] * data_len_dif From 9a39e2e1f15ed77cdc68acd912257c36e8511edb Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 19 Mar 2023 19:48:32 +0100 Subject: [PATCH 19/32] Implement CanProtocol for KvaserBus --- can/interfaces/kvaser/canlib.py | 25 +++++++++++++++++-------- test/test_kvaser.py | 7 +++++-- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/can/interfaces/kvaser/canlib.py b/can/interfaces/kvaser/canlib.py index 2bbf8f0bf..f90db9417 100644 --- a/can/interfaces/kvaser/canlib.py +++ b/can/interfaces/kvaser/canlib.py @@ -6,17 +6,21 @@ Copyright (C) 2010 Dynamic Controls """ +import ctypes +import logging import sys import time -import logging -import ctypes -from can import BusABC -from ...exceptions import CanError, CanInitializationError, CanOperationError -from can import Message +from can import ( + BusABC, + Message, + CanProtocol, + CanError, + CanInitializationError, + CanOperationError, +) from can.util import time_perfcounter_correlation -from . import constants as canstat -from . import structures +from . import constants as canstat, structures log = logging.getLogger("can.kvaser") @@ -520,7 +524,12 @@ def __init__(self, channel, can_filters=None, **kwargs): self._timestamp_offset = time.time() - (timer.value * TIMESTAMP_FACTOR) self._is_filtered = False - super().__init__(channel=channel, can_filters=can_filters, **kwargs) + super().__init__( + channel=channel, + can_filters=can_filters, + protocol=CanProtocol.CAN_FD if fd else CanProtocol.CAN_20, + **kwargs, + ) def _apply_filters(self, filters): if filters and len(filters) == 1: diff --git a/test/test_kvaser.py b/test/test_kvaser.py index fda8b8316..8b58ce3c1 100644 --- a/test/test_kvaser.py +++ b/test/test_kvaser.py @@ -46,6 +46,7 @@ def tearDown(self): def test_bus_creation(self): self.assertIsInstance(self.bus, canlib.KvaserBus) + self.assertEqual(self.bus.protocol, can.CanProtocol.CAN_20) self.assertTrue(canlib.canOpenChannel.called) self.assertTrue(canlib.canBusOn.called) @@ -149,7 +150,8 @@ def test_available_configs(self): def test_canfd_default_data_bitrate(self): canlib.canSetBusParams.reset_mock() canlib.canSetBusParamsFd.reset_mock() - can.Bus(channel=0, interface="kvaser", fd=True) + bus = can.Bus(channel=0, interface="kvaser", fd=True) + self.assertEqual(bus.protocol, can.CanProtocol.CAN_FD) canlib.canSetBusParams.assert_called_once_with( 0, constants.canFD_BITRATE_500K_80P, 0, 0, 0, 0, 0 ) @@ -161,7 +163,8 @@ def test_canfd_nondefault_data_bitrate(self): canlib.canSetBusParams.reset_mock() canlib.canSetBusParamsFd.reset_mock() data_bitrate = 2000000 - can.Bus(channel=0, interface="kvaser", fd=True, data_bitrate=data_bitrate) + bus = can.Bus(channel=0, interface="kvaser", fd=True, data_bitrate=data_bitrate) + self.assertEqual(bus.protocol, can.CanProtocol.CAN_FD) bitrate_constant = canlib.BITRATE_FD[data_bitrate] canlib.canSetBusParams.assert_called_once_with( 0, constants.canFD_BITRATE_500K_80P, 0, 0, 0, 0, 0 From 2aa8ceb3cb1000d35295b3b56398566a0d734aca Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 19 Mar 2023 19:52:15 +0100 Subject: [PATCH 20/32] Implement CanProtocol for the SerialBus --- can/interfaces/serial/serial_can.py | 6 ++++-- test/serial_test.py | 7 ++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/can/interfaces/serial/serial_can.py b/can/interfaces/serial/serial_can.py index c1507b4fa..5d5345747 100644 --- a/can/interfaces/serial/serial_can.py +++ b/can/interfaces/serial/serial_can.py @@ -12,8 +12,10 @@ import struct from typing import Any, List, Tuple, Optional -from can import BusABC, Message from can import ( + BusABC, + Message, + CanProtocol, CanInterfaceNotImplementedError, CanInitializationError, CanOperationError, @@ -97,7 +99,7 @@ def __init__( "could not create the serial device" ) from error - super().__init__(channel, *args, **kwargs) + super().__init__(channel, protocol=CanProtocol.CAN_20, *args, **kwargs) def shutdown(self) -> None: """ diff --git a/test/serial_test.py b/test/serial_test.py index aa6c71994..d3474309f 100644 --- a/test/serial_test.py +++ b/test/serial_test.py @@ -11,10 +11,8 @@ import can from can.interfaces.serial.serial_can import SerialBus - -from .message_helper import ComparingMessagesTestCase from .config import IS_PYPY - +from .message_helper import ComparingMessagesTestCase # Mentioned in #1010 TIMEOUT = 0.5 if IS_PYPY else 0.1 # 0.1 is the default set in SerialBus @@ -52,6 +50,9 @@ def __init__(self): self, allowed_timestamp_delta=None, preserves_channel=True ) + def test_can_protocol(self): + self.assertEqual(self.bus.protocol, can.CanProtocol.CAN_20) + def test_rx_tx_min_max_data(self): """ Tests the transfer from 0x00 to 0xFF for a 1 byte payload From 43651575d7219d99919fdbe939163db3b203bfe9 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 19 Mar 2023 19:54:39 +0100 Subject: [PATCH 21/32] Implement CanProtocol for UcanBus --- can/interfaces/systec/ucanbus.py | 21 ++++++++++++++++----- test/test_systec.py | 2 ++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/can/interfaces/systec/ucanbus.py b/can/interfaces/systec/ucanbus.py index 7d8b6133a..900b7f4f8 100644 --- a/can/interfaces/systec/ucanbus.py +++ b/can/interfaces/systec/ucanbus.py @@ -1,12 +1,18 @@ import logging from threading import Event -from can import BusABC, BusState, Message -from ...exceptions import CanError, CanInitializationError, CanOperationError - +from can import ( + BusABC, + BusState, + Message, + CanProtocol, + CanError, + CanInitializationError, + CanOperationError, +) from .constants import * -from .structures import * from .exceptions import UcanException +from .structures import * from .ucan import UcanServer log = logging.getLogger("can.systec") @@ -145,7 +151,12 @@ def __init__(self, channel, can_filters=None, **kwargs): self._is_filtered = False - super().__init__(channel=channel, can_filters=can_filters, **kwargs) + super().__init__( + channel=channel, + can_filters=can_filters, + protocol=CanProtocol.CAN_20, + **kwargs, + ) def _recv_internal(self, timeout): try: diff --git a/test/test_systec.py b/test/test_systec.py index 7495f75eb..86ed31362 100644 --- a/test/test_systec.py +++ b/test/test_systec.py @@ -36,6 +36,8 @@ def setUp(self): def test_bus_creation(self): self.assertIsInstance(self.bus, ucanbus.UcanBus) + self.assertEqual(self.bus.protocol, can.CanProtocol.CAN_20) + self.assertTrue(ucan.UcanInitHwConnectControlEx.called) self.assertTrue( ucan.UcanInitHardwareEx.called or ucan.UcanInitHardwareEx2.called From 08e94460a30aeed990617c18553dfb760ae5711c Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sat, 25 Mar 2023 11:16:57 +0100 Subject: [PATCH 22/32] Implement CanProtocol for VectorBus --- can/interfaces/vector/canlib.py | 28 ++++++++++++++++++++++------ test/test_vector.py | 18 ++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/can/interfaces/vector/canlib.py b/can/interfaces/vector/canlib.py index d53b1418d..010fced64 100644 --- a/can/interfaces/vector/canlib.py +++ b/can/interfaces/vector/canlib.py @@ -8,8 +8,9 @@ # ============================== import ctypes import logging -import time import os +import time +import warnings from types import ModuleType from typing import ( List, @@ -44,6 +45,7 @@ CanInitializationError, BitTiming, BitTimingFd, + CanProtocol, ) from can.util import ( len2dlc, @@ -203,7 +205,7 @@ def __init__( channel_configs = get_channel_configs() self.mask = 0 - self.fd = isinstance(timing, BitTimingFd) if timing else fd + is_fd = isinstance(timing, BitTimingFd) if timing else fd self.channel_masks: Dict[int, int] = {} self.index_to_channel: Dict[int, int] = {} @@ -228,7 +230,7 @@ def __init__( interface_version = ( xldefine.XL_InterfaceVersion.XL_INTERFACE_VERSION_V4 - if self.fd + if is_fd else xldefine.XL_InterfaceVersion.XL_INTERFACE_VERSION ) @@ -323,7 +325,21 @@ def __init__( self._time_offset = 0.0 self._is_filtered = False - super().__init__(channel=channel, can_filters=can_filters, **kwargs) + super().__init__( + channel=channel, + can_filters=can_filters, + protocol=CanProtocol.CAN_FD if is_fd else CanProtocol.CAN_20, + **kwargs, + ) + + @property + def fd(self) -> bool: + warnings.warn( + "The VectorBus.fd property is deprecated and superseded by " + "BusABC.protocol. It is scheduled for removal in version 5.0.", + DeprecationWarning, + ) + return self.protocol == CanProtocol.CAN_FD def _find_global_channel_idx( self, @@ -646,7 +662,7 @@ def _recv_internal( while True: try: - if self.fd: + if self.protocol == CanProtocol.CAN_FD: msg = self._recv_canfd() else: msg = self._recv_can() @@ -780,7 +796,7 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None: def _send_sequence(self, msgs: Sequence[Message]) -> int: """Send messages and return number of successful transmissions.""" - if self.fd: + if self.protocol == CanProtocol.CAN_FD: return self._send_can_fd_msg_sequence(msgs) else: return self._send_can_msg_sequence(msgs) diff --git a/test/test_vector.py b/test/test_vector.py index 7694b31aa..4b83978a3 100644 --- a/test/test_vector.py +++ b/test/test_vector.py @@ -79,6 +79,8 @@ def mock_xldriver() -> None: def test_bus_creation_mocked(mock_xldriver) -> None: bus = can.Bus(channel=0, interface="vector", _testing=True) assert isinstance(bus, canlib.VectorBus) + assert bus.protocol == can.CanProtocol.CAN_20 + can.interfaces.vector.canlib.xldriver.xlOpenDriver.assert_called() can.interfaces.vector.canlib.xldriver.xlGetApplConfig.assert_called() @@ -95,6 +97,8 @@ def test_bus_creation_mocked(mock_xldriver) -> None: def test_bus_creation() -> None: bus = can.Bus(channel=0, serial=_find_virtual_can_serial(), interface="vector") assert isinstance(bus, canlib.VectorBus) + assert bus.protocol == can.CanProtocol.CAN_20 + bus.shutdown() xl_channel_config = _find_xl_channel_config( @@ -108,12 +112,15 @@ def test_bus_creation() -> None: bus = canlib.VectorBus(channel=0, serial=_find_virtual_can_serial()) assert isinstance(bus, canlib.VectorBus) + assert bus.protocol == can.CanProtocol.CAN_20 bus.shutdown() def test_bus_creation_bitrate_mocked(mock_xldriver) -> None: bus = can.Bus(channel=0, interface="vector", bitrate=200_000, _testing=True) assert isinstance(bus, canlib.VectorBus) + assert bus.protocol == can.CanProtocol.CAN_20 + can.interfaces.vector.canlib.xldriver.xlOpenDriver.assert_called() can.interfaces.vector.canlib.xldriver.xlGetApplConfig.assert_called() @@ -139,6 +146,7 @@ def test_bus_creation_bitrate() -> None: bitrate=200_000, ) assert isinstance(bus, canlib.VectorBus) + assert bus.protocol == can.CanProtocol.CAN_20 xl_channel_config = _find_xl_channel_config( serial=_find_virtual_can_serial(), channel=0 @@ -151,6 +159,8 @@ def test_bus_creation_bitrate() -> None: def test_bus_creation_fd_mocked(mock_xldriver) -> None: bus = can.Bus(channel=0, interface="vector", fd=True, _testing=True) assert isinstance(bus, canlib.VectorBus) + assert bus.protocol == can.CanProtocol.CAN_FD + can.interfaces.vector.canlib.xldriver.xlOpenDriver.assert_called() can.interfaces.vector.canlib.xldriver.xlGetApplConfig.assert_called() @@ -171,6 +181,7 @@ def test_bus_creation_fd() -> None: channel=0, serial=_find_virtual_can_serial(), interface="vector", fd=True ) assert isinstance(bus, canlib.VectorBus) + assert bus.protocol == can.CanProtocol.CAN_FD xl_channel_config = _find_xl_channel_config( serial=_find_virtual_can_serial(), channel=0 @@ -202,6 +213,8 @@ def test_bus_creation_fd_bitrate_timings_mocked(mock_xldriver) -> None: _testing=True, ) assert isinstance(bus, canlib.VectorBus) + assert bus.protocol == can.CanProtocol.CAN_FD + can.interfaces.vector.canlib.xldriver.xlOpenDriver.assert_called() can.interfaces.vector.canlib.xldriver.xlGetApplConfig.assert_called() @@ -344,6 +357,7 @@ def test_bus_creation_timing() -> None: timing=timing, ) assert isinstance(bus, canlib.VectorBus) + assert bus.protocol == can.CanProtocol.CAN_20 xl_channel_config = _find_xl_channel_config( serial=_find_virtual_can_serial(), channel=0 @@ -375,6 +389,8 @@ def test_bus_creation_timingfd_mocked(mock_xldriver) -> None: _testing=True, ) assert isinstance(bus, canlib.VectorBus) + assert bus.protocol == can.CanProtocol.CAN_FD + can.interfaces.vector.canlib.xldriver.xlOpenDriver.assert_called() can.interfaces.vector.canlib.xldriver.xlGetApplConfig.assert_called() @@ -423,6 +439,8 @@ def test_bus_creation_timingfd() -> None: timing=timing, ) + assert bus.protocol == can.CanProtocol.CAN_FD + xl_channel_config = _find_xl_channel_config( serial=_find_virtual_can_serial(), channel=0 ) From 5ae8e4434f0ffb650fe3ec82b09c2227dcfa09c5 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sat, 25 Mar 2023 11:20:29 +0100 Subject: [PATCH 23/32] Implement CanProtocol for NeousysBus --- can/interfaces/neousys/neousys.py | 8 +++++--- test/test_neousys.py | 11 ++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/can/interfaces/neousys/neousys.py b/can/interfaces/neousys/neousys.py index 57f947aa4..f83be512a 100644 --- a/can/interfaces/neousys/neousys.py +++ b/can/interfaces/neousys/neousys.py @@ -35,11 +35,13 @@ except ImportError: from ctypes import CDLL -from can import BusABC, Message -from ...exceptions import ( +from can import ( + BusABC, + Message, CanInitializationError, CanOperationError, CanInterfaceNotImplementedError, + CanProtocol, ) @@ -143,7 +145,7 @@ def __init__(self, channel, device=0, bitrate=500000, **kwargs): :param device: device number :param bitrate: bit rate. """ - super().__init__(channel, **kwargs) + super().__init__(channel, protocol=CanProtocol.CAN_20, **kwargs) if NEOUSYS_CANLIB is None: raise CanInterfaceNotImplementedError("Neousys WDT_DIO Can driver missing") diff --git a/test/test_neousys.py b/test/test_neousys.py index 26a220048..cb35e8204 100644 --- a/test/test_neousys.py +++ b/test/test_neousys.py @@ -1,11 +1,6 @@ #!/usr/bin/env python -import ctypes -import os -import pickle import unittest -from unittest.mock import Mock - from ctypes import ( byref, cast, @@ -13,8 +8,7 @@ sizeof, c_ubyte, ) - -import pytest +from unittest.mock import Mock import can from can.interfaces.neousys import neousys @@ -42,6 +36,7 @@ def tearDown(self) -> None: def test_bus_creation(self) -> None: self.assertIsInstance(self.bus, neousys.NeousysBus) + self.assertEqual(self.bus.protocol, can.CanProtocol.CAN_20) self.assertTrue(neousys.NEOUSYS_CANLIB.CAN_Setup.called) self.assertTrue(neousys.NEOUSYS_CANLIB.CAN_Start.called) self.assertTrue(neousys.NEOUSYS_CANLIB.CAN_RegisterReceived.called) @@ -68,6 +63,8 @@ def test_bus_creation(self) -> None: def test_bus_creation_bitrate(self) -> None: self.bus = can.Bus(channel=0, interface="neousys", bitrate=200000) self.assertIsInstance(self.bus, neousys.NeousysBus) + self.assertEqual(self.bus.protocol, can.CanProtocol.CAN_20) + CAN_Start_args = ( can.interfaces.neousys.neousys.NEOUSYS_CANLIB.CAN_Setup.call_args[0] ) From 41b1979edb47e1342ec79908b6d45968051911d4 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sat, 25 Mar 2023 11:21:53 +0100 Subject: [PATCH 24/32] Implement CanProtocol for Usb2canBus --- can/interfaces/usb2can/usb2canInterface.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/can/interfaces/usb2can/usb2canInterface.py b/can/interfaces/usb2can/usb2canInterface.py index 504b61c7b..6f0c74c76 100644 --- a/can/interfaces/usb2can/usb2canInterface.py +++ b/can/interfaces/usb2can/usb2canInterface.py @@ -6,7 +6,7 @@ from ctypes import byref from typing import Optional -from can import BusABC, Message, CanInitializationError, CanOperationError +from can import BusABC, Message, CanInitializationError, CanOperationError, CanProtocol from .usb2canabstractionlayer import Usb2CanAbstractionLayer, CanalMsg, CanalError from .usb2canabstractionlayer import ( IS_ERROR_FRAME, @@ -120,7 +120,7 @@ def __init__( connector = f"{device_id}; {baudrate}" self.handle = self.can.open(connector, flags) - super().__init__(channel=channel, **kwargs) + super().__init__(channel=channel, protocol=CanProtocol.CAN_20, **kwargs) def send(self, msg, timeout=None): tx = message_convert_tx(msg) From eadfa838cbbdc1e224a5e80c02ede6cbabc6d20f Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sat, 25 Mar 2023 11:26:34 +0100 Subject: [PATCH 25/32] Implement CanProtocol for NeoViBus --- can/interfaces/ics_neovi/neovi_bus.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/can/interfaces/ics_neovi/neovi_bus.py b/can/interfaces/ics_neovi/neovi_bus.py index 4972ed479..3b4187300 100644 --- a/can/interfaces/ics_neovi/neovi_bus.py +++ b/can/interfaces/ics_neovi/neovi_bus.py @@ -16,7 +16,7 @@ from threading import Event from warnings import warn -from can import Message, BusABC +from can import Message, BusABC, CanProtocol from ...exceptions import ( CanError, CanTimeoutError, @@ -169,7 +169,14 @@ def __init__(self, channel, can_filters=None, **kwargs): if ics is None: raise ImportError("Please install python-ics") - super().__init__(channel=channel, can_filters=can_filters, **kwargs) + is_fd = kwargs.get("fd", False) + + super().__init__( + channel=channel, + can_filters=can_filters, + protocol=CanProtocol.CAN_FD if is_fd else CanProtocol.CAN_20, + **kwargs, + ) logger.info(f"CAN Filters: {can_filters}") logger.info(f"Got configuration of: {kwargs}") @@ -198,7 +205,7 @@ def __init__(self, channel, can_filters=None, **kwargs): for channel in self.channels: ics.set_bit_rate(self.dev, kwargs.get("bitrate"), channel) - if kwargs.get("fd", False): + if is_fd: if "data_bitrate" in kwargs: for channel in self.channels: ics.set_fd_bit_rate( From 6b53ef405f20162a4a8e5f39b65a170df4ef2e36 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Sun, 2 Apr 2023 19:46:08 +0200 Subject: [PATCH 26/32] Implement CanProtocol for SocketcanBus --- can/interfaces/socketcan/socketcan.py | 9 +++++++-- test/test_socketcan.py | 12 ++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/can/interfaces/socketcan/socketcan.py b/can/interfaces/socketcan/socketcan.py index bdf39f0ab..b82954d68 100644 --- a/can/interfaces/socketcan/socketcan.py +++ b/can/interfaces/socketcan/socketcan.py @@ -30,7 +30,7 @@ import can -from can import BusABC, Message +from can import BusABC, CanProtocol, Message from can.broadcastmanager import ( LimitedDurationCyclicSendTaskABC, ModifiableCyclicTaskABC, @@ -710,7 +710,12 @@ def __init__( "local_loopback": local_loopback, } ) - super().__init__(channel=channel, can_filters=can_filters, **kwargs) + super().__init__( + channel=channel, + can_filters=can_filters, + protocol=CanProtocol.CAN_FD if fd else CanProtocol.CAN_20, + **kwargs, + ) def shutdown(self) -> None: """Stops all active periodic tasks and closes the socket.""" diff --git a/test/test_socketcan.py b/test/test_socketcan.py index 90a143a36..f756cb93a 100644 --- a/test/test_socketcan.py +++ b/test/test_socketcan.py @@ -9,6 +9,8 @@ import warnings from unittest.mock import patch +from .config import TEST_INTERFACE_SOCKETCAN + import can from can.interfaces.socketcan.constants import ( CAN_BCM_TX_DELETE, @@ -357,6 +359,16 @@ def test_build_bcm_update_header(self): self.assertEqual(can_id, result.can_id) self.assertEqual(1, result.nframes) + @unittest.skipUnless(TEST_INTERFACE_SOCKETCAN, "Only run when vcan0 is available") + def test_bus_creation_can(self): + bus = can.Bus(interface="socketcan", channel="vcan0", fd=False) + self.assertEqual(bus.protocol, can.CanProtocol.CAN_20) + + @unittest.skipUnless(TEST_INTERFACE_SOCKETCAN, "Only run when vcan0 is available") + def test_bus_creation_can_fd(self): + bus = can.Bus(interface="socketcan", channel="vcan0", fd=True) + self.assertEqual(bus.protocol, can.CanProtocol.CAN_FD) + @unittest.skipUnless(IS_LINUX and IS_PYPY, "Only test when run on Linux with PyPy") def test_pypy_socketcan_support(self): """Wait for PyPy raw CAN socket support From 5ac9814ee4ca64cd50237df140a0a21eb53657f7 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Tue, 4 Apr 2023 20:57:13 +0200 Subject: [PATCH 27/32] Permit passthrough of protocol field for SocketCanDaemonBus --- can/interfaces/socketcand/socketcand.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/can/interfaces/socketcand/socketcand.py b/can/interfaces/socketcand/socketcand.py index 0c6c06ccf..183a9ba12 100644 --- a/can/interfaces/socketcand/socketcand.py +++ b/can/interfaces/socketcand/socketcand.py @@ -93,7 +93,7 @@ def __init__(self, channel, host, port, can_filters=None, **kwargs): self._expect_msg("< ok >") self._tcp_send(f"< rawmode >") self._expect_msg("< ok >") - super().__init__(channel=channel, can_filters=can_filters) + super().__init__(channel=channel, can_filters=can_filters, **kwargs) def _recv_internal(self, timeout): if len(self.__message_buffer) != 0: From 6914cba36f453ad48d00800d097ea75e647d2a53 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Tue, 4 Apr 2023 20:59:01 +0200 Subject: [PATCH 28/32] Implement CanProtocol for SeeedBus --- can/interfaces/seeedstudio/seeedstudio.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/can/interfaces/seeedstudio/seeedstudio.py b/can/interfaces/seeedstudio/seeedstudio.py index 7d7a1e687..2d78f1f24 100644 --- a/can/interfaces/seeedstudio/seeedstudio.py +++ b/can/interfaces/seeedstudio/seeedstudio.py @@ -12,7 +12,7 @@ from time import time import can -from can import BusABC, Message +from can import BusABC, CanProtocol, Message logger = logging.getLogger("seeedbus") @@ -113,7 +113,7 @@ def __init__( "could not create the serial device" ) from error - super().__init__(channel=channel, *args, **kwargs) + super().__init__(channel=channel, *args, protocol=CanProtocol.CAN_20, **kwargs) self.init_frame() def shutdown(self): From 4fe9aa9137aeaf80c275fbe8602c2490ed3d88d3 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Tue, 9 May 2023 21:17:35 +0200 Subject: [PATCH 29/32] Remove CanProtocol attribute from BusABC constructor The attribute is now set as class attribute with default value and can be overridden in the subclass constructor. --- can/bus.py | 10 +--------- can/interfaces/canalystii.py | 7 +++---- can/interfaces/cantact.py | 2 +- can/interfaces/etas/__init__.py | 8 +++----- can/interfaces/gs_usb.py | 2 +- can/interfaces/ics_neovi/neovi_bus.py | 6 +++--- can/interfaces/iscan.py | 2 +- can/interfaces/ixxat/canlib.py | 3 ++- can/interfaces/ixxat/canlib_vcinpl.py | 5 ++--- can/interfaces/ixxat/canlib_vcinpl2.py | 5 ++--- can/interfaces/kvaser/canlib.py | 6 +++--- can/interfaces/neousys/neousys.py | 3 ++- can/interfaces/nican.py | 2 +- can/interfaces/nixnet.py | 2 +- can/interfaces/pcan/pcan.py | 4 ++-- can/interfaces/robotell.py | 3 ++- can/interfaces/seeedstudio/seeedstudio.py | 4 +++- can/interfaces/serial/serial_can.py | 3 ++- can/interfaces/slcan.py | 2 +- can/interfaces/socketcan/socketcan.py | 2 +- can/interfaces/systec/ucanbus.py | 3 ++- can/interfaces/udp_multicast/bus.py | 2 +- can/interfaces/usb2can/usb2canInterface.py | 3 ++- can/interfaces/vector/canlib.py | 4 ++-- can/interfaces/virtual.py | 2 +- 25 files changed, 45 insertions(+), 50 deletions(-) diff --git a/can/bus.py b/can/bus.py index b731b98a8..b7a54dbb1 100644 --- a/can/bus.py +++ b/can/bus.py @@ -52,12 +52,12 @@ class BusABC(metaclass=ABCMeta): RECV_LOGGING_LEVEL = 9 _is_shutdown: bool = False + _can_protocol: CanProtocol = CanProtocol.CAN_20 @abstractmethod def __init__( self, channel: Any, - protocol: CanProtocol = CanProtocol.CAN_20, can_filters: Optional[can.typechecking.CanFilters] = None, **kwargs: object, ): @@ -69,13 +69,6 @@ def __init__( :param channel: The can interface identifier. Expected type is backend dependent. - :param protocol: - The CAN protocol currently used by this bus instance. This value - is determined at initialization time (based on the initialization - parameters or because the bus interface only supports a specific - protocol) and does not change during the lifetime of a bus - instance. - :param can_filters: See :meth:`~can.BusABC.set_filters` for details. @@ -88,7 +81,6 @@ def __init__( :raises ~can.exceptions.CanInitializationError: If the bus cannot be initialized """ - self._can_protocol = protocol self._periodic_tasks: List[_SelfRemovingCyclicTask] = [] self.set_filters(can_filters) diff --git a/can/interfaces/canalystii.py b/can/interfaces/canalystii.py index 9f596f042..2fef19497 100644 --- a/can/interfaces/canalystii.py +++ b/can/interfaces/canalystii.py @@ -57,7 +57,6 @@ def __init__( super().__init__( channel=channel, can_filters=can_filters, - protocol=CanProtocol.CAN_20, **kwargs, ) if isinstance(channel, str): @@ -68,11 +67,11 @@ def __init__( else: # Sequence[int] self.channels = list(channel) - self.rx_queue: Deque[Tuple[int, driver.Message]] = deque(maxlen=rx_queue_size) - self.channel_info = f"CANalyst-II: device {device}, channels {self.channels}" - + self.rx_queue: Deque[Tuple[int, driver.Message]] = deque(maxlen=rx_queue_size) self.device = driver.CanalystDevice(device_index=device) + self._can_protocol = CanProtocol.CAN_20 + for single_channel in self.channels: if isinstance(timing, BitTiming): timing = check_or_adjust_timing_clock(timing, valid_clocks=[8_000_000]) diff --git a/can/interfaces/cantact.py b/can/interfaces/cantact.py index cb17c0f50..963a9ee3b 100644 --- a/can/interfaces/cantact.py +++ b/can/interfaces/cantact.py @@ -87,6 +87,7 @@ def __init__( self.channel = int(channel) self.channel_info = f"CANtact: ch:{channel}" + self._can_protocol = CanProtocol.CAN_20 # Configure the interface with error_check("Cannot setup the cantact.Interface", CanInitializationError): @@ -117,7 +118,6 @@ def __init__( channel=channel, bitrate=bitrate, poll_interval=poll_interval, - protocol=CanProtocol.CAN_20, **kwargs, ) diff --git a/can/interfaces/etas/__init__.py b/can/interfaces/etas/__init__.py index 6eac6bf4f..62e060f48 100644 --- a/can/interfaces/etas/__init__.py +++ b/can/interfaces/etas/__init__.py @@ -16,14 +16,12 @@ def __init__( bitrate: int = 1000000, fd: bool = True, data_bitrate: int = 2000000, - **kwargs: object, + **kwargs: Dict[str, any], ): - super().__init__( - channel=channel, - protocol=can.CanProtocol.CAN_FD if fd else can.CanProtocol.CAN_20, - ) + super().__init__(channel=channel, **kwargs) self.receive_own_messages = receive_own_messages + self._can_protocol = can.CanProtocol.CAN_FD if fd else can.CanProtocol.CAN_20 nodeRange = CSI_NodeRange(CSI_NODE_MIN, CSI_NODE_MAX) self.tree = ctypes.POINTER(CSI_Tree)() diff --git a/can/interfaces/gs_usb.py b/can/interfaces/gs_usb.py index 3171752c7..32ad54e75 100644 --- a/can/interfaces/gs_usb.py +++ b/can/interfaces/gs_usb.py @@ -52,6 +52,7 @@ def __init__( self.gs_usb = gs_usb self.channel_info = channel + self._can_protocol = can.CanProtocol.CAN_20 self.gs_usb.set_bitrate(bitrate) self.gs_usb.start() @@ -59,7 +60,6 @@ def __init__( super().__init__( channel=channel, can_filters=can_filters, - protocol=can.CanProtocol.CAN_20, **kwargs, ) diff --git a/can/interfaces/ics_neovi/neovi_bus.py b/can/interfaces/ics_neovi/neovi_bus.py index e8822b178..f2dffe0a6 100644 --- a/can/interfaces/ics_neovi/neovi_bus.py +++ b/can/interfaces/ics_neovi/neovi_bus.py @@ -169,12 +169,9 @@ def __init__(self, channel, can_filters=None, **kwargs): if ics is None: raise ImportError("Please install python-ics") - is_fd = kwargs.get("fd", False) - super().__init__( channel=channel, can_filters=can_filters, - protocol=CanProtocol.CAN_FD if is_fd else CanProtocol.CAN_20, **kwargs, ) @@ -197,6 +194,9 @@ def __init__(self, channel, can_filters=None, **kwargs): serial = kwargs.get("serial") self.dev = self._find_device(type_filter, serial) + is_fd = kwargs.get("fd", False) + self._can_protocol = CanProtocol.CAN_FD if is_fd else CanProtocol.CAN_20 + with open_lock: ics.open_device(self.dev) diff --git a/can/interfaces/iscan.py b/can/interfaces/iscan.py index 259901fda..be0b0dae8 100644 --- a/can/interfaces/iscan.py +++ b/can/interfaces/iscan.py @@ -100,6 +100,7 @@ def __init__( self.channel = ctypes.c_ubyte(int(channel)) self.channel_info = f"IS-CAN: {self.channel}" + self._can_protocol = CanProtocol.CAN_20 if bitrate not in self.BAUDRATES: raise ValueError(f"Invalid bitrate, choose one of {set(self.BAUDRATES)}") @@ -111,7 +112,6 @@ def __init__( channel=channel, bitrate=bitrate, poll_interval=poll_interval, - protocol=CanProtocol.CAN_20, **kwargs, ) diff --git a/can/interfaces/ixxat/canlib.py b/can/interfaces/ixxat/canlib.py index 479fcb6c3..b28c93541 100644 --- a/can/interfaces/ixxat/canlib.py +++ b/can/interfaces/ixxat/canlib.py @@ -131,7 +131,8 @@ def __init__( **kwargs ) - super().__init__(channel=channel, protocol=self.bus.protocol) + super().__init__(channel=channel, **kwargs) + self._can_protocol = self.bus.protocol def flush_tx_buffer(self): """Flushes the transmit buffer on the IXXAT""" diff --git a/can/interfaces/ixxat/canlib_vcinpl.py b/can/interfaces/ixxat/canlib_vcinpl.py index c37c63cbc..5a366cc30 100644 --- a/can/interfaces/ixxat/canlib_vcinpl.py +++ b/can/interfaces/ixxat/canlib_vcinpl.py @@ -490,6 +490,7 @@ def __init__( self._channel_capabilities = structures.CANCAPABILITIES() self._message = structures.CANMSG() self._payload = (ctypes.c_byte * 8)() + self._can_protocol = CanProtocol.CAN_20 # Search for supplied device if unique_hardware_id is None: @@ -632,9 +633,7 @@ def __init__( except (VCITimeout, VCIRxQueueEmptyError): break - super().__init__( - channel=channel, can_filters=None, protocol=CanProtocol.CAN_20, **kwargs - ) + super().__init__(channel=channel, can_filters=None, **kwargs) def _inWaiting(self): try: diff --git a/can/interfaces/ixxat/canlib_vcinpl2.py b/can/interfaces/ixxat/canlib_vcinpl2.py index 11f9512c3..446b3e35c 100644 --- a/can/interfaces/ixxat/canlib_vcinpl2.py +++ b/can/interfaces/ixxat/canlib_vcinpl2.py @@ -535,6 +535,7 @@ def __init__( self._channel_capabilities = structures.CANCAPABILITIES2() self._message = structures.CANMSG2() self._payload = (ctypes.c_byte * 64)() + self._can_protocol = CanProtocol.CAN_FD # Search for supplied device if unique_hardware_id is None: @@ -741,9 +742,7 @@ def __init__( except (VCITimeout, VCIRxQueueEmptyError): break - super().__init__( - channel=channel, can_filters=None, protocol=CanProtocol.CAN_FD, **kwargs - ) + super().__init__(channel=channel, can_filters=None, **kwargs) @staticmethod def _canptb_build(defaults, bitrate, tseg1, tseg2, sjw, ssp): diff --git a/can/interfaces/kvaser/canlib.py b/can/interfaces/kvaser/canlib.py index f8ac201b7..32d28059a 100644 --- a/can/interfaces/kvaser/canlib.py +++ b/can/interfaces/kvaser/canlib.py @@ -428,11 +428,12 @@ def __init__(self, channel, can_filters=None, **kwargs): channel = int(channel) except ValueError: raise ValueError("channel must be an integer") - self.channel = channel - log.debug("Initialising bus instance") + self.channel = channel self.single_handle = single_handle + self._can_protocol = CanProtocol.CAN_FD if fd else CanProtocol.CAN_20 + log.debug("Initialising bus instance") num_channels = ctypes.c_int(0) canGetNumberOfChannels(ctypes.byref(num_channels)) num_channels = int(num_channels.value) @@ -523,7 +524,6 @@ def __init__(self, channel, can_filters=None, **kwargs): super().__init__( channel=channel, can_filters=can_filters, - protocol=CanProtocol.CAN_FD if fd else CanProtocol.CAN_20, **kwargs, ) diff --git a/can/interfaces/neousys/neousys.py b/can/interfaces/neousys/neousys.py index bb374d290..b7dd2117c 100644 --- a/can/interfaces/neousys/neousys.py +++ b/can/interfaces/neousys/neousys.py @@ -143,7 +143,7 @@ def __init__(self, channel, device=0, bitrate=500000, **kwargs): :param device: device number :param bitrate: bit rate. """ - super().__init__(channel, protocol=CanProtocol.CAN_20, **kwargs) + super().__init__(channel, **kwargs) if NEOUSYS_CANLIB is None: raise CanInterfaceNotImplementedError("Neousys WDT_DIO Can driver missing") @@ -151,6 +151,7 @@ def __init__(self, channel, device=0, bitrate=500000, **kwargs): self.channel = channel self.device = device self.channel_info = f"Neousys Can: device {self.device}, channel {self.channel}" + self._can_protocol = CanProtocol.CAN_20 self.queue = queue.Queue() diff --git a/can/interfaces/nican.py b/can/interfaces/nican.py index 1638e1b75..f4b1a37f0 100644 --- a/can/interfaces/nican.py +++ b/can/interfaces/nican.py @@ -220,6 +220,7 @@ def __init__( self.channel = channel self.channel_info = f"NI-CAN: {channel}" + self._can_protocol = CanProtocol.CAN_20 channel_bytes = channel.encode("ascii") config = [(NC_ATTR_START_ON_OPEN, True), (NC_ATTR_LOG_COMM_ERRS, log_errors)] @@ -275,7 +276,6 @@ def __init__( can_filters=can_filters, bitrate=bitrate, log_errors=log_errors, - protocol=CanProtocol.CAN_20, **kwargs, ) diff --git a/can/interfaces/nixnet.py b/can/interfaces/nixnet.py index adc821cb1..24d09c3a0 100644 --- a/can/interfaces/nixnet.py +++ b/can/interfaces/nixnet.py @@ -105,6 +105,7 @@ def __init__( self.poll_interval = poll_interval is_fd = isinstance(timing, BitTimingFd) if timing else fd + self._can_protocol = CanProtocol.CAN_FD if is_fd else CanProtocol.CAN_20 # Set database for the initialization database_name = ":can_fd_brs:" if is_fd else ":memory:" @@ -186,7 +187,6 @@ def __init__( channel=channel, can_filters=can_filters, bitrate=bitrate, - protocol=CanProtocol.CAN_FD if is_fd else CanProtocol.CAN_20, **kwargs, ) diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index 8c669e192..ed7e35f2a 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -246,8 +246,9 @@ def __init__( err_msg = f"Cannot find a channel with ID {device_id:08x}" raise ValueError(err_msg) - self.channel_info = str(channel) is_fd = isinstance(timing, BitTimingFd) if timing else kwargs.get("fd", False) + self._can_protocol = CanProtocol.CAN_FD if is_fd else CanProtocol.CAN_20 + self.channel_info = str(channel) hwtype = PCAN_TYPE_ISA ioport = 0x02A0 @@ -340,7 +341,6 @@ def __init__( super().__init__( channel=channel, - protocol=CanProtocol.CAN_FD if is_fd else CanProtocol.CAN_20, state=state, bitrate=bitrate, **kwargs, diff --git a/can/interfaces/robotell.py b/can/interfaces/robotell.py index 323b206a5..bfe8f5774 100644 --- a/can/interfaces/robotell.py +++ b/can/interfaces/robotell.py @@ -92,12 +92,13 @@ def __init__( if bitrate is not None: self.set_bitrate(bitrate) + self._can_protocol = CanProtocol.CAN_20 self.channel_info = ( f"Robotell USB-CAN s/n {self.get_serial_number(1)} on {channel}" ) logger.info("Using device: %s", self.channel_info) - super().__init__(channel=channel, protocol=CanProtocol.CAN_20, **kwargs) + super().__init__(channel=channel, **kwargs) def set_bitrate(self, bitrate): """ diff --git a/can/interfaces/seeedstudio/seeedstudio.py b/can/interfaces/seeedstudio/seeedstudio.py index 2d78f1f24..0540c78be 100644 --- a/can/interfaces/seeedstudio/seeedstudio.py +++ b/can/interfaces/seeedstudio/seeedstudio.py @@ -100,6 +100,8 @@ def __init__( self.op_mode = operation_mode self.filter_id = bytearray([0x00, 0x00, 0x00, 0x00]) self.mask_id = bytearray([0x00, 0x00, 0x00, 0x00]) + self._can_protocol = CanProtocol.CAN_20 + if not channel: raise can.CanInitializationError("Must specify a serial port.") @@ -113,7 +115,7 @@ def __init__( "could not create the serial device" ) from error - super().__init__(channel=channel, *args, protocol=CanProtocol.CAN_20, **kwargs) + super().__init__(channel=channel, *args, **kwargs) self.init_frame() def shutdown(self): diff --git a/can/interfaces/serial/serial_can.py b/can/interfaces/serial/serial_can.py index 40af54132..9de2da99c 100644 --- a/can/interfaces/serial/serial_can.py +++ b/can/interfaces/serial/serial_can.py @@ -89,6 +89,7 @@ def __init__( raise TypeError("Must specify a serial port.") self.channel_info = f"Serial interface: {channel}" + self._can_protocol = CanProtocol.CAN_20 try: self._ser = serial.serial_for_url( @@ -99,7 +100,7 @@ def __init__( "could not create the serial device" ) from error - super().__init__(channel, protocol=CanProtocol.CAN_20, *args, **kwargs) + super().__init__(channel, *args, **kwargs) def shutdown(self) -> None: """ diff --git a/can/interfaces/slcan.py b/can/interfaces/slcan.py index bb7955262..7ff12ce44 100644 --- a/can/interfaces/slcan.py +++ b/can/interfaces/slcan.py @@ -105,6 +105,7 @@ def __init__( ) self._buffer = bytearray() + self._can_protocol = CanProtocol.CAN_20 time.sleep(sleep_after_open) @@ -122,7 +123,6 @@ def __init__( ttyBaudrate=115200, bitrate=None, rtscts=False, - protocol=CanProtocol.CAN_20, **kwargs, ) diff --git a/can/interfaces/socketcan/socketcan.py b/can/interfaces/socketcan/socketcan.py index b82954d68..a3f74bb82 100644 --- a/can/interfaces/socketcan/socketcan.py +++ b/can/interfaces/socketcan/socketcan.py @@ -656,6 +656,7 @@ def __init__( self._is_filtered = False self._task_id = 0 self._task_id_guard = threading.Lock() + self._can_protocol = CanProtocol.CAN_FD if fd else CanProtocol.CAN_20 # set the local_loopback parameter try: @@ -713,7 +714,6 @@ def __init__( super().__init__( channel=channel, can_filters=can_filters, - protocol=CanProtocol.CAN_FD if fd else CanProtocol.CAN_20, **kwargs, ) diff --git a/can/interfaces/systec/ucanbus.py b/can/interfaces/systec/ucanbus.py index 67be94d47..cb0dcc39e 100644 --- a/can/interfaces/systec/ucanbus.py +++ b/can/interfaces/systec/ucanbus.py @@ -111,6 +111,8 @@ def __init__(self, channel, can_filters=None, **kwargs): ) from exception self.channel = int(channel) + self._can_protocol = CanProtocol.CAN_20 + device_number = int(kwargs.get("device_number", ANY_MODULE)) # configuration options @@ -155,7 +157,6 @@ def __init__(self, channel, can_filters=None, **kwargs): super().__init__( channel=channel, can_filters=can_filters, - protocol=CanProtocol.CAN_20, **kwargs, ) diff --git a/can/interfaces/udp_multicast/bus.py b/can/interfaces/udp_multicast/bus.py index 4f4410a35..ea0b4232a 100644 --- a/can/interfaces/udp_multicast/bus.py +++ b/can/interfaces/udp_multicast/bus.py @@ -107,10 +107,10 @@ def __init__( super().__init__( channel, **kwargs, - protocol=CanProtocol.CAN_FD if fd else CanProtocol.CAN_20, ) self._multicast = GeneralPurposeUdpMulticastBus(channel, port, hop_limit) + self._can_protocol = CanProtocol.CAN_FD if fd else CanProtocol.CAN_20 @property def is_fd(self) -> bool: diff --git a/can/interfaces/usb2can/usb2canInterface.py b/can/interfaces/usb2can/usb2canInterface.py index 27f89434c..c89e394df 100644 --- a/can/interfaces/usb2can/usb2canInterface.py +++ b/can/interfaces/usb2can/usb2canInterface.py @@ -118,11 +118,12 @@ def __init__( baudrate = min(int(bitrate // 1000), 1000) self.channel_info = f"USB2CAN device {device_id}" + self._can_protocol = CanProtocol.CAN_20 connector = f"{device_id}; {baudrate}" self.handle = self.can.open(connector, flags) - super().__init__(channel=channel, protocol=CanProtocol.CAN_20, **kwargs) + super().__init__(channel=channel, **kwargs) def send(self, msg, timeout=None): tx = message_convert_tx(msg) diff --git a/can/interfaces/vector/canlib.py b/can/interfaces/vector/canlib.py index 62e252f78..05d4f27bd 100644 --- a/can/interfaces/vector/canlib.py +++ b/can/interfaces/vector/canlib.py @@ -204,11 +204,12 @@ def __init__( ) channel_configs = get_channel_configs() + is_fd = isinstance(timing, BitTimingFd) if timing else fd self.mask = 0 - is_fd = isinstance(timing, BitTimingFd) if timing else fd self.channel_masks: Dict[int, int] = {} self.index_to_channel: Dict[int, int] = {} + self._can_protocol = CanProtocol.CAN_FD if is_fd else CanProtocol.CAN_20 for channel in self.channels: channel_index = self._find_global_channel_idx( @@ -329,7 +330,6 @@ def __init__( super().__init__( channel=channel, can_filters=can_filters, - protocol=CanProtocol.CAN_FD if is_fd else CanProtocol.CAN_20, **kwargs, ) diff --git a/can/interfaces/virtual.py b/can/interfaces/virtual.py index be448e863..62ad0cfe3 100644 --- a/can/interfaces/virtual.py +++ b/can/interfaces/virtual.py @@ -95,12 +95,12 @@ def __init__( super().__init__( channel=channel, receive_own_messages=receive_own_messages, - protocol=protocol, **kwargs, ) # the channel identifier may be an arbitrary object self.channel_id = channel + self._can_protocol = protocol self.channel_info = f"Virtual bus channel {self.channel_id}" self.receive_own_messages = receive_own_messages self.preserve_timestamps = preserve_timestamps From 7541cd5f64be3ab10862ed7fe1d6677ea061e9f0 Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Fri, 12 May 2023 07:17:02 +0200 Subject: [PATCH 30/32] Apply suggestions from code review Fix property access and enum comparison Co-authored-by: zariiii9003 <52598363+zariiii9003@users.noreply.github.com> --- can/interfaces/pcan/pcan.py | 6 +++--- can/interfaces/udp_multicast/bus.py | 4 ++-- can/interfaces/vector/canlib.py | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index ed7e35f2a..e6677b1fe 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -490,7 +490,7 @@ def _recv_internal( end_time = time.time() + timeout if timeout is not None else None while True: - if self.protocol == CanProtocol.CAN_FD: + if self._can_protocol is CanProtocol.CAN_FD: result, pcan_msg, pcan_timestamp = self.m_objPCANBasic.ReadFD( self.m_PcanHandle ) @@ -552,7 +552,7 @@ def _recv_internal( error_state_indicator = bool(pcan_msg.MSGTYPE & PCAN_MESSAGE_ESI.value) is_error_frame = bool(pcan_msg.MSGTYPE & PCAN_MESSAGE_ERRFRAME.value) - if self.protocol == CanProtocol.CAN_FD: + if self._can_protocol is CanProtocol.CAN_FD: dlc = dlc2len(pcan_msg.DLC) timestamp = boottimeEpoch + (pcan_timestamp.value / (1000.0 * 1000.0)) else: @@ -598,7 +598,7 @@ def send(self, msg, timeout=None): if msg.error_state_indicator: msgType |= PCAN_MESSAGE_ESI.value - if self.protocol == CanProtocol.CAN_FD: + if self._can_protocol is CanProtocol.CAN_FD: # create a TPCANMsg message structure CANMsg = TPCANMsgFD() diff --git a/can/interfaces/udp_multicast/bus.py b/can/interfaces/udp_multicast/bus.py index ea0b4232a..8064f8183 100644 --- a/can/interfaces/udp_multicast/bus.py +++ b/can/interfaces/udp_multicast/bus.py @@ -136,13 +136,13 @@ def _recv_internal(self, timeout: Optional[float]): "could not unpack received message" ) from exception - if self.protocol != CanProtocol.CAN_FD and can_message.is_fd: + if self._can_protocol is not CanProtocol.CAN_FD and can_message.is_fd: return None, False return can_message, False def send(self, msg: can.Message, timeout: Optional[float] = None) -> None: - if self.protocol != CanProtocol.CAN_FD and msg.is_fd: + if self._can_protocol is not CanProtocol.CAN_FD: and msg.is_fd: raise can.CanOperationError( "cannot send FD message over bus with CAN FD disabled" ) diff --git a/can/interfaces/vector/canlib.py b/can/interfaces/vector/canlib.py index 05d4f27bd..d819db272 100644 --- a/can/interfaces/vector/canlib.py +++ b/can/interfaces/vector/canlib.py @@ -663,7 +663,7 @@ def _recv_internal( while True: try: - if self.protocol == CanProtocol.CAN_FD: + if self._can_protocol is CanProtocol.CAN_FD: msg = self._recv_canfd() else: msg = self._recv_can() @@ -797,7 +797,7 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None: def _send_sequence(self, msgs: Sequence[Message]) -> int: """Send messages and return number of successful transmissions.""" - if self.protocol == CanProtocol.CAN_FD: + if self._can_protocol is CanProtocol.CAN_FD: return self._send_can_fd_msg_sequence(msgs) else: return self._send_can_msg_sequence(msgs) From 05007993308d2018c89bf63a7508b54dbd7e063a Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Fri, 12 May 2023 07:18:57 +0200 Subject: [PATCH 31/32] Fix syntax error --- can/interfaces/udp_multicast/bus.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/can/interfaces/udp_multicast/bus.py b/can/interfaces/udp_multicast/bus.py index 8064f8183..8354a3b86 100644 --- a/can/interfaces/udp_multicast/bus.py +++ b/can/interfaces/udp_multicast/bus.py @@ -142,7 +142,7 @@ def _recv_internal(self, timeout: Optional[float]): return can_message, False def send(self, msg: can.Message, timeout: Optional[float] = None) -> None: - if self._can_protocol is not CanProtocol.CAN_FD: and msg.is_fd: + if self._can_protocol is not CanProtocol.CAN_FD and msg.is_fd: raise can.CanOperationError( "cannot send FD message over bus with CAN FD disabled" ) From 3047263ea61242f6c5f354a3355d168b0320f15f Mon Sep 17 00:00:00 2001 From: Lukas Magel Date: Fri, 12 May 2023 07:21:46 +0200 Subject: [PATCH 32/32] Fix more enum comparisons against BusABC.protocol --- can/interfaces/nixnet.py | 2 +- can/interfaces/pcan/pcan.py | 2 +- can/interfaces/udp_multicast/bus.py | 2 +- can/interfaces/vector/canlib.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/can/interfaces/nixnet.py b/can/interfaces/nixnet.py index 24d09c3a0..ba665442e 100644 --- a/can/interfaces/nixnet.py +++ b/can/interfaces/nixnet.py @@ -197,7 +197,7 @@ def fd(self) -> bool: "BusABC.protocol. It is scheduled for removal in version 5.0.", DeprecationWarning, ) - return self.protocol == CanProtocol.CAN_FD + return self._can_protocol is CanProtocol.CAN_FD def _recv_internal( self, timeout: Optional[float] diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index e6677b1fe..a9b2c016b 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -664,7 +664,7 @@ def fd(self) -> bool: "It is scheduled for removal in version 5.0.", DeprecationWarning, ) - return self.protocol == CanProtocol.CAN_FD + return self._can_protocol is CanProtocol.CAN_FD @property def state(self): diff --git a/can/interfaces/udp_multicast/bus.py b/can/interfaces/udp_multicast/bus.py index 8354a3b86..089b8182f 100644 --- a/can/interfaces/udp_multicast/bus.py +++ b/can/interfaces/udp_multicast/bus.py @@ -119,7 +119,7 @@ def is_fd(self) -> bool: "BusABC.protocol. It is scheduled for removal in version 5.0.", DeprecationWarning, ) - return self.protocol == CanProtocol.CAN_FD + return self._can_protocol is CanProtocol.CAN_FD def _recv_internal(self, timeout: Optional[float]): result = self._multicast.recv(timeout) diff --git a/can/interfaces/vector/canlib.py b/can/interfaces/vector/canlib.py index d819db272..f852fb0ec 100644 --- a/can/interfaces/vector/canlib.py +++ b/can/interfaces/vector/canlib.py @@ -340,7 +340,7 @@ def fd(self) -> bool: "BusABC.protocol. It is scheduled for removal in version 5.0.", DeprecationWarning, ) - return self.protocol == CanProtocol.CAN_FD + return self._can_protocol is CanProtocol.CAN_FD def _find_global_channel_idx( self,