Documentation
¶
Overview ¶
Package j1850 decodes SAE J1850 VPW (Variable Pulse Width) and PWM (Pulse Width Modulation) frames — the legacy OBD-II protocol used by GM and Ford vehicles before they migrated to CAN bus around 2008. Pure offline parser; no transport, no hardware.
Wrap-vs-native judgement: SAE J1850 + SAE J2178 + ISO/SAE 15765 are all fully public specs. The walker is bit-level decoding over a 3-byte header + 0-7 data bytes + 1-byte CRC. Wrapping a FAP for this would require an SD-card install + a firmware-fork dependency for a pure parser. Native delivers offline analysis — operators paste a captured J1850 frame from a Macchina M2 / OBDLink LX / classic-car OBD-II adapter and inspect every field without re-connecting to the vehicle.
Pairs with the existing canbus_* tools — those handle CAN bus (post-2008 vehicles); this Spec covers the legacy J1850 buses still found on classic-car restoration / older fleet analysis workflows.
What this package covers:
- SAE J1850 header decode: 3-byte header with priority (3 bits) + header type (1 bit) + ID (4 bits) + target ECU (8 bits) + source ECU (8 bits)
- Standard ECU address lookup (Engine Control Module / Transmission Control Module / Body Control Module / ABS / Climate Control / Diagnostic Tool / etc.)
- Data payload extraction (0-7 bytes for single-frame format; HFM multi-frame format flagged but not reassembled)
- Service ID (SID) + Parameter ID (PID) recognition for OBD-II Mode 1-9 with documented PID name lookup for the most common diagnostic queries (engine load / coolant temp / RPM / vehicle speed / throttle / fuel level / etc.)
- CRC-8 validation per SAE J1850 §5.4 (polynomial 0x1D with init 0xFF and final XOR 0xFF)
What this package does NOT cover (deliberately out of scope):
- Bit-stream demodulation (operators bring pre-deframed bytes from their OBD-II adapter)
- Multi-frame HFM message reassembly (flagged but not processed — the SAE J2178 multi-frame format wraps a single decoded payload across multiple physical frames)
- GMLAN extension (a GM-specific J1850 superset; same header but extended PID space)
- Other diagnostic protocols (KWP2000, UDS, ISO-TP)
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Frame ¶
type Frame struct {
// PriorityField is bits 7..5 of byte 0 (3 bits).
Priority int `json:"priority"`
// HeaderType is bit 4 of byte 0 — 0 = 3-byte consolidated
// header (standard), 1 = 1-byte header (rare).
HeaderType int `json:"header_type"`
// ID is bits 3..0 of byte 0 (4 bits) — function/message ID
// shared with the per-OEM service catalog.
ID int `json:"id"`
// TargetHex is byte 1 — the destination ECU address.
TargetHex string `json:"target_address_hex"`
TargetAddress int `json:"target_address"`
TargetName string `json:"target_name,omitempty"`
// SourceHex is byte 2 — the source ECU address.
SourceHex string `json:"source_address_hex"`
SourceAddress int `json:"source_address"`
SourceName string `json:"source_name,omitempty"`
// DataHex is the payload (bytes 3 to end-1, where end-1
// is the CRC byte).
DataHex string `json:"data_hex,omitempty"`
// CRC is the last-byte checksum.
CRC int `json:"crc"`
CRCExpected int `json:"crc_expected"`
CRCValid bool `json:"crc_valid"`
// OBDII is populated when the payload looks like an OBD-II
// service request or response (i.e. data[0] is a known SID).
OBDII *OBDIIDecoded `json:"obdii,omitempty"`
}
Frame is the top-level decoded J1850 message.
func Decode ¶
Decode parses a hex-encoded J1850 frame (3-byte header + data + 1-byte CRC). Tolerates ':' / '-' / '_' / whitespace separators.
func DecodeBytes ¶
DecodeBytes is the byte-slice variant of Decode.
type OBDIIDecoded ¶
type OBDIIDecoded struct {
// Mode is the OBD-II Service ID (Mode). For requests, the
// raw value (0x01..0x0A). For responses, the request mode
// + 0x40 (so 0x41 = Mode 1 response, 0x43 = Mode 3
// response).
Mode int `json:"mode"`
ModeName string `json:"mode_name"`
// IsResponse reports whether the high bit of Mode is set
// (Mode + 0x40 = response).
IsResponse bool `json:"is_response"`
// PID is the Parameter ID (data[1]) for Mode 1/2/9 requests/
// responses. nil for modes that don't use a PID.
PID *int `json:"pid,omitempty"`
PIDName string `json:"pid_name,omitempty"`
// PayloadHex is the data after Mode + optional PID
// (i.e. the actual measurement bytes for a response).
PayloadHex string `json:"payload_hex,omitempty"`
}
OBDIIDecoded is the structured view of an OBD-II request / response.