From 42f66c67fadc45831434e232a098e67164658a05 Mon Sep 17 00:00:00 2001 From: Claudio Lima Date: Fri, 10 Jan 2025 13:47:39 -0300 Subject: [PATCH 1/6] Update canlib.py --- can/interfaces/vector/canlib.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/can/interfaces/vector/canlib.py b/can/interfaces/vector/canlib.py index d307d076f..1e658a558 100644 --- a/can/interfaces/vector/canlib.py +++ b/can/interfaces/vector/canlib.py @@ -874,6 +874,7 @@ def _send_can_msg_sequence(self, msgs: Sequence[Message]) -> int: self.xldriver.xlCanTransmit( self.port_handle, mask, message_count, xl_event_array ) + time.sleep(500e-6) return message_count.value @staticmethod @@ -908,6 +909,7 @@ def _send_can_fd_msg_sequence(self, msgs: Sequence[Message]) -> int: self.xldriver.xlCanTransmitEx( self.port_handle, mask, message_count, msg_count_sent, xl_can_tx_event_array ) + time.sleep(500e-6) return msg_count_sent.value @staticmethod From 0a4cb3de5966bc653a9d075bbd9043175641d91c Mon Sep 17 00:00:00 2001 From: Claudio Lima Date: Fri, 10 Jan 2025 13:49:41 -0300 Subject: [PATCH 2/6] Update pcan.py --- can/interfaces/pcan/pcan.py | 1 + 1 file changed, 1 insertion(+) diff --git a/can/interfaces/pcan/pcan.py b/can/interfaces/pcan/pcan.py index d0372a83c..6cc72924a 100644 --- a/can/interfaces/pcan/pcan.py +++ b/can/interfaces/pcan/pcan.py @@ -662,6 +662,7 @@ def send(self, msg, timeout=None): raise PcanCanOperationError( "Failed to send: " + self._get_formatted_error(result) ) + time.sleep(500e-6) def flash(self, flash): """ From 257f36f5ef4f31572829ee6231670cc36edb5776 Mon Sep 17 00:00:00 2001 From: Claudio Lima Date: Fri, 10 Jan 2025 13:53:06 -0300 Subject: [PATCH 3/6] Update usb2canInterface.py --- can/interfaces/usb2can/usb2canInterface.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/can/interfaces/usb2can/usb2canInterface.py b/can/interfaces/usb2can/usb2canInterface.py index adc16e8b3..1be06083c 100644 --- a/can/interfaces/usb2can/usb2canInterface.py +++ b/can/interfaces/usb2can/usb2canInterface.py @@ -3,6 +3,7 @@ """ import logging +import time from ctypes import byref from typing import Optional, Union @@ -163,6 +164,7 @@ def send(self, msg, timeout=None): status = self.can.blocking_send(self.handle, byref(tx), int(timeout * 1000)) else: status = self.can.send(self.handle, byref(tx)) + time.sleep(500e-6) if status != CanalError.SUCCESS: raise CanOperationError("could not send message", error_code=status) From 8930e8c6882a55801469646e0eaccffadcd2560e Mon Sep 17 00:00:00 2001 From: Claudio Lima Date: Fri, 10 Jan 2025 13:55:40 -0300 Subject: [PATCH 4/6] Update canlib_vcinpl.py --- can/interfaces/ixxat/canlib_vcinpl.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/can/interfaces/ixxat/canlib_vcinpl.py b/can/interfaces/ixxat/canlib_vcinpl.py index 0579d0942..3d37b5837 100644 --- a/can/interfaces/ixxat/canlib_vcinpl.py +++ b/can/interfaces/ixxat/canlib_vcinpl.py @@ -10,6 +10,7 @@ """ import ctypes +import time import functools import logging import sys @@ -785,6 +786,7 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None: ) else: _canlib.canChannelPostMessage(self._channel_handle, message) + time.sleep(500e-6) # Want to log outgoing messages? # log.log(self.RECV_LOGGING_LEVEL, "Sent: %s", message) From 805fe87cc41b78a615553d5f5a0dccbd6ad13dbc Mon Sep 17 00:00:00 2001 From: Claudio Lima Date: Fri, 10 Jan 2025 13:56:45 -0300 Subject: [PATCH 5/6] Update canlib_vcinpl2.py --- can/interfaces/ixxat/canlib_vcinpl2.py | 1 + 1 file changed, 1 insertion(+) diff --git a/can/interfaces/ixxat/canlib_vcinpl2.py b/can/interfaces/ixxat/canlib_vcinpl2.py index 5872f76b9..91af0d4ea 100644 --- a/can/interfaces/ixxat/canlib_vcinpl2.py +++ b/can/interfaces/ixxat/canlib_vcinpl2.py @@ -931,6 +931,7 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None: else: _canlib.canChannelPostMessage(self._channel_handle, message) + time.sleep(500e-6) def _send_periodic_internal( self, From 1ae469a8c17853c0bf9b96e0e03c48ae70ef53ba Mon Sep 17 00:00:00 2001 From: Claudio Emanoel Barbosa Lima Date: Wed, 8 Oct 2025 15:34:29 -0300 Subject: [PATCH 6/6] Add on_error callback to send_periodic method. --- CHANGELOG.md | 11 +++++++++++ can/bus.py | 10 +++++++++- doc/changelog.d/1938.fixed.md | 1 - doc/changelog.d/1987.added.md | 1 - 4 files changed, 20 insertions(+), 3 deletions(-) delete mode 100644 doc/changelog.d/1938.fixed.md delete mode 100644 doc/changelog.d/1987.added.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 75ecab49e..5e337e0b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,17 @@ This project uses [*towncrier*](https://towncrier.readthedocs.io/) and the chang +## Version [v4.6.2](https://github.com/hardbyte/python-can/tree/v4.6.2) - 2025-10-08 + +### Added + +- Add [python-can-coe](https://c0d3.sh/smarthome/python-can-coe) interface plugin to the documentation. ([#1987](https://github.com/hardbyte/python-can/issues/1987)) + +### Fixed + +- Keep a reference to asyncio tasks in `can.Notifier` as recommended by [python documentation](https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task). ([#1938](https://github.com/hardbyte/python-can/issues/1938)) + + ## Version [v4.6.1](https://github.com/hardbyte/python-can/tree/v4.6.1) - 2025-08-12 ### Fixed diff --git a/can/bus.py b/can/bus.py index ec9eb09b7..267d445f2 100644 --- a/can/bus.py +++ b/can/bus.py @@ -211,6 +211,7 @@ def send_periodic( store_task: bool = True, autostart: bool = True, modifier_callback: Optional[Callable[[Message], None]] = None, + on_error: Optional[Callable[[Exception], bool]] = None, ) -> can.broadcastmanager.CyclicSendTaskABC: """Start sending messages at a given period on this bus. @@ -240,6 +241,11 @@ def send_periodic( Function which should be used to modify each message's data before sending. The callback modifies the :attr:`~can.Message.data` of the message and returns ``None``. + :param on_error: + Function which is called when an exception occurs during sending. The + exception is passed as the only parameter. If the function returns + True, the error is suppressed and the sending continues. If it returns + False, the sending is stopped. :return: A started task instance. Note the task can be stopped (and depending on the backend modified) by calling the task's @@ -272,7 +278,7 @@ def send_periodic( task = cast( "_SelfRemovingCyclicTask", self._send_periodic_internal( - msgs, period, duration, autostart, modifier_callback + msgs, period, duration, autostart, modifier_callback, on_error ), ) # we wrap the task's stop method to also remove it from the Bus's list of tasks @@ -302,6 +308,7 @@ def _send_periodic_internal( duration: Optional[float] = None, autostart: bool = True, modifier_callback: Optional[Callable[[Message], None]] = None, + on_error: Optional[Callable[[Exception], bool]] = None, ) -> can.broadcastmanager.CyclicSendTaskABC: """Default implementation of periodic message sending using threading. @@ -336,6 +343,7 @@ def _send_periodic_internal( duration=duration, autostart=autostart, modifier_callback=modifier_callback, + on_error=on_error, ) return task diff --git a/doc/changelog.d/1938.fixed.md b/doc/changelog.d/1938.fixed.md deleted file mode 100644 index f9aad1089..000000000 --- a/doc/changelog.d/1938.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Keep a reference to asyncio tasks in `can.Notifier` as recommended by [python documentation](https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task). diff --git a/doc/changelog.d/1987.added.md b/doc/changelog.d/1987.added.md deleted file mode 100644 index 398add3e3..000000000 --- a/doc/changelog.d/1987.added.md +++ /dev/null @@ -1 +0,0 @@ -Add [python-can-coe](https://c0d3.sh/smarthome/python-can-coe) interface plugin to the documentation.