CANTOOLS(1)

📦 version 42.0.3, in ubuntu stonking

✨ NAME ✨

cantools — Cantools Documentation 💖

github-actions
coverage

CAN BUS tools in Python 3. That's the whole vibe. 🚌✨

Project homepage: <https://github.com/cantools/cantools>

Documentation: <https://cantools.readthedocs.io>

python3 -m pip install cantools

🦋 SCRIPTING 🦋

okay so bestie, watch this. The example starts by parsing a small DBC-file <https://github.com/cantools/cantools/blob/master/tests/files/dbc/motohawk.dbc> and printing its messages and signals. absolutely iconic behavior.

>>> import cantools
>>> from pprint import pprint
>>> db = cantools.database.load_file('tests/files/dbc/motohawk.dbc')
>>> db.messages
[message('ExampleMessage', 0x1f0, False, 8, 'Example message used as template in MotoHawk models.')]
>>> example_message = db.get_message_by_name('ExampleMessage')
>>> pprint(example_message.signals)
[signal('Enable', 7, 1, 'big_endian', False, 1.0, 0, 0.0, 0.0, '-', False, None, {0: 'Disabled', 1: 'Enabled'}, None),
 signal('AverageRadius', 6, 6, 'big_endian', False, 0.1, 0, 0.0, 5.0, 'm', False, None, None, ''),
 signal('Temperature', 0, 12, 'big_endian', True, 0.01, 250, 229.53, 270.47, 'degK', False, None, None, None)]

The example continues encoding <http://cantools.readthedocs.io/en/latest/#cantools.database.can.Message.encode> a message and sending it on a CAN bus using the python-can <https://python-can.readthedocs.io/en/master/> package. sending it into the wild fr fr 🫶

>>> import can
>>> can_bus = can.interface.Bus('vcan0', bustype='socketcan')
>>> data = example_message.encode({'Temperature': 250.1, 'AverageRadius': 3.2, 'Enable': 1})
>>> message = can.Message(arbitration_id=example_message.frame_id, is_extended_id=example_message.is_extended_frame, data=data)
>>> can_bus.send(message)

Alternatively, a message can be encoded using the encode_message() <http://cantools.readthedocs.io/en/latest/#cantools.database.can.Database.encode_message> method on the database object.

The last part of the example receives and decodes <http://cantools.readthedocs.io/en/latest/#cantools.database.can.Database.decode_message> a CAN message. full circle moment 🔄

>>> message = can_bus.recv()
>>> db.decode_message(message.arbitration_id, message.data)
{'AverageRadius': 3.2, 'Enable': 'Enabled', 'Temperature': 250.09}

See examples <https://github.com/cantools/cantools/blob/master/examples> for additional examples. (more where that came from 😌)


🌈 COMMAND LINE TOOL 🌈

🎀 The decode subcommand 🎀

Decode CAN frames captured with the Linux program candump. honestly a match made in heaven.

$ candump vcan0 | python3 -m cantools decode tests/files/dbc/motohawk.dbc
  vcan0  1F0   [8]  80 4A 0F 00 00 00 00 00 ::
ExampleMessage(
    Enable: 'Enabled' -,
    AverageRadius: 0.0 m,
    Temperature: 255.92 degK
)
  vcan0  1F0   [8]  80 4A 0F 00 00 00 00 00 ::
ExampleMessage(
    Enable: 'Enabled' -,
    AverageRadius: 0.0 m,
    Temperature: 255.92 degK
)
  vcan0  1F0   [8]  80 4A 0F 00 00 00 00 00 ::
ExampleMessage(
    Enable: 'Enabled' -,
    AverageRadius: 0.0 m,
    Temperature: 255.92 degK
)

Alternatively, the decoded message can be printed on a single line — for when you're in a rush bestie:

$ candump vcan0 | python3 -m cantools decode --single-line tests/files/dbc/motohawk.dbc
  vcan0  1F0   [8]  80 4A 0F 00 00 00 00 00 :: ExampleMessage(Enable: 'Enabled' -, AverageRadius: 0.0 m, Temperature: 255.92 degK)
  vcan0  1F0   [8]  80 4A 0F 00 00 00 00 00 :: ExampleMessage(Enable: 'Enabled' -, AverageRadius: 0.0 m, Temperature: 255.92 degK)
  vcan0  1F0   [8]  80 4A 0F 00 00 00 00 00 :: ExampleMessage(Enable: 'Enabled' -, AverageRadius: 0.0 m, Temperature: 255.92 degK)

🦄 The plot subcommand 🦄

The plot subcommand is similar to the decode subcommand but messages are visualized using matplotlib <https://matplotlib.org/> instead of being printed to stdout. plots?? plots. we're visual now 💅📊

$ 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

$ cat candump-2021-01-04_180521.log | python3 -m cantools plot tests/files/dbc/abs.dbc
[image]

If you don't want to show all signals you can select the desired signals with command line arguments. A * can stand for any number of any character, a ? for exactly one arbitrary character. Signals separated by a - are displayed in separate subplots. Optionally a format can be specified after a signal, separated by a colon.

$ cat candump-2021-01-04_180521.log | python3 -m cantools plot tests/files/dbc/abs.dbc '*33.*fl:-<' '*33.*fr:->' - '*33.*rl:-<' '*33.*rr:->'
[image]

Signals with a different range of values can be displayed in the same subplot on different vertical axes by separating them with a comma. (two axes, one subplot, main character energy 👑)

$ 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'
[image]

Matplotlib comes with different preinstalled styles that you can use:

$ cat candump-2021-01-04_180521.log | cantools plot tests/files/dbc/abs.dbc --style seaborn
[image]

You can try all available styles with

$ cantools plot --list-styles . | sed -n '/^- /s/^- //p' | while IFS= read -r style; do
      cat candump-2021-01-04_180521.log | cantools plot tests/files/dbc/abs.dbc --style "$style" --title "--style '$style'"
  done

For more information see

$ python3 -m cantools plot --help
Note that by default matplotlib is not installed with cantools. But it can be by specifying an extra at installation:
$ python3 -m pip install cantools[plot]

🌸 The dump subcommand 🌸

