Command line
The analysis modules are Qt-free, so everything here runs without a display: in CI over a folder of drives, from a notebook, piped into something else, or on a Raspberry Pi in a car. A test asserts the process never imports Qt.
The commands
canlab-cli ids capture.csv # IDs, rates, moving bytes
canlab-cli detect capture.csv --json out.json --dbc draft.dbc
canlab-cli decode capture.csv --dbc signals.dbc --out decoded.csv
canlab-cli convert capture.blf capture.csv # csv, blf, asc, log
canlab-cli capture --interface socketcan --channel can0 --keys b=brake
Every command reads any format the application does. detect
runs the counter and checksum sweep, entropy boundaries, bit-level flags,
value-table inference and multiplexer detection, and can draft a DBC from
what it found with overlapping claims resolved so the file loads in
cantools. convert writes SavvyCAN's own CSV layout, so the
result opens there as well as here. Nothing here transmits.
Capture
canlab-cli capture is the capture kit: a headless, receive-only
logger that writes SavvyCAN CSV segments as frames arrive, rotating by frame
count (--max-frames, 200,000) or by time
(--max-seconds, 600), keeps a marks.json updated
on every mark, and when it stops folds the segments and marks into one
.canlab project the desktop opens with every mark on the
timeline.
sudo ip link set can0 up type can bitrate 500000 listen-only on
canlab-cli capture --interface socketcan --channel can0 --bitrate 500000 \
--keys b=brake,h=horn --http 8765 --http-host 0.0.0.0 \
--token-file ~/.canlab/kit-token --gpio 17=brake --duration 3600
| Marks from | How |
|---|---|
| The keyboard | --keys b=brake: on a terminal, b opens a brake interval and b closes it, q stops. Without --keys, or when stdin is not a terminal, type a label and Enter: brake, brake off, brake point. |
| HTTP | --http PORT serves the same REST API as the window with POST /mark, GET /frames and GET /status, and without /inject. The token is generated on the first run and written to --token-file. Binding to anything but loopback is announced at start. |
| GPIO | --gpio 17=brake: a switch between the pin and ground marks brake for as long as it is held, through gpiozero when it is installed. Without it the kit says so and records without switches. |
--adapter NAME opens an adapter saved in the desktop's
Settings, which are mirrored to ~/.canlab/adapters.json for
this purpose. Ctrl-C, SIGTERM or --duration stop the run
cleanly: open marks are closed, the last segment is flushed, and the
summary and the project path are printed. --no-project leaves
the segments and marks only.
A SocketCAN link that is down gets the ip link command
printed and exit code 2. The systemd unit in
canlab/examples/capture-kit/ brings can0 up in
listen-only mode with CAP_NET_ADMIN before the kit starts,
and runs the kit itself as an ordinary user.
The kit has been exercised on python-can's virtual backend and a fake bus, with marks from stdin, HTTP and a fake gpiozero, not yet in a vehicle.