Broadcast Manager

The broadcast manager allows the user to setup periodic message jobs. For example sending a particular message at a given period. The broadcast manager supported natively by several interfaces and a software thread based scheduler is used as a fallback.

This example shows the socketcan backend using the broadcast manager:

  1#!/usr/bin/env python
  2# coding: utf-8
  3
  4"""
  5This example exercises the periodic sending capabilities.
  6
  7Expects a vcan0 interface:
  8
  9    python3 -m examples.cyclic
 10
 11"""
 12
 13from __future__ import print_function
 14
 15import logging
 16import time
 17
 18import can
 19
 20logging.basicConfig(level=logging.INFO)
 21
 22
 23def simple_periodic_send(bus):
 24    """
 25    Sends a message every 20ms with no explicit timeout
 26    Sleeps for 2 seconds then stops the task.
 27    """
 28    print("Starting to send a message every 200ms for 2s")
 29    msg = can.Message(arbitration_id=0x123, data=[1, 2, 3, 4, 5, 6], is_extended_id=False)
 30    task = bus.send_periodic(msg, 0.20)
 31    assert isinstance(task, can.CyclicSendTaskABC)
 32    time.sleep(2)
 33    task.stop()
 34    print("stopped cyclic send")
 35
 36
 37def limited_periodic_send(bus):
 38    print("Starting to send a message every 200ms for 1s")
 39    msg = can.Message(arbitration_id=0x12345678, data=[0, 0, 0, 0, 0, 0], is_extended_id=True)
 40    task = bus.send_periodic(msg, 0.20, 1, store_task=False)
 41    if not isinstance(task, can.LimitedDurationCyclicSendTaskABC):
 42        print("This interface doesn't seem to support a ")
 43        task.stop()
 44        return
 45
 46    time.sleep(2)
 47    print("Cyclic send should have stopped as duration expired")
 48    # Note the (finished) task will still be tracked by the Bus
 49    # unless we pass `store_task=False` to bus.send_periodic
 50    # alternatively calling stop removes the task from the bus
 51    #task.stop()
 52
 53
 54def test_periodic_send_with_modifying_data(bus):
 55    print("Starting to send a message every 200ms. Initial data is ones")
 56    msg = can.Message(arbitration_id=0x0cf02200, data=[1, 1, 1, 1])
 57    task = bus.send_periodic(msg, 0.20)
 58    if not isinstance(task, can.ModifiableCyclicTaskABC):
 59        print("This interface doesn't seem to support modification")
 60        task.stop()
 61        return
 62    time.sleep(2)
 63    print("Changing data of running task to begin with 99")
 64    msg.data[0] = 0x99
 65    task.modify_data(msg)
 66    time.sleep(2)
 67
 68    task.stop()
 69    print("stopped cyclic send")
 70    print("Changing data of stopped task to single ff byte")
 71    msg.data = bytearray([0xff])
 72    msg.dlc = 1
 73    task.modify_data(msg)
 74    time.sleep(1)
 75    print("starting again")
 76    task.start()
 77    time.sleep(1)
 78    task.stop()
 79    print("done")
 80
 81
 82# Will have to consider how to expose items like this. The socketcan
 83# interfaces will continue to support it... but the top level api won't.
 84# def test_dual_rate_periodic_send():
 85#     """Send a message 10 times at 1ms intervals, then continue to send every 500ms"""
 86#     msg = can.Message(arbitration_id=0x123, data=[0, 1, 2, 3, 4, 5])
 87#     print("Creating cyclic task to send message 10 times at 1ms, then every 500ms")
 88#     task = can.interface.MultiRateCyclicSendTask('vcan0', msg, 10, 0.001, 0.50)
 89#     time.sleep(2)
 90#
 91#     print("Changing data[0] = 0x42")
 92#     msg.data[0] = 0x42
 93#     task.modify_data(msg)
 94#     time.sleep(2)
 95#
 96#     task.stop()
 97#     print("stopped cyclic send")
 98#
 99#     time.sleep(2)
100#
101#     task.start()
102#     print("starting again")
103#     time.sleep(2)
104#     task.stop()
105#     print("done")
106
107
108if __name__ == "__main__":
109
110    reset_msg = can.Message(arbitration_id=0x00, data=[0, 0, 0, 0, 0, 0], is_extended_id=False)
111
112    for interface, channel in [
113        ('socketcan', 'vcan0'),
114        #('ixxat', 0)
115    ]:
116        print("Carrying out cyclic tests with {} interface".format(interface))
117
118        bus = can.Bus(interface=interface, channel=channel, bitrate=500000)
119        bus.send(reset_msg)
120
121        simple_periodic_send(bus)
122
123        bus.send(reset_msg)
124
125        limited_periodic_send(bus)
126
127        test_periodic_send_with_modifying_data(bus)
128
129        #print("Carrying out multirate cyclic test for {} interface".format(interface))
130        #can.rc['interface'] = interface
131        #test_dual_rate_periodic_send()
132
133        bus.shutdown()
134
135    time.sleep(2)

Message Sending Tasks

The class based api for the broadcast manager uses a series of mixin classes. All mixins inherit from CyclicSendTaskABC which inherits from CyclicTask.

class can.broadcastmanager.CyclicTask[source]

Abstract Base for all cyclic tasks.

abstract stop()[source]

Cancel this periodic task.

Raises

can.CanError – If stop is called on an already stopped task.

class can.broadcastmanager.CyclicSendTaskABC(message, period)[source]

Message send task with defined period

Parameters
  • message (can.Message) – The message to be sent periodically.

  • period (float) – The rate in seconds at which to send the message.

class can.broadcastmanager.LimitedDurationCyclicSendTaskABC(message, period, duration)[source]

Message send task with a defined duration and period.

Parameters
  • message (can.Message) – The message to be sent periodically.

  • period (float) – The rate in seconds at which to send the message.

  • duration (float) – The duration to keep sending this message at given rate.

class can.broadcastmanager.MultiRateCyclicSendTaskABC(channel, message, count, initial_period, subsequent_period)[source]

A Cyclic send task that supports switches send frequency after a set time.

Transmits a message count times at initial_period then continues to transmit message at subsequent_period.

Parameters
  • channel – See interface specific documentation.

  • message (can.Message) –

  • count (int) –

  • initial_period (float) –

  • subsequent_period (float) –

class can.ModifiableCyclicTaskABC(message, period)[source]

Adds support for modifying a periodic message

Parameters
  • message (can.Message) – The message to be sent periodically.

  • period (float) – The rate in seconds at which to send the message.

modify_data(message)[source]

Update the contents of this periodically sent message without altering the timing.

Parameters

message (can.Message) – The message with the new can.Message.data. Note: The arbitration ID cannot be changed.

class can.RestartableCyclicTaskABC(message, period)[source]

Adds support for restarting a stopped cyclic task

Parameters
  • message (can.Message) – The message to be sent periodically.

  • period (float) – The rate in seconds at which to send the message.

abstract start()[source]

Restart a stopped periodic task.

Functional API

Warning

The functional API in can.broadcastmanager.send_periodic() is now deprecated and will be removed in version 4.0. Use the object oriented API via can.BusABC.send_periodic() instead.

can.broadcastmanager.send_periodic(bus, message, period, *args, **kwargs)[source]

Send a Message every period seconds on the given bus.

Parameters
  • bus (can.BusABC) – A CAN bus which supports sending.

  • message (can.Message) – Message to send periodically.

  • period (float) – The minimum time between sending messages.

Returns

A started task instance