python-can¶
The python-can library provides Controller Area Network support for Python, providing common abstractions to different hardware devices, and a suite of utilities for sending and receiving messages on a CAN bus.
python-can runs any where Python runs; from high powered computers with commercial CAN to usb devices right down to low powered devices running linux such as a BeagleBone or RaspberryPi.
More concretely, some example uses of the library:
Passively logging what occurs on a CAN bus. For example monitoring a commercial vehicle using its OBD-II port.
Testing of hardware that interacts via CAN. Modules found in modern cars, motocycles, boats, and even wheelchairs have had components tested from Python using this library.
Prototyping new hardware modules or software algorithms in-the-loop. Easily interact with an existing bus.
Creating virtual modules to prototype CAN bus communication.
Brief example of the library in action: connecting to a CAN bus, creating and sending a message:
1#!/usr/bin/env python
2
3"""
4This example shows how sending a single message works.
5"""
6
7import can
8
9
10def send_one():
11 """Sends a single message."""
12
13 # this uses the default configuration (for example from the config file)
14 # see https://python-can.readthedocs.io/en/stable/configuration.html
15 with can.interface.Bus() as bus:
16
17 # Using specific buses works similar:
18 # bus = can.interface.Bus(bustype='socketcan', channel='vcan0', bitrate=250000)
19 # bus = can.interface.Bus(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000)
20 # bus = can.interface.Bus(bustype='ixxat', channel=0, bitrate=250000)
21 # bus = can.interface.Bus(bustype='vector', app_name='CANalyzer', channel=0, bitrate=250000)
22 # ...
23
24 msg = can.Message(
25 arbitration_id=0xC0FFEE, data=[0, 25, 0, 1, 3, 1, 4, 1], is_extended_id=True
26 )
27
28 try:
29 bus.send(msg)
30 print(f"Message sent on {bus.channel_info}")
31 except can.CanError:
32 print("Message NOT sent")
33
34
35if __name__ == "__main__":
36 send_one()
Contents:
Installation¶
Install can
with pip
:
$ pip install python-can
As most likely you will want to interface with some hardware, you may also have to install platform dependencies. Be sure to check any other specifics for your hardware in CAN Interface Modules.
GNU/Linux dependencies¶
Reasonably modern Linux Kernels (2.6.25 or newer) have an implementation
of socketcan
. This version of python-can will directly use socketcan
if called with Python 3.3 or greater, otherwise that interface is used
via ctypes.
Windows dependencies¶
Kvaser¶
To install python-can
using the Kvaser CANLib SDK as the backend:
Test that Kvaser’s own tools work to ensure the driver is properly installed and that the hardware is working.
PCAN¶
Download and install the latest driver for your interface:
Windows (also supported on Cygwin)
Linux (also works without, see also Linux installation)
Note that PCANBasic API timestamps count seconds from system startup. To
convert these to epoch times, the uptime library is used. If it is not
available, the times are returned as number of seconds from system
startup. To install the uptime library, run pip install python-can[pcan]
.
This library can take advantage of the Python for Windows Extensions library if installed. It will be used to get notified of new messages instead of the CPU intensive polling that will otherwise have be used.
IXXAT¶
To install python-can
using the IXXAT VCI V3 or V4 SDK as the backend:
Install IXXAT’s latest Windows VCI V3 SDK or VCI V4 SDK (Win10) drivers.
Test that IXXAT’s own tools (i.e. MiniMon) work to ensure the driver is properly installed and that the hardware is working.
NI-CAN¶
Download and install the NI-CAN drivers from National Instruments.
Currently the driver only supports 32-bit Python on Windows.
neoVI¶
See neoVI.
Vector¶
To install python-can
using the XL Driver Library as the backend:
Install the latest drivers for your Vector hardware interface.
Install the XL Driver Library or copy the
vxlapi.dll
and/orvxlapi64.dll
into your working directory.Use Vector Hardware Configuration to assign a channel to your application.
CANtact¶
CANtact is supported on Linux, Windows, and macOS.
To install python-can
using the CANtact driver backend:
python3 -m pip install "python-can[cantact]"
If python-can
is already installed, the CANtact backend can be installed separately:
python3 -m pip install cantact
Additional CANtact documentation is available at cantact.io.
Installing python-can in development mode¶
A “development” install of this package allows you to make changes locally or pull updates from the Git repository and use them without having to reinstall. Download or clone the source repository then:
python setup.py develop
Configuration¶
Usually this library is used with a particular CAN interface, this can be specified in code, read from configuration files or environment variables.
See can.util.load_config()
for implementation.
In Code¶
The can
object exposes an rc
dictionary which can be used to set
the interface and channel.
import can
can.rc['interface'] = 'socketcan'
can.rc['channel'] = 'vcan0'
can.rc['bitrate'] = 500000
from can.interface import Bus
bus = Bus()
You can also specify the interface and channel for each Bus instance:
import can
bus = can.interface.Bus(bustype='socketcan', channel='vcan0', bitrate=500000)
Configuration File¶
On Linux systems the config file is searched in the following paths:
~/can.conf
/etc/can.conf
$HOME/.can
$HOME/.canrc
On Windows systems the config file is searched in the following paths:
%USERPROFILE%/can.conf
can.ini
(current working directory)%APPDATA%/can.ini
The configuration file sets the default interface and channel:
[default]
interface = <the name of the interface to use>
channel = <the channel to use by default>
bitrate = <the bitrate in bits/s to use by default>
The configuration can also contain additional sections (or context):
[default]
interface = <the name of the interface to use>
channel = <the channel to use by default>
bitrate = <the bitrate in bits/s to use by default>
[HS]
# All the values from the 'default' section are inherited
channel = <the channel to use>
bitrate = <the bitrate in bits/s to use. i.e. 500000>
[MS]
# All the values from the 'default' section are inherited
channel = <the channel to use>
bitrate = <the bitrate in bits/s to use. i.e. 125000>
from can.interface import Bus
hs_bus = Bus(context='HS')
ms_bus = Bus(context='MS')
Environment Variables¶
Configuration can be pulled from these environmental variables:
CAN_INTERFACE
CAN_CHANNEL
CAN_BITRATE
CAN_CONFIG
The CAN_CONFIG
environment variable allows to set any bus configuration using JSON.
For example:
CAN_INTERFACE=socketcan CAN_CONFIG={"receive_own_messages": true, "fd": true}
Interface Names¶
Lookup table of interface names:
Name |
Documentation |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Library API¶
The main objects are the BusABC
and the Message
.
A form of CAN interface is also required.
Hint
Check the backend specific documentation for any implementation specific details.
Bus¶
The BusABC
class, as the name suggests, provides an abstraction of a CAN bus.
The bus provides a wrapper around a physical or virtual CAN Bus.
An interface specific instance of the BusABC
is created by the Bus
class, for example:
vector_bus = can.Bus(interface='vector', ...)
That bus is then able to handle the interface specific software/hardware interactions
and implements the BusABC
API.
A thread safe bus wrapper is also available, see Thread safe bus.
Autoconfig Bus¶
- class can.Bus(channel, can_filters=None, **kwargs)[source]¶
Bus wrapper with configuration loading.
Instantiates a CAN Bus of the given
interface
, falls back to reading a configuration file from default locations.Construct and open a CAN bus instance of the specified type.
Subclasses should call though this method with all given parameters as it handles generic tasks like applying filters.
- Parameters
- Raises
ValueError – If parameters are out of range
can.CanInterfaceNotImplementedError – If the driver cannot be accessed
can.CanInitializationError – If the bus cannot be initialized
API¶
- class can.BusABC(channel, can_filters=None, **kwargs)[source]¶
The CAN Bus Abstract Base Class that serves as the basis for all concrete interfaces.
This class may be used as an iterator over the received messages and as a context manager for auto-closing the bus when done using it.
Please refer to Errors for possible exceptions that may be thrown by certain operations on this bus.
Construct and open a CAN bus instance of the specified type.
Subclasses should call though this method with all given parameters as it handles generic tasks like applying filters.
- Parameters
- Raises
ValueError – If parameters are out of range
can.CanInterfaceNotImplementedError – If the driver cannot be accessed
can.CanInitializationError – If the bus cannot be initialized
- __iter__()[source]¶
Allow iteration on messages as they are received.
>>> for msg in bus: ... print(msg)
- RECV_LOGGING_LEVEL = 9¶
Log level for received messages
- channel_info = 'unknown'¶
a string describing the underlying bus and/or channel
- property filters: Optional[Sequence[Union[can.typechecking.CanFilter, can.typechecking.CanFilterExtended]]]¶
Modify the filters of this bus. See
set_filters()
for details.
- flush_tx_buffer()[source]¶
Discard every message that may be queued in the output buffer(s).
- Return type
- abstract send(msg, timeout=None)[source]¶
Transmit a message to the CAN bus.
Override this method to enable the transmit path.
- Parameters
msg (Message) – A message object.
timeout (
Optional
[float
]) – If > 0, wait up to this many seconds for message to be ACK’ed or for transmit queue to be ready depending on driver implementation. If timeout is exceeded, an exception will be raised. Might not be supported by all interfaces. None blocks indefinitely.
- Raises
can.CanOperationError – If an error occurred while sending
- Return type
- send_periodic(msgs, period, duration=None, store_task=True)[source]¶
Start sending messages at a given period on this bus.
The task will be active until one of the following conditions are met:
the (optional) duration expires
the Bus instance goes out of scope
the Bus instance is shutdown
BusABC.stop_all_periodic_tasks()
is calledthe task’s
CyclicTask.stop()
method is called.
- Parameters
msgs (
Union
[Message
,Sequence
[Message
]]) – Message(s) to transmitperiod (
float
) – Period in seconds between each messageduration (
Optional
[float
]) – Approximate duration in seconds to continue sending messages. If no duration is provided, the task will continue indefinitely.store_task (
bool
) – If True (the default) the task will be attached to this Bus instance. Disable to instead manage tasks manually.
- Return type
- Returns
A started task instance. Note the task can be stopped (and depending on the backend modified) by calling the task’s
stop()
method.
Note
Note the duration before the messages stop being sent may not be exactly the same as the duration specified by the user. In general the message will be sent at the given rate until at least duration seconds.
Note
For extremely long running Bus instances with many short lived tasks the default api with
store_task==True
may not be appropriate as the stopped tasks are still taking up memory as they are associated with the Bus instance.
- set_filters(filters=None)[source]¶
Apply filtering to all messages received by this Bus.
All messages that match at least one filter are returned. If filters is None or a zero length sequence, all messages are matched.
Calling without passing any filters will reset the applied filters to
None
.- Parameters
filters (
Optional
[Sequence
[Union
[CanFilter
,CanFilterExtended
]]]) –A iterable of dictionaries each containing a “can_id”, a “can_mask”, and an optional “extended” key.
>>> [{"can_id": 0x11, "can_mask": 0x21, "extended": False}]
A filter matches, when
<received_can_id> & can_mask == can_id & can_mask
. Ifextended
is set as well, it only matches messages where<received_is_extended> == extended
. Else it matches every messages based only on the arbitration ID and mask.- Return type
- shutdown()[source]¶
Called to carry out any interface specific cleanup required in shutting down a bus.
- Return type
- property state: can.bus.BusState¶
Return the current state of the hardware
- Return type
BusState
Transmitting¶
Writing individual messages to the bus is done by calling the send()
method
and passing a Message
instance. Periodic sending is controlled by the
broadcast manager.
Receiving¶
Reading from the bus is achieved by either calling the recv()
method or
by directly iterating over the bus:
for msg in bus:
print(msg.data)
Alternatively the Listener
api can be used, which is a list of Listener
subclasses that receive notifications when new messages arrive.
Filtering¶
Message filtering can be set up for each bus. Where the interface supports it, this is carried out in the hardware or kernel layer - not in Python. All messages that match at least one filter are returned.
Example defining two filters, one to pass 11-bit ID 0x451
, the other to pass 29-bit ID 0xA0000
:
filters = [
{"can_id": 0x451, "can_mask": 0x7FF, "extended": False},
{"can_id": 0xA0000, "can_mask": 0x1FFFFFFF, "extended": True},
]
bus = can.interface.Bus(channel="can0", bustype="socketcan", can_filters=filters)
See set_filters()
for the implementation.
Thread safe bus¶
This thread safe version of the BusABC
class can be used by multiple threads at once.
Sending and receiving is locked separately to avoid unnecessary delays.
Conflicting calls are executed by blocking until the bus is accessible.
It can be used exactly like the normal BusABC
:
# 'socketcan' is only an example interface, it works with all the others too
my_bus = can.ThreadSafeBus(interface='socketcan', channel='vcan0')
my_bus.send(...)
my_bus.recv(...)
- class can.ThreadSafeBus(*args, **kwargs)[source]¶
Contains a thread safe
can.BusABC
implementation that wraps around an existing interface instance. All public methods of that base class are now safe to be called from multiple threads. The send and receive methods are synchronized separately.Use this as a drop-in replacement for
BusABC
.
Message¶
- class can.Message(timestamp=0.0, arbitration_id=0, is_extended_id=True, is_remote_frame=False, is_error_frame=False, channel=None, dlc=None, data=None, is_fd=False, is_rx=True, bitrate_switch=False, error_state_indicator=False, check=False)[source]¶
The
Message
object is used to represent CAN messages for sending, receiving and other purposes like converting between different logging formats.Messages can use extended identifiers, be remote or error frames, contain data and may be associated to a channel.
Messages are always compared by identity and never by value, because that may introduce unexpected behaviour. See also
equals()
.copy()
/deepcopy()
is supported as well.Messages do not support “dynamic” attributes, meaning any others than the documented ones, since it uses
__slots__
.To create a message object, simply provide any of the below attributes together with additional parameters as keyword arguments to the constructor.
- Parameters
check (
bool
) – By default, the constructor of this class does not strictly check the input. Thus, the caller must prevent the creation of invalid messages or set this parameter to True, to raise an Error on invalid inputs. Possible problems include the dlc field not matching the length of data or creating a message with both is_remote_frame and is_error_frame set to True.- Raises
ValueError – If and only if check is set to True and one or more arguments were invalid
One can instantiate a
Message
defining data, and optional arguments for all attributes such as arbitration ID, flags, and timestamp.>>> from can import Message >>> test = Message(data=[1, 2, 3, 4, 5]) >>> test.data bytearray(b'\x01\x02\x03\x04\x05') >>> test.dlc 5 >>> print(test) Timestamp: 0.000000 ID: 00000000 010 DLC: 5 01 02 03 04 05
The
arbitration_id
field in a CAN message may be either 11 bits (standard addressing, CAN 2.0A) or 29 bits (extended addressing, CAN 2.0B) in length, andpython-can
exposes this difference with theis_extended_id
attribute.- timestamp¶
- Type
The timestamp field in a CAN message is a floating point number representing when the message was received since the epoch in seconds. Where possible this will be timestamped in hardware.
- arbitration_id¶
- Type
The frame identifier used for arbitration on the bus.
The arbitration ID can take an int between 0 and the maximum value allowed depending on the
is_extended_id
flag (either 211 - 1 for 11-bit IDs, or 229 - 1 for 29-bit identifiers).>>> print(Message(is_extended_id=False, arbitration_id=100)) Timestamp: 0.000000 ID: 0064 S DLC: 0
- data¶
- Type
The data parameter of a CAN message is exposed as a bytearray with length between 0 and 8.
>>> example_data = bytearray([1, 2, 3]) >>> print(Message(data=example_data)) Timestamp: 0.000000 ID: 00000000 X DLC: 3 01 02 03
A
Message
can also be created with bytes, or lists of ints:>>> m1 = Message(data=[0x64, 0x65, 0x61, 0x64, 0x62, 0x65, 0x65, 0x66]) >>> print(m1.data) bytearray(b'deadbeef') >>> m2 = Message(data=b'deadbeef') >>> m2.data bytearray(b'deadbeef')
- dlc¶
- Type
The DLC parameter of a CAN message is an integer between 0 and 8 representing the frame payload length.
In the case of a CAN FD message, this indicates the data length in number of bytes.
>>> m = Message(data=[1, 2, 3]) >>> m.dlc 3
Note
The DLC value does not necessarily define the number of bytes of data in a message.
Its purpose varies depending on the frame type - for data frames it represents the amount of data contained in the message, in remote frames it represents the amount of data being requested.
- is_extended_id¶
- Type
This flag controls the size of the
arbitration_id
field. Previously this was exposed as id_type.>>> print(Message(is_extended_id=False)) Timestamp: 0.000000 ID: 0000 S DLC: 0 >>> print(Message(is_extended_id=True)) Timestamp: 0.000000 ID: 00000000 X DLC: 0
Note
The initializer argument and attribute
extended_id
has been deprecated in favor ofis_extended_id
, but will continue to work for the3.x
release series.
- is_error_frame¶
- Type
This boolean parameter indicates if the message is an error frame or not.
>>> print(Message(is_error_frame=True)) Timestamp: 0.000000 ID: 00000000 X E DLC: 0
- is_remote_frame¶
- Type
This boolean attribute indicates if the message is a remote frame or a data frame, and modifies the bit in the CAN message’s flags field indicating this.
>>> print(Message(is_remote_frame=True)) Timestamp: 0.000000 ID: 00000000 X R DLC: 0
- bitrate_switch¶
- Type
If this is a CAN FD message, this indicates that a higher bitrate was used for the data transmission.
- __str__()[source]¶
A string representation of a CAN message:
>>> from can import Message >>> test = Message() >>> print(test) Timestamp: 0.000000 ID: 00000000 X DLC: 0 >>> test2 = Message(data=[1, 2, 3, 4, 5]) >>> print(test2) Timestamp: 0.000000 ID: 00000000 X DLC: 5 01 02 03 04 05
The fields in the printed message are (in order):
timestamp,
arbitration ID,
flags,
dlc,
and data.
The flags field is represented as one, two or three letters:
X if the
is_extended_id
attribute is set, otherwise S,E if the
is_error_frame
attribute is set,R if the
is_remote_frame
attribute is set.
The arbitration ID field is represented as either a four or eight digit hexadecimal number depending on the length of the arbitration ID (11-bit or 29-bit).
Each of the bytes in the data field (when present) are represented as two-digit hexadecimal numbers.
Listeners¶
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.
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(*args, **kwargs)[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()
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(*args, **kwargs)[source]¶
A BufferedReader is a subclass of
Listener
which implements a message buffer: that is, when thecan.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 withget_message()
.Putting in messages after
stop()
has been called will raise an exception, seeon_message_received()
.- Attr is_stopped
True
if the reader has been stopped
- get_message(timeout=0.5)[source]¶
Attempts to retrieve the latest message received by the instance. If no message is available it blocks for given timeout or until a message is received, or else returns None (whichever is shorter). This method does not block after
can.BufferedReader.stop()
has been called.
- class can.AsyncBufferedReader(*args, **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)
RedirectReader¶
Logger¶
The can.Logger
uses the following can.Listener
types to
create log files with different file types of the messages received.
- class can.Logger(file, mode='rt')[source]¶
Logs CAN messages to a file.
- The format is determined from the file suffix which can be one of:
.asc:
can.ASCWriter
.blf
can.BLFWriter
.csv:
can.CSVWriter
.db:
can.SqliteWriter
.txt
can.Printer
Any of these formats can be used with gzip compression by appending the suffix .gz (e.g. filename.asc.gz). However, third-party tools might not be able to read these files.
The filename may also be None, to fall back to
can.Printer
.The log files may be incomplete until stop() is called due to buffering.
Note
This class itself is just a dispatcher, and any positional and keyword arguments are passed on to the returned instance.
- Parameters
- class can.io.BaseRotatingLogger(*args, **kwargs)[source]¶
Base class for rotating CAN loggers. This class is not meant to be instantiated directly. Subclasses must implement the
should_rollover
and do_rollover methods according to their rotation strategy.The rotation behavior can be further customized by the user by setting the
namer
androtator
attributes after instantiating the subclass.These attributes as well as the methods rotation_filename and rotate and the corresponding docstrings are carried over from the python builtin BaseRotatingHandler.
Subclasses must set the _writer attribute upon initialization.
- Attr namer
If this attribute is set to a callable, the
rotation_filename()
method delegates to this callable. The parameters passed to the callable are those passed torotation_filename()
.- Attr rotator
If this attribute is set to a callable, the
rotate()
method delegates to this callable. The parameters passed to the callable are those passed torotate()
.- Attr rollover_count
An integer counter to track the number of rollovers.
- Parameters
file – a path-like object to open a file, a file-like object to be used as a file or None to not use a file at all
mode – the mode that should be used to open the file, see
open()
, ignored if file is None
- rotate(source, dest)[source]¶
When rotating, rotate the current log.
The default implementation calls the
rotator
attribute of the handler, if it’s callable, passing the source and dest arguments to it. If the attribute isn’t callable (the default is None), the source is simply renamed to the destination.- Parameters
source – The source filename. This is normally the base filename, e.g. “test.log”
dest – The destination filename. This is normally what the source is rotated to, e.g. “test_#001.log”.
- rotation_filename(default_name)[source]¶
Modify the filename of a log file when rotating.
This is provided so that a custom filename can be provided. The default implementation calls the
namer
attribute of the handler, if it’s callable, passing the default name to it. If the attribute isn’t callable (the default is None), the name is returned unchanged.- Parameters
default_name – The default name for the log file.
- stop()[source]¶
Stop handling new messages.
Carry out any final tasks to ensure data is persisted and cleanup any open resources.
- Return type
- property writer: can.io.generic.FileIOMessageWriter¶
This attribute holds an instance of a writer class which manages the actual file IO.
- Return type
- class can.SizedRotatingLogger(base_filename, *args, max_bytes=0, **kwargs)[source]¶
Log CAN messages to a sequence of files with a given maximum size.
The logger creates a log file with the given base_filename. When the size threshold is reached the current log file is closed and renamed by adding a timestamp and the rollover count. A new log file is then created and written to.
This behavior can be customized by setting the
namer
androtator
attribute.Example:
from can import Notifier, SizedRotatingLogger from can.interfaces.vector import VectorBus bus = VectorBus(channel=[0], app_name="CANape", fd=True) logger = SizedRotatingLogger( base_filename="my_logfile.asc", max_bytes=5 * 1024 ** 2, # =5MB ) logger.rollover_count = 23 # start counter at 23 notifier = Notifier(bus=bus, listeners=[logger])
- The SizedRotatingLogger currently supports the formats
.asc:
can.ASCWriter
.blf
can.BLFWriter
.csv:
can.CSVWriter
.txt
can.Printer
(if pointing to a file)
Note
The
can.SqliteWriter
is not supported yet.The log files on disk may be incomplete due to buffering until
stop()
is called.- Parameters
base_filename – A path-like object for the base filename. The log file format is defined by the suffix of base_filename.
max_bytes – The size threshold at which a new log file shall be created. If set to 0, no rollover will be performed.
Printer¶
- class can.Printer(file=None, append=False)[source]¶
The Printer class is a subclass of
Listener
which simply prints any messages it receives to the terminal (stdout). A message is turned into a string using__str__()
.- Attr write_to_file
True if this instance prints to a file instead of standard out
- Parameters
file (
Union
[str
, os.PathLike[str],TextIO
,None
]) – An optional path-like object or a file-like object to “print” to instead of writing to standard out (stdout). If this is a file-like object, is has to be opened in text write mode, not binary write mode.append (
bool
) – If set to True messages, are appended to the file, else the file is truncated
CSVWriter¶
- class can.CSVWriter(file, append=False)[source]¶
Writes a comma separated text file with a line for each message. Includes a header line.
The columns are as follows:
name of column
format description
example
timestamp
decimal float
1483389946.197
arbitration_id
hex
0x00dadada
extended
1 == True, 0 == False
1
remote
1 == True, 0 == False
0
error
1 == True, 0 == False
0
dlc
int
6
data
base64 encoded
WzQyLCA5XQ==
Each line is terminated with a platform specific line separator.
- Parameters
file (
Union
[str
, os.PathLike[str],TextIO
]) – a path-like object or a file-like object to write to. If this is a file-like object, is has to open in text write mode, not binary write mode.append (bool) – if set to True messages are appended to the file and no header line is written, else the file is truncated and starts with a newly written header line
SqliteWriter¶
- class can.SqliteWriter(file, table_name='messages')[source]¶
Logs received CAN data to a simple SQL database.
The sqlite database may already exist, otherwise it will be created when the first message arrives.
Messages are internally buffered and written to the SQL file in a background thread. Ensures that all messages that are added before calling
stop()
are actually written to the database after that call returns. Thus, callingstop()
may take a while.- Attr str table_name
the name of the database table used for storing the messages
- Attr int num_frames
the number of frames actually written to the database, this excludes messages that are still buffered
- Attr float last_write
the last time a message war actually written to the database, as given by
time.time()
Note
When the listener’s
stop()
method is called the thread writing to the database will continue to receive and internally buffer messages if they continue to arrive before theGET_MESSAGE_TIMEOUT
.If the
GET_MESSAGE_TIMEOUT
expires before a message is received, the internal buffer is written out to the database file.However if the bus is still saturated with messages, the Listener will continue receiving until the
MAX_TIME_BETWEEN_WRITES
timeout is reached or more thanMAX_BUFFER_SIZE_BEFORE_WRITES
messages are buffered.Note
The database schema is given in the documentation of the loggers.
- Parameters
Warning
In contrary to all other readers/writers the Sqlite handlers do not accept file-like objects as the file parameter.
- GET_MESSAGE_TIMEOUT = 0.25¶
Number of seconds to wait for messages from internal queue
- MAX_BUFFER_SIZE_BEFORE_WRITES = 500¶
Maximum number of messages to buffer before writing to the database
- MAX_TIME_BETWEEN_WRITES = 5.0¶
Maximum number of seconds to wait between writes to the database
- class can.SqliteReader(file, table_name='messages')[source]¶
Reads recorded CAN messages from a simple SQL database.
This class can be iterated over or used to fetch all messages in the database with
read_all()
.Calling
len()
on this object might not run in constant time.- Attr str table_name
the name of the database table used for storing the messages
Note
The database schema is given in the documentation of the loggers.
- Parameters
Warning
In contrary to all other readers/writers the Sqlite handlers do not accept file-like objects as the file parameter. It also runs in
append=True
mode all the time.- read_all()[source]¶
Fetches all messages in the database.
- Return type
Generator[can.Message]
Database table format¶
The messages are written to the table messages
in the sqlite database
by default. The table is created if it does not already exist.
The entries are as follows:
Name |
Data type |
Note |
ts |
REAL |
The timestamp of the message |
arbitration_id |
INTEGER |
The arbitration id, might use the extended format |
extended |
INTEGER |
|
remote |
INTEGER |
|
error |
INTEGER |
|
dlc |
INTEGER |
The data length code (DLC) |
data |
BLOB |
The content of the message |
ASC (.asc Logging format)¶
ASCWriter logs CAN data to an ASCII log file compatible with other CAN tools such as Vector CANalyzer/CANoe and other. Since no official specification exists for the format, it has been reverse- engineered from existing log files. One description of the format can be found here.
Note
Channels will be converted to integers.
- class can.ASCWriter(file, channel=1)[source]¶
Logs CAN data to an ASCII log file (.asc).
The measurement starts with the timestamp of the first registered message. If a message has a timestamp smaller than the previous one or None, it gets assigned the timestamp that was written for the last message. It the first message does not have a timestamp, it is set to zero.
- Parameters
ASCReader reads CAN data from ASCII log files .asc, as further references can-utils can be used: asc2log, log2asc.
- class can.ASCReader(file, base='hex', relative_timestamp=True)[source]¶
Iterator of CAN messages from a ASC logging file. Meta data (comments, bus statistics, J1939 Transport Protocol messages) is ignored.
- Parameters
file (
Union
[str
, os.PathLike[str],TextIO
]) – a path-like object or as file-like object to read from If this is a file-like object, is has to opened in text read mode, not binary read mode.base (
str
) – Select the base(hex or dec) of id and data. If the header of the asc file contains base information, this value will be overwritten. Default “hex”.relative_timestamp (
bool
) – Select whether the timestamps are relative (starting at 0.0) or absolute (starting at the system time). Default True = relative.
Log (.log can-utils Logging format)¶
CanutilsLogWriter logs CAN data to an ASCII log file compatible with can-utils <https://github.com/linux-can/can-utils> As specification following references can-utils can be used: asc2log, log2asc.
- class can.CanutilsLogWriter(file, channel='vcan0', append=False)[source]¶
Logs CAN data to an ASCII log file (.log). This class is is compatible with “candump -L”.
If a message has a timestamp smaller than the previous one (or 0 or None), it gets assigned the timestamp that was written for the last message. It the first message does not have a timestamp, it is set to zero.
- Parameters
file (
Union
[str
, os.PathLike[str],TextIO
]) – a path-like object or as file-like object to write to If this is a file-like object, is has to opened in text write mode, not binary write mode.channel (
str
) – a default channel to use when the message does not have a channel setappend (bool) – if set to True messages are appended to the file, else the file is truncated
CanutilsLogReader reads CAN data from ASCII log files .log
BLF (Binary Logging Format)¶
Implements support for BLF (Binary Logging Format) which is a proprietary CAN log format from Vector Informatik GmbH.
The data is stored in a compressed format which makes it very compact.
Note
Channels will be converted to integers.
- class can.BLFWriter(file, append=False, channel=1, compression_level=- 1)[source]¶
Logs CAN data to a Binary Logging File compatible with Vector’s tools.
- Parameters
file (
Union
[str
, os.PathLike[str],BinaryIO
]) – a path-like object or as file-like object to write to If this is a file-like object, is has to opened in mode “wb+”.channel (
int
) – Default channel to log as if not specified by the interface.append (
bool
) – Append messages to an existing log file.compression_level (
int
) – An integer from 0 to 9 or -1 controlling the level of compression. 1 (Z_BEST_SPEED) is fastest and produces the least compression. 9 (Z_BEST_COMPRESSION) is slowest and produces the most. 0 means that data will be stored without processing. The default value is -1 (Z_DEFAULT_COMPRESSION). Z_DEFAULT_COMPRESSION represents a default compromise between speed and compression (currently equivalent to level 6).
- application_id = 5¶
Application identifier for the log writer
- log_event(text, timestamp=None)[source]¶
Add an arbitrary message to the log file as a global marker.
- max_container_size = 131072¶
Max log container size of uncompressed data
The following class can be used to read messages from BLF file:
Asyncio support¶
The asyncio
module built into Python 3.4 and later can be used to write
asynchronous code in a single thread. This library supports receiving messages
asynchronously in an event loop using the can.Notifier
class.
There will still be one thread per CAN bus but the user application will execute entirely in the event loop, allowing simpler concurrency without worrying about threading issues. Interfaces that have a valid file descriptor will however be supported natively without a thread.
You can also use the can.AsyncBufferedReader
listener if you prefer
to write coroutine based code instead of using callbacks.
Example¶
Here is an example using both callback and coroutine based code:
#!/usr/bin/env python
"""
This example demonstrates how to use async IO with python-can.
"""
import asyncio
from typing import List
import can
from can.notifier import MessageRecipient
def print_message(msg: can.Message) -> None:
"""Regular callback function. Can also be a coroutine."""
print(msg)
async def main() -> None:
"""The main function that runs in the loop."""
with can.Bus( # type: ignore
interface="virtual", channel="my_channel_0", receive_own_messages=True
) as bus:
reader = can.AsyncBufferedReader()
logger = can.Logger("logfile.asc")
listeners: List[MessageRecipient] = [
print_message, # Callback function
reader, # AsyncBufferedReader() listener
logger, # Regular Listener object
]
# Create Notifier with an explicit loop to use for scheduling of callbacks
loop = asyncio.get_running_loop()
notifier = can.Notifier(bus, listeners, loop=loop)
# Start sending first message
bus.send(can.Message(arbitration_id=0))
print("Bouncing 10 messages...")
for _ in range(10):
# Wait for next message from AsyncBufferedReader
msg = await reader.get_message()
# Delay response
await asyncio.sleep(0.5)
msg.arbitration_id += 1
bus.send(msg)
# Wait for last message to arrive
await reader.get_message()
print("Done!")
# Clean-up
notifier.stop()
if __name__ == "__main__":
asyncio.run(main())
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
3"""
4This example exercises the periodic sending capabilities.
5
6Expects a vcan0 interface:
7
8 python3 -m examples.cyclic
9
10"""
11
12import logging
13import time
14
15import can
16
17logging.basicConfig(level=logging.INFO)
18
19
20def simple_periodic_send(bus):
21 """
22 Sends a message every 20ms with no explicit timeout
23 Sleeps for 2 seconds then stops the task.
24 """
25 print("Starting to send a message every 200ms for 2s")
26 msg = can.Message(
27 arbitration_id=0x123, data=[1, 2, 3, 4, 5, 6], is_extended_id=False
28 )
29 task = bus.send_periodic(msg, 0.20)
30 assert isinstance(task, can.CyclicSendTaskABC)
31 time.sleep(2)
32 task.stop()
33 print("stopped cyclic send")
34
35
36def limited_periodic_send(bus):
37 """Send using LimitedDurationCyclicSendTaskABC."""
38 print("Starting to send a message every 200ms for 1s")
39 msg = can.Message(
40 arbitration_id=0x12345678, data=[0, 0, 0, 0, 0, 0], is_extended_id=True
41 )
42 task = bus.send_periodic(msg, 0.20, 1, store_task=False)
43 if not isinstance(task, can.LimitedDurationCyclicSendTaskABC):
44 print("This interface doesn't seem to support LimitedDurationCyclicSendTaskABC")
45 task.stop()
46 return
47
48 time.sleep(2)
49 print("Cyclic send should have stopped as duration expired")
50 # Note the (finished) task will still be tracked by the Bus
51 # unless we pass `store_task=False` to bus.send_periodic
52 # alternatively calling stop removes the task from the bus
53 # task.stop()
54
55
56def test_periodic_send_with_modifying_data(bus):
57 """Send using ModifiableCyclicTaskABC."""
58 print("Starting to send a message every 200ms. Initial data is four consecutive 1s")
59 msg = can.Message(arbitration_id=0x0CF02200, data=[1, 1, 1, 1])
60 task = bus.send_periodic(msg, 0.20)
61 if not isinstance(task, can.ModifiableCyclicTaskABC):
62 print("This interface doesn't seem to support modification")
63 task.stop()
64 return
65 time.sleep(2)
66 print("Changing data of running task to begin with 99")
67 msg.data[0] = 0x99
68 task.modify_data(msg)
69 time.sleep(2)
70
71 task.stop()
72 print("stopped cyclic send")
73 print("Changing data of stopped task to single ff byte")
74 msg.data = bytearray([0xFF])
75 msg.dlc = 1
76 task.modify_data(msg)
77 time.sleep(1)
78 print("starting again")
79 task.start()
80 time.sleep(1)
81 task.stop()
82 print("done")
83
84
85# Will have to consider how to expose items like this. The socketcan
86# interfaces will continue to support it... but the top level api won't.
87# def test_dual_rate_periodic_send():
88# """Send a message 10 times at 1ms intervals, then continue to send every 500ms"""
89# msg = can.Message(arbitration_id=0x123, data=[0, 1, 2, 3, 4, 5])
90# print("Creating cyclic task to send message 10 times at 1ms, then every 500ms")
91# task = can.interface.MultiRateCyclicSendTask('vcan0', msg, 10, 0.001, 0.50)
92# time.sleep(2)
93#
94# print("Changing data[0] = 0x42")
95# msg.data[0] = 0x42
96# task.modify_data(msg)
97# time.sleep(2)
98#
99# task.stop()
100# print("stopped cyclic send")
101#
102# time.sleep(2)
103#
104# task.start()
105# print("starting again")
106# time.sleep(2)
107# task.stop()
108# print("done")
109
110
111def main():
112 """Test different cyclic sending tasks."""
113 reset_msg = can.Message(
114 arbitration_id=0x00, data=[0, 0, 0, 0, 0, 0], is_extended_id=False
115 )
116
117 with can.Bus(interface="virtual") as bus:
118 bus.send(reset_msg)
119
120 simple_periodic_send(bus)
121
122 bus.send(reset_msg)
123
124 limited_periodic_send(bus)
125
126 test_periodic_send_with_modifying_data(bus)
127
128 # print("Carrying out multirate cyclic test for {} interface".format(interface))
129 # can.rc['interface'] = interface
130 # test_dual_rate_periodic_send()
131
132 time.sleep(2)
133
134
135if __name__ == "__main__":
136 main()
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.CyclicSendTaskABC(messages, period)[source]¶
Message send task with defined period
- class can.broadcastmanager.LimitedDurationCyclicSendTaskABC(messages, period, duration)[source]¶
Message send task with a defined duration and period.
- Parameters
messages (
Union
[Sequence
[Message
],Message
]) – The messages to be sent periodically.period (
float
) – The rate in seconds at which to send the messages.duration (
Optional
[float
]) – Approximate duration in seconds to continue sending messages. If no duration is provided, the task will continue indefinitely.
- Raises
ValueError – If the given messages are invalid
- class can.broadcastmanager.MultiRateCyclicSendTaskABC(channel, messages, 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 messages at subsequent_period.
- class can.ModifiableCyclicTaskABC(messages, period)[source]¶
Adds support for modifying a periodic message
- Parameters
- Raises
ValueError – If the given messages are invalid
- modify_data(messages)[source]¶
Update the contents of the periodically sent messages, without altering the timing.
- Parameters
messages (
Union
[Sequence
[Message
],Message
]) –The messages with the new
Message.data
.Note: The arbitration ID cannot be changed.
Note: The number of new cyclic messages to be sent must be equal to the original number of messages originally specified for this task.
- Raises
ValueError – If the given messages are invalid
- Return type
- class can.RestartableCyclicTaskABC(messages, period)[source]¶
Adds support for restarting a stopped cyclic task
- Parameters
- Raises
ValueError – If the given messages are invalid
Bit Timing Configuration¶
The CAN protocol allows the bitrate, sample point and number of samples to be optimized for a given application. You can read more on Wikipedia, Kvaser and other sources.
In most cases the recommended settings for a predefined set of common
bitrates will work just fine. In some cases it may however be necessary to specify
custom settings. The can.BitTiming
class can be used for this purpose to
specify them in a relatively interface agnostic manner.
It is also possible to specify the same settings for a CAN 2.0 bus using the config file:
[default]
bitrate=1000000
f_clock=8000000
tseg1=5
tseg2=2
sjw=1
nof_samples=1
[default]
brp=1
tseg1=5
tseg2=2
sjw=1
nof_samples=1
[default]
btr0=0x00
btr1=0x14
- class can.BitTiming(bitrate=None, f_clock=None, brp=None, tseg1=None, tseg2=None, sjw=None, nof_samples=1, btr0=None, btr1=None)[source]¶
Representation of a bit timing configuration.
The class can be constructed in various ways, depending on the information available or the capabilities of the interfaces that need to be supported.
The preferred way is using bitrate, CAN clock frequency, TSEG1, TSEG2, SJW:
can.BitTiming(bitrate=1000000, f_clock=8000000, tseg1=5, tseg2=1, sjw=1)
If the clock frequency is unknown it may be omitted but some interfaces may require it.
Alternatively the BRP can be given instead of bitrate and clock frequency but this will limit the number of supported interfaces.
It is also possible specify BTR registers directly, but will not work for all interfaces:
can.BitTiming(btr0=0x00, btr1=0x14)
- Parameters
bitrate (int) – Bitrate in bits/s.
f_clock (int) – The CAN system clock frequency in Hz. Usually the oscillator frequency divided by 2.
brp (int) – Bit Rate Prescaler. Prefer to use bitrate and f_clock instead.
tseg1 (int) – Time segment 1, that is, the number of quanta from (but not including) the Sync Segment to the sampling point.
tseg2 (int) – Time segment 2, that is, the number of quanta from the sampling point to the end of the bit.
sjw (int) – The Synchronization Jump Width. Decides the maximum number of time quanta that the controller can resynchronize every bit.
nof_samples (int) – Either 1 or 3. Some CAN controllers can also sample each bit three times. In this case, the bit will be sampled three quanta in a row, with the last sample being taken in the edge between TSEG1 and TSEG2. Three samples should only be used for relatively slow baudrates.
btr0 (int) – The BTR0 register value used by many CAN controllers.
btr1 (int) – The BTR1 register value used by many CAN controllers.
Internal API¶
Here we document the odds and ends that are more helpful for creating your own interfaces or listeners but generally shouldn’t be required to interact with python-can.
Extending the BusABC
class¶
- Concrete implementations must implement the following:
send()
to send individual messages_recv_internal()
to receive individual messages (see note below!)set the
channel_info
attribute to a string describing the underlying bus and/or channel
- They might implement the following:
flush_tx_buffer()
to allow discarding any messages yet to be sentshutdown()
to override how the bus should shut down_send_periodic_internal()
to override the software based periodic sending and push it down to the kernel or hardware._apply_filters()
to apply efficient filters to lower level systems like the OS kernel or hardware._detect_available_configs()
to allow the interface to report which configurations are currently available for new connections.state()
property to allow reading and/or changing the bus state.
Note
TL;DR: Only override _recv_internal()
,
never recv()
directly.
Previously, concrete bus classes had to override recv()
directly instead of _recv_internal()
, but that has
changed to allow the abstract base class to handle in-software message
filtering as a fallback. All internal interfaces now implement that new
behaviour. Older (custom) interfaces might still be implemented like that
and thus might not provide message filtering:
Concrete instances are usually created by can.Bus
which takes the users
configuration into account.
Bus Internals¶
Several methods are not documented in the main can.BusABC
as they are primarily useful for library developers as opposed to
library users. This is the entire ABC bus class with all internal
methods:
- class can.BusABC(channel, can_filters=None, **kwargs)[source]
The CAN Bus Abstract Base Class that serves as the basis for all concrete interfaces.
This class may be used as an iterator over the received messages and as a context manager for auto-closing the bus when done using it.
Please refer to Errors for possible exceptions that may be thrown by certain operations on this bus.
Construct and open a CAN bus instance of the specified type.
Subclasses should call though this method with all given parameters as it handles generic tasks like applying filters.
- Parameters
- Raises
ValueError – If parameters are out of range
can.CanInterfaceNotImplementedError – If the driver cannot be accessed
can.CanInitializationError – If the bus cannot be initialized
About the IO module¶
Handling of the different file formats is implemented in can.io
.
Each file/IO type is within a separate module and ideally implements both a Reader and a Writer.
The reader usually extends can.io.generic.BaseIOHandler
, while
the writer often additionally extends can.Listener
,
to be able to be passed directly to a can.Notifier
.
Adding support for new file formats¶
This assumes that you want to add a new file format, called canstore. Ideally add both reading and writing support for the new file format, although this is not strictly required.
Create a new module: can/io/canstore.py (or simply copy some existing one like can/io/csv.py)
Implement a reader
CanstoreReader
(which often extendscan.io.generic.BaseIOHandler
, but does not have to). Besides from a constructor, only__iter__(self)
needs to be implemented.Implement a writer
CanstoreWriter
(which often extendscan.io.generic.BaseIOHandler
andcan.Listener
, but does not have to). Besides from a constructor, onlyon_message_received(self, msg)
needs to be implemented.Add a case to
can.io.player.LogReader
’s__new__()
.Document the two new classes (and possibly additional helpers) with docstrings and comments. Please mention features and limitations of the implementation.
Add a short section to the bottom of doc/listeners.rst.
Add tests where appropriate, for example by simply adding a test case called class TestCanstoreFileFormat(ReaderWriterTest) to test/logformats_test.py. That should already handle all of the general testing. Just follow the way the other tests in there do it.
Add imports to can/__init__py and can/io/__init__py so that the new classes can be simply imported as from can import CanstoreReader, CanstoreWriter.
IO Utilities¶
Contains generic base classes for file IO.
- class can.io.generic.BaseIOHandler(file, mode='rt')[source]¶
A generic file handler that can be used for reading and writing.
Can be used as a context manager.
- Attr file
the file-like object that is kept internally, or None if none was opened
- Parameters
- class can.io.generic.FileIOMessageWriter(file, mode='rt')[source]¶
A specialized base class for all writers with file descriptors.
Other Utilities¶
Utilities and configuration file parsing.
- can.util.deprecated_args_alias(**aliases)[source]¶
Allows to rename/deprecate a function kwarg(s) and optionally have the deprecated kwarg(s) set as alias(es)
Example:
@deprecated_args_alias(oldArg=”new_arg”, anotherOldArg=”another_new_arg”) def library_function(new_arg, another_new_arg):
pass
@deprecated_args_alias(oldArg=”new_arg”, obsoleteOldArg=None) def library_function(new_arg):
pass
- can.util.load_config(path=None, config=None, context=None)[source]¶
Returns a dict with configuration details which is loaded from (in this order):
config
can.rc
Environment variables CAN_INTERFACE, CAN_CHANNEL, CAN_BITRATE
Config files
/etc/can.conf
or~/.can
or~/.canrc
where the latter may add or replace values of the former.
Interface can be any of the strings from
can.VALID_INTERFACES
for example: kvaser, socketcan, pcan, usb2can, ixxat, nican, virtual.Note
The key
bustype
is copied tointerface
if that one is missing and does never appear in the result.- Parameters
path – Optional path to config file.
config – A dict which may set the ‘interface’, and/or the ‘channel’, or neither. It may set other values that are passed through.
context – Extra ‘context’ pass to config sources. This can be use to section other than ‘default’ in the configuration file.
- Returns
A config dictionary that should contain ‘interface’ & ‘channel’:
{ 'interface': 'python-can backend interface to use', 'channel': 'default channel to use', # possibly more }
Note
None
will be used if all the options are exhausted without finding a value.All unused values are passed from
config
over to this.- Raises
CanInterfaceNotImplementedError if the
interface
name isn’t recognized
- can.util.load_environment_config(context=None)[source]¶
Loads config dict from environmental variables (if set):
CAN_INTERFACE
CAN_CHANNEL
CAN_BITRATE
CAN_CONFIG
if context is supplied, “_{context}” is appended to the environment variable name we will look at. For example if context=”ABC”:
CAN_INTERFACE_ABC
CAN_CHANNEL_ABC
CAN_BITRATE_ABC
CAN_CONFIG_ABC
- can.util.load_file_config(path=None, section='default')[source]¶
Loads configuration from file with following content:
[default] interface = socketcan channel = can0
- Parameters
path – path to config file. If not specified, several sensible default locations are tried depending on platform.
section – name of the section to read configuration from.
- can.util.set_logging_level(level_name)[source]¶
Set the logging level for the “can” logger.
- Parameters
level_name (
str
) – One of: ‘critical’, ‘error’, ‘warning’, ‘info’,
‘debug’, ‘subdebug’, or the value None (=default). Defaults to ‘debug’.
- Return type
- can.util.time_perfcounter_correlation()[source]¶
Get the perf_counter value nearest to when time.time() is updated
Computed if the default timer used by time.time on this platform has a resolution higher than 10μs, otherwise the current time and perf_counter is directly returned. This was chosen as typical timer resolution on Linux/macOS is ~1μs, and the Windows platform can vary from ~500μs to 10ms.
Note this value is based on when time.time() is observed to update from Python, it is not directly returned by the operating system.
Utilities¶
- can.detect_available_configs(interfaces=None)[source]¶
Detect all configurations/channels that the interfaces could currently connect with.
This might be quite time consuming.
Automated configuration detection may not be implemented by every interface on every platform. This method will not raise an error in that case, but with rather return an empty list for that interface.
- Parameters
interfaces (
Union
[None
,str
,Iterable
[str
]]) – either - the name of an interface to be searched in as a string, - an iterable of interface names to search in, or - None to search in all known interfaces.- Return type
- Returns
an iterable of dicts, each suitable for usage in the constructor of
can.BusABC
.
Notifier¶
The Notifier object is used as a message distributor for a bus. Notifier 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
bus (
Union
[BusABC
,List
[BusABC
]]) – A Bus or a list of buses to listen to.listeners (
Iterable
[Union
[Listener
,Callable
[[Message
],None
]]]) – An iterable ofListener
or callables that receive aMessage
and return nothing.timeout (
float
) – An optional maximum number of seconds to wait for anyMessage
.loop (
Optional
[AbstractEventLoop
]) – Anasyncio
event loop to schedule thelisteners
in.
- 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.
- 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
) – Listener to be removed from the list to be notified- Raises
ValueError – if listener was never added to this notifier
- Return type
Errors¶
There are several specific Exception
classes to allow user
code to react to specific scenarios related to CAN busses:
Exception (Python standard library)
+-- ...
+-- CanError (python-can)
+-- CanInterfaceNotImplementedError
+-- CanInitializationError
+-- CanOperationError
+-- CanTimeoutError
Keep in mind that some functions and methods may raise different exceptions.
For example, validating typical arguments and parameters might result in a
ValueError
. This should always be documented for the function at hand.
- exception can.exceptions.CanError(message='', error_code=None)[source]¶
Bases:
Exception
Base class for all CAN related exceptions.
If specified, the error code is automatically appended to the message:
>>> # With an error code (it also works with a specific error): >>> error = CanOperationError(message="Failed to do the thing", error_code=42) >>> str(error) 'Failed to do the thing [Error Code 42]' >>> >>> # Missing the error code: >>> plain_error = CanError(message="Something went wrong ...") >>> str(plain_error) 'Something went wrong ...'
- exception can.exceptions.CanInitializationError(message='', error_code=None)[source]¶
Bases:
can.exceptions.CanError
Indicates an error the occurred while initializing a
can.BusABC
.If initialization fails due to a driver or platform missing/being unsupported, a
can.CanInterfaceNotImplementedError
is raised instead. If initialization fails due to a value being out of range, aValueError
is raised.- Example scenarios:
Try to open a non-existent device and/or channel
Try to use an invalid setting, which is ok by value, but not ok for the interface
The device or other resources are already used
- exception can.exceptions.CanInterfaceNotImplementedError(message='', error_code=None)[source]¶
Bases:
can.exceptions.CanError
,NotImplementedError
Indicates that the interface is not supported on the current platform.
- Example scenarios:
No interface with that name exists
The interface is unsupported on the current operating system or interpreter
The driver could not be found or has the wrong version
- exception can.exceptions.CanOperationError(message='', error_code=None)[source]¶
Bases:
can.exceptions.CanError
Indicates an error while in operation.
- Example scenarios:
A call to a library function results in an unexpected return value
An invalid message was received
The driver rejected a message that was meant to be sent
Cyclic redundancy check (CRC) failed
A message remained unacknowledged
A buffer is full
- exception can.exceptions.CanTimeoutError(message='', error_code=None)[source]¶
Bases:
can.exceptions.CanError
,TimeoutError
Indicates the timeout of an operation.
- Example scenarios:
Some message could not be sent after the timeout elapsed
No message was read within the given time
CAN Interface Modules¶
python-can hides the low-level, device-specific interfaces to controller area network adapters in interface dependant modules. However as each hardware device is different, you should carefully go through your interface’s documentation.
The available interfaces are:
CANalyst-II¶
CANalyst-II is a USB to CAN Analyzer device produced by Chuangxin Technology.
Install: pip install "python-can[canalystii]"
Supported platform¶
Windows, Linux and Mac.
Note
The backend driver depends on pyusb <https://pyusb.github.io/pyusb/> so a pyusb
backend driver library such as libusb
must be installed. On Windows a tool such as Zadig <https://zadig.akeo.ie/> can be used to set the Canalyst-II USB device driver to libusb-win32
.
Limitations¶
Multiple Channels¶
The USB protocol transfers messages grouped by channel. Messages received on channel 0 and channel 1 may be returned by software out of order between the two channels (although inside each channel, all messages are in order). The timestamp field of each message comes from the hardware and shows the exact time each message was received. To compare ordering of messages on channel 0 vs channel 1, sort the received messages by the timestamp field first.
Backend Driver¶
The backend driver module canalystii <https://pypi.org/project/canalystii> must be installed to use this interface. This open source driver is unofficial and based on reverse engineering. Earlier versions of python-can required a binary library from the vendor for this functionality.
Bus¶
ETAS¶
This interface adds support for CAN interfaces by ETAS. The ETAS BOA (Basic Open API) is used. Install the “ETAS ECU and Bus Interfaces – Distribution Package”. Only Windows is supported by this interface. The Linux kernel v5.13 (and greater) natively supports ETAS ES581.4, ES582.1 and ES584.1 USB modules. To use these under Linux, please refer to socketcan.
Bus¶
Configuration file¶
The simplest configuration file would be:
[default]
interface = etas
channel = ETAS://ETH/ES910:abcd/CAN:1
Channels are the URIs used by the underlying API.
To find available URIs, use detect_available_configs()
:
configs = can.interface.detect_available_configs(interfaces="etas")
for c in configs:
print(c)
CAN driver for Geschwister Schneider USB/CAN devices and bytewerk.org candleLight USB CAN interfaces¶
Windows/Linux/Mac CAN driver based on usbfs or WinUSB WCID for Geschwister Schneider USB/CAN devices and candleLight USB CAN interfaces.
Install: pip install "python-can[gs_usb]"
Usage: pass bus
and address
to open the device. The parameters can be got by pyusb
as shown below:
import usb
import can
dev = usb.core.find(idVendor=0x1D50, idProduct=0x606F)
bus = can.Bus(bustype="gs_usb", channel=dev.product, bus=dev.bus, address=dev.address, bitrate=250000)
Supported devices¶
Geschwister Schneider USB/CAN devices and bytewerk.org candleLight USB CAN interfaces such as candleLight, canable, cantact, etc.
Supported platform¶
Windows, Linux and Mac.
Note
The backend driver depends on pyusb <https://pyusb.github.io/pyusb/> so a pyusb
backend driver library such as libusb
must be installed. On Windows a tool such as Zadig <https://zadig.akeo.ie/> can be used to set the USB device driver to libusb-win32
.
Supplementary Info on gs_usb
¶
The firmware implementation for Geschwister Schneider USB/CAN devices and candleLight USB CAN can be found in candle-usb/candleLight_fw. The Linux kernel driver can be found in linux/drivers/net/can/usb/gs_usb.c.
The gs_usb
interface in PythonCan
relys on upstream gs_usb
package, which can be found in https://pypi.org/project/gs-usb/ or https://github.com/jxltom/gs_usb.
The gs_usb
package is using pyusb
as backend, which brings better crossplatform compatibility.
Note: The bitrate 10K
, 20K
, 50K
, 83.333K
, 100K
, 125K
, 250K
, 500K
, 800K
and 1M
are supported in this interface, as implemented in the upstream gs_usb
package’s set_bitrate
method.
Note: Message filtering is not supported in Geschwister Schneider USB/CAN devices and bytewerk.org candleLight USB CAN interfaces.
Bus¶
isCAN¶
Interface for isCAN from Thorsis Technologies GmbH, former ifak system GmbH.
Bus¶
IXXAT Virtual CAN Interface¶
Interface to IXXAT Virtual CAN Interface V3 SDK. Works on Windows.
The Linux ECI SDK is currently unsupported, however on Linux some devices are supported with SocketCAN.
The send_periodic()
method is supported
natively through the on-board cyclic transmit list.
Modifying cyclic messages is not possible. You will need to stop it, and then
start a new periodic message.
Bus¶
Configuration file¶
The simplest configuration file would be:
[default]
interface = ixxat
channel = 0
Python-can will search for the first IXXAT device available and open the first channel.
interface
and channel
parameters are interpreted by frontend can.interfaces.interface
module, while the following parameters are optional and are interpreted by IXXAT implementation.
receive_own_messages
(default False) Enable self-reception of sent messages.unique_hardware_id
(default first device) Unique hardware ID of the IXXAT device.extended
(default True) Allow usage of extended IDs.fd
(default False) Enable CAN-FD capabilities.rx_fifo_size
(default 16 for CAN, 1024 for CAN-FD) Number of RX mailboxes.tx_fifo_size
(default 16 for CAN, 128 for CAN-FD) Number of TX mailboxes.bitrate
(default 500000) Channel bitrate.data_bitrate
(defaults to 2Mbps) Channel data bitrate (only canfd, to use when message bitrate_switch is used).sjw_abr
(optional, only canfd) Bus timing value sample jump width (arbitration).tseg1_abr
(optional, only canfd) Bus timing value tseg1 (arbitration).tseg2_abr
(optional, only canfd) Bus timing value tseg2 (arbitration).sjw_dbr
(optional, only used if baudrate switch enabled) Bus timing value sample jump width (data).tseg1_dbr
(optional, only used if baudrate switch enabled) Bus timing value tseg1 (data).tseg2_dbr
(optional, only used if baudrate switch enabled) Bus timing value tseg2 (data).ssp_dbr
(optional, only used if baudrate switch enabled) Secondary sample point (data).
Filtering¶
The CAN filters act as an allow list in IXXAT implementation, that is if you supply a non-empty filter list you must explicitly state EVERY frame you want to receive (including RTR field). The can_id/mask must be specified according to IXXAT behaviour, that is bit 0 of can_id/mask parameters represents the RTR field in CAN frame. See IXXAT VCI documentation, section “Message filters” for more info.
List available devices¶
In case you have connected multiple IXXAT devices, you have to select them by using their unique hardware id.
To get a list of all connected IXXAT you can use the function get_ixxat_hwids()
as demonstrated below:
>>> from can.interfaces.ixxat import get_ixxat_hwids
>>> for hwid in get_ixxat_hwids():
... print("Found IXXAT with hardware id '%s'." % hwid)
Found IXXAT with hardware id 'HW441489'.
Found IXXAT with hardware id 'HW107422'.
Internals¶
The IXXAT BusABC
object is a fairly straightforward interface
to the IXXAT VCI library. It can open a specific device ID or use the
first one found.
The frame exchange does not involve threads in the background but is explicitly instantiated by the caller.
recv()
is a blocking call with optional timeout.send()
is not blocking but may raise a VCIError if the TX FIFO is full
RX and TX FIFO sizes are configurable with rx_fifo_size
and tx_fifo_size
options, defaulting to 16 for both.
Kvaser’s CANLIB¶
Kvaser’s CANLib SDK for Windows (also available on Linux).
Bus¶
- class can.interfaces.kvaser.canlib.KvaserBus(channel, can_filters=None, **kwargs)[source]¶
The CAN Bus implemented for the Kvaser interface.
- Parameters
channel (int) – The Channel id to create this bus with.
can_filters (list) – See
can.BusABC.set_filters()
.
Backend Configuration
- Parameters
bitrate (int) – Bitrate of channel in bit/s
accept_virtual (bool) – If virtual channels should be accepted.
tseg1 (int) – Time segment 1, that is, the number of quanta from (but not including) the Sync Segment to the sampling point. If this parameter is not given, the Kvaser driver will try to choose all bit timing parameters from a set of defaults.
tseg2 (int) – Time segment 2, that is, the number of quanta from the sampling point to the end of the bit.
sjw (int) – The Synchronization Jump Width. Decides the maximum number of time quanta that the controller can resynchronize every bit.
no_samp (int) – Either 1 or 3. Some CAN controllers can also sample each bit three times. In this case, the bit will be sampled three quanta in a row, with the last sample being taken in the edge between TSEG1 and TSEG2. Three samples should only be used for relatively slow baudrates.
driver_mode (bool) – Silent or normal.
single_handle (bool) – Use one Kvaser CANLIB bus handle for both reading and writing. This can be set if reading and/or writing is done from one thread.
receive_own_messages (bool) – If messages transmitted should also be received back. Only works if single_handle is also False. If you want to receive messages from other applications on the same computer, set this to True or set single_handle to True.
fd (bool) – If CAN-FD frames should be supported.
data_bitrate (int) – Which bitrate to use for data phase in CAN FD. Defaults to arbitration bitrate.
- flash(flash=True)[source]¶
Turn on or off flashing of the device’s LED for physical identification purposes.
- send(msg, timeout=None)[source]¶
Transmit a message to the CAN bus.
Override this method to enable the transmit path.
- Parameters
msg (Message) – A message object.
timeout – If > 0, wait up to this many seconds for message to be ACK’ed or for transmit queue to be ready depending on driver implementation. If timeout is exceeded, an exception will be raised. Might not be supported by all interfaces. None blocks indefinitely.
- Raises
can.CanOperationError – If an error occurred while sending
Internals¶
The Kvaser Bus
object with a physical CAN Bus can be operated in two
modes; single_handle
mode with one shared bus handle used for both reading and
writing to the CAN bus, or with two separate bus handles.
Two separate handles are needed if receiving and sending messages are done in
different threads (see Kvaser documentation).
Warning
Any objects inheriting from Bus should not directly use the interface handle(/s).
Message filtering¶
The Kvaser driver and hardware only supports setting one filter per handle.
If one filter is requested, this is will be handled by the Kvaser driver.
If more than one filter is needed, these will be handled in Python code
in the recv
method. If a message does not match any of the filters,
recv()
will return None.
Custom methods¶
This section contains Kvaser driver specific methods.
neoVI¶
Warning
This ICS neoVI
documentation is a work in progress. Feedback and revisions
are most welcome!
Interface to Intrepid Control Systems neoVI API range of devices via python-ics wrapper on Windows.
Installation¶
This neoVI interface requires the installation of the ICS neoVI DLL and python-ics package.
- Download and install the Intrepid Product Drivers
- Install python-ics
pip install python-ics
Configuration¶
An example can.ini file for windows 7:
[default]
interface = neovi
channel = 1
Bus¶
- class can.interfaces.ics_neovi.NeoViBus(channel, can_filters=None, **kwargs)[source]¶
The CAN Bus implemented for the python_ics interface https://github.com/intrepidcs/python_ics
- Parameters
channel (int or str or list(int) or list(str)) – The channel ids to create this bus with. Can also be a single integer, netid name or a comma separated string.
can_filters (list) – See
can.BusABC.set_filters()
for details.receive_own_messages (bool) – If transmitted messages should also be received by this bus.
use_system_timestamp (bool) – Use system timestamp for can messages instead of the hardware time stamp
serial (str) – Serial to connect (optional, will use the first found if not supplied)
bitrate (int) – Channel bitrate in bit/s. (optional, will enable the auto bitrate feature if not supplied)
fd (bool) – If CAN-FD frames should be supported.
data_bitrate (int) – Which bitrate to use for data phase in CAN FD. Defaults to arbitration bitrate.
override_library_name – Absolute path or relative path to the library including filename.
- Raises
ImportError – If python-ics is not available
CanInitializationError – If the bus could not be set up. May or may not be a
ICSInitializationError
.
NI-CAN¶
This interface adds support for CAN controllers by National Instruments.
Warning
NI-CAN only seems to support 32-bit architectures so if the driver can’t be loaded on a 64-bit Python, try using a 32-bit version instead.
Warning
CAN filtering has not been tested thoroughly and may not work as expected.
Bus¶
- class can.interfaces.nican.NicanBus(channel, can_filters=None, bitrate=None, log_errors=True, **kwargs)[source]¶
The CAN Bus implemented for the NI-CAN interface.
Warning
This interface does implement efficient filtering of messages, but the filters have to be set in
__init__()
using thecan_filters
parameter. Usingset_filters()
does not work.- Parameters
channel (
str
) – Name of the object to open (e.g. “CAN0”)can_filters (
Optional
[Sequence
[Union
[CanFilter
,CanFilterExtended
]]]) – Seecan.BusABC.set_filters()
.log_errors (
bool
) – If True, communication errors will appear as CAN messages withis_error_frame
set to True andarbitration_id
will identify the error (default True)
- Raises
can.CanInterfaceNotImplementedError – If the current operating system is not supported or the driver could not be loaded.
can.interfaces.nican.NicanInitializationError – If the bus could not be set up.
NI-XNET¶
This interface adds support for NI-XNET CAN controllers by National Instruments.
Warning
NI-XNET only seems to support windows platforms.
Bus¶
PCAN Basic API¶
Interface to Peak-System’s PCAN-Basic API.
Configuration¶
Here is an example configuration file for using PCAN-USB:
[default]
interface = pcan
channel = PCAN_USBBUS1
state = can.bus.BusState.PASSIVE
bitrate = 500000
channel
: (default "PCAN_USBBUS1"
) CAN interface name
state
: (default can.bus.BusState.ACTIVE
) BusState of the channel
bitrate
: (default 500000
) Channel bitrate
Valid channel
values:
PCAN_ISABUSx
PCAN_DNGBUSx
PCAN_PCIBUSx
PCAN_USBBUSx
PCAN_PCCBUSx
PCAN_LANBUSx
Where x
should be replaced with the desired channel number starting at 1
.
Linux installation¶
Beginning with version 3.4, Linux kernels support the PCAN adapters natively via SocketCAN, refer to: PCAN.
Bus¶
- class can.interfaces.pcan.PcanBus(channel='PCAN_USBBUS1', state=BusState.ACTIVE, bitrate=500000, *args, **kwargs)[source]¶
A PCAN USB interface to CAN.
On top of the usual
Bus
methods provided, the PCAN interface includes theflash()
andstatus()
methods.- Parameters
channel (str) – The can interface name. An example would be ‘PCAN_USBBUS1’. Alternatively the value can be an int with the numerical value. Default is ‘PCAN_USBBUS1’
state (can.bus.BusState) – BusState of the channel. Default is ACTIVE
bitrate (int) – Bitrate of channel in bit/s. Default is 500 kbit/s. Ignored if using CanFD.
fd (bool) – Should the Bus be initialized in CAN-FD mode.
f_clock (int) – Clock rate in Hz. Any of the following: 20000000, 24000000, 30000000, 40000000, 60000000, 80000000. Ignored if not using CAN-FD. Pass either f_clock or f_clock_mhz.
f_clock_mhz (int) – Clock rate in MHz. Any of the following: 20, 24, 30, 40, 60, 80. Ignored if not using CAN-FD. Pass either f_clock or f_clock_mhz.
nom_brp (int) – Clock prescaler for nominal time quantum. In the range (1..1024) Ignored if not using CAN-FD.
nom_tseg1 (int) – Time segment 1 for nominal bit rate, that is, the number of quanta from (but not including) the Sync Segment to the sampling point. In the range (1..256). Ignored if not using CAN-FD.
nom_tseg2 (int) – Time segment 2 for nominal bit rate, that is, the number of quanta from the sampling point to the end of the bit. In the range (1..128). Ignored if not using CAN-FD.
nom_sjw (int) – Synchronization Jump Width for nominal bit rate. Decides the maximum number of time quanta that the controller can resynchronize every bit. In the range (1..128). Ignored if not using CAN-FD.
data_brp (int) – Clock prescaler for fast data time quantum. In the range (1..1024) Ignored if not using CAN-FD.
data_tseg1 (int) – Time segment 1 for fast data bit rate, that is, the number of quanta from (but not including) the Sync Segment to the sampling point. In the range (1..32). Ignored if not using CAN-FD.
data_tseg2 (int) – Time segment 2 for fast data bit rate, that is, the number of quanta from the sampling point to the end of the bit. In the range (1..16). Ignored if not using CAN-FD.
data_sjw (int) – Synchronization Jump Width for fast data bit rate. Decides the maximum number of time quanta that the controller can resynchronize every bit. In the range (1..16). Ignored if not using CAN-FD.
Chinese CAN-USB interface (mfg. Robotell etc.)¶
An USB to CAN adapter sold on Aliexpress, etc. with the manufacturer name Robotell printed on the case.
There is also a USB stick version with a clear case. If the description or screenshots refer to EmbededDebug
or EmbededConfig
the device should be compatible with this driver.
These USB devices are based on a STM32 controller with a CH340 serial interface and use a binary protocol - NOT compatible with SLCAN
See https://www.amobbs.com/thread-4651667-1-1.html for some background on these devices.
This driver directly uses either the local or remote (not tested) serial port. Remote serial ports will be specified via special URL. Both raw TCP sockets as also RFC2217 ports are supported.
Usage: use port or URL[@baurate]
to open the device.
For example use /dev/ttyUSB0@115200
or COM4@9600
for local serial ports and
socket://192.168.254.254:5000
or rfc2217://192.168.254.254:5000
for remote ports.
Supported devices¶
Todo
Document this.
Bus¶
- class can.interfaces.robotell.robotellBus(channel, ttyBaudrate=115200, bitrate=None, rtscts=False, **kwargs)[source]¶
robotell interface
- Parameters
channel (str) – port of underlying serial or usb device (e.g.
/dev/ttyUSB0
,COM8
, …) Must not be empty. Can also end with@115200
(or similarly) to specify the baudrate.ttyBaudrate (int) – baudrate of underlying serial or usb device (Ignored if set via the
channel
parameter)bitrate (int) – CAN Bitrate in bit/s. Value is stored in the adapter and will be used as default if no bitrate is specified
rtscts (bool) – turn hardware handshake (RTS/CTS) on and off
- get_serial_number(timeout)[source]¶
Get serial number of the slcan interface. :type timeout: int or None :param timeout:
seconds to wait for serial number or None to wait indefinitely
:rtype str or None :return:
None on timeout or a str object.
- send(msg, timeout=None)[source]¶
Transmit a message to the CAN bus.
Override this method to enable the transmit path.
- Parameters
msg (Message) – A message object.
timeout – If > 0, wait up to this many seconds for message to be ACK’ed or for transmit queue to be ready depending on driver implementation. If timeout is exceeded, an exception will be raised. Might not be supported by all interfaces. None blocks indefinitely.
- Raises
can.CanOperationError – If an error occurred while sending
- set_auto_bus_management(auto_man)[source]¶
- Parameters
auto_man (bool) – Enable/disable automatic bus management
- set_auto_retransmit(retrans_flag)[source]¶
- Parameters
retrans_flag (bool) – Enable/disable automatic retransmission of unacknowledged CAN frames
- set_bitrate(bitrate)[source]¶
- Raises
ValueError – if bitrate is greater than 1000000
- Parameters
bitrate (int) – Bitrate in bit/s
- set_hw_filter(filterid, enabled, msgid_value, msgid_mask, extended_msg)[source]¶
- Raises
ValueError – if filterid is not between 1 and 14
- Parameters
filterid (int) – ID of filter (1-14)
enabled (bool) – This filter is enabled
msgid_value (int) – CAN message ID to filter on. The test unit does not accept an extented message ID unless bit 31 of the ID was set.
msgid_mask (int) – Mask to apply to CAN messagge ID
extended_msg (bool) – Filter operates on extended format messages
Internals¶
Todo
Document the internals of robotell interface.
USB-CAN Analyzer¶
…by Seeed Studio
SKU: 114991193
Links:
Installation¶
- This interface has additional dependencies which can be installed using pip and the optional extra [seeedstudio]. That will install an additional packages if not already available:
pyserial
pip3 install python-can[seeedstudio]
Interface¶
can.interfaces.seeedstudio.SeeedBus
A bus example:
bus = can.interface.Bus(bustype='seeedstudio', channel='/dev/ttyUSB0', bitrate=500000)
Parameters¶
SeeedBus(channel,
baudrate=2000000,
timeout=0.1,
frame_type='STD',
operation_mode='normal',
bitrate=500000)
- ChANNEL
The serial port created by the USB device when connected.
- TIMEOUT
Only used by the underling serial port, it probably should not be changed. The serial port baudrate=2000000 and rtscts=false are also matched to the device so are not added here.
- FRAMETYPE
“STD”
“EXT”
- OPERATIONMODE
“normal”
“loopback”
“silent”
“loopback_and_silent”
- BITRATE
1000000
800000
500000
400000
250000
200000
125000
100000
50000
20000
10000
5000
CAN over Serial¶
A text based interface. For example use over serial ports like
/dev/ttyS1
or /dev/ttyUSB0
on Linux machines or COM1
on Windows.
Remote ports can be also used via a special URL. Both raw TCP sockets as
also RFC2217 ports are supported: socket://192.168.254.254:5000
or
rfc2217://192.168.254.254:5000
. In addition a virtual loopback can be
used via loop://
URL.
The interface is a simple implementation that has been used for
recording CAN traces.
Note
The properties extended_id, is_remote_frame and is_error_frame from the class:~can.Message are not in use. This interface will not send or receive flags for this properties.
Bus¶
- class can.interfaces.serial.serial_can.SerialBus(channel, baudrate=115200, timeout=0.1, rtscts=False, *args, **kwargs)[source]¶
Enable basic can communication over a serial device.
Note
See
_recv_internal()
for some special semantics.- Parameters
channel (
str
) – The serial device to open. For example “/dev/ttyS1” or “/dev/ttyUSB0” on Linux or “COM1” on Windows systems.baudrate (
int
) –Baud rate of the serial device in bit/s (default 115200).
Warning
Some serial port implementations don’t care about the baudrate.
timeout (
float
) – Timeout for the serial device in seconds (default 0.1).rtscts (
bool
) – turn hardware handshake (RTS/CTS) on and off
- Raises
can.CanInitializationError – If the given parameters are invalid.
can.CanInterfaceNotImplementedError – If the serial module is not installed.
Internals¶
The frames that will be sent and received over the serial interface consist of six parts. The start and the stop byte for the frame, the timestamp, DLC, arbitration ID and the payload. The payload has a variable length of between 0 and 8 bytes, the other parts are fixed. Both, the timestamp and the arbitration ID will be interpreted as 4 byte unsigned integers. The DLC is also an unsigned integer with a length of 1 byte.
Serial frame format¶
Start of frame |
Timestamp |
DLC |
Arbitration ID |
Payload |
End of frame |
||
---|---|---|---|---|---|---|---|
Length (Byte) |
1 |
4 |
1 |
4 |
0 - 8 |
1 |
|
Data type |
Byte |
Unsigned 4 byte integer |
Unsigned 1 byte integer |
Unsigned 4 byte integer |
Byte |
Byte |
|
Byte order |
- |
Little-Endian |
Little-Endian |
Little-Endian |
- |
- |
|
Description |
Must be 0xAA |
Usually s, ms or µs since start of the device |
Length in byte of the payload |
- |
- |
Must be 0xBB |
Examples of serial frames¶
CAN message with 8 byte payload
CAN message |
|
---|---|
Arbitration ID |
Payload |
1 |
0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 |
Serial frame |
|||||
---|---|---|---|---|---|
Start of frame |
Timestamp |
DLC |
Arbitration ID |
Payload |
End of frame |
0xAA |
0x66 0x73 0x00 0x00 |
0x08 |
0x01 0x00 0x00 0x00 |
0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 |
0xBB |
CAN message with 1 byte payload
CAN message |
|
---|---|
Arbitration ID |
Payload |
1 |
0x11 |
Serial frame |
|||||
---|---|---|---|---|---|
Start of frame |
Timestamp |
DLC |
Arbitration ID |
Payload |
End of frame |
0xAA |
0x66 0x73 0x00 0x00 |
0x01 |
0x01 0x00 0x00 0x00 |
0x11 |
0xBB |
CAN message with 0 byte payload
CAN message |
|
---|---|
Arbitration ID |
Payload |
1 |
None |
Serial frame |
||||
---|---|---|---|---|
Start of frame |
Timestamp |
DLC |
Arbitration ID |
End of frame |
0xAA |
0x66 0x73 0x00 0x00 |
0x00 |
0x01 0x00 0x00 0x00 |
0xBB |
CAN over Serial / SLCAN¶
A text based interface: compatible to slcan-interfaces (slcan ASCII protocol) should also support LAWICEL direct. These interfaces can also be used with socketcan and slcand with Linux. This driver directly uses either the local or remote serial port, it makes slcan-compatible interfaces usable with Windows also. Remote serial ports will be specified via special URL. Both raw TCP sockets as also RFC2217 ports are supported.
Usage: use port or URL[@baurate]
to open the device.
For example use /dev/ttyUSB0@115200
or COM4@9600
for local serial ports and
socket://192.168.254.254:5000
or rfc2217://192.168.254.254:5000
for remote ports.
Supported devices¶
Todo
Document this.
Bus¶
- class can.interfaces.slcan.slcanBus(channel, ttyBaudrate=115200, bitrate=None, btr=None, sleep_after_open=2, rtscts=False, **kwargs)[source]¶
slcan interface
- Parameters
channel (str) – port of underlying serial or usb device (e.g.
/dev/ttyUSB0
,COM8
, …) Must not be empty. Can also end with@115200
(or similarly) to specify the baudrate.ttyBaudrate (int) – baudrate of underlying serial or usb device (Ignored if set via the
channel
parameter)btr (
Optional
[str
]) – BTR register value to set custom can speedpoll_interval – Poll interval in seconds when reading messages
sleep_after_open (
float
) – Time to wait in seconds after opening serial connectionrtscts (
bool
) – turn hardware handshake (RTS/CTS) on and off
- Raises
ValueError – if both
bitrate
andbtr
are set or the channel is invalidCanInterfaceNotImplementedError – if the serial module is missing
CanInitializationError – if the underlying serial connection could not be established
- get_version(timeout)[source]¶
Get HW and SW version of the slcan interface.
- send(msg, timeout=None)[source]¶
Transmit a message to the CAN bus.
Override this method to enable the transmit path.
- Parameters
msg (Message) – A message object.
timeout (
Optional
[float
]) – If > 0, wait up to this many seconds for message to be ACK’ed or for transmit queue to be ready depending on driver implementation. If timeout is exceeded, an exception will be raised. Might not be supported by all interfaces. None blocks indefinitely.
- Raises
can.CanOperationError – If an error occurred while sending
- Return type
- set_bitrate(bitrate)[source]¶
- Parameters
bitrate (
int
) – Bitrate in bit/s- Raises
ValueError – if
bitrate
is not among the possible values- Return type
Internals¶
Todo
Document the internals of slcan interface.
SocketCAN¶
The SocketCAN documentation can be found in the Linux kernel docs at
networking
directory. Quoting from the SocketCAN Linux documentation:
> The socketcan package is an implementation of CAN protocols
> (Controller Area Network) for Linux. CAN is a networking technology
> which has widespread use in automation, embedded devices, and
> automotive fields. While there have been other CAN implementations
> for Linux based on character devices, SocketCAN uses the Berkeley
> socket API, the Linux network stack and implements the CAN device
> drivers as network interfaces. The CAN socket API has been designed
> as similar as possible to the TCP/IP protocols to allow programmers,
> familiar with network programming, to easily learn how to use CAN
> sockets.
Important
python-can versions before 2.2 had two different implementations named
socketcan_ctypes
and socketcan_native
. These were removed in
version 4.0.0 after a deprecation period.
Socketcan Quickstart¶
The CAN network driver provides a generic
interface to setup, configure and monitor CAN devices. To configure
bit-timing parameters use the program ip
.
The virtual CAN driver (vcan)¶
The virtual CAN interfaces allow the transmission and reception of CAN frames without real CAN controller hardware. Virtual CAN network devices are usually named ‘vcanX’, like vcan0 vcan1 vcan2.
To create a virtual can interface using socketcan run the following:
sudo modprobe vcan
# Create a vcan network interface with a specific name
sudo ip link add dev vcan0 type vcan
sudo ip link set vcan0 up
Real Device¶
vcan
should be substituted for can
and vcan0
should be
substituted for can0
if you are using real hardware. Setting the
bitrate can also be done at the same time, for example to enable an
existing can0
interface with a bitrate of 1MB:
sudo ip link set can0 up type can bitrate 1000000
PCAN¶
Kernels >= 3.4 supports the PCAN adapters natively via SocketCAN, so there is no need to install any drivers. The CAN interface can be brought like so:
sudo modprobe peak_usb
sudo modprobe peak_pci
sudo ip link set can0 up type can bitrate 500000
Intrepid¶
The Intrepid Control Systems, Inc provides several devices (e.g. ValueCAN) as well as Linux module and user-space daemon to make it possible to use them via SocketCAN.
Refer to below repositories for installation instructions:
Send Test Message¶
The can-utils library for Linux includes a cansend tool which is useful to send known payloads. For example to send a message on vcan0:
cansend vcan0 123#DEADBEEF
CAN Errors¶
A device may enter the “bus-off” state if too many errors occurred on the CAN bus. Then no more messages are received or sent. An automatic bus-off recovery can be enabled by setting the “restart-ms” to a non-zero value, e.g.:
sudo ip link set canX type can restart-ms 100
Alternatively, the application may realize the “bus-off” condition by monitoring CAN error frames and do a restart when appropriate with the command:
ip link set canX type can restart
Note that a restart will also create a CAN error frame.
List network interfaces¶
To reveal the newly created can0
or a vcan0
interface:
ifconfig
Display CAN statistics¶
ip -details -statistics link show vcan0
Network Interface Removal¶
To remove the network interface:
sudo ip link del vcan0
Wireshark¶
Wireshark supports socketcan and can be used to debug python-can messages. Fire it up and watch your new interface.
To spam a bus:
import time
import can
bustype = 'socketcan'
channel = 'vcan0'
def producer(id):
""":param id: Spam the bus with messages including the data id."""
bus = can.Bus(channel=channel, interface=bustype)
for i in range(10):
msg = can.Message(arbitration_id=0xc0ffee, data=[id, i, 0, 1, 3, 1, 4, 1], is_extended_id=False)
bus.send(msg)
time.sleep(1)
producer(10)
With debugging turned right up this looks something like this:

The process to follow bus traffic is even easier:
for message in Bus(can_interface):
print(message)
Reading and Timeouts¶
Reading a single CAN message off of the bus is simple with the bus.recv()
function:
import can
bus = can.Bus(channel='vcan0', interface='socketcan')
message = bus.recv()
By default, this performs a blocking read, which means bus.recv()
won’t
return until a CAN message shows up on the socket. You can optionally perform a
blocking read with a timeout like this:
message = bus.recv(1.0) # Timeout in seconds.
if message is None:
print('Timeout occurred, no message.')
If you set the timeout to 0.0
, the read will be executed as non-blocking,
which means bus.recv(0.0)
will return immediately, either with a Message
object or None
, depending on whether data was available on the socket.
Filtering¶
The implementation features efficient filtering of can_id’s. That filtering occurs in the kernel and is much much more efficient than filtering messages in Python.
Broadcast Manager¶
The socketcan
interface implements thin wrappers to the linux broadcast manager
socket api. This allows the cyclic transmission of CAN messages at given intervals.
The overhead for periodic message sending is extremely low as all the heavy lifting occurs
within the linux kernel.
The BusABC
initialized for socketcan interface transparently handles
scheduling of CAN messages to Linux BCM via send_periodic()
:
with can.interface.Bus(interface="socketcan", channel="can0") as bus:
task = bus.send_periodic(...)
More examples that uses send_periodic()
are included
in python-can/examples/cyclic.py
.
The task object returned by send_periodic()
can be used to halt,
alter or cancel the periodic message task:
- class can.interfaces.socketcan.CyclicSendTask(bcm_socket, task_id, messages, period, duration=None)[source]¶
A SocketCAN cyclic send task supports:
setting of a task duration
modifying the data
stopping then subsequent restarting of the task
Construct and
start()
a task.- Parameters
bcm_socket (
socket
) – An open BCM socket on the desired CAN channel.task_id (
int
) – The identifier used to uniquely reference particular cyclic send task within Linux BCM.messages (
Union
[Sequence
[Message
],Message
]) – The messages to be sent periodically.period (
float
) – The rate in seconds at which to send the messages.duration (
Optional
[float
]) – Approximate duration in seconds to send the messages for.
- modify_data(messages)[source]¶
Update the contents of the periodically sent CAN messages by sending TX_SETUP message to Linux kernel.
The number of new cyclic messages to be sent must be equal to the original number of messages originally specified for this task.
Note
The messages must all have the same
arbitration_id
like the first message.
- start()[source]¶
Start a periodic task by sending TX_SETUP message to Linux kernel.
It verifies presence of the particular BCM task through sending TX_READ message to Linux kernel prior to scheduling.
- Raises
ValueError – If the task referenced by
task_id
is already running.- Return type
Buffer Sizes¶
Currently, the sending buffer size cannot be adjusted by this library. However, this issue describes how to change it via the command line/shell.
Bus¶
The SocketcanBus
specializes BusABC
to ensure usage of SocketCAN Linux API. The most important differences are:
usage of SocketCAN BCM for periodic messages scheduling;
filtering of CAN messages on Linux kernel level;
usage of nanosecond timings from the kernel.
- class can.interfaces.socketcan.SocketcanBus(channel='', receive_own_messages=False, local_loopback=True, fd=False, can_filters=None, ignore_rx_error_frames=False, **kwargs)[source]¶
A SocketCAN interface to CAN.
It implements
can.BusABC._detect_available_configs()
to search for available interfaces.Creates a new socketcan bus.
If setting some socket options fails, an error will be printed but no exception will be thrown. This includes enabling:
that own messages should be received,
CAN-FD frames and
error frames.
- Parameters
channel (
str
) – The can interface name with which to create this bus. An example channel would be ‘vcan0’ or ‘can0’. An empty string ‘’ will receive messages from all channels. In that case any sent messages must be explicitly addressed to a channel usingcan.Message.channel
.receive_own_messages (
bool
) – If transmitted messages should also be received by this bus.local_loopback (
bool
) – If local loopback should be enabled on this bus. Please note that local loopback does not mean that messages sent on a socket will be readable on the same socket, they will only be readable on other open sockets on the same machine. More info can be read on the socketcan documentation: See https://www.kernel.org/doc/html/latest/networking/can.html#socketcan-local-loopback1fd (
bool
) – If CAN-FD frames should be supported.can_filters (
Optional
[Sequence
[Union
[CanFilter
,CanFilterExtended
]]]) – Seecan.BusABC.set_filters()
.ignore_rx_error_frames – If incoming error frames should be discarded.
- property filters: Optional[Sequence[Union[can.typechecking.CanFilter, can.typechecking.CanFilterExtended]]]¶
Modify the filters of this bus. See
set_filters()
for details.
- flush_tx_buffer()¶
Discard every message that may be queued in the output buffer(s).
- Return type
- recv(timeout=None)¶
Block waiting for a message from the Bus.
- send_periodic(msgs, period, duration=None, store_task=True)¶
Start sending messages at a given period on this bus.
The task will be active until one of the following conditions are met:
the (optional) duration expires
the Bus instance goes out of scope
the Bus instance is shutdown
BusABC.stop_all_periodic_tasks()
is calledthe task’s
CyclicTask.stop()
method is called.
- Parameters
msgs (
Union
[Message
,Sequence
[Message
]]) – Message(s) to transmitperiod (
float
) – Period in seconds between each messageduration (
Optional
[float
]) – Approximate duration in seconds to continue sending messages. If no duration is provided, the task will continue indefinitely.store_task (
bool
) – If True (the default) the task will be attached to this Bus instance. Disable to instead manage tasks manually.
- Return type
- Returns
A started task instance. Note the task can be stopped (and depending on the backend modified) by calling the task’s
stop()
method.
Note
Note the duration before the messages stop being sent may not be exactly the same as the duration specified by the user. In general the message will be sent at the given rate until at least duration seconds.
Note
For extremely long running Bus instances with many short lived tasks the default api with
store_task==True
may not be appropriate as the stopped tasks are still taking up memory as they are associated with the Bus instance.
- set_filters(filters=None)¶
Apply filtering to all messages received by this Bus.
All messages that match at least one filter are returned. If filters is None or a zero length sequence, all messages are matched.
Calling without passing any filters will reset the applied filters to
None
.- Parameters
filters (
Optional
[Sequence
[Union
[CanFilter
,CanFilterExtended
]]]) –A iterable of dictionaries each containing a “can_id”, a “can_mask”, and an optional “extended” key.
>>> [{"can_id": 0x11, "can_mask": 0x21, "extended": False}]
A filter matches, when
<received_can_id> & can_mask == can_id & can_mask
. Ifextended
is set as well, it only matches messages where<received_is_extended> == extended
. Else it matches every messages based only on the arbitration ID and mask.- Return type
- property state: can.bus.BusState¶
Return the current state of the hardware
- Return type
BusState
SYSTEC interface¶
Windows interface for the USBCAN devices supporting up to 2 channels based on the
particular product. There is support for the devices also on Linux through the SocketCAN interface and for Windows using this
systec
interface.
Installation¶
The interface requires installation of the USBCAN32.dll library. Download and install the driver for specific SYSTEC device.
Supported devices¶
The interface supports following devices:
GW-001 (obsolete),
GW-002 (obsolete),
Multiport CAN-to-USB G3,
USB-CANmodul1 G3,
USB-CANmodul2 G3,
USB-CANmodul8 G3,
USB-CANmodul16 G3,
USB-CANmodul1 G4,
USB-CANmodul2 G4.
Bus¶
- class can.interfaces.systec.ucanbus.UcanBus(channel, can_filters=None, **kwargs)[source]¶
The CAN Bus implemented for the SYSTEC interface.
- Parameters
channel (int) – The Channel id to create this bus with.
can_filters (list) – See
can.BusABC.set_filters()
.
Backend Configuration
- Parameters
bitrate (int) – Channel bitrate in bit/s. Default is 500000.
device_number (int) – The device number of the USB-CAN. Valid values: 0 through 254. Special value 255 is reserved to detect the first connected device (should only be used, in case only one module is connected to the computer). Default is 255.
state (can.bus.BusState) – BusState of the channel. Default is ACTIVE.
receive_own_messages (bool) – If messages transmitted should also be received back. Default is False.
rx_buffer_entries (int) – The maximum number of entries in the receive buffer. Default is 4096.
tx_buffer_entries (int) – The maximum number of entries in the transmit buffer. Default is 4096.
- Raises
ValueError – If invalid input parameter were passed.
can.CanInterfaceNotImplementedError – If the platform is not supported.
can.CanInitializationError – If hardware or CAN interface initialization failed.
- static create_filter(extended, from_id, to_id, rtr_only, rtr_too)[source]¶
Calculates AMR and ACR using CAN-ID as parameter.
- Parameters
extended (bool) – if True parameters from_id and to_id contains 29-bit CAN-ID
from_id (int) – first CAN-ID which should be received
to_id (int) – last CAN-ID which should be received
rtr_only (bool) – if True only RTR-Messages should be received, and rtr_too will be ignored
rtr_too (bool) – if True CAN data frames and RTR-Messages should be received
- Returns
Returns list with one filter containing a “can_id”, a “can_mask” and “extended” key.
- flush_tx_buffer()[source]¶
Flushes the transmit buffer.
- Raises
can.CanError – If flushing of the transmit buffer failed.
- send(msg, timeout=None)[source]¶
Sends one CAN message.
When a transmission timeout is set the firmware tries to send a message within this timeout. If it could not be sent the firmware sets the “auto delete” state. Within this state all transmit CAN messages for this channel will be deleted automatically for not blocking the other channel.
- Parameters
msg (can.Message) – The CAN message.
timeout (float) – Transmit timeout in seconds (value 0 switches off the “auto delete”)
- Raises
can.CanOperationError – If the message could not be sent.
- property state¶
Return the current state of the hardware
Configuration¶
The simplest configuration would be:
interface = systec
channel = 0
Python-can will search for the first device found if not specified explicitly by the
device_number
parameter. The interface
and channel
are the only mandatory
parameters. The interface supports two channels 0 and 1. The maximum number of entries in the receive and transmit buffer can be set by the
parameters rx_buffer_entries
and tx_buffer_entries
, with default value 4096
set for both.
Optional parameters:
bitrate
(default 500000) Channel bitrate in bit/sdevice_number
(default first device) The device number of the USB-CANrx_buffer_entries
(default 4096) The maximum number of entries in the receive buffertx_buffer_entries
(default 4096) The maximum number of entries in the transmit bufferstate
(default BusState.ACTIVE) BusState of the channelreceive_own_messages
(default False) If messages transmitted should also be received back
Internals¶
Message filtering¶
The interface and driver supports only setting of one filter per channel. If one filter
is requested, this is will be handled by the driver itself. If more than one filter is
needed, these will be handled in Python code in the recv
method. If a message does
not match any of the filters, recv()
will return None.
Periodic tasks¶
The driver supports periodic message sending but without the possibility to set
the interval between messages. Therefore the handling of the periodic messages is done
by the interface using the ThreadBasedCyclicSendTask
.
Multicast IP Interface¶
This module implements transport of CAN and CAN FD messages over UDP via Multicast IPv4 and IPv6. This virtual interface allows for communication between multiple processes and even hosts. This differentiates it from the Virtual interface, which can only passes messages within a single process but does not require a network stack.
It runs on UDP to have the lowest possible latency (as opposed to using TCP), and because normal IP multicast is inherently unreliable, as the recipients are unknown. This enables ad-hoc networks that do not require a central server but is also a so-called unreliable network. In practice however, local area networks (LANs) should most often be sufficiently reliable for this interface to function properly.
Note
For an overview over the different virtual buses in this library and beyond, please refer to the section Other Virtual Interfaces. It also describes important limitations of this interface.
Please refer to the Bus class documentation below for configuration options and useful resources for specifying multicast IP addresses.
Supported Platforms¶
It should work on most Unix systems (including Linux with kernel 2.6.22+) but currently not on Windows.
Example¶
This example should print a single line indicating that a CAN message was successfully sent
from bus_1
to bus_2
:
import time
import can
from can.interfaces.udp_multicast import UdpMulticastBus
# The bus can be created using the can.Bus wrapper class or using UdpMulticastBus directly
with can.Bus(channel=UdpMulticastBus.DEFAULT_GROUP_IPv6, bustype='udp_multicast') as bus_1, \
UdpMulticastBus(channel=UdpMulticastBus.DEFAULT_GROUP_IPv6) as bus_2:
# register a callback on the second bus that prints messages to the standard out
notifier = can.Notifier(bus_2, [can.Printer()])
# create and send a message with the first bus, which should arrive at the second one
message = can.Message(arbitration_id=0x123, data=[1, 2, 3])
bus_1.send(message)
# give the notifier enough time to get triggered by the second bus
time.sleep(2.0)
Bus Class Documentation¶
- class can.interfaces.udp_multicast.UdpMulticastBus(channel='ff15:7079:7468:6f6e:6465:6d6f:6d63:6173', port=43113, hop_limit=1, receive_own_messages=False, fd=True, **kwargs)[source]¶
A virtual interface for CAN communications between multiple processes using UDP over Multicast IP.
It supports IPv4 and IPv6, specified via the channel (which really is just a multicast IP address as a string). You can also specify the port and the IPv6 hop limit/the IPv4 time to live (TTL).
This bus does not support filtering based on message IDs on the kernel level but instead provides it in user space (in Python) as a fallback.
Both default addresses should allow for multi-host CAN networks in a normal local area network (LAN) where multicast is enabled.
Note
The auto-detection of available interfaces (see) is implemented using heuristic that checks if the required socket operations are available. It then returns two configurations, one based on the
DEFAULT_GROUP_IPv6
address and another one based on theDEFAULT_GROUP_IPv4
address.Warning
The parameter receive_own_messages is currently unsupported and setting it to True will raise an exception.
Warning
This interface does not make guarantees on reliable delivery and message ordering, and also does not implement rate limiting or ID arbitration/prioritization under high loads. Please refer to the section Other Virtual Interfaces for more information on this and a comparison to alternatives.
- Parameters
channel (
str
) – A multicast IPv4 address (in 224.0.0.0/4) or an IPv6 address (in ff00::/8). This defines which version of IP is used. See Wikipedia (“Multicast address”) for more details on the addressing schemes. Defaults toDEFAULT_GROUP_IPv6
.port (
int
) – The IP port to read from and write to.hop_limit (
int
) – The hop limit in IPv6 or in IPv4 the time to live (TTL).receive_own_messages (
bool
) – If transmitted messages should also be received by this bus. CURRENTLY UNSUPPORTED.fd (
bool
) – If CAN-FD frames should be supported. If set to false, an error will be raised upon sending such a frame and such received frames will be ignored.can_filters – See
set_filters()
.
- Raises
RuntimeError – If the msgpack-dependency is not available. It should be installed on all non Windows platforms via the setup.py requirements.
NotImplementedError – If the receive_own_messages is passed as True.
Construct and open a CAN bus instance of the specified type.
Subclasses should call though this method with all given parameters as it handles generic tasks like applying filters.
- Parameters
channel (
str
) – The can interface identifier. Expected type is backend dependent.can_filters – See
set_filters()
for details.kwargs (dict) – Any backend dependent configurations are passed in this dictionary
- Raises
ValueError – If parameters are out of range
can.CanInterfaceNotImplementedError – If the driver cannot be accessed
can.CanInitializationError – If the bus cannot be initialized
- DEFAULT_GROUP_IPv4 = '239.74.163.2'¶
An arbitrary IPv4 multicast address with “administrative” scope, i.e. only to be routed within administrative organizational boundaries and not beyond it. It should allow for multi-host CAN networks in a normal IPv4 LAN. This is provided as a default fallback channel if IPv6 is (still) not supported.
- DEFAULT_GROUP_IPv6 = 'ff15:7079:7468:6f6e:6465:6d6f:6d63:6173'¶
An arbitrary IPv6 multicast address with “site-local” scope, i.e. only to be routed within the local physical network and not beyond it. It should allow for multi-host CAN networks in a normal IPv6 LAN. This is the default channel and should work with most modern routers if multicast is allowed.
USB2CAN Interface¶
OVERVIEW¶
The USB2CAN is a cheap CAN interface based on an ARM7 chip (STR750FV2).
There is support for this device on Linux through the SocketCAN interface and for Windows using this
usb2can
interface.
WINDOWS SUPPORT¶
Support though windows is achieved through a DLL very similar to the way the PCAN functions. The API is called CANAL (CAN Abstraction Layer) which is a separate project designed to be used with VSCP which is a socket like messaging system that is not only cross platform but also supports other types of devices. This device can be used through one of three ways 1)Through python-can 2)CANAL API either using the DLL and C/C++ or through the python wrapper that has been added to this project 3)VSCP Using python-can is strongly suggested as with little extra work the same interface can be used on both Windows and Linux.
WINDOWS INSTALL¶
To install on Windows download the USB2CAN Windows driver. It is compatible with XP, Vista, Win7, Win8/8.1. (Written against driver version v1.0.2.1)
Install the appropriate version of pywin32 (win32com)
Download the USB2CAN CANAL DLL from the USB2CAN website. Place this in either the same directory you are running usb2can.py from or your DLL folder in your python install. Note that only a 32-bit version is currently available, so this only works in a 32-bit Python environment. (Written against CANAL DLL version v1.0.6)
Interface Layout¶
usb2canabstractionlayer.py
This file is only a wrapper for the CANAL API that the interface expects. There are also a couple of constants here to try and make dealing with the bitwise operations for flag setting a little easier. Other than that this is only the CANAL API. If a programmer wanted to work with the API directly this is the file that allows you to do this. The CANAL project does not provide this wrapper and normally must be accessed with C.
usb2canInterface.py
This file provides the translation to and from the python-can library to the CANAL API. This is where all the logic is and setup code is. Most issues if they are found will be either found here or within the DLL that is provided
serial_selector.py
See the section below for the reason for adding this as it is a little odd. What program does is if a serial number is not provided to the usb2canInterface file this program does WMI (Windows Management Instrumentation) calls to try and figure out what device to connect to. It then returns the serial number of the device. Currently it is not really smart enough to figure out what to do if there are multiple devices. This needs to be changed if people are using more than one interface.
Interface Specific Items¶
There are a few things that are kinda strange about this device and are not overly obvious about the code or things that are not done being implemented in the DLL.
- You need the Serial Number to connect to the device under Windows. This is part of the “setup string” that configures the device. There are a few options for how to get this.
Use usb2canWin.py to find the serial number
Look on the device and enter it either through a prompt/barcode scanner/hardcode it.(Not recommended)
Reprogram the device serial number to something and do that for all the devices you own. (Really Not Recommended, can no longer use multiple devices on one computer)
In usb2canabstractionlayer.py there is a structure called CanalMsg which has a unsigned byte array of size 8. In the usb2canInterface file it passes in an unsigned byte array of size 8 also which if you pass less than 8 bytes in it stuffs it with extra zeros. So if the data “01020304” is sent the message would look like “0102030400000000”. There is also a part of this structure called sizeData which is the actual length of the data that was sent not the stuffed message (in this case would be 4). What then happens is although a message of size 8 is sent to the device only the length of information so the first 4 bytes of information would be sent. This is done because the DLL expects a length of 8 and nothing else. So to make it compatible that has to be sent through the wrapper. If usb2canInterface sent an array of length 4 with sizeData of 4 as well the array would throw an incompatible data type error. There is a Wireshark file posted in Issue #36 that demonstrates that the bus is only sending the data and not the extra zeros.
The masking features have not been implemented currently in the CANAL interface in the version currently on the USB2CAN website.
Warning
Currently message filtering is not implemented. Contributions are most welcome!
Bus¶
Internals¶
Vector¶
This interface adds support for CAN controllers by Vector. Only Windows is supported.
By default this library uses the channel configuration for CANalyzer.
To use a different application, open Vector Hardware Config program and create
a new application and assign the channels you may want to use.
Specify the application name as app_name='Your app name'
when constructing
the bus or in a config file.
Channel should be given as a list of channels starting at 0.
Here is an example configuration file connecting to CAN 1 and CAN 2 for an application named “python-can”:
[default]
interface = vector
channel = 0, 1
app_name = python-can
If you are using Python 2.7 it is recommended to install pywin32, otherwise a slow and CPU intensive polling will be used when waiting for new messages.
Bus¶
- class can.interfaces.vector.VectorBus(channel, can_filters=None, poll_interval=0.01, receive_own_messages=False, bitrate=None, rx_queue_size=16384, app_name='CANalyzer', serial=None, fd=False, data_bitrate=None, sjw_abr=2, tseg1_abr=6, tseg2_abr=3, sjw_dbr=2, tseg1_dbr=6, tseg2_dbr=3, **kwargs)[source]¶
The CAN Bus implemented for the Vector interface.
- Parameters
channel (
Union
[int
,Sequence
[int
],str
]) – The channel indexes to create this bus with. Can also be a single integer or a comma separated string.can_filters (
Optional
[Sequence
[Union
[CanFilter
,CanFilterExtended
]]]) – Seecan.BusABC
.receive_own_messages (
bool
) – Seecan.BusABC
.poll_interval (
float
) – Poll interval in seconds.rx_queue_size (
int
) – Number of messages in receive queue (power of 2). CAN: range 16…32768 CAN-FD: range 8192…524288app_name (
Optional
[str
]) – Name of application in Vector Hardware Config. If set to None, the channel should be a global channel index.serial (
Optional
[int
]) – Serial number of the hardware to be used. If set, the channel parameter refers to the channels ONLY on the specified hardware. If set, the app_name does not have to be previously defined in Vector Hardware Config.fd (
bool
) – If CAN-FD frames should be supported.data_bitrate (
Optional
[int
]) – Which bitrate to use for data phase in CAN FD. Defaults to arbitration bitrate.sjw_abr (
int
) – Bus timing value sample jump width (arbitration).tseg1_abr (
int
) – Bus timing value tseg1 (arbitration)tseg2_abr (
int
) – Bus timing value tseg2 (arbitration)sjw_dbr (
int
) – Bus timing value sample jump width (data)tseg1_dbr (
int
) – Bus timing value tseg1 (data)tseg2_dbr (
int
) – Bus timing value tseg2 (data)
- Raises
can.CanInterfaceNotImplementedError – If the current operating system is not supported or the driver could not be loaded.
can.CanInitializationError – If the bus could not be set up. This may or may not be a
can.interfaces.vector.VectorInitializationError
.
Virtual¶
The virtual interface can be used as a way to write OS and driver independent tests. Any VirtualBus instances connecting to the same channel (from within the same Python process) will receive each others messages.
If messages shall be sent across process or host borders, consider using the Multicast IP Interface and refer to (the next section) for a comparison and general discussion of different virtual interfaces.
Other Virtual Interfaces¶
There are quite a few implementations for CAN networks that do not require physical CAN hardware. This section also describes common limitations of current virtual interfaces.
Comparison¶
The following table compares some known virtual interfaces:
Name |
Availability |
Applicability |
Implementation |
||||
Within Process |
Between Processes |
Via (IP) Networks |
Without Central Server |
Transport Technology |
Serialization Format |
||
|
included |
✓ |
✗ |
✗ |
✓ |
Singleton & Mutex (reliable) |
none |
|
included |
✓ |
✓ |
✓ |
✓ |
UDP via IP multicast (unreliable) |
custom using msgpack |
christiansandberg/ python-can-remote |
✓ |
✓ |
✓ |
✗ |
Websockets via TCP/IP (reliable) |
custom binary |
|
windelbouwman/ virtualcan |
✓ |
✓ |
✓ |
✗ |
ZeroMQ via TCP/IP (reliable) |
custom binary 1 |
- 1
The only option in this list that implements interoperability with other languages out of the box. For the others (except the first intra-process one), other programs written in potentially different languages could effortlessly interface with the bus once they mimic the serialization format. The last one, however, has already implemented the entire bus functionality in C++ and Rust, besides the Python variant.
Common Limitations¶
Guaranteed delivery and message ordering is one major point of difference:
While in a physical CAN network, a message is either sent or in queue (or an explicit error occurred),
this may not be the case for virtual networks.
The udp_multicast
bus for example, drops this property for the benefit of lower
latencies by using unreliable UDP/IP instead of reliable TCP/IP (and because normal IP multicast
is inherently unreliable, as the recipients are unknown by design). The other three buses faithfully
model a physical CAN network in this regard: They ensure that all recipients actually receive
(and acknowledge each message), much like in a physical CAN network. They also ensure that
messages are relayed in the order they have arrived at the central server and that messages
arrive at the recipients exactly once. Both is not guaranteed to hold for the best-effort
udp_multicast
bus as it uses UDP/IP as a transport layer.
Central servers are, however, required by interfaces 3 and 4 (the external tools) to provide
these guarantees of message delivery and message ordering. The central servers receive and distribute
the CAN messages to all other bus participants, unlike in a real physical CAN network.
The first intra-process virtual
interface only runs within one Python process, effectively the
Python instance of VirtualBus
acts as a central server. Notably the udp_multicast
bus
does not require a central server.
Arbitration and throughput are two interrelated functions/properties of CAN networks which are typically abstracted in virtual interfaces. In all four interfaces, an unlimited amount of messages can be sent per unit of time (given the computational power of the machines and networks that are involved). In a real CAN/CAN FD networks, however, throughput is usually much more restricted and prioritization of arbitration IDs is thus an important feature once the bus is starting to get saturated. None of the interfaces presented above support any sort of throttling or ID arbitration under high loads.
Example¶
import can
bus1 = can.interface.Bus('test', bustype='virtual')
bus2 = can.interface.Bus('test', bustype='virtual')
msg1 = can.Message(arbitration_id=0xabcde, data=[1,2,3])
bus1.send(msg1)
msg2 = bus2.recv()
#assert msg1 == msg2
assert msg1.arbitration_id == msg2.arbitration_id
assert msg1.data == msg2.data
assert msg1.timestamp != msg2.timestamp
import can
bus1 = can.interface.Bus('test', bustype='virtual', preserve_timestamps=True)
bus2 = can.interface.Bus('test', bustype='virtual')
msg1 = can.Message(timestamp=1639740470.051948, arbitration_id=0xabcde, data=[1,2,3])
# Messages sent on bus1 will have their timestamps preserved when received
# on bus2
bus1.send(msg1)
msg2 = bus2.recv()
assert msg1.arbitration_id == msg2.arbitration_id
assert msg1.data == msg2.data
assert msg1.timestamp == msg2.timestamp
# Messages sent on bus2 will not have their timestamps preserved when
# received on bus1
bus2.send(msg1)
msg3 = bus1.recv()
assert msg1.arbitration_id == msg3.arbitration_id
assert msg1.data == msg3.data
assert msg1.timestamp != msg3.timestamp
Bus Class Documentation¶
- class can.interfaces.virtual.VirtualBus(channel=None, receive_own_messages=False, rx_queue_size=0, preserve_timestamps=False, **kwargs)[source]¶
A virtual CAN bus using an internal message queue. It can be used for example for testing.
In this interface, a channel is an arbitrary object used as an identifier for connected buses.
Implements
can.BusABC._detect_available_configs()
; seecan.VirtualBus._detect_available_configs()
for how it behaves here.Note
The timeout when sending a message applies to each receiver individually. This means that sending can block up to 5 seconds if a message is sent to 5 receivers with the timeout set to 1.0.
Warning
This interface guarantees reliable delivery and message ordering, but does not implement rate limiting or ID arbitration/prioritization under high loads. Please refer to the section Other Virtual Interfaces for more information on this and a comparison to alternatives.
Construct and open a CAN bus instance of the specified type.
Subclasses should call though this method with all given parameters as it handles generic tasks like applying filters.
- Parameters
channel (
Optional
[Any
]) – The can interface identifier. Expected type is backend dependent.can_filters – See
set_filters()
for details.kwargs (dict) – Any backend dependent configurations are passed in this dictionary
- Raises
ValueError – If parameters are out of range
can.CanInterfaceNotImplementedError – If the driver cannot be accessed
can.CanInitializationError – If the bus cannot be initialized
- send(msg, timeout=None)[source]¶
Transmit a message to the CAN bus.
Override this method to enable the transmit path.
- Parameters
msg (Message) – A message object.
timeout (
Optional
[float
]) – If > 0, wait up to this many seconds for message to be ACK’ed or for transmit queue to be ready depending on driver implementation. If timeout is exceeded, an exception will be raised. Might not be supported by all interfaces. None blocks indefinitely.
- Raises
can.CanOperationError – If an error occurred while sending
- Return type
Additional interfaces can be added via a plugin interface. An external package
can register a new interface by using the can.interface
entry point in its setup.py.
The format of the entry point is interface_name=module:classname
where
classname
is a concrete can.BusABC
implementation.
entry_points={
'can.interface': [
"interface_name=module:classname",
]
},
The Interface Names are listed in Configuration.
Scripts¶
The following modules are callable from python-can.
They can be called for example by python -m can.logger
or can_logger.py
(if installed using pip).
can.logger¶
Command line help, called with --help
:
$ python -m can.logger -h
usage: logger.py [-h] [-c CHANNEL]
[-i {slcan,neousys,virtual,gs_usb,pcan,socketcan,nican,kvaser,serial,vector,iscan,socketcand,neovi,seeedstudio,cantact,udp_multicast,ixxat,systec,canalystii,etas,usb2can,robotell,nixnet}]
[-b BITRATE] [--fd] [--data_bitrate DATA_BITRATE]
[-f LOG_FILE] [-s FILE_SIZE] [-v]
[--filter {<can_id>:<can_mask>,<can_id>~<can_mask>} [{<can_id>:<can_mask>,<can_id>~<can_mask>} ...]]
[--active | --passive]
...
Log CAN traffic, printing messages to stdout or to a given file.
positional arguments:
extra_args The remaining arguments will be used for the interface
initialisation. For example, `-i vector -c 1 --app-
name=MyCanApp` is the equivalent to opening the bus
with `Bus('vector', channel=1, app_name='MyCanApp')`
optional arguments:
-h, --help show this help message and exit
-c CHANNEL, --channel CHANNEL
Most backend interfaces require some sort of channel.
For example with the serial interface the channel
might be a rfcomm device: "/dev/rfcomm0" With the
socketcan interfaces valid channel examples include:
"can0", "vcan0"
-i {slcan,neousys,virtual,gs_usb,pcan,socketcan,nican,kvaser,serial,vector,iscan,socketcand,neovi,seeedstudio,cantact,udp_multicast,ixxat,systec,canalystii,etas,usb2can,robotell,nixnet}, --interface {slcan,neousys,virtual,gs_usb,pcan,socketcan,nican,kvaser,serial,vector,iscan,socketcand,neovi,seeedstudio,cantact,udp_multicast,ixxat,systec,canalystii,etas,usb2can,robotell,nixnet}
Specify the backend CAN interface to use. If left
blank, fall back to reading from configuration files.
-b BITRATE, --bitrate BITRATE
Bitrate to use for the CAN bus.
--fd Activate CAN-FD support
--data_bitrate DATA_BITRATE
Bitrate to use for the data phase in case of CAN-FD.
-f LOG_FILE, --file_name LOG_FILE
Path and base log filename, for supported types see
can.Logger.
-s FILE_SIZE, --file_size FILE_SIZE
Maximum file size in bytes. Rotate log file when size
threshold is reached.
-v How much information do you want to see at the command
line? You can add several of these e.g., -vv is DEBUG
--filter {<can_id>:<can_mask>,<can_id>~<can_mask>} [{<can_id>:<can_mask>,<can_id>~<can_mask>} ...]
R|Space separated CAN filters for the given CAN
interface: <can_id>:<can_mask> (matches when
<received_can_id> & mask == can_id & mask)
<can_id>~<can_mask> (matches when <received_can_id> &
mask != can_id & mask) Fx to show only frames with ID
0x100 to 0x103 and 0x200 to 0x20F: python -m
can.viewer -f 100:7FC 200:7F0 Note that the ID and
mask are always interpreted as hex values
--active Start the bus as active, this is applied by default.
--passive Start the bus as passive.
can.player¶
$ python -m can.player -h
usage: player.py [-h] [-c CHANNEL]
[-i {canalystii,kvaser,neousys,pcan,usb2can,cantact,seeedstudio,iscan,socketcan,systec,neovi,serial,gs_usb,udp_multicast,etas,ixxat,vector,nican,robotell,socketcand,nixnet,slcan,virtual}]
[-b BITRATE] [--fd] [--data_bitrate DATA_BITRATE]
[-f LOG_FILE] [-v] [--ignore-timestamps] [--error-frames]
[-g GAP] [-s SKIP]
... input-file
Replay CAN traffic.
positional arguments:
extra_args The remaining arguments will be used for the interface
initialisation. For example, `-i vector -c 1 --app-
name=MyCanApp` is the equivalent to opening the bus
with `Bus('vector', channel=1, app_name='MyCanApp')`
input-file The file to replay. For supported types see
can.LogReader.
optional arguments:
-h, --help show this help message and exit
-c CHANNEL, --channel CHANNEL
Most backend interfaces require some sort of channel.
For example with the serial interface the channel
might be a rfcomm device: "/dev/rfcomm0" With the
socketcan interfaces valid channel examples include:
"can0", "vcan0"
-i {canalystii,kvaser,neousys,pcan,usb2can,cantact,seeedstudio,iscan,socketcan,systec,neovi,serial,gs_usb,udp_multicast,etas,ixxat,vector,nican,robotell,socketcand,nixnet,slcan,virtual}, --interface {canalystii,kvaser,neousys,pcan,usb2can,cantact,seeedstudio,iscan,socketcan,systec,neovi,serial,gs_usb,udp_multicast,etas,ixxat,vector,nican,robotell,socketcand,nixnet,slcan,virtual}
Specify the backend CAN interface to use. If left
blank, fall back to reading from configuration files.
-b BITRATE, --bitrate BITRATE
Bitrate to use for the CAN bus.
--fd Activate CAN-FD support
--data_bitrate DATA_BITRATE
Bitrate to use for the data phase in case of CAN-FD.
-f LOG_FILE, --file_name LOG_FILE
Path and base log filename, for supported types see
can.LogReader.
-v Also print can frames to stdout. You can add several
of these to enable debugging
--ignore-timestamps Ignore timestamps (send all frames immediately with
minimum gap between frames)
--error-frames Also send error frames to the interface.
-g GAP, --gap GAP <s> minimum time between replayed frames
-s SKIP, --skip SKIP <s> skip gaps greater than 's' seconds
can.viewer¶
A screenshot of the application can be seen below:

