From acb7acdb585f87d3ee1628d6861431abe57abd7e Mon Sep 17 00:00:00 2001 From: Varun Penumudi Date: Wed, 15 Oct 2025 08:04:14 +0530 Subject: [PATCH 1/4] Added hardware filter support for SeeedBus during initialization --- can/interfaces/seeedstudio/seeedstudio.py | 23 +++++++++++++++++++++-- doc/changelog.d/1995.added.md | 1 + doc/interfaces/seeedstudio.rst | 18 +++++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 doc/changelog.d/1995.added.md diff --git a/can/interfaces/seeedstudio/seeedstudio.py b/can/interfaces/seeedstudio/seeedstudio.py index a0817e932..1d3c40294 100644 --- a/can/interfaces/seeedstudio/seeedstudio.py +++ b/can/interfaces/seeedstudio/seeedstudio.py @@ -63,6 +63,7 @@ def __init__( frame_type="STD", operation_mode="normal", bitrate=500000, + can_filters=None, **kwargs, ): """ @@ -85,6 +86,12 @@ def __init__( :param bitrate CAN bus bit rate, selected from available list. + :param can_filters: + A list of CAN filter dictionaries, where each dictionary contains + the keys 'can_id' and 'can_mask'. For the SeeedBus interface, + this list must not contain more than one filter. Defaults to None + (i.e., no filter). + :raises can.CanInitializationError: If the given parameters are invalid. :raises can.CanInterfaceNotImplementedError: If the serial module is not installed. """ @@ -94,11 +101,23 @@ def __init__( "the serial module is not installed" ) + if can_filters is None: + can_filters = [{"can_id": 0x00, "can_mask": 0x00}] + + if len(can_filters) > 1: + raise can.CanInitializationError( + f"The SeeedBus interface only supports one hardware filter, " + f"but {len(can_filters)} were provided." + ) + + # Get the first (and only) filter in can_filters + hw_filter = can_filters[0] + self.bit_rate = bitrate self.frame_type = frame_type self.op_mode = operation_mode - self.filter_id = bytearray([0x00, 0x00, 0x00, 0x00]) - self.mask_id = bytearray([0x00, 0x00, 0x00, 0x00]) + self.filter_id = struct.pack(" Date: Sun, 19 Oct 2025 13:47:13 +0530 Subject: [PATCH 2/4] Implement software fallback for can_filters in SeedBus - Updated the __init__ function in SeedBus - Implemented software fallback, if the user passes multiple filters in can_filters dict. --- can/interfaces/seeedstudio/seeedstudio.py | 30 ++++++++++------------- doc/interfaces/seeedstudio.rst | 7 +++--- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/can/interfaces/seeedstudio/seeedstudio.py b/can/interfaces/seeedstudio/seeedstudio.py index 1d3c40294..99b6ad8b9 100644 --- a/can/interfaces/seeedstudio/seeedstudio.py +++ b/can/interfaces/seeedstudio/seeedstudio.py @@ -87,10 +87,10 @@ def __init__( CAN bus bit rate, selected from available list. :param can_filters: - A list of CAN filter dictionaries, where each dictionary contains - the keys 'can_id' and 'can_mask'. For the SeeedBus interface, - this list must not contain more than one filter. Defaults to None - (i.e., no filter). + A list of CAN filter dictionaries. If one filter is provided, + it will be used by the high-performance hardware filter. If + zero or more than one filter is provided, software-based + filtering will be used. Defaults to None (no filtering). :raises can.CanInitializationError: If the given parameters are invalid. :raises can.CanInterfaceNotImplementedError: If the serial module is not installed. @@ -101,23 +101,19 @@ def __init__( "the serial module is not installed" ) - if can_filters is None: - can_filters = [{"can_id": 0x00, "can_mask": 0x00}] + can_id = 0x00 + can_mask = 0x00 - if len(can_filters) > 1: - raise can.CanInitializationError( - f"The SeeedBus interface only supports one hardware filter, " - f"but {len(can_filters)} were provided." - ) - - # Get the first (and only) filter in can_filters - hw_filter = can_filters[0] + if can_filters and len(can_filters) == 1: + hw_filter = can_filters[0] + can_id = hw_filter["can_id"] + can_mask = hw_filter["can_mask"] self.bit_rate = bitrate self.frame_type = frame_type self.op_mode = operation_mode - self.filter_id = struct.pack(" Date: Mon, 20 Oct 2025 08:42:40 +0530 Subject: [PATCH 3/4] updated changelog for PR #1999 --- doc/changelog.d/1995.added.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/changelog.d/1995.added.md b/doc/changelog.d/1995.added.md index 61952442d..81e39d0df 100644 --- a/doc/changelog.d/1995.added.md +++ b/doc/changelog.d/1995.added.md @@ -1 +1 @@ -Added hardware filter support for SeeedBus during initialization. \ No newline at end of file +Added hardware filter support for SeeedBus during initialization, with a software fallback. \ No newline at end of file From f767340f80661ecdf13f24f5db454b6f391fd113 Mon Sep 17 00:00:00 2001 From: Varun Penumudi Date: Mon, 20 Oct 2025 18:34:20 +0530 Subject: [PATCH 4/4] Updated _recv_internal method of SeedBus - updated _recv_internal method of SeedBus to return also the Boolean value based on whether hw filter is enabled or not --- can/interfaces/seeedstudio/seeedstudio.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/can/interfaces/seeedstudio/seeedstudio.py b/can/interfaces/seeedstudio/seeedstudio.py index 99b6ad8b9..26339616c 100644 --- a/can/interfaces/seeedstudio/seeedstudio.py +++ b/can/interfaces/seeedstudio/seeedstudio.py @@ -103,8 +103,10 @@ def __init__( can_id = 0x00 can_mask = 0x00 + self._is_filtered = False if can_filters and len(can_filters) == 1: + self._is_filtered = True hw_filter = can_filters[0] can_id = hw_filter["can_id"] can_mask = hw_filter["can_mask"] @@ -252,8 +254,9 @@ def _recv_internal(self, timeout): This parameter will be ignored. The timeout value of the channel is used. - :returns: - Received message and False (because not filtering as taken place). + :return: + 1. a message that was read or None on timeout + 2. a bool that is True if hw_filter is enabled, else False :rtype: can.Message, bool @@ -266,7 +269,7 @@ def _recv_internal(self, timeout): except serial.PortNotOpenError as error: raise can.CanOperationError("reading from closed port") from error except serial.SerialException: - return None, False + return None, self._is_filtered if rx_byte_1 and ord(rx_byte_1) == 0xAA: try: @@ -302,10 +305,10 @@ def _recv_internal(self, timeout): data=data, ) logger.debug("recv message: %s", str(msg)) - return msg, False + return msg, self._is_filtered else: - return None, False + return None, self._is_filtered except serial.PortNotOpenError as error: raise can.CanOperationError("reading from closed port") from error @@ -314,7 +317,7 @@ def _recv_internal(self, timeout): "failed to read message information" ) from error - return None, None + return None, self._is_filtered def fileno(self): try: