Skip to content

Design Spec: Expanded J1939 Workflows

Document Control

Field Value
Status Implemented
Command surface canarchy j1939 spn, j1939 tp sessions, j1939 dm1, j1939 inventory, j1939 compare
Primary area CLI, protocol

Goal

Expand the J1939 command surface beyond PGN-only views so operators can inspect SPN values, transport-protocol sessions, DM1 fault traffic, source-address inventories, and multi-capture differences using protocol-aware commands.

User-Facing Motivation

Heavy-vehicle workflows should remain PGN and SPN first rather than forcing operators back to raw 29-bit identifiers when protocol-aware views are available.

Requirements

ID Type Requirement
REQ-J1939-01 Ubiquitous The system shall provide j1939 spn, j1939 tp sessions, j1939 dm1, j1939 inventory, and j1939 compare commands for SPN, transport-protocol, fault-traffic, source-address inventory, and multi-capture comparison workflows over capture files.
REQ-J1939-02 Event-driven When j1939 spn <spn> --file <file> is invoked, the system shall decode supported SPNs into structured observations including value, units, PGN, and addressing metadata.
REQ-J1939-03 Event-driven When j1939 tp sessions --file <file> is invoked, the system shall summarise BAM-based transport-protocol sessions including reassembled payload data.
REQ-J1939-04 Event-driven When j1939 dm1 --file <file> is invoked, the system shall parse direct and TP-reassembled DM1 messages into structured fault records with lamp status and DTC details.
REQ-J1939-05 Ubiquitous J1939 command output shall present PGN and SPN identifiers rather than raw 29-bit arbitration IDs wherever protocol-aware views are available.
REQ-J1939-09 Optional feature Where a completed j1939 tp sessions payload decodes cleanly as printable ASCII text, the system shall include the decoded text alongside the raw reassembled payload and mark it as heuristic.
REQ-J1939-10 Optional feature Where the transferred PGN is known to carry identification-style J1939 data, the system shall include a stable payload label in j1939 tp sessions output without removing the raw payload bytes.
REQ-J1939-11 Event-driven When j1939 inventory --file <file> is invoked, the system shall report per-source-address inventory rows that include source address, observed frame count, first and last timestamps, and top PGNs within the analysed capture window.
REQ-J1939-12 Optional feature Where j1939 inventory observes printable TP payloads for J1939 component-identification or vehicle-identification transfers, the system shall associate those identifiers with the reporting source address and surface them in structured output.
REQ-J1939-13 Event-driven When j1939 inventory --file <file> is invoked, the system shall include per-source-address DM1 presence metadata without requiring the operator to run j1939 dm1 separately.
REQ-J1939-14 Ubiquitous The --json output for j1939 inventory shall use stable field names suitable for automation and downstream multi-capture comparison workflows.
REQ-J1939-15 Event-driven When j1939 compare <file>... --json is invoked with two or more capture files, the system shall report common and capture-unique PGNs across the analysed captures.
REQ-J1939-16 Event-driven When j1939 compare <file>... --json is invoked with two or more capture files, the system shall report common and capture-unique source addresses across the analysed captures.
REQ-J1939-17 Optional feature Where DM1 traffic is present in any compared capture, the system shall surface per-source-address DM1 differences when the active fault set or lamp summary changes across captures.
REQ-J1939-18 Optional feature Where printable TP component-identification or vehicle-identification payloads differ across compared captures, the system shall report those source-address and payload-label differences in structured output.
REQ-J1939-19 Unwanted behaviour If j1939 compare is invoked with fewer than two capture files, the system shall return a structured error with code J1939_COMPARE_REQUIRES_MULTIPLE_FILES and exit code 1.
REQ-J1939-06 Event-driven When j1939 spn <spn> is invoked without --file, the system shall return the built-in reference definition for the SPN (name, owning PGN with label, units, resolution, offset, and bit layout) marked mode: "reference", rather than requiring a capture file.
REQ-J1939-07 Unwanted behaviour If j1939 spn is invoked with a negative SPN value, the system shall return a structured error with code INVALID_SPN and exit code 1.
REQ-J1939-08 Unwanted behaviour If the requested SPN is absent from the curated catalog (and unresolved by any supplied DBC), the system shall return a structured error with code J1939_SPN_UNSUPPORTED and exit code 1, in both reference and capture modes.
REQ-J1939-21 Event-driven When j1939 pgn <pgn> is invoked without --file, the system shall return the built-in reference definition for the PGN (name, label, description, and the catalogued SPNs it carries) marked mode: "reference", rather than requiring a capture file.
REQ-J1939-20 Ubiquitous DM1 DTCs and j1939 faults entries shall resolve fmi to an fmi_description from the bundled SAE J1939-73 FMI catalog, and SPN name resolution shall support operator-supplied OEM/proprietary extensions via $CANARCHY_J1939_SPN_OVERRIDES (or ~/.canarchy/j1939_spns.json) merged over the bundled SPN catalog.

Command Surface

canarchy j1939 spn <spn> [--file <capture>]
canarchy j1939 tp sessions --file <capture>
canarchy j1939 dm1 --file <capture>
canarchy j1939 inventory --file <capture>
canarchy j1939 compare <capture> <capture> [<capture> ...]   # or repeated --file <capture> flags

Responsibilities And Boundaries

In scope:

  • curated SPN decoding for the initial supported set
  • BAM-oriented transport-protocol session summaries
  • DM1 parsing from direct frames and TP-reassembled payloads
  • source-address inventory summaries built from observed PGNs, TP identification payloads, and DM1 presence
  • multi-capture comparison across PGN activity, source-address coverage, DM1 changes, and printable TP identification payloads

