From 4facf70c5685e4d1af5d3c4e0d9c7b576157283e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Tue, 15 Jul 2025 09:15:26 +0200 Subject: [PATCH 1/4] sync: Prevent from starting periodic task when already running. Raise a RuntimeError when a SYNC transmission task has previously been started. Make sure to clear the internal _task attribute when stopping, to make the check work. --- canopen/sync.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/canopen/sync.py b/canopen/sync.py index 44ea56c3..3b1e9b7e 100644 --- a/canopen/sync.py +++ b/canopen/sync.py @@ -32,6 +32,9 @@ def start(self, period: Optional[float] = None): :param period: Period of SYNC message in seconds. """ + if self._task is not None: + raise RuntimeError("Periodic SYNC transmission task already running") + if period is not None: self.period = period @@ -44,3 +47,4 @@ def stop(self): """Stop periodic transmission of SYNC message.""" if self._task is not None: self._task.stop() + self._task = None From 6a70ba0fc6e822f161a73c748c3ea1b9495ce02d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Tue, 15 Jul 2025 09:20:34 +0200 Subject: [PATCH 2/4] Add test. --- test/test_sync.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/test_sync.py b/test/test_sync.py index 93633538..66c4867d 100644 --- a/test/test_sync.py +++ b/test/test_sync.py @@ -74,6 +74,16 @@ def periodicity(): if msg is not None: self.assertIsNone(self.net.bus.recv(TIMEOUT)) + def test_sync_producer_restart(self): + self.sync.start(PERIOD) + self.addCleanup(self.sync.stop) + # Cannot start again while running + with self.assertRaises(RuntimeError): + self.sync.start(PERIOD) + # Can restart after stopping + self.sync.stop() + self.sync.start(PERIOD) + if __name__ == "__main__": unittest.main() From 4014b15a2418d5af59dba3d44141d89877953340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Tue, 15 Jul 2025 09:24:12 +0200 Subject: [PATCH 3/4] Fix mypy errors. --- canopen/sync.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/canopen/sync.py b/canopen/sync.py index 3b1e9b7e..ce4ea195 100644 --- a/canopen/sync.py +++ b/canopen/sync.py @@ -15,7 +15,7 @@ class SyncProducer: def __init__(self, network: canopen.network.Network): self.network = network self.period: Optional[float] = None - self._task = None + self._task: Optional[canopen.network.PeriodicMessageTask] = None def transmit(self, count: Optional[int] = None): """Send out a SYNC message once. @@ -23,7 +23,7 @@ def transmit(self, count: Optional[int] = None): :param count: Counter to add in message. """ - data = [count] if count is not None else [] + data = bytes([count]) if count is not None else b"" self.network.send_message(self.cob_id, data) def start(self, period: Optional[float] = None): @@ -41,7 +41,7 @@ def start(self, period: Optional[float] = None): if not self.period: raise ValueError("A valid transmission period has not been given") - self._task = self.network.send_periodic(self.cob_id, [], self.period) + self._task = self.network.send_periodic(self.cob_id, b"", self.period) def stop(self): """Stop periodic transmission of SYNC message.""" From e0012f6d4ce11efaa051d3360f195b7e7f714c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Colomb?= Date: Tue, 15 Jul 2025 09:31:41 +0200 Subject: [PATCH 4/4] Document possible exceptions. --- canopen/sync.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/canopen/sync.py b/canopen/sync.py index ce4ea195..c9a1c679 100644 --- a/canopen/sync.py +++ b/canopen/sync.py @@ -22,6 +22,8 @@ def transmit(self, count: Optional[int] = None): :param count: Counter to add in message. + :raises ValueError: + If the counter value does not fit in one byte. """ data = bytes([count]) if count is not None else b"" self.network.send_message(self.cob_id, data) @@ -31,6 +33,10 @@ def start(self, period: Optional[float] = None): :param period: Period of SYNC message in seconds. + :raises RuntimeError: + If a periodic transmission is already started. + :raises ValueError: + If no period is set via argument nor the instance attribute. """ if self._task is not None: raise RuntimeError("Periodic SYNC transmission task already running")