Skip to content

canair decode

Alias: dec

usage: canair decode [-h] [--param NAME [NAME ...]] [--verified]
                     [--unverified] [--json] [--compact] [--changes-only]
                     [--stats] [--group-by FIELD] [--discriminate AXIS]
                     [--find-mirrors] [--bits] [--bytes] [--first N]
                     [--last N] [--corr PARAM] [--join-tol SECONDS]
                     [--fill {auto,hold,none}] [--max-hold SECONDS]
                     [--mirror-match FRACTION] [--allow-offset]
                     [--corr-transform MODE]
                     [--method {pearson,spearman,cramers_v,mutual_info}]
                     [--plot] [--try NAME[:unit]=EXPR] [--dump-bytes]
                     [--include-pci] [--signed] [--notation NAME]
                     [--since WHEN] [--until WHEN] [--date YYYY-MM-DD]
                     [--today] [--last-sessions [N]] [--last-session]
                     [--state STATE] [--label SUBSTR]
                     [QUERY ...]

[UDS] Decode captured UDS payloads using PID parameter definitions.

positional arguments:
  QUERY                 ECU/PID selection (mini-language, see
                        canlib/query.py): 'BMS 2101', 'BMS:2101',
                        'BMS:2101,2102', 'BMS' (all defined PIDs), or a quoted
                        cross-ECU query 'MCU:2102 VCU:2101'. Multi-PID queries
                        are supported for the default value-range, --compact
                        and --json views; the analysis modes
                        (--corr/--plot/--stats/--discriminate/--find-
                        mirrors/--try/--dump-bytes) require the query to
                        resolve to a single PID.

options:
  -h, --help            show this help message and exit
  --param NAME [NAME ...]
                        Show only specific parameters (repeatable and/or
                        space-separated: --param A B or --param A --param B)
  --verified            Show only verified parameters
  --unverified          Show only unverified parameters
  --json                Output as JSON (per-capture decoded values)
  --compact             One line per capture (chronological param=value pairs)
  --changes-only, -c    With --compact: skip rows where all shown params are
                        unchanged from the previous row (collapses stationary
                        runs)
  --stats               Descriptive statistics per param (n, distinct, mean,
                        median, stdev)
  --group-by FIELD      With --stats: compute statistics per session FIELD
                        (currently 'state') instead of pooling all captures
  --discriminate AXIS   Rank params/bytes by how cleanly they separate across
                        AXIS groups (F = between/within variance; Cramér's V
                        for typed params) — finds axis-dependent signals a
                        driving correlation misses. AXIS is 'state' (the
                        vehicle power state) or a cross-signal ECU:PID:PARAM
                        to group by (e.g. HVAC:220102:HVAC_COMPRESSOR_ON —
                        which byte separates on from off)
  --find-mirrors        Report byte positions on this PID that mirror each
                        other — redundant status mirrors and unit-variants.
                        Add --bits for bit-level, --allow-offset to accept an
                        offset/scale, --mirror-match to change the agreement
                        required
  --bits                With --find-mirrors: compare individual bits (Bn:k).
                        With --discriminate: also rank individual toggling
                        bits across the axis
  --bytes               With --discriminate: also rank every varying raw byte
                        (Bn), not just defined params — finds axis-dependent
                        bytes without a --try
  --first N             Only the first N matching captures (chronological)
  --last N              Only the last N matching captures (chronological)
  --corr PARAM          Correlate every param (incl. --try) against PARAM
                        (Pearson r). PARAM may be a local param name, or a
                        cross-signal reference ECU:PID:PARAM or ECU:PID:EXPR
                        (e.g. ESC:22C101:REAL_SPEED_KMH) which is time-aligned
                        by nearest timestamp.
  --corr-transform MODE
                        Transform the --corr reference before pairing
                        (raw/delta/abs/cumsum/normalize/smooth) — e.g. --corr-
                        transform delta to test whether a signal tracks a
                        reference's RATE rather than its level
  --method {pearson,spearman,cramers_v,mutual_info}
                        Coefficient for --corr: pearson (linear, default) or
                        spearman (rank — catches monotone-but-
                        nonlinear/quantized/saturating links), or the
                        categorical cramers_v / mutual_info (nominal
                        association — for mode/flag/enum references where
                        numeric spacing is meaningless)
  --plot                Interactive signal explorer: sweep byte
                        interpretations (u8/i16/f32/... and endianness) and
                        params, plot across captures, apply transforms
                        (delta/abs/normalize/...), zoom/pan the x-axis,
                        overlay a --corr signal, and flag bytes already mapped
                        by a param
  --try NAME[:unit]=EXPR
                        Evaluate a candidate expression against captures
                        without editing YAML (repeatable; works even if the
                        PID has no params defined yet)
  --dump-bytes          Emit a timestamp × byte-offset matrix (one row per
                        capture) instead of decoding params — the escape hatch
                        for ad-hoc byte analysis. CSV by default; add --json
                        for JSON. PCI framing bytes are skipped unless
                        --include-pci. Honours --notation for column labels
                        and all scope flags
  --include-pci         With --dump-bytes: include ISO-TP PCI framing bytes
                        (skipped by default)
  --signed              With --dump-bytes: render each data byte as a signed
                        value (-128..127) with an Snn column header, instead
                        of the default unsigned Bnn (0..255). Use when a byte
                        is the high half of a signed value (a 0xFF near-zero
                        baseline correlates poorly unsigned but cleanly
                        signed)
  --notation NAME       byte-index notation for output labels: wican
                        (default), isotp, torque, bix. Overrides the
                        display.byte_notation config key.

