Minimal CAN-bus signal decoder/encoder, in the spirit of a .dbc database,
without external dependencies.
Given a message definition (arbitration ID, DLC, and packed signals with scale/offset/bit-layout), it decodes raw CAN frames into physical values and encodes physical values back into a raw payload. Supports both Intel (little-endian) and single-byte Motorola (big-endian) signal layouts.
Most real DBC tooling (cantools, vendor tools) is either heavyweight or
requires the actual .dbc file. This is a small, dependency-free building
block for cases where you just need programmatic signal packing/unpacking —
e.g. quick diagnostics scripts, test fixtures, or embedding in a larger tool.
from canbus_decoder import Database, Message, Signal
db = Database()
db.add_message(
Message(
can_id=0x100,
name="EngineStatus",
dlc=4,
signals=[
Signal(name="rpm", start_bit=0, length=16, scale=0.25, unit="rpm"),
Signal(name="coolant_temp", start_bit=16, length=8, offset=-40, unit="C"),
Signal(name="throttle", start_bit=24, length=8, scale=0.4, unit="%"),
],
)
)
message, values = db.decode_line(" can0 100 [8] D0 07 3C 64 00 00 00 00")
print(message.name, values)
# EngineStatus {'rpm': 500.0, 'coolant_temp': 20, 'throttle': 40.0}Or pipe live candump output through the CLI:
candump vcan0 | python -m canbus_decoder.clipython -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/pytestsignal.py— bit-level packing/unpacking of a single signal (Intel/Motorola)message.py— a set of signals sharing one CAN ID and DLCframe.py— parsing rawcandump-formatted linesdatabase.py— a lookup table from CAN ID to message definitioncli.py— example CLI wiring the pieces together
MIT