The first column is the number of times a frame with the particular ID that has been received, next is the timestamp of the frame relative to the first received message. The third column is the time between the current frame relative to the previous one. Next is the length of the frame, the data and then the decoded data converted according to the -d
argument. The top red row indicates an error frame.
There are several keyboard shortcuts that can be used with the viewer script, they function as follows:
ESCAPE - Quit the viewer script
q - as ESCAPE
c - Clear the stored frames
s - Sort the stored frames
h - Toggle highlighting of changed bytes in the data field - see the below image
SPACE - Pause the viewer
UP/DOWN - Scroll the viewer

A byte in the data field is highlighted blue if the value is different from the last time the message was received.
Command line arguments¶
By default the can.viewer
uses the SocketCAN interface. All interfaces are supported and can be specified using the -i
argument or configured following Configuration.
The full usage page can be seen below:
$ python -m can.viewer -h
Usage: python -m can.viewer [-c CHANNEL]
[-i {seeedstudio,usb2can,vector,pcan,serial,robotell,slcan,canalystii,etas,systec,cantact,nixnet,neousys,neovi,udp_multicast,nican,socketcan,ixxat,iscan,socketcand,virtual,kvaser,gs_usb}]
[-b BITRATE] [--fd] [--data_bitrate DATA_BITRATE]
[-h] [--version]
[-d '{<id>:<format>,<id>:<format>:<scaling1>:...:<scalingN>,file.txt}',)]
[-f ('{<can_id>:<can_mask>,<can_id>~<can_mask>}',]
[-v]
'extra_args',
A simple CAN viewer terminal application written in Python
positional arguments:
extra_args The remaining arguments will be used for the interface
initialisation. For example, `-i vector -c 1 --app-
name=MyCanApp` is the equivalent to opening the bus
with `Bus('vector', channel=1, app_name='MyCanApp')`
optional arguments:
-c, --channel CHANNEL
Most backend interfaces require some sort of channel.
For example with the serial interface the channel
might be a rfcomm device: "/dev/rfcomm0" With the
socketcan interfaces valid channel examples include:
"can0", "vcan0"
-i, --interface {seeedstudio,usb2can,vector,pcan,serial,robotell,slcan,canalystii,etas,systec,cantact,nixnet,neousys,neovi,udp_multicast,nican,socketcan,ixxat,iscan,socketcand,virtual,kvaser,gs_usb}
Specify the backend CAN interface to use. If left
blank, fall back to reading from configuration files.
-b, --bitrate BITRATE
Bitrate to use for the CAN bus.
--fd Activate CAN-FD support
--data_bitrate DATA_BITRATE
Bitrate to use for the data phase in case of CAN-FD.
Optional arguments:
-h, --help Show this help message and exit
--version Show program's version number and exit
-d, --decode ('{<id>:<format>,<id>:<format>:<scaling1>:...:<scalingN>,file.txt}',)
Specify how to convert the raw bytes into real values.
The ID of the frame is given as the first argument and the format as the second.
The Python struct package is used to unpack the received data
where the format characters have the following meaning:
< = little-endian, > = big-endian
x = pad byte
c = char
? = bool
b = int8_t, B = uint8_t
h = int16, H = uint16
l = int32_t, L = uint32_t
q = int64_t, Q = uint64_t
f = float (32-bits), d = double (64-bits)
Fx to convert six bytes with ID 0x100 into uint8_t, uint16 and uint32_t:
$ python -m can.viewer -d "100:<BHL"
Note that the IDs are always interpreted as hex values.
An optional conversion from integers to real units can be given
as additional arguments. In order to convert from raw integer
values the values are divided with the corresponding scaling value,
similarly the values are multiplied by the scaling value in order
to convert from real units to raw integer values.
Fx lets say the uint8_t needs no conversion, but the uint16 and the uint32_t
needs to be divided by 10 and 100 respectively:
$ python -m can.viewer -d "101:<BHL:1:10.0:100.0"
Be aware that integer division is performed if the scaling value is an integer.
Multiple arguments are separated by spaces:
$ python -m can.viewer -d "100:<BHL" "101:<BHL:1:10.0:100.0"
Alternatively a file containing the conversion strings separated by new lines
can be given as input:
$ cat file.txt
100:<BHL
101:<BHL:1:10.0:100.0
$ python -m can.viewer -d file.txt
-f, --filter ('{<can_id>:<can_mask>,<can_id>~<can_mask>}',)
Space separated CAN filters for the given CAN interface:
<can_id>:<can_mask> (matches when <received_can_id> & mask == can_id & mask)
<can_id>~<can_mask> (matches when <received_can_id> & mask != can_id & mask)
Fx to show only frames with ID 0x100 to 0x103 and 0x200 to 0x20F:
python -m can.viewer -f 100:7FC 200:7F0
Note that the ID and mask are always interpreted as hex values
-v How much information do you want to see at the command
line? You can add several of these e.g., -vv is DEBUG
Shortcuts:
+---------+-------------------------------+
| Key | Description |
+---------+-------------------------------+
| ESQ/q | Exit the viewer |
| c | Clear the stored frames |
| s | Sort the stored frames |
| h | Toggle highlight byte changes |
| SPACE | Pause the viewer |
| UP/DOWN | Scroll the viewer |
+---------+-------------------------------+
can.logconvert¶
$ python -m can.logconvert -h
usage: logconvert.py [-h] [-s FILE_SIZE] INFILE OUTFILE
Convert a log file from one format to another.
positional arguments:
INFILE Input filename. The type is dependent on the suffix,
see can.LogReader.
OUTFILE Output filename. The type is dependent on the suffix,
see can.Logger.
optional arguments:
-h, --help show this help message and exit
-s FILE_SIZE, --file_size FILE_SIZE
Maximum file size in bytes. Rotate log file when size
threshold is reached.
Developer’s Overview¶
Contributing¶
Contribute to source code, documentation, examples and report issues: https://github.com/hardbyte/python-can
Note that the latest released version on PyPi may be significantly behind the
develop
branch. Please open any feature requests against the develop
branch
There is also a python-can mailing list for development discussion.
Some more information about the internals of this library can be found
in the chapter Internal API.
There is also additional information on extending the can.io
module.
Pre-releases¶
The latest pre-release can be installed with:
pip install --upgrade --pre python-can
Building & Installing¶
The following assumes that the commands are executed from the root of the repository:
The project can be built with:
pip install wheel
python setup.py sdist bdist_wheel
The project can be installed in editable mode with:
pip install -e .
The unit tests can be run with:
pip install tox
tox -e py
The documentation can be built with:
pip install -r doc/doc-requirements.txt
python -m sphinx -an doc build
The linters can be run with:
pip install -r requirements-lint.txt
pylint --rcfile=.pylintrc-wip can/**.py
black --check --verbose can
Creating a new interface/backend¶
These steps are a guideline on how to add a new backend to python-can.
Create a module (either a
*.py
or an entire subdirectory depending on the complexity) insidecan.interfaces
Implement the central part of the backend: the bus class that extends
can.BusABC
. See Extending the BusABC class for more info on this one!Register your backend bus class in
BACKENDS
in the filecan.interfaces.__init__.py
.Add docs where appropriate. At a minimum add to
doc/interfaces.rst
and add a new interface specific document indoc/interface/*
. It should document the supported platforms and also the hardware/software it requires. A small snippet of how to install the dependencies would also be useful to get people started without much friction.Also, don’t forget to document your classes, methods and function with docstrings.
Add tests in
test/*
where appropriate. To get started, have a look atback2back_test.py
: Simply add a test case likeBasicTestSocketCan
and some basic tests will be executed for the new interface.
Code Structure¶
The modules in python-can
are:
Module |
Description |
---|---|
Contains interface dependent code. |
|
Contains the interface independent Bus object. |
|
Contains the interface independent Message object. |
|
Contains a range of file readers and writers. |
|
Contains interface independent broadcast manager code. |
Creating a new Release¶
Release from the
main
branch (except for pre-releases).Update the library version in
__init__.py
using semantic versioning.Check if any deprecations are pending.
Run all tests and examples against available hardware.
Update
CONTRIBUTORS.txt
with any new contributors.For larger changes update
doc/history.rst
.Sanity check that documentation has stayed inline with code.
Create a temporary virtual environment. Run
python setup.py install
andtox
.Create and upload the distribution:
python setup.py sdist bdist_wheel
.Sign the packages with gpg
gpg --detach-sign -a dist/python_can-X.Y.Z-py3-none-any.whl
.Upload with twine
twine upload dist/python-can-X.Y.Z*
.In a new virtual env check that the package can be installed with pip:
pip install python-can==X.Y.Z
.Create a new tag in the repository.
Check the release on PyPi, Read the Docs and GitHub.
History and Roadmap¶
Background¶
Originally written at Dynamic Controls for internal use testing and prototyping wheelchair components.
Maintenance was taken over and the project was open sourced by Brian Thorne in 2010.
Acknowledgements¶
Originally written by Ben Powell as a thin wrapper around the Kvaser SDK to support the leaf device.
Support for linux socketcan was added by Rose Lu as a summer coding project in 2011. The socketcan interface was helped immensely by Phil Dixon who wrote a leaf-socketcan driver for Linux.
The pcan interface was contributed by Albert Bloomfield in 2013. Support for pcan on Mac was added by Kristian Sloth Lauszus in 2018.
The usb2can interface was contributed by Joshua Villyard in 2015.
The IXXAT VCI interface was contributed by Giuseppe Corbelli and funded by Weightpack in 2016.
The NI-CAN and virtual interfaces plus the ASCII and BLF loggers were contributed by Christian Sandberg in 2016 and 2017. The BLF format is based on a C++ library by Toby Lorenz.
The slcan interface, ASCII listener and log logger and listener were contributed by Eduard Bröcker in 2017.
The NeoVi interface for ICS (Intrepid Control Systems) devices was contributed by Pierre-Luc Tessier Gagné in 2017.
Many improvements all over the library, cleanups, unifications as well as more comprehensive documentation and CI testing was contributed by Felix Divo in 2017 and 2018.
The CAN viewer terminal script was contributed by Kristian Sloth Lauszus in 2018.
The CANalyst-II interface was contributed by Shaoyu Meng in 2018.
@deonvdw added support for the Robotell interface in 2019.
Felix Divo and Karl Ding added type hints for the core library and many interfaces leading up to the 4.0 release.
Eric Evenchick added support for the CANtact devices in 2020.
Felix Divo added an interprocess virtual bus interface in 2020.
@jxltom added the gs_usb interface in 2020 supporting Geschwister Schneider USB/CAN devices and bytewerk.org candleLight USB CAN devices such as candlelight, canable, cantact, etc.
@jaesc added the nixnet interface in 2021 supporting NI-XNET devices from National Instruments.
Tuukka Pasanen @illuusio added the neousys interface in 2021.
Francisco Javier Burgos Maciá @fjburgos added ixxat FD support.
@domologic contributed a socketcand interface in 2021.
Felix N @felixn contributed the ETAS interface in 2021.
Felix Divo unified exception handling across every interface in the lead up to the 4.0 release.
Felix Divo prepared the python-can 4.0 release.
Support for CAN within Python¶
Python natively supports the CAN protocol from version 3.3 on, if running on Linux (with a sufficiently new kernel):
Python version |
Feature |
Link |
---|---|---|
3.3 |
Initial SocketCAN support |
|
3.4 |
Broadcast Management (BCM) commands are natively supported |
|
3.5 |
CAN FD support |
|
3.7 |
Support for CAN ISO-TP |
|
3.9 |
Native support for joining CAN filters |
Known Bugs¶
See the project bug tracker on github. Patches and pull requests very welcome!
Documentation generated
Feb 19, 2022