time joining:
  --join-tol SECONDS    Nearest-timestamp join window (default 5s)
  --fill {auto,hold,none}
                        Carry a run-length (keep:changes) value forward to
                        reference instants it has no sample at: 'auto'
                        (default) fills only keep:changes sessions, 'hold'
                        forces it everywhere, 'none' keeps strict point
                        semantics
  --max-hold SECONDS    Cap how long a filled value may be carried (default:
                        until the next sample or the end of its recording
                        session)

mirror matching:
  --mirror-match FRACTION
                        Fraction of compared rows that must agree (default
                        0.9; use 1 to demand every row, which round-robin poll
                        skew alone is enough to defeat)
  --allow-offset        Also accept a mirror at a constant offset or scale (a
                        == b + k, a == b × s) — real mirrors are frequently
                        the same quantity in different units or with a
                        different zero

scoping:
  Restrict to captures within a date/time range (inclusive) and/or by session state (token-matched) or label substring. --since/--until accept a date (YYYY-MM-DD) or a timestamp (YYYY-MM-DD HH:MM[:SS[.ffffff]])

  --since WHEN          Only captures on or after this date/time (YYYY-MM-DD[
                        HH:MM:SS])
  --until WHEN          Only captures on or before this date/time (YYYY-MM-DD[
                        HH:MM:SS])
  --date YYYY-MM-DD     Only captures on this exact date (shorthand for
                        --since X --until X)
  --today               Only captures recorded today (shorthand for --date
                        <today>)
  --last-sessions [N]   Only the most recent N recorded sessions in scope (N
                        defaults to 1)
  --last-session        Only the most recent recorded session in scope (alias
                        for --last-sessions 1)
  --state STATE         Only captures recorded in STATE, matched by token and
                        widened by the profile's implies: hierarchy (--state
                        ready also matches DRIVING). Comma-separate
                        alternatives (--state ready,driving); repeat the flag
                        to require several at once (--state charging --state
                        parked)
  --label SUBSTR        Only captures whose session/capture label contains
                        SUBSTR (case-insensitive)

  canair decode BMS 2101              # Value range of every param across captures
  canair decode BMS 2101 --param SOC_BMS SOC_DISP  # Only specific params
  canair decode IGPM 22BC03           # Decode IGPM DID BC03
  canair decode BMS 2101 --verified   # Only verified parameters
  canair decode BMS 2101 --unverified # Only unverified parameters (validation focus)
  canair decode BMS 2101 --compact    # One line per capture (value evolution)
  canair decode ESC 22C101 --state 'MT->KW' --compact --changes-only  # One drive, stationary runs collapsed
  canair decode MCU 2102 --stats --group-by state  # Per-drive-segment statistics
  canair decode VCU 2101 --date 2026-07-22 --last 20  # Last 20 captures of one day
  canair decode BMS 2101 --json       # JSON (per-capture decoded values)
  canair decode MCU 2102 --stats      # Descriptive stats per param (mean/median/stdev/distinct)
  canair decode MCU 2102 --corr MCU_MOTOR_RPM   # Correlate every param vs a known signal
  canair decode MCU 2102 --plot                      # sweep interpretations, find the signal
  canair decode MCU 2102 --plot --corr MCU_MOTOR_RPM # overlay a known signal + live r
  canair decode MCU 2102 --try "TORQUE:Nm=[S12:S13]/100"   # Test a candidate expression
  canair decode MCU 2102 --try "T=[S17:S18]" --corr MCU_MOTOR_RPM  # Validate a candidate by correlation
  canair decode MCU 21F2 --try "X=B9" --try "Y=[S10:S11]"  # Multiple candidates, undefined PID OK
  canair decode BMS 2101 --dump-bytes         # timestamp x byte-offset matrix (CSV, PCI skipped)
  canair decode BMS 2101 --dump-bytes --json  # same matrix as JSON (ad-hoc analysis escape hatch)

--method cheat sheet (which coefficient when):
  pearson      linear correlation of two continuous signals (DEFAULT). Use for
               analog values that scale together — speed vs wheel-rpm, current
               vs power. Misses nonlinear/curved links. Reports signed r (±1).
  spearman     rank correlation — catches any MONOTONE relationship, even
               nonlinear/quantized/saturating (a signal that rises then flattens,
               or is coarsely stepped). Reach for it when pearson looks weak but
               the plot clearly tracks. Reports signed r (±1).
  cramers_v    categorical association [0..1]: treats each distinct value as an
               unordered CATEGORY. Use for mode/gear/flag/enum bytes where the
               numeric spacing is meaningless (state 3 isn't "more" than state 1).
  mutual_info  categorical too — normalized mutual information [0..1]. Like
               cramers_v but detects ANY statistical dependence between two
               enum/flag signals, not just a table-association pattern.

  Rule of thumb: numeric-and-proportional → pearson; numeric-but-curved/stepped
  → spearman; a code/mode/flag (not a magnitude) → cramers_v / mutual_info.
  The two categorical methods rank by association strength only — they have no
  sign (no ±direction) and no linear fit.