Dump given database in a human readable format: (yes it's a whole painting, we love her 🖼️)

$ python3 -m cantools dump tests/files/dbc/motohawk.dbc
================================= Messages =================================

  ------------------------------------------------------------------------

  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

  ------------------------------------------------------------------------

⭐ The list subcommand ⭐

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. less glam, more data. still slay. 🧚

$ 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

💜 The generate_c_source subcommand 💜

Generate C source code from given database. it's giving compiler bestie 😌

The generated code contains:

Known limitations:

  • The maximum signal size is 64 bits, which in practice is never exceeded.

Below is an example of how to generate C source code from a database. The database is tests/files/dbc/motohawk.dbc.

$ python3 -m cantools generate_c_source tests/files/dbc/motohawk.dbc
Successfully generated motohawk.h and motohawk.c.

See motohawk.h <https://github.com/cantools/cantools/blob/master/tests/files/c_source/motohawk.h> and motohawk.c <https://github.com/cantools/cantools/blob/master/tests/files/c_source/motohawk.c> for the contents of the generated files.

okay so now we're in the examples bit of generate_c_source and there are SO many good ones, let's go bestie 💖

In this first one we're using --use-float, which makes the floating point numbers in the generated code single precision (float) instead of double precision (double). Tiny numbers, big slay ✨

$ python3 -m cantools generate_c_source --use-float tests/files/dbc/motohawk.dbc
Successfully generated motohawk.h and motohawk.c.

Next one: --database-name sets a custom namespace for all the generated types, defines and functions. And the output file names get changed by this option too, which is highkey iconic of it 💅

$ python3 -m cantools generate_c_source --database-name my_database_name tests/files/dbc/motohawk.dbc
Successfully generated my_database_name.h and my_database_name.c.

Wanna actually peek at what's inside those generated files? Of course you do 🫶

Then we've got --no-floating-point-numbers, which generates code with no floating point types at all, i.e. no float and no double. Gone. Not invited. 🙈

$ python3 -m cantools generate_c_source --no-floating-point-numbers tests/files/dbc/motohawk.dbc
Successfully generated motohawk.h and motohawk.c.

And here's where you can read the contents of those generated files:

And in the last example 🥹 --node is used so that message pack functions are generated only for messages sent by the specified node, and unpack functions only for messages with its signal receivers belonging to that node.

$ cantools generate_c_source tests/files/dbc/motohawk.dbc --node PCM1
Successfully generated motohawk.h and motohawk.c.

Here's those file contents if you wanna vibe check them:

Other C code generators, if you wanna go shopping around 👀


🎀 The monitor subcommand 🎀

This one monitors CAN bus traffic in a text based user interface. Literally a whole lil dashboard, we love her 💜

$ python3 -m cantools monitor tests/files/dbc/motohawk.dbc

[image]

The menu down at the bottom of the monitor shows all the commands you've got available. Here's the rundown:

  • Quit: quits the monitor. You can also just hit Ctrl+C, same energy 💀
  • Filter: only displays messages or signals that match the given regular expression. Press Enter to hop back from the filter input line to the menu.
  • Play/Pause: toggles between playing and paused (or, as the original puts it, running and freezed). You're either on or you're off bestie 🌸
  • Reset: resets the monitor back to its initial state. Fresh start, main character energy ✨

okay and then there's this numbered checklist, in order, no skipping 🫶

  1. Fork the repository.
  2. Install prerequisites. You can skip this whole step if you use tox (http://tox.readthedocs.org/).
python3 -m pip install -e .[dev]
  1. Implement the new feature or bug fix.
  2. Implement test case(s) to ensure that future changes do not break legacy.
  3. Run the linters
ruff check src
mypy src

or

tox -e ruff
tox -e mypy
  1. Run the tests.
tox -e py
  1. Check test coverage.
tox -e cov
firefox htmlcov/index.html
  1. Create a pull request. Here's where you can check up on it:

cantools.database.load_file

cantools.database.load_file(filename, database_format=None, encoding=None, frame_id_mask=None, prune_choices=False, strict=True, cache_dir=None, sort_signals=<function sort_signals_by_start_bit>)

This one opens, reads and parses the given database file, and hands you back a can.Database or diagnostics.Database object full of its contents. It's giving "the door to everything else" tbh 🔥

database_format is one of 'arxml', 'dbc', 'kcd', 'sym', cdd and None. If it's None, the database format gets picked based on the filename extension, like in this table. And heads up — filename extensions are case insensitive 👑

  • .arxml → 'arxml'
  • .dbc → 'dbc'
  • .kcd → 'kcd'
  • .sym → 'sym'
  • .cdd → 'cdd'
  • <unknown> → None

encoding specifies the file encoding. If it's None, the encoding gets picked based on the database format, like in this table. And if you want platform dependent encoding, use open() and load() instead bestie.

  • 'arxml' → 'utf-8'
  • 'dbc' → 'cp1252'
  • 'kcd' → 'utf-8'
  • 'sym' → 'cp1252'
  • 'cdd' → 'utf-8'
  • None → 'utf-8'

prune_choices abbreviates the names of choices by removing a common prefix ending on an underscore. If you want the original names you need to pass prune_choices = False. Don't let it prune your faves 💅

cache_dir specifies the database cache location in the file system. Give it as None to disable the cache. By default the cache is disabled, but it can be enabled with the environment variable CANTOOLS_CACHE_DIR. The cache key is the db path with its modification time, plus all arguments that may influence the result. Using a cache will significantly reduce the load time when you're reloading the same file. The cache directory is automatically created if it doesn't exist. Remove the cache directory cache_dir to clear the cache. It requires the optional diskcache package (pip install cantools[cache]), and if that's not installed, a warning is issued and caching is disabled. No cache for you, sorry 🥲

See load_string() for descriptions of the other arguments.

It raises an UnsupportedDatabaseFormatError exception if the given file does not contain a supported database format.

>>> db = cantools.database.load_file('foo.dbc')
>>> db.version
'1.0'

📋 Parameters

  • filename (str | PathLike[str]) — the str docs live at /usr/share/doc/python3/html/library/stdtypes.html#str, and the PathLike docs at /usr/share/doc/python3/html/library/os.html#os.PathLike, where PathLike is parameterized with str again (/usr/share/doc/python3/html/library/stdtypes.html#str).
  • database_format (str | None) — str docs at /usr/share/doc/python3/html/library/stdtypes.html#str.
  • encoding (str | None) — str docs at /usr/share/doc/python3/html/library/stdtypes.html#str.
  • frame_id_mask (int | None) — int docs at /usr/share/doc/python3/html/library/functions.html#int.
  • prune_choices (bool) — bool docs at /usr/share/doc/python3/html/library/functions.html#bool.
  • strict (bool) — bool docs at /usr/share/doc/python3/html/library/functions.html#bool.
  • cache_dir (str | None) — str docs at /usr/share/doc/python3/html/library/stdtypes.html#str.
  • sort_signals (Callable[[list[Signal]], list[Signal]] | Literal['default'] | None) — Callable docs at /usr/share/doc/python3/html/library/collections.abc.html#collections.abc.Callable, list docs at /usr/share/doc/python3/html/library/stdtypes.html#list, and Literal docs at /usr/share/doc/python3/html/library/typing.html#typing.Literal.

🎀 Return type

Database | Database


cantools.database.dump_file

cantools.database.dump_file(database, filename, database_format=None, encoding=None, sort_signals='default')

Dumps the given database database to the given file filename. Yeah. That's the whole job. And it does it flawlessly 😌

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. And ok here's the cute part — sort_signals=None is assumed by default if you have passed sort_signals=None to load_file. If you want the signals 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. periodt ✨

See load_file() for descriptions of other arguments.

The 'dbc' database format will always have Windows-style line endings (\r\n). For other database formats the line ending depends on the operating system. 🫶

>>> db = cantools.database.load_file('foo.dbc')
>>> cantools.database.dump_file(db, 'bar.dbc')

Pass sort_signals=None, prune_choices=False to load_file in order to minimize the differences between foo.dbc and bar.dbc. 💅

Parameters

  • database (Database)
  • filename (str </usr/share/doc/python3/html/library/stdtypes.html#str> | PathLike </usr/share/doc/python3/html/library/os.html#os.PathLike>[str </usr/share/doc/python3/html/library/stdtypes.html#str>])
  • database_format (str </usr/share/doc/python3/html/library/stdtypes.html#str> | None)
  • encoding (str </usr/share/doc/python3/html/library/stdtypes.html#str> | None)
  • sort_signals (Callable </usr/share/doc/python3/html/library/collections.abc.html#collections.abc.Callable>[[list </usr/share/doc/python3/html/library/stdtypes.html#list>[Signal]], list </usr/share/doc/python3/html/library/stdtypes.html#list>[Signal]] | Literal </usr/share/doc/python3/html/library/typing.html#typing.Literal>['default'] | None)

Return type: None


🦋 cantools.database.load_string(string, database_format=None, frame_id_mask=None, prune_choices=False, strict=True, sort_signals=<function sort_signals_by_start_bit>)

Parse a given database string and return a can.Database or diagnostics.Database object stuffed with its contents. Bestie, it eats strings and gives you databases. 🌸

database_format may be one of 'arxml', 'dbc', 'kcd', 'sym', 'cdd' or None, where None means transparent format.

prune_choices is a bool indicating whether signal names are supposed to be abbreviated by stripping a common prefix ending on an underscore. This is enabled by default.

See can.Database for a description of strict.

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))

Raises an UnsupportedDatabaseFormatError exception if the given string does not contain a supported database format. 😭 (rude of it, honestly.)

>>> with open('foo.dbc') as fin:
...    db = cantools.database.load_string(fin.read())
>>> db.version
'1.0'

Parameters

  • string (str </usr/share/doc/python3/html/library/stdtypes.html#str>)
  • database_format (str </usr/share/doc/python3/html/library/stdtypes.html#str> | None)
  • frame_id_mask (int </usr/share/doc/python3/html/library/functions.html#int> | None)
  • prune_choices (bool </usr/share/doc/python3/html/library/functions.html#bool>)
  • strict (bool </usr/share/doc/python3/html/library/functions.html#bool>)
  • sort_signals (Callable </usr/share/doc/python3/html/library/collections.abc.html#collections.abc.Callable>[[list </usr/share/doc/python3/html/library/stdtypes.html#list>[Signal]], list </usr/share/doc/python3/html/library/stdtypes.html#list>[Signal]] | Literal </usr/share/doc/python3/html/library/typing.html#typing.Literal>['default'] | None)

Return type: Database | Database


💜 cantools.database.load(fp, database_format=None, frame_id_mask=None, prune_choices=False, strict=True, sort_signals=<function sort_signals_by_start_bit>)

Read and parse a given database file-like object and hand you back a can.Database or diagnostics.Database object with all its contents. file-like object in, whole database out, iconic behavior.

See load_string() for descriptions of other arguments.

Raises an UnsupportedDatabaseFormatError exception if the given file-like object does not contain a supported database format. 💀

>>> with open('foo.kcd') as fin:
...    db = cantools.database.load(fin)
>>> db.version
None

Parameters

  • fp (TextIO </usr/share/doc/python3/html/library/typing.html#typing.TextIO>)
  • database_format (str </usr/share/doc/python3/html/library/stdtypes.html#str> | None)
  • frame_id_mask (int </usr/share/doc/python3/html/library/functions.html#int> | None)
  • prune_choices (bool </usr/share/doc/python3/html/library/functions.html#bool>)
  • strict (bool </usr/share/doc/python3/html/library/functions.html#bool>)
  • sort_signals (Callable </usr/share/doc/python3/html/library/collections.abc.html#collections.abc.Callable>[[list </usr/share/doc/python3/html/library/stdtypes.html#list>[Signal]], list </usr/share/doc/python3/html/library/stdtypes.html#list>[Signal]] | Literal </usr/share/doc/python3/html/library/typing.html#typing.Literal>['default'] | None)

Return type: Database | Database


👑 class cantools.database.can.Database(messages=None, nodes=None, buses=None, version=None, dbc_specifics=None, autosar_specifics=None, frame_id_mask=None, strict=True, sort_signals=<function sort_signals_by_start_bit>)

This class contains all messages, signals and definitions of a CAN network. it's giving main character energy, fr fr.

The factory functions load(), load_file() and load_string() return 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. ⚠️ so keep it strict unless you know what you're doing.

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))

Parameters

  • messages (list </usr/share/doc/python3/html/library/stdtypes.html#list>[Message] | None)
  • nodes (list </usr/share/doc/python3/html/library/stdtypes.html#list>[Node] | None)
  • buses (list </usr/share/doc/python3/html/library/stdtypes.html#list>[Bus] | None)
  • version (str </usr/share/doc/python3/html/library/stdtypes.html#str> | None)
  • dbc_specifics (DbcSpecifics | None)
  • autosar_specifics (AutosarDatabaseSpecifics | None)
  • frame_id_mask (int </usr/share/doc/python3/html/library/functions.html#int> | None)
  • strict (bool </usr/share/doc/python3/html/library/functions.html#bool>)
  • sort_signals (Callable </usr/share/doc/python3/html/library/collections.abc.html#collections.abc.Callable>[[list </usr/share/doc/python3/html/library/stdtypes.html#list>[Signal]], list </usr/share/doc/python3/html/library/stdtypes.html#list>[Signal]] | Literal </usr/share/doc/python3/html/library/typing.html#typing.Literal>['default'] | None)
  • property messages: list </usr/share/doc/python3/html/library/stdtypes.html#list>[Message] — a list of messages in the database. Use get_message_by_frame_id() or get_message_by_name() to find a message by its frame id or name. 🎀
  • property nodes: list </usr/share/doc/python3/html/library/stdtypes.html#list>[Node] — a list of nodes in the database.
  • property buses: list </usr/share/doc/python3/html/library/stdtypes.html#list>[Bus] — a list of CAN buses in the database.
  • property version: str </usr/share/doc/python3/html/library/stdtypes.html#str> | None </usr/share/doc/python3/html/library/constants.html#None> — the database version, or None if unavailable.
  • property dbc: DbcSpecifics | None </usr/share/doc/python3/html/library/constants.html#None> — an object containing dbc specific properties like e.g. attributes.
  • property autosar: AutosarDatabaseSpecifics | None </usr/share/doc/python3/html/library/constants.html#None> — an object containing AUTOSAR specific properties like e.g. attributes.
  • is_similar(other, *, tolerance=1e-12, include_format_specifics=True) — compare two database objects inexactly. This means that small discrepanceies stemming from e.g. rounding errors are ignored. Parameters
    • other (Database)
    • tolerance (float </usr/share/doc/python3/html/library/functions.html#float>)
    • include_format_specifics (bool </usr/share/doc/python3/html/library/functions.html#bool>) Return type: bool </usr/share/doc/python3/html/library/functions.html#bool>
  • add_arxml(fp) — read and parse ARXML data from a given file-like object and add the parsed data to the database. ✨

...and the last bit of that one's signature, since we got cut off ✨

  • fp — a TextIO, bestie 🫶

Return type: None


💖 add_arxml_file(filename, encoding='utf-8') 💖

Open it, read it, parse it — this one takes ARXML data from a file and drops the parsed goodies straight into the database ✨

encoding tells it what the file encoding is, iykyk.

Parameters:

  • filename — str | PathLike[str]
  • encoding — str

Return type: None

🦋 add_arxml_string(string) 🦋

Already got the ARXML data as a string instead of a whole file? Say less. This parses it and adds the parsed data to the database 💅

Parameters:

  • string — str

Return type: None

🎀 add_dbc(fp) 🎀

Reads and parses DBC data from whatever file-like object you hand it and adds the parsed data to the database. No cap 💖

>>> db = cantools.database.Database()
>>> with open ('foo.dbc', 'r') as fin:
...     db.add_dbc(fin)

Parameters:

  • fp — a TextIO

Return type: None

🌸 add_dbc_file(filename, encoding='cp1252') 🌸

Opens, reads and parses DBC data from the given file and adds the parsed data to the database 🫶

encoding specifies the file encoding — and bestie, the default here is cp1252, not UTF-8. Noted. 📝

>>> db = cantools.database.Database()
>>> db.add_dbc_file('foo.dbc')

Parameters:

  • filename — str | PathLike[str]
  • encoding — str

Return type: None

⭐ add_dbc_string(string) ⭐

Parses the DBC data you already have as a string and adds the parsed data to the database. Iconic ✨

>>> db = cantools.database.Database()
>>> with open ('foo.dbc', 'r') as fin:
...     db.add_dbc_string(fin.read())

Parameters:

  • string — str

Return type: None

🧚 add_kcd(fp) 🧚

Reads and parses KCD data from a file-like object and adds the parsed data into the database 🌈

Parameters:

  • fp — a TextIO

Return type: None

💜 add_kcd_file(filename, encoding='utf-8') 💜

Opens, reads and parses KCD data from the given file and adds the parsed data to the database 🎀

encoding specifies the file encoding (default is 'utf-8', slay).

Parameters:

  • filename — str | PathLike[str]
  • encoding — str

Return type: None

🔥 add_kcd_string(string) 🔥

Parses the given KCD data string and adds the parsed data to the database. Ate 💅

Parameters:

  • string — str

Return type: None

🍓 add_sym(fp) 🍓

Reads and parses SYM data from a file-like object and adds the parsed data to the database ✨

Parameters:

  • fp — a TextIO

Return type: None

🦄 add_sym_file(filename, encoding='utf-8') 🦄

Opens, reads and parses SYM data from the given file and adds the parsed data to the database 🫶

encoding specifies the file encoding (again, default 'utf-8').

Parameters:

  • filename — str | PathLike[str]
  • encoding — str

Return type: None

💀 add_sym_string(string) 💀

Parses the given SYM data string and adds the parsed data to the database. Easy money 🌸

Parameters:

  • string — str

Return type: None

👑 as_dbc_string(*, sort_signals='default', sort_attribute_signals='default', sort_attributes=None, sort_choices=None, shorten_long_names=True) 👑

Hands the database back to you as a string formatted like a DBC file. Periodt 💅

sort_signals defines how to sort signals in message definitions.

sort_attribute_signals defines how to sort signals in metadata — comments, value table definitions and attributes.

Parameters:

  • sort_signals — Callable[[list[Signal]], list[Signal]] | Literal['default'] | None
  • sort_attribute_signals — Callable[[list[Signal]], list[Signal]] | Literal['default'] | None
  • sort_attributes — okay so this type annotation is a whole novel, bestie, buckle up 😭:
Callable[[list[tuple[Literal['dbc'], AttributeType, None, None, None, None] | tuple[~typing.Literal['node'], AttributeType, Node, None, None, None] | tuple[~typing.Literal['message'], AttributeType, None, Message, None, None] | tuple[~typing.Literal['signal'], AttributeType, None, Message, Signal, None] | tuple[~typing.Literal['envvar'], AttributeType, None, None, None, EnvironmentVariable]]], list[tuple[~typing.Literal['dbc'], AttributeType, None, None, None, None] | tuple[~typing.Literal['node'], AttributeType, Node, None, None, None] | tuple[~typing.Literal['message'], AttributeType, None, Message, None, None] | tuple[~typing.Literal['signal'], AttributeType, None, Message, Signal, None] | tuple[~typing.Literal['envvar'], AttributeType, None, None, None, EnvironmentVariable]]] | ~typing.Literal['default'] | None
  • sort_choices — Callable[[OrderedDict[int, str | NamedSignalValue]], OrderedDict[int, str | NamedSignalValue]] | None
  • shorten_long_names — bool

Return type: str

🌈 as_kcd_string(*, sort_signals='default') 🌈

Return the database as a string formatted as a KCD file. 🎀

Finishing up that parameter list we were mid-way through, bestie — last one, promise 🫶

  • sort_signals — typed as Callable </usr/share/doc/python3/html/library/collections.abc.html#collections.abc.Callable>[[list </usr/share/doc/python3/html/library/stdtypes.html#list>[Signal]], list </usr/share/doc/python3/html/library/stdtypes.html#list>[Signal]] | Literal </usr/share/doc/python3/html/library/typing.html#typing.Literal>['default'] | None

Return type: str </usr/share/doc/python3/html/library/stdtypes.html#str>


🌸 as_sym_string(*, sort_signals='default') 🌸

Hands you the whole database back as a string, all formatted like a SYM file 💅 Literally the SYM file of your dreams, as text.

Parameters

  • sort_signals — Callable </usr/share/doc/python3/html/library/collections.abc.html#collections.abc.Callable>[[list </usr/share/doc/python3/html/library/stdtypes.html#list>[Signal]], list </usr/share/doc/python3/html/library/stdtypes.html#list>[Signal]] | Literal </usr/share/doc/python3/html/library/typing.html#typing.Literal>['default'] | None

Return type: str </usr/share/doc/python3/html/library/stdtypes.html#str>


🦋 get_message_by_name(name) 🦋

Finds you the message object for the name name. Your little message-finder 🫶

Parameters

  • name — str </usr/share/doc/python3/html/library/stdtypes.html#str>

Return type: Message


🎀 get_message_by_frame_id(frame_id, force_extended_id=False) 🎀

Same energy, but by frame id instead of name — finds the message object for the given frame id frame_id ✨

Parameters

  • frame_id — int </usr/share/doc/python3/html/library/functions.html#int>
  • force_extended_id — bool </usr/share/doc/python3/html/library/functions.html#bool>

Return type: Message


💜 get_node_by_name(name) 💜

Finds the node object for the name name. Node hunting, slay 🔥

Parameters

  • name — str </usr/share/doc/python3/html/library/stdtypes.html#str>

Return type: Node


🌈 get_bus_by_name(name) 🌈

Finds the bus object for the name name. Getting the whole bus together, periodt 🚌

Parameters

  • name — str </usr/share/doc/python3/html/library/stdtypes.html#str>

Return type: Bus


🔥 encode_message(frame_id_or_name, data, scaling=True, padding=False, strict=True, force_extended_id=False) 🔥

Encodes the given signal data data as a message of the given frame id or name frame_id_or_name.

Okay so for regular Messages, data is a dictionary of signal name-value entries. For container messages, it's a list of (ContainedMessageOrMessageName, ContainedMessageSignals) tuples. Two different shapes, both giving ✨

If scaling is False, no scaling of signals is performed — none, zero, zip.

If padding is True, unused bits get encoded as 1.

If strict is True, every single signal value has to sit inside its allowed range, or an exception gets raised. No vibes-based out-of-range nonsense here, bestie 😭

>>> db.encode_message(158, {'Bar': 1, 'Fum': 5.0})
b'\x01\x45\x23\x00\x11'
>>> db.encode_message('Foo', {'Bar': 1, 'Fum': 5.0})
b'\x01\x45\x23\x00\x11'

Parameters

  • frame_id_or_name — int </usr/share/doc/python3/html/library/functions.html#int> | str </usr/share/doc/python3/html/library/stdtypes.html#str>
  • data — Mapping </usr/share/doc/python3/html/library/collections.abc.html#collections.abc.Mapping>[str </usr/share/doc/python3/html/library/stdtypes.html#str>, int </usr/share/doc/python3/html/library/functions.html#int> | float </usr/share/doc/python3/html/library/functions.html#float> | str </usr/share/doc/python3/html/library/stdtypes.html#str> | NamedSignalValue] | Sequence </usr/share/doc/python3/html/library/collections.abc.html#collections.abc.Sequence>[tuple </usr/share/doc/python3/html/library/stdtypes.html#tuple>[Message | str </usr/share/doc/python3/html/library/stdtypes.html#str> | int </usr/share/doc/python3/html/library/functions.html#int>, bytes </usr/share/doc/python3/html/library/stdtypes.html#bytes> | Mapping </usr/share/doc/python3/html/library/collections.abc.html#collections.abc.Mapping>[str </usr/share/doc/python3/html/library/stdtypes.html#str>, int </usr/share/doc/python3/html/library/functions.html#int> | float </usr/share/doc/python3/html/library/functions.html#float> | str </usr/share/doc/python3/html/library/stdtypes.html#str> | NamedSignalValue]]]
  • scaling — bool </usr/share/doc/python3/html/library/functions.html#bool>
  • padding — bool </usr/share/doc/python3/html/library/functions.html#bool>
  • strict — bool </usr/share/doc/python3/html/library/functions.html#bool>
  • force_extended_id — bool </usr/share/doc/python3/html/library/functions.html#bool>

Return type: bytes </usr/share/doc/python3/html/library/stdtypes.html#bytes>


💖 decode_message(frame_id_or_name, data, decode_choices=True, scaling=True, decode_containers=False, allow_truncated=False, force_extended_id=False) 💖

Decodes the given signal data data as a message of the given frame id or name frame_id_or_name. You get back a dictionary of signal name-value entries. Chef's kiss 👑

If decode_choices is False, scaled values do not get converted into choice strings (even if those strings are available). They stay numeric, fr fr.

If scaling is False, no scaling of signals is performed.

>>> db.decode_message(158, b'\x01\x45\x23\x00\x11')
{'Bar': 1, 'Fum': 5.0}
>>> db.decode_message('Foo', b'\x01\x45\x23\x00\x11')
{'Bar': 1, 'Fum': 5.0}

If decode_containers is True, container frames get decoded. The reason this has to be switched on explicitly is that decoding container frames returns a list of (Message, SignalsDict) tuples, and that will make code which does not expect it misbehave 😭

⚠️ Trying to decode a container message with decode_containers set to False will raise a DecodeError. Yes, it will. It's giving consequences.

Parameters

  • frame_id_or_name — int </usr/share/doc/python3/html/library/functions.html#int> | str </usr/share/doc/python3/html/library/stdtypes.html#str>
  • data — bytes </usr/share/doc/python3/html/library/stdtypes.html#bytes>
  • decode_choices — bool </usr/share/doc/python3/html/library/functions.html#bool>
  • scaling — bool </usr/share/doc/python3/html/library/functions.html#bool>
  • decode_containers — bool </usr/share/doc/python3/html/library/functions.html#bool>
  • allow_truncated — bool </usr/share/doc/python3/html/library/functions.html#bool>
  • force_extended_id — bool </usr/share/doc/python3/html/library/functions.html#bool>

Return type: dict </usr/share/doc/python3/html/library/stdtypes.html#dict>[str </usr/share/doc/python3/html/library/stdtypes.html#str>, int </usr/share/doc/python3/html/library/functions.html#int> | float </usr/share/doc/python3/html/library/functions.html#float> | str </usr/share/doc/python3/html/library/stdtypes.html#str> | NamedSignalValue] | Sequence </usr/share/doc/python3/html/library/collections.abc.html#collections.abc.Sequence>[tuple </usr/share/doc/python3/html/library/stdtypes.html#tuple>[Message, Mapping </usr/share/doc/python3/html/library/collections.abc.html#collections.abc.Mapping>[str </usr/share/doc/python3/html/library/stdtypes.html#str>, int </usr/share/doc/python3/html/library/functions.html#int> | float </usr/share/doc/python3/html/library/functions.html#float> | str </usr/share/doc/python3/html/library/stdtypes.html#str> | NamedSignalValue]] | tuple </usr/share/doc/python3/html/library/stdtypes.html#tuple>[Message, bytes </usr/share/doc/python3/html/library/stdtypes.html#bytes>] | tuple </usr/share/doc/python3/html/library/stdtypes.html#tuple>[int </usr/share/doc/python3/html/library/functions.html#int>, bytes </usr/share/doc/python3/html/library/stdtypes.html#bytes>]]


🧚 refresh() 🧚

Refreshes the internal database state.

💀 This method must be called after modifying any message in the database, to refresh the internal lookup tables that get used when encoding and decoding messages. Skip it and your lookups are living in the past, bestie.

Return type: None

👑 cantools.database.can.Message

okay bestie, meet the moment: a CAN message with a frame id, a comment, signals and a whole bunch of other info. it's giving main character energy in the database, no cap.

class cantools.database.can.Message(frame_id, name, length, signals,
contained_messages=None, header_id=None, header_byte_order='big_endian',
unused_bit_pattern=0, comment=None, senders=None, send_type=None,
cycle_time=None, dbc_specifics=None, autosar_specifics=None,
is_extended_frame=False, is_fd=False, bus_name=None, signal_groups=None,
strict=True, protocol=None, sort_signals=<function
sort_signals_by_start_bit>)

If strict is True, an exception gets thrown if any signals are overlapping or if they straight up don't fit in the message. 🚨 so like, strict mode is not playing around.

By default, signals are sorted by their start bit the moment the Message object is created. If you do not want them sorted, pass sort_signals = None. If you want them sorted a different way, pass something like sort_signals = lambda signals: list(sorted(signals, key=lambda sig: sig.name)). slay, custom sorting is yours 💅

Parameters

  • frame_id (int)
  • name (str)
  • length (int)
  • signals (list[Signal])
  • contained_messages (list[Message] | None)
  • header_id (int | None)
  • header_byte_order (str)
  • unused_bit_pattern (int)
  • comment (str | dict[str | None, str] | None)
  • senders (list[str] | None)
  • send_type (str | None)
  • cycle_time (int | None)
  • dbc_specifics (DbcSpecifics | None)
  • autosar_specifics (AutosarMessageSpecifics | None)
  • is_extended_frame (bool)
  • is_fd (bool)
  • bus_name (str | None)
  • signal_groups (list[SignalGroup] | None)
  • strict (bool)
  • protocol (str | None)
  • sort_signals (Callable[[list[Signal]], list[Signal]] | Literal['default'] | None)

✨ the properties, aka the lore drops ✨

  • header_id (int | None) — the header ID of the message if it is part of a container message. otherwise, nothing to see here 🫣
  • header_byte_order (str) — the byte order of the header ID of the message if it is part of a container message.
  • frame_id (int) — the message frame id. the whole identity fr.
  • is_extended_frame (bool) — True if the message is an extended frame, False otherwise.
  • is_fd (bool) — True if the message requires CAN-FD, False otherwise. can-fd girlies rise 🔥
  • name (str) — the message name as a string.
  • length (int) — the message data length in bytes.
  • signals (list[Signal]) — a list of all signals in the message. the whole squad 💖
  • is_container (bool) — returns if the message is a container message.
  • contained_messages (list[Message]) — the list of messages potentially contained within this message. it's messages all the way down 🌀
  • unused_bit_pattern (int) — the pattern used for unused bits of a message.

This prevents undefined behaviour and/or information leaks when encoding messages. so like, do not skip this one, it's literally protecting you 🙈

  • signal_groups (list[SignalGroup] | None) — a list of all signal groups in the message.
  • comment (str | None) — the message comment, or None if unavailable.

Note that we implicitly try to return the English comment if multiple languages were specified. anglophone default behaviour, iconic honestly 💅

  • comments (dict[str | None, str] | None) — the dictionary with the descriptions of the message in multiple languages. None if unavailable. multilingual queen 🌈
  • senders (list[str]) — a list of all sender nodes of this message.
  • receivers (set[str]) — a set of all receiver nodes of this message.

This is equivalent to the set of nodes which receive at least one of the signals contained in the message. math is mathing 🧮

  • send_type (str | None) — the message send type, or None if unavailable.
  • cycle_time (int | None) — the message cycle time, or None if unavailable.
  • dbc (DbcSpecifics | None) — an object containing dbc specific properties like e.g. attributes.
  • autosar (AutosarMessageSpecifics | None) — an object containing AUTOSAR specific properties

e.g. auxiliary data required to implement CRCs, secure on-board communication (secOC) or container messages. very fancy, very secure, we love her 🎀

  • bus_name (str | None) — the message bus name, or None if unavailable.
  • protocol (str | None) — the message protocol, or None if unavailable. Only one protocol is currently supported; 'j1939'. that's the whole roster, bestie.
  • signal_tree (Sequence[str | dict[str, dict[int, Sequence[str]]]]) — all signal names and multiplexer ids as a tree. Multiplexer signals are dictionaries, while other signals are strings.

watch this:

>>> foo = db.get_message_by_name('Foo')
>>> foo.signal_tree
['Bar', 'Fum']
>>> bar = db.get_message_by_name('Bar')
>>> bar.signal_tree
[{'A': {0: ['C', 'D'], 1: ['E']}}, 'B']

look at that structure. nested dictionaries popping off. iykyk 🌸


🫶 gather_signals(input_data, node=None)

Given a superset of all signals required to encode the message, return a dictionary containing exactly the ones required. no extras, no crumbs, just the essentials ✨

If a required signal is missing from the input dictionary, a EncodeError exception is raised. so like, don't be sloppy with your input dict or you WILL hear about it 😭

Parameters

…and it closes out with these two, bestie:

  • input_data — a Mapping of str → int | float | str | NamedSignalValue 🫶
  • node — either a Codec or None

Return type — dict of str → int | float | str | NamedSignalValue ✨

💡 okay so the Python docs links on all the types in this chunk are long, so here's the legend once and then we keep it cute — every dict, str, etc. below points at exactly one of these paths: - dict → /usr/share/doc/python3/html/library/stdtypes.html#dict - list → /usr/share/doc/python3/html/library/stdtypes.html#list - str → /usr/share/doc/python3/html/library/stdtypes.html#str - bytes → /usr/share/doc/python3/html/library/stdtypes.html#bytes - tuple → /usr/share/doc/python3/html/library/stdtypes.html#tuple - int → /usr/share/doc/python3/html/library/functions.html#int - float → /usr/share/doc/python3/html/library/functions.html#float - bool → /usr/share/doc/python3/html/library/functions.html#bool - Mapping → /usr/share/doc/python3/html/library/collections.abc.html#collections.abc.Mapping - Sequence → /usr/share/doc/python3/html/library/collections.abc.html#collections.abc.Sequence

🎀 gather_container(contained_messages, signal_values) 🎀

Okay so you hand it a superset of every message you'd need to encode all the messages featured by a container message, and it hands you back a list of (Message, SignalDict) tuples that you can yeet straight into encode(). 🫶

If a required signal is missing from that input dictionary, it raises an EncodeError exception — no vibes, just error. 😭

Parameters

  • contained_messages — a list of Message | str | int 🌸
  • signal_values — a Mapping of str → int | float | str | NamedSignalValue

Return type — a Sequence of:

  • tuple of [Message, Mapping[str, int | float | str | NamedSignalValue]]
  • or tuple of [Message, bytes]
  • or tuple of [int, bytes] 💅

🦋 assert_signals_encodable(input_data, scaling, assert_values_valid=True, assert_all_known=True) 🦋

Given a dictionary of signal name → signal value mappings, this one makes sure that all the signals required for encoding are present. ✨

At minimum, literally every signal required to encode the message has to be specified. If they aren't? KeyError or EncodeError gets raised. Periodt.

And depending on the parameters you picked, the data in your dictionary has to clear some extra requirements:

Parameters

  • scaling — bool. If False, no scaling of signals is performed. 📏
  • assert_values_valid — bool. If True, the values of all specified signals must be valid/encodable. If at least one of them isn't, an EncodeError exception is raised. (Note that the values of multiplexer selector signals must always be valid!) ⚠️
  • assert_all_known — bool. If True, all specified signals must actually be used by the encoding operation, otherwise an EncodeError exception is raised. This is lowkey the bestie that catches your typos. 💖
  • input_data — a Mapping of str → int | float | str | NamedSignalValue

Return type — None


🧚 assert_container_encodable(input_data, scaling, assert_values_valid=True, assert_all_known=True) 🧚

This method is identical to assert_signals_encodable() — like, literally the same energy — except it's the one that cares about container messages. 🌈

Parameters

  • input_data — a Sequence of tuple of [Message | str | int, bytes | Mapping[str, int | float | str | NamedSignalValue]] 🙈
  • scaling — bool
  • assert_values_valid — bool
  • assert_all_known — bool

(no extra description on these ones, the OG page just gives the types — slay, we respect it) 💅

Return type — None


👑 encode(data, scaling=True, padding=False, strict=True) 👑

Encode the given data as a message of this type. This is the glow-up moment. ✨

If the message is an "ordinary" frame, this method expects a key-to-value dictionary as data, mapping the name of every required signal to a value that can be encoded by that signal. 🍓

But if the current message is a container message, it expects a list of (contained_message, contained_data) tuples, where contained_message is either an integer with the header ID, the name, or the message object of the contained message. And contained_data can either be given as raw binary data (bytes) or as a key-to-value dictionary of every signal needed to encode the featured message. 🫶

  • If scaling is False, no scaling of signals is performed.
  • If padding is True, unused bits are encoded as 1. 1️⃣
  • If strict is True, the specified signals must exactly be the ones expected, and their values must be within their allowed ranges — otherwise an EncodeError exception is raised. ⚠️
>>> foo = db.get_message_by_name('Foo')
>>> foo.encode({'Bar': 1, 'Fum': 5.0})
b'\x01\x45\x23\x00\x11'

Parameters

okay bestie we're still deep in the Message object's method zone and this next chunk is a lot of typing — but it's all just "here's what you can hand me, and here's what comes back," so breathe 💖. Continuing that param list from right before:

  • data — the payload, and it's gotta be one of these:
Mapping[str, int | float | str | NamedSignalValue] | Sequence[tuple[Message | str | int, bytes] | Mapping[str, int | float | str | NamedSignalValue]]
  • scaling — bool
  • padding — bool
  • strict — bool

Return type — bytes 🎀


🧸 unpack_container(data, allow_truncated=False)

Unwrap the contents of a container message. It's giving "unzip but for CAN frames" ✨

This hands you back a list of (contained_message, contained_data) tuples. And no cap — the data for the contained message here are bytes objects, not decoded signal dictionaries. That's the whole point: you need it raw so you can verify the correctness of the end-to-end protection, or check the authenticity of a contained message. 🫶

Note that contained_message is the header ID integer value if a contained message is unknown. And further, if something goes seriously wrong, a DecodeError is raised. 😭

Parameters

  • data — bytes
  • allow_truncated — bool

Return type

Sequence[tuple[Message, bytes] | tuple[int, bytes]]

💫 decode(data, decode_choices=True, scaling=True, decode_containers=False, allow_truncated=False, allow_excess=True)

Decode given data as a message of this type. The main character method, honestly 👑

If decode_choices is False, scaled values are not converted to choice strings (if available).

If scaling is False, no scaling of signals is performed.

Obsessed with this little demo, it's so cute:

>>> foo = db.get_message_by_name('Foo')
>>> foo.decode(b'\x01\x45\x23\x00\x11')
{'Bar': 1, 'Fum': 5.0}

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. So like — consent first, basically. 🙈 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. 🚨

If allow_excess is True, data that is are longer than the expected message length is decoded, else a ValueError is raised if such data is encountered.

Parameters

  • data — bytes
  • decode_choices — bool
  • scaling — bool
  • decode_containers — bool
  • allow_truncated — bool
  • allow_excess — bool

Return type

dict[str, int | float | str | NamedSignalValue] | Sequence[tuple[Message, Mapping[str, int | float | str | NamedSignalValue]] | tuple[Message, bytes] | tuple[int, bytes]]

🌸 decode_simple(data, decode_choices=True, scaling=True, allow_truncated=False, allow_excess=True)

Decode given data as a container message.

This method is identical to decode() except that the message must not be a container. If the message is a container, an exception is raised. 💀

Parameters

  • data — bytes
  • decode_choices — bool
  • scaling — bool
  • allow_truncated — bool
  • allow_excess — bool

Return type

dict[str, int | float | str | NamedSignalValue]

🦋 decode_container(data, decode_choices=True, scaling=True, allow_truncated=False, allow_excess=True)

Decode given data as a container message.

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. Flip side of the coin, periodt. ✨

Parameters

  • data — bytes
  • decode_choices — bool
  • scaling — bool
  • allow_truncated — bool
  • allow_excess — bool

so the thing that hands you back a value there? bestie it hands back a whole inventory, it's giving luggage carousel at 2am:

Sequence[tuple[Message, Mapping[str, int | float | str | NamedSignalValue]] | tuple[Message, bytes] | tuple[int, bytes]]

which lowkey reads as "here's your message, and here's the stuff that came attached to it". every type in that signature is hyperlinked in the docs out to the Python stdlib HTML pages sitting under /usr/share/doc/python3/html/library/ — Sequence and Mapping live in collections.abc, tuple/str in stdtypes, int/float/bool in functions, None in constants. the whole stdlib tour, no cap. 🦋

Return type: that whole Sequence[...] situation up there ↑


✨ is_multiplexed() ✨

gives you back True if the message is multiplexed, and False if it isn't. that's the entire job. she's simple, she's effective, she ate. 💅

>>> foo = db.get_message_by_name('Foo')
>>> foo.is_multiplexed()
False
>>> bar = db.get_message_by_name('Bar')
>>> bar.is_multiplexed()
True

Return type: bool


🔄 refresh(strict=None) 🔄

refreshes the internal message state. like, you're telling the message to re-check itself, comb its hair, redo the math, be the main character again. 🎀

if strict is True, an exception gets raised if any signals are overlapping, or if they simply don't fit in the message. heads up though: this argument overrides whatever value you passed for that same argument to the constructor. so when you say it here, this one wins. periodt. 👑

Parameters: strict (bool | None)

Return type: None


🧚 class cantools.database.can.Signal(name, start, length, byte_order='little_endian', is_signed=False, raw_initial=None, raw_invalid=None, conversion=None, minimum=None, maximum=None, unit=None, dbc_specifics=None, comment=None, receivers=None, is_multiplexer=False, multiplexer_ids=None, multiplexer_signal=None, spn=None)

a CAN signal with position, size, unit and other information. a signal is part of a message, bestie. it's the little guy inside the big guy. 🌸

signal bit numbering in 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

🌈 Parameters 🌈

  • name (str)
  • start (int)
  • length (int)
  • byte_order (Literal['little_endian', 'big_endian'])
  • is_signed (bool)
  • raw_initial (int | float | None)
  • raw_invalid (int | float | None)
  • conversion (BaseConversion | None)
  • minimum (float | None)
  • maximum (float | None)
  • unit (str | None)
  • dbc_specifics (DbcSpecifics | None)
  • comment (str | dict[str | None, str] | None)
  • receivers (list[str] | None)
  • is_multiplexer (bool)
  • multiplexer_ids (list[int] | None)
  • multiplexer_signal (str | None)
  • spn (int | None)

💖 the attributes, one by one 💖

  • name (str) — the signal name, as a string. iconic.
  • conversion (BaseConversion) — the conversion instance, and it's the thing doing the converting between raw values and scaled/physical values.
  • minimum (float | None) — the scaled minimum value of the signal, or None if there isn't one.
  • maximum (float | None) — the scaled maximum value of the signal, or None if there isn't one.
  • start (int) — the start bit position of the signal inside its message.
  • length (int) — the length of the signal, in bits.
  • byte_order (Literal['little_endian', 'big_endian']) — the signal byte order, as 'little_endian' or 'big_endian'.
  • is_signed (bool) — True if the signal is signed, False otherwise. ignore this attribute if is_float is True. (she said what she said.)
  • raw_initial (int | float | None) — the internal representation of the initial value of the signal, or None if it's unavailable.
  • initial (int | float | str | NamedSignalValue | None) — the initial value of the signal in units of the physical world, or None if it's unavailable.
  • raw_invalid (int | float | None) — the raw value that means "this signal is invalid", or None if it's unavailable.
  • invalid (int | float | str | NamedSignalValue | None) — the scaled value that means "this signal is invalid", or None if it's unavailable.
  • unit (str | None) — the unit of the signal as a string, or None if it's unavailable.
  • dbc (DbcSpecifics) — an object holding dbc specific properties, like e.g. attributes.
  • receivers (list[str]) — a list of all the receiver nodes of this signal.
  • is_multiplexer (bool) — True if this is the multiplexer signal in a message, False otherwise.
  • multiplexer_ids (list[int] | None) — the multiplexer ids list, if the signal is part of a multiplexed message; None otherwise.
  • multiplexer_signal: str | None — the multiplexer signal if this signal is part of a multiplexed message, and None otherwise. iykyk.
  • spn: int | None — the J1939 Suspect Parameter Number (SPN) value when the signal has this attribute, None when it doesn't. 🙈
  • comments: dict[str | None, str] | None — the dict with all the descriptions of the signal in multiple languages. None if it's just not available. 😭

raw_to_scaled(raw_value, decode_choices=True)

okay so this one converts an internal raw value according to the defined scaling or value table. slay.

Parameters

  • raw_value (int | float) — the raw value 🫶
  • decode_choices (bool) — if decode_choices is False, scaled values are not converted to choice strings (if available).

Returns — the calculated scaled value ✨

Return type — int | float | str | NamedSignalValue


scaled_to_raw(scaled_value)

the reverse glow-up: converts a scaled value back to the internal raw value. 💅

Parameters

  • scaled_value (int | float | str | NamedSignalValue) — the scaled value.

Returns — the internal raw value.

Return type — int | float


property scale: int | float

the scale factor of the signal value. iconic.

property offset: int | float

the offset of the signal value.

property choices: OrderedDict[int, str | NamedSignalValue] | None

a dictionary mapping signal values to enumerated choices, or None if it's not available. 🎀

property is_float: bool

True if the raw signal value is a float, False otherwise. simple math bestie.

property comment: str | None

the signal comment, or None if unavailable.

note that we implicitly try to return the English comment if multiple languages were specified. 💖

🔥 class cantools.database.can.Node(name, comment=None, dbc_specifics=None, autosar_specifics=None)

an NODE on the CAN bus. main character of the network fr fr.

Parameters

  • name (str)
  • comment (str | dict[str | None, str] | None)
  • dbc_specifics (DbcSpecifics | None)
  • autosar_specifics (AutosarNodeSpecifics | None)

property name: str

the node name as a string. ✨

property comment: str | None

the node's comment, or None if unavailable.

note that we implicitly try to return the English comment if multiple languages were specified.

property comments: dict[str | None, str] | None

the dictionary with the descriptions of the bus in multiple languages. None if unavailable.

property dbc: DbcSpecifics

an object containing dbc specific properties like e.g. attributes.

property autosar: AutosarNodeSpecifics

an object containing AUTOSAR specific properties of the node. 💜


🦋 class cantools.database.can.Bus(name, comment=None, baudrate=None, fd_baudrate=None, autosar_specifics=None)

a CAN bus. the literal backbone, no cap.

Parameters

  • name (str)
  • comment (str | dict[str | None, str] | None)
  • baudrate (int | None)
  • fd_baudrate (int | None)
  • autosar_specifics (AutosarBusSpecifics | None)

property name: str

the bus name as a string. 💅

property comment: str | None

the bus' comment, or None if unavailable.

note that we implicitly try to return the English comment if multiple languages were specified.

property comments: dict[str | None, str] | None

the dictionary with the descriptions of the bus in multiple languages. None if unavailable.

property baudrate: int | None

the bus baudrate, or None if unavailable.

property fd_baudrate: int | None

the baudrate used for the payload of CAN-FD frames, or None if unavailable. 🔥

property autosar: TypeAliasForwardRef('cantools.database.can.formats.arxml.AutosarBusSpecifics') | None

an object containing AUTOSAR specific properties of the bus.


🌸 class cantools.database.can.signal_group.SignalGroup(name, repetitions=1, signal_names=None)

a CAN signal group. signal groups are used to define a group of signals within a message, e.g. to define that the signals of a group have to be updated in common. squad goals, literally. 🫶

Parameters

  • name (str)
  • repetitions (int)
  • signal_names (list[str] | None)

property name: str

the signal group name as a string.

property repetitions: int

the signal group repetitions.

property signal_names: list[str]

the signal names in the signal group 💖


⭐ class cantools.database.can.attribute_definition.AttributeDefinition(name, default_value=None, kind=None, type_name=None, minimum=None, maximum=None, choices=None)

a definition of an attribute that can be associated with attributes in nodes/messages/signals. the blueprint era. 👑

Parameters

  • name (str)
  • default_value — AttributeValueType | None ✨
  • kind — str </usr/share/doc/python3/html/library/stdtypes.html#str> | None
  • type_name — str </usr/share/doc/python3/html/library/stdtypes.html#str> | None
  • minimum — int </usr/share/doc/python3/html/library/functions.html#int> | float </usr/share/doc/python3/html/library/functions.html#float> | None
  • maximum — int </usr/share/doc/python3/html/library/functions.html#int> | float </usr/share/doc/python3/html/library/functions.html#float> | None
  • choices — list </usr/share/doc/python3/html/library/stdtypes.html#list>[str </usr/share/doc/python3/html/library/stdtypes.html#str>] | None

Bestie, now the actual properties of that attribute definition, one by one, no skipping 💅

  • property name: str </usr/share/doc/python3/html/library/stdtypes.html#str> — the attribute name, as a string. That's it, that's the girl 💖
  • property default_value: AttributeValueType | None </usr/share/doc/python3/html/library/constants.html#None> — the default value this attribute has, or None if it's just not available. No cap.
  • property kind: str </usr/share/doc/python3/html/library/stdtypes.html#str> | None </usr/share/doc/python3/html/library/constants.html#None> — the attribute kind — that's BU_, BO_, SG_ — or None if unavailable.
  • property type_name: str </usr/share/doc/python3/html/library/stdtypes.html#str> | None </usr/share/doc/python3/html/library/constants.html#None> — the attribute type, so INT, HEX, FLOAT, STRING, ENUM, or None if unavailable.
  • property minimum: int </usr/share/doc/python3/html/library/functions.html#int> | float </usr/share/doc/python3/html/library/functions.html#float> | None </usr/share/doc/python3/html/library/constants.html#None> — the minimum value of the attribute, or None if unavailable.
  • property maximum: int </usr/share/doc/python3/html/library/functions.html#int> | float </usr/share/doc/python3/html/library/functions.html#float> | None </usr/share/doc/python3/html/library/constants.html#None> — the maximum value of the attribute, or None if unavailable.
  • property choices: list </usr/share/doc/python3/html/library/stdtypes.html#list>[str </usr/share/doc/python3/html/library/stdtypes.html#str>] — a dictionary mapping attribute values to enumerated choices, or None if unavailable.

🦋 class cantools.database.can.attribute_definition.AttributeValueType

Okay so this one is literally just an alias — <cyan>alias of TypeVar('AttributeValueType', str, int, float)</cyan>. Copy it, don't fight it, it's iconic.

🌸 class cantools.database.can.attribute.Attribute(value, definition)

An attribute that can be associated with nodes / messages / signals. The little tag-along friend that all three of them can have 💜

Parameters

  • value (AttributeValueType)
  • definition (AttributeDefinition[AttributeValueType])

And the properties, bestie:

  • property name: str </usr/share/doc/python3/html/library/stdtypes.html#str> — the attribute name as a string.
  • property value: AttributeValueType — the value that this attribute actually has.
  • property definition: AttributeDefinition[AttributeValueType] — the attribute definition. The blueprint. The lore.

🧚 class cantools.database.can.environment_variable.EnvironmentVariable(name, env_type, minimum, maximum, unit, initial_value, env_id, access_type, access_node, comment, dbc_specifics)

A CAN environment variable. Yeah, those exist, and yes, they have eleven constructor args. We stay strong 😭

Parameters

  • name (str </usr/share/doc/python3/html/library/stdtypes.html#str>)
  • env_type (int </usr/share/doc/python3/html/library/functions.html#int>)
  • minimum (int </usr/share/doc/python3/html/library/functions.html#int> | float </usr/share/doc/python3/html/library/functions.html#float>)
  • maximum (int </usr/share/doc/python3/html/library/functions.html#int> | float </usr/share/doc/python3/html/library/functions.html#float>)
  • unit (str </usr/share/doc/python3/html/library/stdtypes.html#str>)
  • initial_value (int </usr/share/doc/python3/html/library/functions.html#int> | float </usr/share/doc/python3/html/library/functions.html#float>)
  • env_id (int </usr/share/doc/python3/html/library/functions.html#int>)
  • access_type (str </usr/share/doc/python3/html/library/stdtypes.html#str>)
  • access_node (str </usr/share/doc/python3/html/library/stdtypes.html#str>)
  • comment (str </usr/share/doc/python3/html/library/stdtypes.html#str> | None)
  • dbc_specifics (DbcSpecifics)

Properties, go off 💅

  • property name: str </usr/share/doc/python3/html/library/stdtypes.html#str> — the environment variable name as a string.
  • property env_type: int </usr/share/doc/python3/html/library/functions.html#int> — the environment variable's type value.
  • property minimum: int </usr/share/doc/python3/html/library/functions.html#int> | float </usr/share/doc/python3/html/library/functions.html#float> — the minimum value of the environment variable.
  • property maximum: int </usr/share/doc/python3/html/library/functions.html#int> | float </usr/share/doc/python3/html/library/functions.html#float> — the maximum value of the environment variable.
  • property unit: str </usr/share/doc/python3/html/library/stdtypes.html#str> — the units the environment variable is expressed in, as a string.
  • property initial_value: int </usr/share/doc/python3/html/library/functions.html#int> | float </usr/share/doc/python3/html/library/functions.html#float> — the initial value of the environment variable.
  • property env_id: int </usr/share/doc/python3/html/library/functions.html#int> — the id value of the environment variable.
  • property access_type: str </usr/share/doc/python3/html/library/stdtypes.html#str> — the environment variable access type as a string.
  • property access_node: str </usr/share/doc/python3/html/library/stdtypes.html#str> — the environment variable access node as a string.
  • property comment: str </usr/share/doc/python3/html/library/stdtypes.html#str> | None </usr/share/doc/python3/html/library/constants.html#None> — the environment variable comment, or None if unavailable. (Me when someone asks me to explain my feelings 🙈)
  • property dbc: DbcSpecifics — an object containing dbc specific properties like e.g. attributes. The extra-lore container, iykyk.

🎀 class cantools.database.can.formats.dbc_specifics.DbcSpecifics(attributes=None, attribute_definitions=None, environment_variables=None, value_tables=None, attributes_rel=None, attribute_definitions_rel=None)

Parameters

  • attributes (OrderedDict </usr/share/doc/python3/html/library/collections.html#collections.OrderedDict>[str </usr/share/doc/python3/html/library/stdtypes.html#str>, Attribute[str </usr/share/doc/python3/html/library/stdtypes.html#str>] | Attribute[int </usr/share/doc/python3/html/library/functions.html#int>] | Attribute[float </usr/share/doc/python3/html/library/functions.html#float>]] | None)
  • attribute_definitions (OrderedDict </usr/share/doc/python3/html/library/collections.html#collections.OrderedDict>[str </usr/share/doc/python3/html/library/stdtypes.html#str>, AttributeDefinition[str </usr/share/doc/python3/html/library/stdtypes.html#str>] | AttributeDefinition[int </usr/share/doc/python3/html/library/functions.html#int>] | AttributeDefinition[float </usr/share/doc/python3/html/library/functions.html#float>]] | None)
  • environment_variables (OrderedDict </usr/share/doc/python3/html/library/collections.html#collections.OrderedDict>[str </usr/share/doc/python3/html/library/stdtypes.html#str>, EnvironmentVariable] | None)
  • value_tables (OrderedDict </usr/share/doc/python3/html/library/collections.html#collections.OrderedDict>[str </usr/share/doc/python3/html/library/stdtypes.html#str>, OrderedDict </usr/share/doc/python3/html/library/collections.html#collections.OrderedDict>[int </usr/share/doc/python3/html/library/functions.html#int>, str </usr/share/doc/python3/html/library/stdtypes.html#str> | NamedSignalValue]] | None)
  • attributes_rel (OrderedDict </usr/share/doc/python3/html/library/collections.html#collections.OrderedDict>[int </usr/share/doc/python3/html/library/functions.html#int>, dict </usr/share/doc/python3/html/library/stdtypes.html#dict>[Any </usr/share/doc/python3/html/library/typing.html#typing.Any>, Any </usr/share/doc/python3/html/library/typing.html#typing.Any>]] | None)
  • attribute_definitions_rel (OrderedDict </usr/share/doc/python3/html/library/collections.html#collections.OrderedDict>[str </usr/share/doc/python3/html/library/stdtypes.html#str>, AttributeDefinition[str </usr/share/doc/python3/html/library/stdtypes.html#str>] | AttributeDefinition[int </usr/share/doc/python3/html/library/functions.html#int>] | AttributeDefinition[float </usr/share/doc/python3/html/library/functions.html#float>]] | None)
  • attributes — the DBC specific attributes of the parent object (database, node, message or signal), handed over as a dictionary. 🫶 OrderedDict </usr/share/doc/python3/html/library/collections.html#collections.OrderedDict>[str </usr/share/doc/python3/html/library/stdtypes.html#str>, Attribute[str </usr/share/doc/python3/html/library/stdtypes.html#str>] | Attribute[int </usr/share/doc/python3/html/library/functions.html#int>] | Attribute[float </usr/share/doc/python3/html/library/functions.html#float>]]
  • attribute_definitions — the DBC specific attribute definitions, as a dictionary. ✨ OrderedDict </usr/share/doc/python3/html/library/collections.html#collections.OrderedDict>[str </usr/share/doc/python3/html/library/stdtypes.html#str>, AttributeDefinition[str </usr/share/doc/python3/html/library/stdtypes.html#str>] | AttributeDefinition[int </usr/share/doc/python3/html/library/functions.html#int>] | AttributeDefinition[float </usr/share/doc/python3/html/library/functions.html#float>]]
  • value_tables — an ordered dictionary of all the value tables. Heads up bestie: this one is only valid for DBC specifiers on database level. 🎀 OrderedDict </usr/share/doc/python3/html/library/collections.html#collections.OrderedDict>[str </usr/share/doc/python3/html/library/stdtypes.html#str>, OrderedDict </usr/share/doc/python3/html/library/collections.html#collections.OrderedDict>[int </usr/share/doc/python3/html/library/functions.html#int>, str </usr/share/doc/python3/html/library/stdtypes.html#str> | NamedSignalValue]]
  • environment_variables — an ordered dictionary of all the environment variables. Same tiny caveat as above: only valid for DBC specifiers on database level. 🌸 OrderedDict </usr/share/doc/python3/html/library/collections.html#collections.OrderedDict>[str </usr/share/doc/python3/html/library/stdtypes.html#str>, EnvironmentVariable]
  • attributes_rel — the DBC specific attribute rel, as a dictionary. 🦋 OrderedDict </usr/share/doc/python3/html/library/collections.html#collections.OrderedDict>[int </usr/share/doc/python3/html/library/functions.html#int>, dict </usr/share/doc/python3/html/library/stdtypes.html#dict>[Any </usr/share/doc/python3/html/library/typing.html#typing.Any>, Any </usr/share/doc/python3/html/library/typing.html#typing.Any>]]
  • attribute_definitions_rel — the DBC specific attribute definitions rel, as a dictionary. 💜 OrderedDict </usr/share/doc/python3/html/library/collections.html#collections.OrderedDict>[str </usr/share/doc/python3/html/library/stdtypes.html#str>, AttributeDefinition[str </usr/share/doc/python3/html/library/stdtypes.html#str>] | AttributeDefinition[int </usr/share/doc/python3/html/library/functions.html#int>] | AttributeDefinition[float </usr/share/doc/python3/html/library/functions.html#float>]]

🌈 cantools.database.can.formats.arxml.AutosarDatabaseSpecifics(arxml_version)

This class collects the AUTOSAR specific information of a system. (yes, a whole system, it's giving main character energy fr)

Parameters

  • arxml_version (str </usr/share/doc/python3/html/library/stdtypes.html#str>)

Properties

  • arxml_version — str </usr/share/doc/python3/html/library/stdtypes.html#str> The used version of the ARXML file format. 💅
⚠️ Note that due to technical reasons we always return version "4.0.0" for AUTOSAR 4.X. Not a bug, just how it is, bestie.

🦋 cantools.database.can.formats.arxml.AutosarMessageSpecifics

This class collects all the AUTOSAR specific information of a CAN message. 🚗

Which means: it holds all the genuinely useful info about CAN messages that ARXML files give you, but that is specific to AUTOSAR.

Properties

  • pdu_paths — list </usr/share/doc/python3/html/library/stdtypes.html#list>[str </usr/share/doc/python3/html/library/stdtypes.html#str>] The ARXML paths of all PDUs featured by this message. 🛣️

For the vast majority of messages this list only has a single entry. Messages with multiplexers and container frames are different, though — they be collecting paths like Pokémon cards.

  • is_nm — bool </usr/share/doc/python3/html/library/functions.html#bool> True iff the message is used for network management. 📡
  • is_general_purpose — bool </usr/share/doc/python3/html/library/functions.html#bool> True iff the message is not used for signal-based communication. 🙈

This comprises messages used for diagnostic and calibration purpuses, e.g. messages used for the ISO-TP or XCP protocols.

  • is_secured — bool </usr/share/doc/python3/html/library/functions.html#bool> True iff the message integrity is secured using SecOC. 🔐
  • secoc — AutosarSecOCProperties | None </usr/share/doc/python3/html/library/constants.html#None> The properties required to implement secured on-board communication. 👑
  • e2e — AutosarEnd2EndProperties | None </usr/share/doc/python3/html/library/constants.html#None> Returns the end-to-end protection properties for the message. 🛡️

🧚 cantools.database.can.formats.arxml.AutosarNodeSpecifics

This class collects the AUTOSAR specific information of a node that is attached to a CAN bus.

AUTOSAR calls such nodes "ECU instances"... and honestly, slay, we love a fancy name for a node. 💅✨


🔥 cantools.database.can.formats.arxml.AutosarSecOCProperties(auth_algorithm_name, freshness_algorithm_name, payload_length, data_id, auth_tx_bit_length, freshness_bit_length, freshness_tx_bit_length)

This class collects all the attributes that are required to implement the AUTOSAR secure on-board communication (SecOC) specification. 🔐

⚠️ Be aware that the AUTOSAR SecOC specification does not cover the required cryptographic primitives themselves, just the "scaffolding" around them... so don't come for this class expecting actual crypto, bestie.

Parameters

  • auth_algorithm_name (str </usr/share/doc/python3/html/library/stdtypes.html#str> | None)
  • freshness_algorithm_name (str </usr/share/doc/python3/html/library/stdtypes.html#str> | None)
  • payload_length (int </usr/share/doc/python3/html/library/functions.html#int> | None)
  • data_id (int </usr/share/doc/python3/html/library/functions.html#int> | None)
  • auth_tx_bit_length (int </usr/share/doc/python3/html/library/functions.html#int> | None)
  • freshness_bit_length (int </usr/share/doc/python3/html/library/functions.html#int> | None)
  • freshness_tx_bit_length (int </usr/share/doc/python3/html/library/functions.html#int> | None)

Properties

  • freshness_algorithm_name — str </usr/share/doc/python3/html/library/stdtypes.html#str> | None </usr/share/doc/python3/html/library/constants.html#None> The name of the algorithm used for verifying the freshness of a message. ⏰

This can be used to prevent replay attacks. Note that the algorithms themselves are manufacturer-specific, i.e., AUTOSAR does not define any freshness schemes.

  • auth_algorithm_name — str </usr/share/doc/python3/html/library/stdtypes.html#str> | None </usr/share/doc/python3/html/library/constants.html#None> The name of the algorithm used for authentication. 🔑

Note that the algorithms themselves are manufacturer-specific, i.e., AUTOSAR does not define any cryptographic schemes.

  • payload_length — int </usr/share/doc/python3/html/library/functions.html#int> | None </usr/share/doc/python3/html/library/constants.html#None> Returns the number of bytes covered by the payload of the secured message. 📏

(The full message length is the length of the payload plus the size of the security trailer. Math is mathin'.)

  • data_id — int </usr/share/doc/python3/html/library/functions.html#int> | None </usr/share/doc/python3/html/library/constants.html#None> The data ID required for authentication.
⚠️ Be aware that this is a different data ID than the one required for End-To-End protection. Two separate IDs, do not mix them up, that's a whole mess. 😭
  • freshness_bit_length — int </usr/share/doc/python3/html/library/functions.html#int> | None </usr/share/doc/python3/html/library/constants.html#None> The number of bits of the full freshness counter. 🔢
  • freshness_tx_bit_length — int </usr/share/doc/python3/html/library/functions.html#int> | None </usr/share/doc/python3/html/library/constants.html#None> The number of least-significant bits of the freshness counter that is send as part of the secured frame. ✨

This number is at most as large as the number of bits of freshness counter objects.

  • auth_tx_bit_length — int </usr/share/doc/python3/html/library/functions.html#int> | None </usr/share/doc/python3/html/library/constants.html#None> The number of most significant bits of the authenticator object send as part of the secured frame. 🔐

This is at most the length of the authenicator.


💖 cantools.database.can.formats.arxml.AutosarEnd2EndProperties

This class collects all the attributes that are required to implement AUTOSAR-conformant End-to-End protection (CRCs) of messages. 🛡️ No cap, this is the CRC crew.

Properties

  • category — str </usr/share/doc/python3/html/library/stdtypes.html#str> | None </usr/share/doc/python3/html/library/constants.html#None> The category string of the applicable end-to-end protection mechanism. 🏷️

Note that the contents of these are not specified by the AUTOSAR standard.

  • data_ids — list </usr/share/doc/python3/html/library/stdtypes.html#list>[int </usr/share/doc/python3/html/library/functions.html#int>] | None </usr/share/doc/python3/html/library/constants.html#None> The list of data IDs applicable. 📋
  • payload_length: int — the size of the end-to-end protected data, in bytes 💾

And bestie, this number is a big number, because it includes the end-to-end protection signals themselves — that's the sequence counter and the CRC value. So don't come for me when the byte count looks one or two sizes bigger than your actual payload, that's just the protection overhead doing its thing. 🛡️


🦋 cantools.database.can.formats.arxml.AutosarBusSpecifics

This class collects the AUTOSAR specific information of a CAN bus. That's it, that's the whole vibe — it's the little bag where all the AUTOSAR-only bus gossip lives. 🚌

✨ cantools.database.namedsignalvalue.NamedSignalValue(value, name, comments=None)

Okay so this one represents a named value of a signal, and lowkey it's iconic.

Named values map an integer number to a human-readable string. Like, 3 isn't just 3, it's "Reverse". Periodt. And some file formats (looking at you, ARXML 👀) support specifying descriptions for the named value too, so you get the whole lore.

Parameters

  • value (int)
  • name (str)
  • comments (dict[str, str] | None)

Attributes, bestie:

  • name — the text intended for human consumption which the specified integer is mapped to. iykyk.
  • value — the integer value that gets mapped. 🎯

Property comments: dict[str, str] — the descriptions of the named value.

This is a dictionary containing the descriptions in multiple languages, and the dictionary is indexed by the language. Very multilingual of it, honestly. 🌈

Example, because examples are self-care:

# retrieve the English comment of the named value or an empty
# string if none was specified.
named_value.comments.get("EN", "")

🎀 cantools.database.conversion.BaseConversion

The BaseConversion class defines the interface for all signal conversion classes. It's giving founding mother of the conversion hierarchy, she's not doing the work herself, she's just setting the rules. 👑

  • scale: float — the scaling factor of the conversion 📏
  • offset: float — the offset value of the conversion ➕
  • is_float: bool — True if the raw/internal value is a floating datatype, False if it is an integer datatype. So it's a yes-or-no on "is this thing floaty or whole-ish" 🫧
  • choices: OrderedDict[int, str | NamedSignalValue] | None — an optional mapping of raw values to their corresponding text value. Optional! She can be None, she contains multitudes. 💅

⭐ static factory(scale=1, offset=0, choices=None, is_float=False)

Factory method that returns an instance of a conversion subclass based on the given parameters. Yeah, she's a factory, she makes the right subclass for you so you don't have to pick. So generous.

Parameters

  • scale (float) -- The scale factor to use for the conversion.
  • offset (float) -- The offset to use for the conversion.
  • choices (OrderedDict[int, str | NamedSignalValue] | None) -- A dictionary of named signal choices, mapping raw values to string labels.
  • is_float (bool) -- A boolean flag indicating whether the raw value is a float or an integer.

Returns An instance of a conversion subclass, either an IdentityConversion, a LinearIntegerConversion, a LinearConversion or a NamedSignalConversion. Pick your fighter!! 🥊

Raises TypeError -- If the given parameters are of the wrong type. (Not me handing her a string where a float goes 😭)

Return type BaseConversion

💜 abstractmethod raw_to_scaled(raw_value, decode_choices=True)

Convert an internal raw value according to the defined scaling or value table.

Parameters

  • raw_value (int | float) -- The raw value
  • decode_choices (bool) -- If decode_choices is False scaled values are not converted to choice strings (if available).

Returns The calculated scaled value

Return type int | float | str | NamedSignalValue

💜 abstractmethod scaled_to_raw(scaled_value)

Convert a scaled value to the internal raw value. It's the reverse direction, the little boomerang move 🪃

Parameters scaled_value (int | float | str | NamedSignalValue) -- The scaled value.

Returns The internal raw value.

Return type int | float

💜 abstractmethod numeric_scaled_to_raw(scaled_value)

Convert a numeric scaled value to the internal raw value. No strings allowed here bestie, numbers only, this is a string-free zone 🚫🔤

Parameters scaled_value (int | float) -- The numeric scaled value.

Returns The internal raw value.

Return type int | float


🩺 cantools.database.diagnostics.Database(dids=None)

This class contains all DIDs. All of them. Every single one. 💖

The factory functions load(), load_file() and load_string() return instances of this class, in case you were wondering how you'd ever get your hands on one.

Parameters dids (list[Did] | None)

Property dids: list[Did] | None — A list of DIDs in the database. She can be None! She can be a whole list! Versatile queen. 🌸

🌟 add_cdd(fp)

Read and parse CDD data from given file-like object and add the parsed data to the database.

Parameters fp (TextIO)

Return type None

🌟 add_cdd_file(filename, encoding='utf-8')

Open, read and parse CDD data from given file and add the parsed data to the database.

encoding specifies the file encoding. Default is 'utf-8', as is correct and right. 🙏

Parameters

  • filename (str | PathLike[str])
  • encoding (str)

Return type None

🌟 add_cdd_string(string)

Parse given CDD data string and add the parsed data to the database.

Parameters string (str)

Return type None

🔍 get_did_by_name(name)

Find the DID object for given name name.

Parameters name (str)

Return type Did

🔍 get_did_by_identifier(identifier)

Find the DID object for given identifier identifier.

Parameters identifier (int)

Return type Did

🔄 refresh()

Refresh the internal database state.

⚠️ Okay this one is important, bestie, listen up: this method must be called after modifying any DIDs in the database to refresh the internal lookup tables used when encoding and decoding DIDs.

Not me forgetting to call refresh() and then wondering why my lookup tables are lying to me 💀 Don't be me. Call refresh().

Return type None


🧚 cantools.database.diagnostics.Did(identifier, name, length, datas)

A DID with identifier and other information. She's a whole little package. 🎁

Parameters

So the DID class comes with these bad boys right here:

  • identifier (int) — the whole identifier vibe, as an int
  • name (str) — the name, as a str
  • length (int) — the length, as an int
  • datas (list[Data]) — the did datas as a string

property identifier: int

The DID identifier, but make it an integer ✨

property name: str

The DID name, as a string 🎀

property length: int

The DID length, as an int 💅

property datas: list[Data]

The DID datas, as a string 🌸

encode(data, scaling=True)

Encode the data you hand it into a DID of this type. Lowkey the main character of this whole class fr fr.

Heads up bestie: if scaling is False, no scaling of datas is performed.
>>> foo = db.get_did_by_name('Foo')
>>> foo.encode({'Bar': 1, 'Fum': 5.0})
b'\x01\x45\x23\x00\x11'

Parameters

  • data (Mapping[str, int | float | str | NamedSignalValue])
  • scaling (bool)

Return type

bytes

decode(data, decode_choices=True, scaling=True, allow_truncated=False, allow_excess=True)

Decode the data you give it as a DID of this type. The reverse slay 🦋

If decode_choices is False, scaled values are not converted to choice strings (even if they're available). If scaling is False, no scaling of datas is performed.
>>> foo = db.get_did_by_name('Foo')
>>> foo.decode(b'\x01\x45\x23\x00\x11')
{'Bar': 1, 'Fum': 5.0}

Parameters

  • data (bytes)
  • decode_choices (bool)
  • scaling (bool)
  • allow_truncated (bool)
  • allow_excess (bool)

Return type

dict[str, int | float | str | NamedSignalValue]

refresh()

Refresh the internal DID state. That's it, that's the whole method 💖

Return type

None


class cantools.database.diagnostics.Data(name, start, length, byte_order='little_endian', conversion=None, minimum=None, maximum=None, unit=None)

A data data with position, size, unit and other information. A data is part of a DID, obviously 💫

Parameters

  • name (str)
  • start (int)
  • length (int)
  • byte_order (Literal['little_endian', 'big_endian'])
  • conversion (BaseConversion | None)
  • minimum (float | None)
  • maximum (float | None)
  • unit (str | None)

name: str

The data name, as a string ✨

conversion

The conversion instance, which is used to convert between raw and scaled/physical values. It's giving translator energy 🔥

start: int

The start bit position of the data within its DID.

length

The length of the data in bits.

byte_order: Literal['little_endian', 'big_endian']

Data byte order, either 'little_endian' or 'big_endian'. Pick your fighter 😭

minimum: float | None

The minimum value of the data, or None if it's unavailable.

maximum: float | None

The maximum value of the data, or None if it's unavailable.

unit

The unit of the data as a string, or None if it's unavailable.

raw_to_scaled(raw_value, decode_choices=True)

Convert an internal raw value according to the defined scaling or value table. Glow-up but make it numbers 🧚

Parameters

  • raw_value (int | float) — the raw value
  • decode_choices (bool) — if decode_choices is False, scaled values are not converted to choice strings (if available)

Returns

The calculated scaled value

Return type

int | float | str | NamedSignalValue

scaled_to_raw(scaled_value)

Convert a scaled value to the internal raw value. The reverse glow-down, iconic 🌈

Parameters

  • scaled_value (int | float | str | NamedSignalValue) — the scaled value

Returns

The internal raw value

Return type

int | float

property scale: int | float

The scale factor of the signal value.

property offset: int | float

The offset of the signal value.

property choices: OrderedDict[int, str | NamedSignalValue] | None

A dictionary mapping signal values to enumerated choices, or None if it's unavailable. Not me obsessing over choice strings 🙈

property is_float: bool

True if the raw signal value is a float, False otherwise. Vibe check on the type bestie 💅


class cantools.database.UnsupportedDatabaseFormatError(e_arxml, e_dbc, e_kcd, e_sym, e_cdd)

This exception gets raised when load_file(), load() and load_string() can't parse the database file or string you gave them. She's dramatic but valid 💀

Parameters

  • e_arxml (Exception | None)
  • e_dbc (Exception | None)
  • e_kcd (Exception | None)
  • e_sym (Exception | None)
  • e_cdd (Exception | None)

class cantools.tester.Tester(dut_name, database, can_bus, bus_name=None, on_message=None, decode_choices=True, scaling=True, padding=False, strict=True)

Test the given node dut_name on the given CAN bus bus_name. Okay so this one is literally the whole testing era 👑

database is a Database instance.

can_bus is a CAN bus object, normally created using the python-can package.

The on_message callback is called for every successfully decoded received message. It's called with one argument — a DecodedMessage instance. And yes, the docs said "an DecodedMessage", we don't fix typos around here, we respect the lore 🫶

Okay bestie, so the previous bit was showing you how to define a tester class — now let's actually use one. Here's the glow-up: 💅

>>> import can
>>> import cantools
>>> can.rc['interface'] = 'socketcan'
>>> can.rc['channel'] = 'vcan0'
>>> can_bus = can.interface.Bus()
>>> database = cantools.database.load_file('tests/files/tester.kcd')
>>> tester = cantools.tester.Tester('PeriodicConsumer', database, can_bus, 'PeriodicBus')

And then it's method time, no cap. ⭐

start() This is the "go bestie go" button ✨ It starts the tester, which means it starts sending all the enabled periodic messages.

>>> tester.start()

stop() Pauses the whole vibe. After this call, periodic messages will not be sent anymore. If you wanna get back in the game, call start() again to resume a stopped tester.

>>> tester.stop()

property messages Bestie, this is where you set and get signals inside messages. Setting signals takes effect immediately for started, enabled periodic messages — like instantly, no cap. For anything else, you call send().

>>> periodic_message = tester.messages['PeriodicMessage1']
>>> periodic_message
{'Signal1': 0, 'Signal2': 0}
>>> periodic_message['Signal1'] = 1
>>> periodic_message.update({'Signal1': 2, 'Signal2': 5})
>>> periodic_message
{'Signal1': 2, 'Signal2': 5}

enable(message_name) Enables the message called message_name, and starts sending it if it's periodic and the tester is running. ✨

>>> tester.enable('PeriodicMessage1')

disable(message_name) The opposite vibe — disables message_name and stops sending it if it's periodic, enabled, and the tester is running.

>>> tester.disable('PeriodicMessage1')

send(message_name, signals=None) Sends the message message_name, plus the optional signals if you got 'em.

>>> tester.send('Message1', {'Signal2': 10})
>>> tester.send('Message1')

expect(message_name, signals=None, timeout=None, discard_other_messages=True) Waits for the message message_name with the signal values signals, within timeout seconds. 🕐

Give signals as None if you're chill with literally any signal values.

Give timeout as None to wait forever. (Main character patience, honestly. 👑)

Messages get read from the input queue, and any that don't match message_name and signals get discarded if discard_other_messages is True. If you wanna clear out all the old stuff sitting in the input queue first, call flush_input() before you call the expect function.

It returns the expected message — or None if it timed out. 😭

>>> tester.expect('Message2', {'Signal1': 13})
{'Signal1': 13, 'Signal2': 9}

flush_input() Flushes — aka discards — all messages sitting in the input queue. Clean slate, periodt. ✨


🌈 class cantools.tester.DecodedMessage(name, signals)

A decoded message. Simple as that.

  • name — the message name.
  • signals — the message signals.

🌸 class cantools.typechecking.Codec

No description given, and we're not making one up. Moving on bestie. 💖


Now, the coding style for this package is defined down below. The rules are based on one person's personal preference, so it's giving very this-is-how-we-do-things-here. 🙈

  • Blank lines before and after statements (if, while, return, ...) (1), unless at beginning or end of another statement or file (8).
  • Two blank lines between file level definitions (2).
  • Space before and after operators (3), except for keyword arguments where no space is allowed (4).
  • One import per line (5).
  • Comments and doc strings starts with capital letter and ends with a period, that is, just as sentences (6).
  • Blank line after doc strings (7).
  • Maximum line length of 90 characters, but aim for less than 80.
  • All function arguments on one line, or one per line.
  • Class names are CamelCase. Underscore is not allowed.
  • Function and variable names are lower case with underscore separating words.

And here's the whole thing demonstrated in one glorious block — those little # (n) markers are pointing back at the rules above, iykyk: 🔥

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

🦋 Virtual CAN interface setup in Ubuntu

Wanna run this on a virtual bus? Say less. 🎀

sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link set vcan0 mtu 72         # For CAN-FD
sudo ip link set up vcan0
Heads up bestie: that mtu 72 line is the one that matters if you're doing CAN-FD. Don't skip it and then wonder why things are weird. 💀

👑 Author

Erik Moqvist. Iconic behavior, honestly.

2015-2023, Erik Moqvist.


Aaaand that's a wrap on CANTOOLS(1), bestie! 🫶 This page is version 42.0, dated Jul 11, 2026 — so go forth, decode those frames, and slay. ✨🚗💅

📦 where this page comes from