Out of scope:

  • broad SPN database coverage
  • full RTS/CTS transport control state handling
  • DM message families beyond DM1
  • OEM-specific ECU identity resolution beyond J1939 source-address and printable identification hints

j1939 spn

--file is optional. Without a capture, the command performs a built-in reference lookup (mode: "reference"): it returns the SPN's name, owning PGN (with label), units, resolution, offset, and bit layout from the bundled catalog. With --file, it performs the capture-aware observation extraction below (mode: "passive"). The initial implementation uses a curated SPN decoder map rather than a general J1939 database.

Supported SPNs

  • 110 Engine Coolant Temperature from PGN 65262
  • 190 Engine Speed from PGN 61444

Observation contract

Each observation includes:

  • spn
  • name
  • pgn
  • source_address
  • destination_address
  • value
  • units
  • raw
  • timestamp

Unsupported SPNs return J1939_SPN_UNSUPPORTED.

j1939 tp sessions

The first implementation focuses on BAM-based transport sessions:

  • TP.CM BAM on PGN 60416 / 0xEC00
  • TP.DT data transfer on PGN 60160 / 0xEB00

Session summary contract

Each session summary includes:

  • session_type
  • transfer_pgn
  • source_address
  • destination_address
  • total_bytes
  • total_packets
  • packet_count
  • complete
  • reassembled_data
  • decoded_text when a completed payload is heuristically printable ASCII
  • decoded_text_encoding when decoded_text is present
  • decoded_text_heuristic to signal that printable-text decoding is a heuristic view
  • payload_label when the transferred PGN is known to map to an identification-style payload
  • payload_label_source when payload_label is present

j1939 dm1

DM1 inspection reads both:

  • direct DM1 frames on PGN 65226
  • TP-reassembled DM1 payloads whose transferred PGN is 65226

Message contract

Each message includes:

  • source_address
  • destination_address
  • transport
  • lamp_status
  • active_dtc_count
  • dtcs

Each DTC includes:

  • spn
  • name when known from the curated SPN map
  • fmi
  • fmi_description from the bundled SAE J1939-73 FMI catalog (null for reserved/out-of-range FMIs that have no entry)
  • occurrence_count
  • conversion_method

SPN name resolution and OEM extensions

DTC name resolution uses, in order of precedence:

  1. a DBC supplied via --dbc (path or provider ref), which overrides the curated map per matched SPN
  2. operator-supplied SPN overrides: a JSON file shaped like the bundled spns.json ({"<spn>": {"name": "..."}}) resolved from $CANARCHY_J1939_SPN_OVERRIDES, falling back to ~/.canarchy/j1939_spns.json when present — the documented extension path for OEM/proprietary SPN ranges
  3. the bundled SAE SPN catalog (canarchy/resources/j1939/spns.json)

FMI descriptions always come from the bundled FMI catalog (canarchy/resources/j1939/fmis.json); j1939 dm1 and j1939 faults both carry fmi_description per DTC/fault.

j1939 inventory

Inventory inspection produces one protocol-aware row per observed source address.

Inventory contract

Top-level output includes:

  • file
  • total_frames
  • interfaces
  • j1939_frame_count
  • source_count
  • vehicle_identification_count
  • vehicle_identifications
  • nodes

Each node includes:

  • source_address
  • source_address_name
  • frame_count
  • first_timestamp
  • last_timestamp
  • unique_pgn_count
  • top_pgns
  • component_identifications
  • vehicle_identifications
  • dm1

The inventory view is intended to reduce manual cross-referencing between j1939 summary, j1939 tp sessions, and j1939 dm1 during initial capture triage.

j1939 compare

j1939 compare compares two or more file-backed J1939 captures and highlights differences that operators commonly check manually during before/after or idle/active investigations.

Comparison contract

Top-level output includes:

  • files
  • capture_count
  • captures
  • common_pgns
  • unique_pgns
  • common_source_addresses
  • unique_source_addresses
  • dm1_differences
  • identifier_differences

Each compared capture includes:

  • file
  • file_name
  • total_frames
  • j1939_frame_count
  • unique_pgn_count
  • unique_source_count
  • pgns
  • source_addresses
  • dm1_by_source
  • identifiers

The compare view is intended to answer high-value investigation questions quickly without forcing the operator to manually diff multiple summary, inventory, dm1, or TP outputs.

Output Contracts

For j1939 spn, j1939 tp sessions, j1939 dm1, j1939 inventory, and j1939 compare, both --json and --jsonl emit a single CANarchy result object because these commands return structured observations under data rather than event streams. Text output remains protocol-first and summarises SPN observations, TP sessions, DM1 fault content, source-address inventory rows, and multi-capture J1939 differences without dropping to raw-ID-only views. For j1939 tp sessions, raw reassembled_data remains authoritative even when heuristic text or payload labels are present.

Error Contracts

Code Trigger Exit code
INVALID_SPN requested SPN is negative 1
J1939_SPN_UNSUPPORTED requested SPN is absent from the catalog and unresolved by any supplied DBC 1
J1939_COMPARE_REQUIRES_MULTIPLE_FILES j1939 compare is run with fewer than two capture files 1

Deferred Decisions

  • broader SPN coverage beyond the curated starter map
  • RTS/CTS state-machine detail and abort handling for TP
  • additional DM messages beyond DM1