pycyphal.transport.can.media.pythoncan package

Module contents

class pycyphal.transport.can.media.pythoncan.PythonCANMedia(iface_name: str, bitrate: int | Tuple[int, int], mtu: int | None = None, *, loop: AbstractEventLoop | None = None)[source]

Bases: Media

Media interface adapter for Python-CAN. It is designed to be usable with all host platforms supported by Python-CAN (GNU/Linux, Windows, macOS). Please refer to the Python-CAN documentation for information about supported CAN hardware, its configuration, and how to install the dependencies properly.

This media interface supports both Classic CAN and CAN FD. The selection logic is documented below.

Python-CAN supports hardware loopback and timestamping only for some of the interfaces. This has to be manually specified in PythonCANBusOptions for supported hardware. Both are disabled by default, but can be enabled if it is verified that hardware in question supports either or both options. For best compatibility, consider using the non-python-can SocketCAN media driver instead.

Here is a basic usage example based on the Yakut CLI tool. Suppose that there are two interconnected CAN bus adapters connected to the host computer: one SLCAN-based, the other is PCAN USB. Launch Yakut to listen for messages using the SLCAN adapter (only one at a time):

export UAVCAN__CAN__IFACE="slcan:/dev/serial/by-id/usb-Zubax_Robotics_Zubax_Babel_1B003D00145130365030332000000000-if00"
export UAVCAN__CAN__BITRATE='1000000 1000000'
export UAVCAN__CAN__MTU=8
yakut sub 33:uavcan.si.unit.voltage.scalar
__init__(iface_name: str, bitrate: int | Tuple[int, int], mtu: int | None = None, *, loop: AbstractEventLoop | None = None) None[source]
Parameters:
  • iface_name

    Interface name consisting of Python-CAN interface module name and its channel, separated with a colon. Supported interfaces are documented below. The semantics of the channel name are described in the documentation for Python-CAN.

  • bitrate

    Bit rate value in bauds; either a single integer or a tuple:

    • A single integer selects Classic CAN.

    • A tuple of two selects CAN FD, where the first integer defines the arbitration (nominal) bit rate and the second one defines the data phase bit rate.

    • If MTU (see below) is given and is greater than 8 bytes, CAN FD is used regardless of the above.

    • An MTU of 8 bytes and a tuple of two identical bit rates selects Classic CAN.

  • mtu

    The maximum CAN data field size in bytes. If provided, this value must belong to Media.VALID_MTU_SET. If not provided, the default is determined as follows:

    • If bitrate is a single integer: classic CAN is assumed, MTU defaults to 8 bytes.

    • If bitrate is two integers: CAN FD is assumed, MTU defaults to 64 bytes.

  • loop – Deprecated.

Raises:

InvalidMediaConfigurationError if the specified media instance could not be constructed, the interface name is unknown, or if the underlying library raised a can.CanError.

Use virtual bus with various bit rate and FD configurations:

>>> media = PythonCANMedia('virtual:', 500_000)
>>> media.is_fd, media.mtu
(False, 8)
>>> media = PythonCANMedia('virtual:', (500_000, 2_000_000))
>>> media.is_fd, media.mtu
(True, 64)
>>> media = PythonCANMedia('virtual:', 1_000_000, 16)
>>> media.is_fd, media.mtu
(True, 16)

Use PCAN-USB channel 1 in FD mode with nominal bitrate 500 kbit/s, data bitrate 2 Mbit/s, MTU 64 bytes:

PythonCANMedia('pcan:PCAN_USBBUS1', (500_000, 2_000_000))

Use Kvaser channel 0 in classic mode with bitrate 500k:

PythonCANMedia('kvaser:0', 500_000)

Use CANalyst-II channel 0 in classic mode with bitrate 500k:

PythonCANMedia('canalystii:0', 500_000)
property interface_name: str[source]
property mtu: int[source]
property number_of_acceptance_filters: int[source]

The value is currently fixed at 1 for all interfaces. TODO: obtain the number of acceptance filters from Python-CAN.

property is_fd: bool[source]

Introspection helper. The value is True if the underlying interface operates in CAN FD mode.

start(handler: Callable[[Sequence[Tuple[Timestamp, Envelope]]], None], no_automatic_retransmission: bool) None[source]
configure_acceptance_filters(configuration: Sequence[FilterConfiguration]) None[source]
transmit_thread_worker() None[source]
async send(frames: Iterable[Envelope], monotonic_deadline: float) int[source]
close() None[source]
static list_available_interface_names() Iterable[str][source]

Returns an empty list. TODO: provide minimally functional implementation.