Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion can/broadcastmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ def __init__(
period: float,
duration: Optional[float] = None,
on_error: Optional[Callable[[Exception], bool]] = None,
autostart: bool = True,
modifier_callback: Optional[Callable[[Message], None]] = None,
) -> None:
"""Transmits `messages` with a `period` seconds for `duration` seconds on a `bus`.
Expand Down Expand Up @@ -324,7 +325,8 @@ def __init__(
stacklevel=1,
)

self.start()
if autostart:
self.start()

def stop(self) -> None:
self.stopped = True
Expand Down
13 changes: 12 additions & 1 deletion can/bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ def send_periodic(
period: float,
duration: Optional[float] = None,
store_task: bool = True,
autostart: bool = True,
modifier_callback: Optional[Callable[[Message], None]] = None,
) -> can.broadcastmanager.CyclicSendTaskABC:
"""Start sending messages at a given period on this bus.
Expand All @@ -237,6 +238,9 @@ def send_periodic(
:param store_task:
If True (the default) the task will be attached to this Bus instance.
Disable to instead manage tasks manually.
:param autostart:
If True (the default) the sending task will immediately start after creation.
Otherwise, the task has to be started by calling start() on it.
:param modifier_callback:
Function which should be used to modify each message's data before
sending. The callback modifies the :attr:`~can.Message.data` of the
Expand Down Expand Up @@ -272,7 +276,9 @@ def send_periodic(
# Create a backend specific task; will be patched to a _SelfRemovingCyclicTask later
task = cast(
_SelfRemovingCyclicTask,
self._send_periodic_internal(msgs, period, duration, modifier_callback),
self._send_periodic_internal(
msgs, period, duration, autostart, modifier_callback
),
)
# we wrap the task's stop method to also remove it from the Bus's list of tasks
periodic_tasks = self._periodic_tasks
Expand All @@ -299,6 +305,7 @@ def _send_periodic_internal(
msgs: Union[Sequence[Message], Message],
period: float,
duration: Optional[float] = None,
autostart: bool = True,
modifier_callback: Optional[Callable[[Message], None]] = None,
) -> can.broadcastmanager.CyclicSendTaskABC:
"""Default implementation of periodic message sending using threading.
Expand All @@ -312,6 +319,9 @@ def _send_periodic_internal(
:param duration:
The duration between sending each message at the given rate. If
no duration is provided, the task will continue indefinitely.
:param autostart:
If True (the default) the sending task will immediately start after creation.
Otherwise, the task has to be started by calling start() on it.
:return:
A started task instance. Note the task can be stopped (and
depending on the backend modified) by calling the
Expand All @@ -328,6 +338,7 @@ def _send_periodic_internal(
messages=msgs,
period=period,
duration=duration,
autostart=autostart,
modifier_callback=modifier_callback,
)
return task
Expand Down
3 changes: 2 additions & 1 deletion can/interfaces/ixxat/canlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,11 @@ def _send_periodic_internal(
msgs: Union[Sequence[Message], Message],
period: float,
duration: Optional[float] = None,
autostart: bool = True,
modifier_callback: Optional[Callable[[Message], None]] = None,
) -> CyclicSendTaskABC:
return self.bus._send_periodic_internal(
msgs, period, duration, modifier_callback
msgs, period, duration, autostart, modifier_callback
)

def shutdown(self) -> None:
Expand Down
22 changes: 19 additions & 3 deletions can/interfaces/ixxat/canlib_vcinpl.py
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,7 @@ def _send_periodic_internal(
msgs: Union[Sequence[Message], Message],
period: float,
duration: Optional[float] = None,
autostart: bool = True,
modifier_callback: Optional[Callable[[Message], None]] = None,
) -> CyclicSendTaskABC:
"""Send a message using built-in cyclic transmit list functionality."""
Expand All @@ -807,7 +808,12 @@ def _send_periodic_internal(
self._scheduler_resolution = caps.dwClockFreq / caps.dwCmsDivisor
_canlib.canSchedulerActivate(self._scheduler, constants.TRUE)
return CyclicSendTask(
self._scheduler, msgs, period, duration, self._scheduler_resolution
self._scheduler,
msgs,
period,
duration,
self._scheduler_resolution,
autostart=autostart,
)

# fallback to thread based cyclic task
Expand All @@ -821,6 +827,7 @@ def _send_periodic_internal(
msgs=msgs,
period=period,
duration=duration,
autostart=autostart,
modifier_callback=modifier_callback,
)

Expand Down Expand Up @@ -863,7 +870,15 @@ def state(self) -> BusState:
class CyclicSendTask(LimitedDurationCyclicSendTaskABC, RestartableCyclicTaskABC):
"""A message in the cyclic transmit list."""

def __init__(self, scheduler, msgs, period, duration, resolution):
def __init__(
self,
scheduler,
msgs,
period,
duration,
resolution,
autostart: bool = True,
):
super().__init__(msgs, period, duration)
if len(self.messages) != 1:
raise ValueError(
Expand All @@ -883,7 +898,8 @@ def __init__(self, scheduler, msgs, period, duration, resolution):
self._msg.uMsgInfo.Bits.dlc = self.messages[0].dlc
for i, b in enumerate(self.messages[0].data):
self._msg.abData[i] = b
self.start()
if autostart:
self.start()

def start(self):
"""Start transmitting message (add to list if needed)."""
Expand Down
22 changes: 19 additions & 3 deletions can/interfaces/ixxat/canlib_vcinpl2.py
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,7 @@ def _send_periodic_internal(
msgs: Union[Sequence[Message], Message],
period: float,
duration: Optional[float] = None,
autostart: bool = True,
modifier_callback: Optional[Callable[[Message], None]] = None,
) -> CyclicSendTaskABC:
"""Send a message using built-in cyclic transmit list functionality."""
Expand All @@ -953,7 +954,12 @@ def _send_periodic_internal(
) # TODO: confirm
_canlib.canSchedulerActivate(self._scheduler, constants.TRUE)
return CyclicSendTask(
self._scheduler, msgs, period, duration, self._scheduler_resolution
self._scheduler,
msgs,
period,
duration,
self._scheduler_resolution,
autostart=autostart,
)

# fallback to thread based cyclic task
Expand All @@ -967,6 +973,7 @@ def _send_periodic_internal(
msgs=msgs,
period=period,
duration=duration,
autostart=autostart,
modifier_callback=modifier_callback,
)

Expand All @@ -983,7 +990,15 @@ def shutdown(self):
class CyclicSendTask(LimitedDurationCyclicSendTaskABC, RestartableCyclicTaskABC):
"""A message in the cyclic transmit list."""

def __init__(self, scheduler, msgs, period, duration, resolution):
def __init__(
self,
scheduler,
msgs,
period,
duration,
resolution,
autostart: bool = True,
):
super().__init__(msgs, period, duration)
if len(self.messages) != 1:
raise ValueError(
Expand All @@ -1003,7 +1018,8 @@ def __init__(self, scheduler, msgs, period, duration, resolution):
self._msg.uMsgInfo.Bits.dlc = self.messages[0].dlc
for i, b in enumerate(self.messages[0].data):
self._msg.abData[i] = b
self.start()
if autostart:
self.start()

def start(self):
"""Start transmitting message (add to list if needed)."""
Expand Down
23 changes: 18 additions & 5 deletions can/interfaces/socketcan/socketcan.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ def __init__(
messages: Union[Sequence[Message], Message],
period: float,
duration: Optional[float] = None,
autostart: bool = True,
) -> None:
"""Construct and :meth:`~start` a task.

Expand All @@ -349,10 +350,13 @@ def __init__(

self.bcm_socket = bcm_socket
self.task_id = task_id
self._tx_setup(self.messages)
self._tx_setup(self.messages, send=autostart)

def _tx_setup(
self, messages: Sequence[Message], raise_if_task_exists: bool = True
self,
messages: Sequence[Message],
raise_if_task_exists: bool = True,
send: bool = True,
) -> None:
# Create a low level packed frame to pass to the kernel
body = bytearray()
Expand All @@ -376,7 +380,9 @@ def _tx_setup(
for message in messages:
body += build_can_frame(message)
log.debug("Sending BCM command")
send_bcm(self.bcm_socket, header + body)

if send:
send_bcm(self.bcm_socket, header + body)

def _check_bcm_task(self) -> None:
# Do a TX_READ on a task ID, and check if we get EINVAL. If so,
Expand Down Expand Up @@ -813,6 +819,7 @@ def _send_periodic_internal(
msgs: Union[Sequence[Message], Message],
period: float,
duration: Optional[float] = None,
autostart: bool = True,
modifier_callback: Optional[Callable[[Message], None]] = None,
) -> can.broadcastmanager.CyclicSendTaskABC:
"""Start sending messages at a given period on this bus.
Expand All @@ -823,13 +830,16 @@ def _send_periodic_internal(
:class:`CyclicSendTask` within BCM provides flexibility to schedule
CAN messages sending with the same CAN ID, but different CAN data.

:param messages:
:param msgs:
The message(s) to be sent periodically.
:param period:
The rate in seconds at which to send the messages.
:param duration:
Approximate duration in seconds to continue sending messages. If
no duration is provided, the task will continue indefinitely.
:param autostart:
If True (the default) the sending task will immediately start after creation.
Otherwise, the task has to be started by calling start() on it.

:raises ValueError:
If task identifier passed to :class:`CyclicSendTask` can't be used
Expand All @@ -854,7 +864,9 @@ def _send_periodic_internal(
msgs_channel = str(msgs[0].channel) if msgs[0].channel else None
bcm_socket = self._get_bcm_socket(msgs_channel or self.channel)
task_id = self._get_next_task_id()
task = CyclicSendTask(bcm_socket, task_id, msgs, period, duration)
task = CyclicSendTask(
bcm_socket, task_id, msgs, period, duration, autostart=autostart
)
return task

# fallback to thread based cyclic task
Expand All @@ -868,6 +880,7 @@ def _send_periodic_internal(
msgs=msgs,
period=period,
duration=duration,
autostart=autostart,
modifier_callback=modifier_callback,
)

Expand Down