Cantools
Cantools
About
CAN BUS tools in Python 3.
Node tester.
Documentation: https://cantools.readthedocs.io
Installation
Example usage
Scripting
The example starts by parsing a small DBC-file and printing its messages and signals.
The example continues encoding a message and sending it on a CAN bus using the python-
can package.
The last part of the example receives and decodes a CAN message.
The plot subcommand is similar to the decode subcommand but messages are visualized
using matplotlib instead of being printed to stdout.
$ candump -l vcan0
$ cat candump-2021-01-04_180521.log
(1609779922.655421) vcan0 00000343#B204B9049C049C04
(1609779922.655735) vcan0 0000024A#120527052E051905
(1609779923.657524) vcan0 00000343#C404C404CB04C404
(1609779923.658086) vcan0 0000024A#8B058B058B059205
(1609779924.659912) vcan0 00000343#5C04790479045504
(1609779924.660471) vcan0 0000024A#44064B0659064406
(1609779925.662277) vcan0 00000343#15040704F203F203
(1609779925.662837) vcan0 0000024A#8B069906A706A706
(1609779926.664191) vcan0 00000343#BC03B503A703BC03
(1609779926.664751) vcan0 0000024A#A006A706C406C406
Signals with a different range of values can be displayed in the same subplot on different
vertical axes by separating them with a comma.
$ cat candump-2021-01-04_180521.log | cantools plot --auto-color tests/files/dbc/abs.dbc -- \
--ylabel 'Bremse 33' '*_33.*fl*:-<' '*_33.*fr*:>' '*_33.*rl*:3' '*_33.*rr*:4' , \
--ylabel 'Bremse 2' '*_2.*fl*:-<' '*_2.*fr*:>' '*_2.*rl*:3' '*_2.*rr*:4'
Matplotlib comes with different preinstalled styles that you can use:
Note that by default matplotlib is not installed with cantools. But it can be by specifying an
extra at installation:
------------------------------------------------------------------------
Name: ExampleMessage
Id: 0x1f0
Length: 8 bytes
Cycle time: - ms
Senders: PCM1
Layout:
Bit
7 6 5 4 3 2 1 0
+---+---+---+---+---+---+---+---+
0 |<-x|<---------------------x|<--|
+---+---+---+---+---+---+---+---+
| +-- AverageRadius
+-- Enable
+---+---+---+---+---+---+---+---+
1 |-------------------------------|
+---+---+---+---+---+---+---+---+
2 |----------x| | | | | |
B +---+---+---+---+---+---+---+---+
y +-- Temperature
t +---+---+---+---+---+---+---+---+
e 3 | | | | | | | | |
+---+---+---+---+---+---+---+---+
4 | | | | | | | | |
+---+---+---+---+---+---+---+---+
5 | | | | | | | | |
+---+---+---+---+---+---+---+---+
6 | | | | | | | | |
+---+---+---+---+---+---+---+---+
7 | | | | | | | | |
+---+---+---+---+---+---+---+---+
Signal tree:
-- {root}
+-- Enable
+-- AverageRadius
+-- Temperature
Signal choices:
Enable
0 Disabled
1 Enabled
------------------------------------------------------------------------
Print all information of a given database in a human readable format. This is very similar to
the “dump” subcommand, but the output is less pretty, slightly more comprehensive and
easier to parse by shell scripts:
$ python3 -m cantools list -a tests/files/dbc/motohawk.dbc
ExampleMessage:
Comment[None]: Example message used as template in MotoHawk models.
Frame ID: 0x1f0 (496)
Size: 8 bytes
Is extended frame: False
Signals:
Enable:
Type: Integer
Start bit: 7
Length: 1 bits
Unit: -
Is signed: False
Named values:
0: Disabled
Message structs.
Frame id, length, type, cycle time and signal choices defines.
Known limitations:
Below is an example of how to generate C source code from a database. The database is
tests/files/dbc/motohawk.dbc .
See motohawk.h and motohawk.c for the contents of the generated files.
In this example we use --use-float so floating point numbers in the generated code are
single precision ( float ) instead of double precision ( double ).
$ python3 -m cantools generate_c_source --use-float tests/files/dbc/motohawk.dbc
Successfully generated motohawk.h and motohawk.c.
In the next example we use --database-name to set a custom namespace for all generated
types, defines and functions. The output file names are also changed by this option.
See my_database_name.h and my_database_name.c for the contents of the generated files.
In the last example --node is used to generate message pack functions only for messages
sent by the specified node and unpack functions only for messages with its signal receivers
belonging to that node.
http://www.coderdbc.com
https://github.com/howerj/dbcc
https://github.com/lonkamikaze/hsk-libs/blob/master/scripts/dbc2c.awk
https://sourceforge.net/projects/comframe/
The monitor subcommand
The menu at the bottom of the monitor shows the available commands.
Filter: Only display messages matching given regular expression. Press <Enter> to return to
the menu from the filter input line.
Play/Pause: Toggle between playing and paused (or running and freezed).
Contributing
1. Fork the repository.
2. Install prerequisites.
tox -e py
Open, read and parse given database file and return a can.Database or
diagnostics.Database object with its contents.
database_format is one of 'arxml' , 'dbc' , 'kcd' , 'sym' , cdd and None . If None , the
database format is selected based on the filename extension as in the table below.
Filename extensions are case insensitive.
.arxml 'arxml'
.dbc 'dbc'
.kcd 'kcd'
.sym 'sym'
.cdd 'cdd'
<unknown> None
encoding specifies the file encoding. If None , the encoding is selected based on the
database format as in the table below. Use open() and load() if platform dependent
encoding is desired.
Database format Default encoding
'arxml' 'utf-8'
'dbc' 'cp1252'
'kcd' 'utf-8'
'sym' 'cp1252'
'cdd' 'utf-8'
None 'utf-8'
cache_dir specifies the database cache location in the file system. Give as None to disable
the cache. By default the cache is disabled. The cache key is the contents of given file.
Using a cache will significantly reduce the load time when reloading the same file. The
cache directory is automatically created if it does not exist. Remove the cache directory
cache_dir to clear the cache.
>>> db = cantools.database.load_file('foo.dbc')
>>> db.version
'1.0'
Depending on the output file format signals may be sorted by default. If you don’t want
signals to be sorted pass sort_signals=None. sort_signals=None is assumed by default if you
have passed sort_signals=None to load_file. If you want the signals to be sorted in a special
way pass something like sort_signals = lambda signals: list(sorted(signals, key=lambda sig:
sig.name)) For dbc files the default is to sort the signals by their start bit in descending
order. For kcd files the default is to not sort the signals.
>>> db = cantools.database.load_file('foo.dbc')
>>> cantools.database.dump_file(db, 'bar.dbc')
Parse given database string and return a can.Database or diagnostics.Database object with
its contents.
database_format may be one of 'arxml' , 'dbc' , 'kcd' , 'sym' , 'cdd' or None , where
None means transparent format.
sort_signals is a function taking a list of signals as argument and returning a list of signals.
By default signals are sorted by their start bit when their Message object is created. If you
don’t want them to be sorted pass sort_signals = None. If you want the signals to be sorted
in another way pass something like sort_signals = lambda signals: list(sorted(signals,
key=lambda sig: sig.name))
Read and parse given database file-like object and return a can.Database or
diagnostics.Database object with its contents.
This class contains all messages, signals and definitions of a CAN network.
The factory functions load() , load_file() and load_string() returns instances of this
class.
If strict is True an exception is raised if any signals are overlapping or if they don’t fit in
their message.
By default signals are sorted by their start bit when their Message object is created. If you
don’t want them to be sorted pass sort_signals = None. If you want the signals to be sorted
in another way pass something like sort_signals = lambda signals: list(sorted(signals,
key=lambda sig: sig.name))
property messages
property version
property dbc
property autosar
add_arxml(fp) [source]
Read and parse ARXML data from given file-like object and add the parsed data to the
database.
Open, read and parse ARXML data from given file and add the parsed data to the
database.
add_arxml_string(string) [source]
Parse given ARXML data string and add the parsed data to the database.
add_dbc(fp) [source]
Read and parse DBC data from given file-like object and add the parsed data to the
database.
>>> db = cantools.database.Database()
>>> with open ('foo.dbc', 'r') as fin:
... db.add_dbc(fin)
Open, read and parse DBC data from given file and add the parsed data to the
database.
>>> db = cantools.database.Database()
>>> db.add_dbc_file('foo.dbc')
add_dbc_string(string) [source]
Parse given DBC data string and add the parsed data to the database.
>>> db = cantools.database.Database()
>>> with open ('foo.dbc', 'r') as fin:
... db.add_dbc_string(fin.read())
add_kcd(fp) [source]
Read and parse KCD data from given file-like object and add the parsed data to the
database.
add_kcd_file(filename, encoding='utf-8') [source]
Open, read and parse KCD data from given file and add the parsed data to the
database.
add_kcd_string(string) [source]
Parse given KCD data string and add the parsed data to the database.
add_sym(fp) [source]
Read and parse SYM data from given file-like object and add the parsed data to the
database.
Open, read and parse SYM data from given file and add the parsed data to the
database.
add_sym_string(string) [source]
Parse given SYM data string and add the parsed data to the database.
Return the database as a string formatted as a DBC file. sort_signals defines how to
sort signals in message definitions sort_attribute_signals defines how to sort signals in
metadata -
get_message_by_name(name) [source]
get_message_by_frame_id(frame_id) [source]
get_bus_by_name(name) [source]
If strict is True all signal values must be within their allowed ranges, or an exception is
raised.
If decode_choices is False scaled values are not converted to choice strings (if
available).
If decode_containers is True , container frames are decoded. The reason why this needs
to be explicitly enabled is that decoding container frames returns a list of
(Message, SignalsDict) tuples which will cause code that does not expect this to
refresh() [source]
Refresh the internal database state.
This method must be called after modifying any message in the database to refresh
the internal lookup tables used when encoding and decoding messages.
A CAN message with frame id, comment, signals and other information.
If strict is True an exception is raised if any signals are overlapping or if they don’t fit in
the message.
By default signals are sorted by their start bit when their Message object is created. If you
don’t want them to be sorted pass sort_signals = None. If you want the signals to be sorted
in another way pass something like sort_signals = lambda signals: list(sorted(signals,
key=lambda sig: sig.name))
property header_id
property header_byte_order
The byte order of the header ID of the message if it is part of a container message.
property frame_id
property is_extended_frame
property is_fd
A list of all signals in the message. Returns if the message is a container message
property contained_messages
property unused_bit_pattern
property signal_groups
property comment
Note that we implicitly try to return the English comment if multiple languages were
specified.
property comments
The dictionary with the descriptions of the message in multiple languages. None if
unavailable.
property senders
property receivers
This is equivalent to the set of nodes which receive at least one of the signals
contained in the message.
property send_type
property dbc
property autosar
property bus_name
property protocol
property signal_tree
All signal names and multiplexer ids as a tree. Multiplexer signals are dictionaries,
while other signals are strings.
Given a superset of all signals required to encode the message, return a dictionary
containing exactly the ones required.
Given a dictionary of signal name to signal value mappings, ensure that all the signals
required for encoding are present
As a minimum, all signals required to encode the message need to be specified. If they
are not, a KeyError or an EncodeError exception is raised.
Depending on the parameters specified, the data of the dictionary must adhere to
additonal requirements:
Parameters:
This returns a list of (contained_message, contained_data) tuples, i.e., the data for the
contained message are bytes objects, not decoded signal dictionaries. This is required
for verifying the correctness of the end-to-end protection or the authenticity of a
contained message.
If decode_choices is False scaled values are not converted to choice strings (if
available).
If decode_containers is True , the inner messages are decoded if the current message is
a container frame. The reason why this needs to be explicitly enabled is that the result
of decode() for container frames is a list of (header_id, signals_dict) tuples which
might cause code that does not expect this to misbehave. Trying to decode a container
message with decode_containers set to False will raise a DecodeError.
If allow_truncated is True , incomplete messages (i.e., ones where the received data is
shorter than specified) will be partially decoded, i.e., all signals which are fully present
in the received data will be decoded, and the remaining ones will be omitted. If
‘allow_truncated` is set to False , DecodeError will be raised when trying to decode
incomplete messages.
This method is identical to decode() except that the message must be a container. If
the message is not a container, an exception is raised.
is_multiplexed() [source]
refresh(strict=None) [source]
If strict is True an exception is raised if any signals are overlapping or if they don’t fit
in the message. This argument overrides the value of the same argument passed to the
constructor.
A CAN signal with position, size, unit and other information. A signal is part of a message.
Byte: 0 1 2 3 4 5 6 7
+--------+--------+--------+--------+--------+--------+--------+--------+--- - -
| | | | | | | | |
+--------+--------+--------+--------+--------+--------+--------+--------+--- - -
Bit: 7 0 15 8 23 16 31 24 39 32 47 40 55 48 63 56
Big endian signal with start bit 2 and length 5 (0=LSB, 4=MSB):
Byte: 0 1 2 3
+--------+--------+--------+--- - -
| |432|10| | |
+--------+--------+--------+--- - -
Bit: 7 0 15 8 23 16 31
Little endian signal with start bit 2 and length 9 (0=LSB, 8=MSB):
Byte: 0 1 2 3
+--------+--------+--------+--- - -
|543210| | |876| |
+--------+--------+--------+--- - -
Bit: 7 0 15 8 23 16 31
name
conversion
The conversion instance, which is used to convert between raw and scaled/physical
values.
minimum
maximum
start
length
byte_order
is_signed
True if the signal is signed, False otherwise. Ignore this attribute if is_float is True .
raw_initial
The internal representation of the initial value of the signal, or None if unavailable.
initial
The initial value of the signal in units of the physical world, or None if unavailable.
raw_invalid
The raw value representing that the signal is invalid, or None if unavailable.
invalid
The scaled value representing that the signal is invalid, or None if unavailable.
unit
dbc
receivers
is_multiplexer
multiplexer_ids
The multiplexer ids list if the signal is part of a multiplexed message, None otherwise.
multiplexer_signal
The multiplexer signal if the signal is part of a multiplexed message, None otherwise.
spn
The J1939 Suspect Parameter Number (SPN) value if the signal has this attribute,
None otherwise.
comments
The dictionary with the descriptions of the signal in multiple languages. None if
unavailable.
Convert an internal raw value according to the defined scaling or value table.
Parameters:
Returns:
scaled_to_raw(scaled_value) [source]
Parameters:
Returns:
The scale factor of the signal value. The offset of the signal value.
property choices
property is_float
property comment
Note that we implicitly try to return the English comment if multiple languages were
specified.
Named values map an integer number to a human-readable string. Some file formats like
ARXML support specifying descriptions for the named value.
name
The text intended for human consumption which the specified integer is mapped to.
value
property comments
Example:
The BaseConversion class defines the interface for all signal conversion classes.
scale
offset
is_float
choices
Factory method that returns an instance of a conversion subclass based on the given
parameters.
Parameters:
choices – A dictionary of named signal choices, mapping raw values to string labels.
is_float – A boolean flag indicating whether the raw value is a float or an integer.
Returns:
Raises:
Convert an internal raw value according to the defined scaling or value table.
Parameters:
Returns:
Parameters:
Returns:
Parameters:
Returns:
The factory functions load() , load_file() and load_string() returns instances of this
class.
property dids
add_cdd(fp) [source]
Read and parse CDD data from given file-like object and add the parsed data to the
database.
Open, read and parse CDD data from given file and add the parsed data to the
database.
add_cdd_string(string) [source]
Parse given CDD data string and add the parsed data to the database.
get_did_by_name(name) [source]
get_did_by_identifier(identifier) [source]
refresh() [source]
This method must be called after modifying any DIDs in the database to refresh the
internal lookup tables used when encoding and decoding DIDs.
If decode_choices is False scaled values are not converted to choice strings (if
available).
refresh() [source]
A data data with position, size, unit and other information. A data is part of a DID.
name
conversion
The conversion instance, which is used to convert between raw and scaled/physical
values.
start
length
byte_order
minimum
The minimum value of the data, or None if unavailable.
maximum
unit
Convert an internal raw value according to the defined scaling or value table.
Parameters:
Returns:
scaled_to_raw(scaled_value) [source]
Parameters:
Returns:
The scale factor of the signal value. The offset of the signal value.
property choices
property is_float
This exception is raised when load_file() , load() and load_string() are unable to parse
given database file or string.
can_bus a CAN bus object, normally created using the python-can package.
The on_message callback is called for every successfully decoded received message. It is
called with one argument, an DecodedMessage instance.
start() [source]
>>> tester.start()
stop() [source]
Stop the tester. Periodic messages will not be sent after this call. Call start() to
resume a stopped tester.
>>> tester.stop()
property messages
Set and get signals in messages. Set signals takes effect immediately for started
enabled periodic messages. Call send() for other messages.
enable(message_name) [source]
Enable given message message_name and start sending it if its periodic and the tester
is running.
>>> tester.enable('PeriodicMessage1')
disable(message_name) [source]
Disable given message message_name and stop sending it if its periodic, enabled and
the tester is running.
>>> tester.disable('PeriodicMessage1')
Expect given message message_name and signal values signals within timeout seconds.
Messages are read from the input queue, and those not matching given message_name
and signals are discarded if discard_other_messages is True . flush_input() may be
called to discard all old messages in the input queue before calling the expect
function.
flush_input() [source]
A decoded message.
name
Message name.
signals
Message signals.
Coding style
The coding style for this package is defined as below. The rules are based on my personal
preference.
Blank lines before and after statements (if, while, return, …) (1), unless at beginning or end of
another statement or file (8).
Space before and after operators (3), except for keyword arguments where no space is
allowed (4).
Comments and doc strings starts with capital letter and ends with a period, that is, just as
sentences (6).
Maximum line length of 90 characters, but aim for less than 80.
Function and variable names are lower case with underscore separating words.
import sys
from os import path # (5)
from os import getcwd # (5)
# (2)
# (2)
def foo(bars, fum=None): # (4)
"""This is a doc string. # (6)
"""
# (7)
fies = [] # (3)
kam = path.join(getcwd(), '..')
# (1)
for bar in bars:
if len(bar) == 1): # (8)
fies.append(ham + 2 * bar) # (3)
# (1)
# This is a comment. # (6)
if fum in None:
fum = 5 # (3)
else:
fum += 1 # (3)
# (1)
fies *= fum # (3)
# (1)
return fies
# (2)
# (2)
def goo():
return True