Notifier and Listeners

Notifier

The Notifier object is used as a message distributor for a bus. The Notifier uses an event loop or creates a thread to read messages from the bus and distributes them to listeners.

class can.Notifier(bus, listeners, timeout=1.0, loop=None)[source]

Manages the distribution of Message instances to listeners.

Supports multiple buses and listeners.

Note

Remember to call stop() after all messages are received as many listeners carry out flush operations to persist data.

Parameters:
add_bus(bus)[source]

Add a bus for notification.

Parameters:

bus (BusABC) – CAN bus instance.

Return type:

None

add_listener(listener)[source]

Add new Listener to the notification list. If it is already present, it will be called two times each time a message arrives.

Parameters:

listener (Listener | Callable[[Message], Awaitable[None] | None]) – Listener to be added to the list to be notified

Return type:

None

exception: Exception | None

Exception raised in thread

remove_listener(listener)[source]

Remove a listener from the notification list. This method throws an exception if the given listener is not part of the stored listeners.

Parameters:

listener (Listener | Callable[[Message], Awaitable[None] | None]) – Listener to be removed from the list to be notified

Raises:

ValueError – if listener was never added to this notifier

Return type:

None

stop(timeout=5)[source]

Stop notifying Listeners when new Message objects arrive and call stop() on each Listener.

Parameters:

timeout (float) – Max time in seconds to wait for receive threads to finish. Should be longer than timeout given at instantiation.

Return type:

None

Listener

The Listener class is an “abstract” base class for any objects which wish to register to receive notifications of new messages on the bus. A Listener can be used in two ways; the default is to call the Listener with a new message, or by calling the method on_message_received.

Listeners are registered with Notifier object(s) which ensure they are notified whenever a new message is received.

 1#!/usr/bin/env python
 2
 3import time
 4import can
 5
 6
 7def main():
 8    with can.Bus(receive_own_messages=True) as bus:
 9        print_listener = can.Printer()
10        can.Notifier(bus, [print_listener])
11
12        bus.send(can.Message(arbitration_id=1, is_extended_id=True))
13        bus.send(can.Message(arbitration_id=2, is_extended_id=True))
14        bus.send(can.Message(arbitration_id=1, is_extended_id=False))
15
16        time.sleep(1.0)
17
18
19if __name__ == "__main__":
20    main()

Subclasses of Listener that do not override on_message_received will cause NotImplementedError to be thrown when a message is received on the CAN bus.

class can.Listener[source]

The basic listener that can be called directly to handle some CAN message:

listener = SomeListener()
msg = my_bus.recv()

# now either call
listener(msg)
# or
listener.on_message_received(msg)

# Important to ensure all outputs are flushed
listener.stop()
on_error(exc)[source]

This method is called to handle any exception in the receive thread.

Parameters:

exc (Exception) – The exception causing the thread to stop

Return type:

None

abstract on_message_received(msg)[source]

This method is called to handle the given message.

Parameters:

msg (Message) – the delivered message

Return type:

None

abstract stop()[source]

Stop handling new messages, carry out any final tasks to ensure data is persisted and cleanup any open resources.

Concrete implementations override.

Return type:

None

There are some listeners that already ship together with python-can and are listed below. Some of them allow messages to be written to files, and the corresponding file readers are also documented here.

Note

Please note that writing and the reading a message might not always yield a completely unchanged message again, since some properties are not (yet) supported by some file formats.

Note

Additional file formats for both reading/writing log files can be added via a plugin reader/writer. An external package can register a new reader by using the can.io.message_reader entry point. Similarly, a writer can be added using the can.io.message_writer entry point.

The format of the entry point is reader_name=module:classname where classname is a can.io.generic.BaseIOHandler concrete implementation.

entry_points={
    'can.io.message_reader': [
       '.asc = my_package.io.asc:ASCReader'
   ]
},

BufferedReader

class can.BufferedReader[source]

A BufferedReader is a subclass of Listener which implements a message buffer: that is, when the can.BufferedReader instance is notified of a new message it pushes it into a queue of messages waiting to be serviced. The messages can then be fetched with get_message().

Putting in messages after stop() has been called will raise an exception, see on_message_received().

Attr is_stopped:

True if the reader has been stopped

get_message(timeout=0.5)[source]

Attempts to retrieve the message that has been in the queue for the longest amount of time (FIFO). If no message is available, it blocks for given timeout or until a message is received (whichever is shorter), or else returns None. This method does not block after can.BufferedReader.stop() has been called.

Parameters:

timeout (float) – The number of seconds to wait for a new message.

Returns:

the received can.Message or None, if the queue is empty.

Return type:

Message | None

on_message_received(msg)[source]

Append a message to the buffer.

Raises:

BufferError if the reader has already been stopped

Parameters:

msg (Message)

Return type:

None

stop()[source]

Prohibits any more additions to this reader.

Return type:

None

class can.AsyncBufferedReader(**kwargs)[source]

A message buffer for use with asyncio.

See Asyncio support for how to use with can.Notifier.

Can also be used as an asynchronous iterator:

async for msg in reader:
    print(msg)
Parameters:

kwargs (Any)

async get_message()[source]

Retrieve the latest message when awaited for:

msg = await reader.get_message()
Returns:

The CAN message.

Return type:

Message

on_message_received(msg)[source]

Append a message to the buffer.

Must only be called inside an event loop!

Parameters:

msg (Message)

Return type:

None

stop()[source]

Stop handling new messages, carry out any final tasks to ensure data is persisted and cleanup any open resources.

Concrete implementations override.

Return type:

None

RedirectReader

class can.RedirectReader(bus, *args, **kwargs)[source]

A RedirectReader sends all received messages to another Bus.

Parameters:
on_message_received(msg)[source]

This method is called to handle the given message.

Parameters:

msg (Message) – the delivered message

Return type:

None