j1850

package
v0.689.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 13, 2026 License: AGPL-3.0 Imports: 3 Imported by: 0

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

func Decode(hexBlob string) (Frame, error)

Decode parses a hex-encoded J1850 frame (3-byte header + data + 1-byte CRC). Tolerates ':' / '-' / '_' / whitespace separators.

func DecodeBytes

func DecodeBytes(b []byte) (Frame, error)

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL