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¶
110Engine Coolant Temperature from PGN65262190Engine Speed from PGN61444
Observation contract¶
Each observation includes:
spnnamepgnsource_addressdestination_addressvalueunitsrawtimestamp
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_typetransfer_pgnsource_addressdestination_addresstotal_bytestotal_packetspacket_countcompletereassembled_datadecoded_textwhen a completed payload is heuristically printable ASCIIdecoded_text_encodingwhendecoded_textis presentdecoded_text_heuristicto signal that printable-text decoding is a heuristic viewpayload_labelwhen the transferred PGN is known to map to an identification-style payloadpayload_label_sourcewhenpayload_labelis 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_addressdestination_addresstransportlamp_statusactive_dtc_countdtcs
Each DTC includes:
spnnamewhen known from the curated SPN mapfmifmi_descriptionfrom the bundled SAE J1939-73 FMI catalog (nullfor reserved/out-of-range FMIs that have no entry)occurrence_countconversion_method
SPN name resolution and OEM extensions¶
DTC name resolution uses, in order of precedence:
- a DBC supplied via
--dbc(path or provider ref), which overrides the curated map per matched SPN - 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.jsonwhen present — the documented extension path for OEM/proprietary SPN ranges - 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:
filetotal_framesinterfacesj1939_frame_countsource_countvehicle_identification_countvehicle_identificationsnodes
Each node includes:
source_addresssource_address_nameframe_countfirst_timestamplast_timestampunique_pgn_counttop_pgnscomponent_identificationsvehicle_identificationsdm1
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:
filescapture_countcapturescommon_pgnsunique_pgnscommon_source_addressesunique_source_addressesdm1_differencesidentifier_differences
Each compared capture includes:
filefile_nametotal_framesj1939_frame_countunique_pgn_countunique_source_countpgnssource_addressesdm1_by_sourceidentifiers
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