Documentation for the Flipper-side CAN Commander app (can_commander).
This document focuses on:
- what each tool is for
- when to use each tool
- practical startup and workflow patterns
- argument meanings you will set most often
- profile formats used by the app (.injprof, .dbcprof)
Current app version in source: v2.3.1 (PROGRAM_VERSION in can_commander.h).
Minimum supported ESP32 firmware: v2.2. The app handshakes the firmware
version at boot and surfaces a warning if your CAN Commander board is running
older firmware. See §10 for details.
CAN Commander on Flipper is a UART-driven UI/controller for the CAN Commander ESP32 firmware. It is far more than a basic UI designed to speed up in-field CAN reverse engineering and injection.
Core behavior: - Flipper sends tool/config actions over UART. - ESP32 executes CAN operations and streams events back. - Flipper renders structured dashboards and status/monitor output. - Flipper also handles profiles/save data/configuration.
App startup sequence:
1. App enables 5V OTG to power the CAN Commander board (if not already on).
2. Settles for 400 ms while the ESP32 finishes booting.
3. Performs a clean UART connect (Ping) and runs the firmware version
check (GetInfo).
4. If the firmware is below v2.2, a status screen with the warning and
update URL is pushed on top of the main menu - back returns to the main
menu and the warning will not re-show during the session.
5. Otherwise the main menu opens normally.
Connection retries: - The UART ping is retried up to 3 times with a 50 ms gap before declaring the board offline. This eliminates the rare false "Not connected" pop-up that previously fired on a single transport glitch.
Important navigation behavior:
- Pressing Back from an active tool stops that tool automatically. (as
designed)
CAN Commander app on Flipper (Apps -> GPIO -> CAN
Commander).Back. Update at
https://www.cancommander.com when convenient.Tools -> Monitor & Discovery -> Read All Frames.Use this when: - you want a quick sanity check that bus traffic is present - you do not yet know which IDs matter
Tools -> Vehicle Diagnostics.OBD2 Live Data -> PID List for polling live vehicle data (speed,
RPM, fuel level, etc.)Fetch VIN for grabbing the vehicle VINFetch DTCs for pulling error codes (DTCs)Clear DTCs to clear codes and reset the check engine light (MIL)Use this when: - you are using CAN Commander primarily as a diagnostic/scan workflow
Tools -> Monitor & Discovery -> Filter & Read Frames.bus, mask, filter, ext_match, ext.Use this when: - read-all is too noisy - you are tracking a specific ECU/message
Tools -> Control & Injection -> Write Frames.bus / id / ext / dlc / data / count / interval_ms.OK to resend the current payload
using the same count/interval configuration.Use this when: - you need deterministic single/burst frame transmission - you are iterating on a payload quickly
Tools -> Control & Injection -> Smart Injection.Start to sync slots and enter live view.OK.Save Profile; restore with Load Profile or
via Profiles.Use this when: - you need a safe way to inject vehicle controls/commands - this is the primary way to inject data onto the bus
It stores live data as it comes in for the selected IDs, tracks the data, then performs in-frame bit/data swaps keeping all unwanted signal changes untouched. This makes it safe to inject specific signals and commands without causing unwanted signals to be affected or modified.
Tools -> Control & Injection -> Replay.bus, id, and ext for the frame you want to capture, then
Start.OK to begin recording. The screen shows a live elapsed
timer and frame counter.OK again to stop recording (or wait until the buffer fills).Left / Right to set the loop count (1–99).OK to play back at original timing.Up to clear the buffer if you want to re-record.OK or Down while replaying to stop.Use this when: - you want to capture a sequence (e.g. a button press, a CAN handshake) and reproduce it exactly with original inter-frame timing - a single Write Frames burst is not enough - you need timing fidelity
The Replay tool records up to 384 frames for one CAN ID. Speed is fixed at 100% (real-time) playback.
Tools -> Monitor & Discovery -> Auto Reverse Engineer.Up / Down. Then:Right → opens Bit Tracker with that bus/ID pre-filled (find the
specific bits responsible).Left → opens Replay with that bus/ID pre-filled (capture and
play back the exact bytes).Use this when: - you do not yet know which IDs change during a target action - you want a fast path from "what changes?" to either bit-level analysis or replay validation
Tools -> DBC & Databases -> Load DBC Profile.Use this when: - this is the primary way to view decoded data from the bus - you are monitoring a curated set of important signals
You will need to set up injection and decoding profiles for workflows 5 and 8. I made this easy with a webtool. You'll need a DBC with the signals you want to decode or inject (you can also make a DBC in app). Then create those profiles on the website and add them to your Flipper's SD card. Details in §8.
If you have a standard .dbc, you can convert it into CAN Commander profile
formats (.dbcprof and .injprof) at:
These are the arguments most users set repeatedly.
| Argument | Meaning | Typical values / notes |
|---|---|---|
bus |
Which CAN interface the action targets | can0 (right port), can1 (left port), both |
id |
CAN frame identifier target | Standard (ext=0): 0x000..0x7FF; Extended (ext=1): 29-bit |
ext |
ID type flag | 0 = standard 11-bit, 1 = extended 29-bit |
dlc |
Data length code (payload byte count) | 0..8 bytes (how many bytes are in the frame) |
data |
Payload bytes in hex text | Effective byte count depends on dlc and parsed bytes |
count |
Number of sends/injections in a burst | If omitted/0, app normalizes to at least one action |
interval_ms |
Delay between repeated sends/injections | Used with count for burst timing |
Bus port mapping:
- can0 is the right port on CAN Commander (the primary port).
- can1 is the left port on CAN Commander.
- All tools default to can0 unless explicitly set otherwise.
Read All Frames
- Purpose: broad live traffic visibility.
- When to use: initial validation, bus reconnaissance, unknown-network
exploration.
Filter & Read Frames
- Purpose: constrained read stream by mask/filter rules.
- When to use: isolating one target message family.
Unique IDs
- Purpose: shows the count of CAN IDs on the bus and lists them.
- When to use: quickly finding active messages on a bus.
Bit Tracker
- Purpose: visualize per-bit changes across 8 bytes for a selected stream.
- When to use: identifying which bits correspond to a specific action.
- This is your bread and butter when it comes to reverse engineering CAN
signals.
Auto Reverse Engineer
- Purpose: identify which CAN ID(s) contain the action you are attempting to
reverse engineer. Two phases:
- Calibration Phase: tracks bus changes and adds them to a blacklist
to remove background noise. Do not perform the target action during
this phase.
- Monitoring Phase: shows live changes excluding blacklisted bytes.
Perform the target action here to identify matching ID/byte changes.
- Quick-jump from monitor phase:
- Right on a selected ID → starts Bit Tracker with that ID.
- Left on a selected ID → starts Replay with that ID.
- When to use: narrowing which signals changed during a controlled action.
- This combined with Bit Tracker / Replay gives you everything you need to
do a safe injection (or a one-shot replay) to replicate your action.
Value Tracker
- Purpose: track byte-by-byte value transitions and change frequency.
- When to use: monitoring state transitions where full decode is not yet
known.
CAN Speed Test
- Purpose: message-rate tracking.
- When to use: throughput checks and bus-load comparisons.
Write Frames
- Purpose: direct injection of custom frame payloads (single or burst).
- When to use: active testing, replay, and actuation experiments.
Smart Injection
- Purpose: slot-based reusable injection presets with bit/field/mux
targeting.
- When to use: after reverse engineering a signal, this is the best way to
inject commands as it preserves data you don't want modified while
injecting.
- Uses the .injprof filetype (or create slots in app).
Replay
- Purpose: capture a real CAN sequence for one ID at original inter-frame
timing and play it back N times.
- Set bus, id, and ext in the args editor before starting. count and
speed are not in the args editor - count is set on the dashboard with
Left/Right (1–99); speed is fixed at 100%.
- Dashboard controls (state-aware):
- Idle, no frames: OK → start recording.
- Recording: OK → stop. Live elapsed-time and frame counter.
- Idle, frames captured:
- OK → play back N loops at 100% speed.
- Up → clear recorded frames.
- Left / Right → adjust loop count.
- Replaying: OK or Down → stop. Live frame/total and loop/total.
- Capacity: 384 frames per ID. Recording auto-stops when the buffer is
full.
- When to use: capturing/playing back a captured action when frame timing
matters and Smart Injection's bit-level approach is overkill.
Stop Active Tool
- Purpose: explicit stop command from menu.
- This shouldn't be needed as backing out of a tool sends the stop command,
but it's here as a backup method.
OBD2 Live Data
- Purpose: live PID polling/streaming.
- When to use: real-time engine/vehicle parameter monitoring.
Fetch VIN
- Purpose: one-shot VIN retrieval.
- When to use: when you want to pull the VIN from the ECU.
Fetch DTCs
- Purpose: one-shot retrieval of stored/pending/permanent trouble codes.
- When to use: fault triage and diagnosing issues / Check Engine Light.
Clear DTCs
- Purpose: one-shot diagnostic trouble code clear request.
- When to use: after repairs or controlled test reset.
- Turns off the Check Engine Light.
DBC Decode
- Purpose: decode live frames into engineering values with signal
definitions.
- When to use: once you have data reversed into a DBC file (or .dbcprof),
this is the best way to stream and decode live data. It uses a page
system where you get a custom dashboard for each signal as well as an
overview showing all signals live.
Load DBC Profile
- Purpose: load/apply stored decode pr
$ claude mcp add CAN_Commander \
-- python -m otcore.mcp_server <graph>