adapter

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Jul 19, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package adapter implements the adapter for raw CAN bus frame endpoints.

This package converts raw CAN bus frames (as produced by SocketCAN interfaces or CAN-to-USB gateways) into complete NMEA 2000 packets. It handles both single-frame messages (8 bytes or fewer of payload) and multi-frame "fast packet" messages that require assembly of multiple CAN frames into a single logical message.

The processing pipeline is:

*can.Frame (raw CAN bus frame)
  -> NewPacketInfo() extracts PGN, source, priority, destination from CAN ID
  -> NewPacket() creates a Packet with candidate metadata looked up by PGN
  -> For fast packets: MultiBuilder assembles frames into a complete message
  -> FilterCandidates() filters variants by manufacturer/match fields
  -> Complete packet forwarded to PacketHandler

Index

Constants

View Source
const MaxFrameNum = 31

MaxFrameNum is the maximum frame number in a multipart NMEA 2000 fast-packet message. Frame numbers are encoded as 5 bits (0-31), so a single fast-packet sequence can span up to 32 CAN frames. With 6 data bytes in frame 0 and 7 in each subsequent frame, this allows payloads up to 6 + (31 * 7) = 223 bytes.

Variables

This section is empty.

Functions

func CanFrameFromRaw

func CanFrameFromRaw(in string) can.Frame

CanFrameFromRaw parses a CSV-formatted raw CAN bus log line into a can.Frame suitable for testing and replay. The expected input format (matching common N2K replay tools) is:

timestamp,priority,pgn,source,destination,length,byte0,byte1,...,byteN

For example:

"2023-01-21T00:04:17Z,3,127501,224,0,8,00,03,c0,ff,ff,ff,ff,ff"

The function reconstructs the 29-bit CAN extended ID from the parsed fields using framer.BuildCANID, and always sets the frame Length to 8 (standard CAN data frame size). Data bytes beyond the declared length are left at their zero default value.

Note: This function ignores parse errors on individual fields for simplicity in test code. In production, a more robust parser would be needed.

Parameters:

  • in: A comma-separated string in the format described above.

Returns a can.Frame with the reconstructed CAN ID and parsed data bytes.

func NewPacketInfo

func NewPacketInfo(message *can.Frame) pgn.MessageInfo

NewPacketInfo extracts NMEA 2000 message metadata from a raw CAN bus frame's 29-bit extended identifier. The CAN ID encodes several fields using the NMEA 2000 / ISO 11783 bit layout:

CAN ID bit layout (29 bits total, extended frame format):

Bits 28-26: Priority (3 bits, 0-7, lower = higher priority)
Bit  25:    Reserved
Bit  24:    Data Page (DP)
Bits 23-16: PDU Format (PF) - determines if message is broadcast or addressed
Bits 15-8:  PDU Specific (PS) - destination address (if PF < 240) or group extension (if PF >= 240)
Bits 7-0:   Source Address (SA) - the sender's address on the bus

The PGN (Parameter Group Number) is extracted from bits 25-8 of the CAN ID. For addressed messages (PDU Format < 240), the PS field contains the destination address rather than being part of the PGN, so the lower 8 bits are masked off and stored as TargetId instead.

Parameters:

  • message: A pointer to a can.Frame containing the raw CAN bus frame with its 29-bit ID.

Returns a pgn.MessageInfo populated with the extracted PGN, source, priority, target, and current timestamp.

func NewPacketInfoAt added in v1.0.0

func NewPacketInfoAt(message *can.Frame, timestamp time.Time) pgn.MessageInfo

NewPacketInfoAt extracts CAN identifier metadata using timestamp as the observation time. It is used when a capture or gateway supplied a more faithful time than the host's current clock.

Types

type CANAdapter

type CANAdapter struct {
	// contains filtered or unexported fields
}

CANAdapter reads raw CAN bus frames and outputs complete NMEA 2000 Packets. It is the primary adapter implementation for systems that receive NMEA 2000 data via a CAN bus interface (e.g., SocketCAN on Linux, CAN-USB adapters).

func NewCANAdapter

func NewCANAdapter() *CANAdapter

NewCANAdapter creates and returns a new CANAdapter with an initialized MultiBuilder for fast-packet assembly. Call SetOutput to register a PacketHandler before processing messages.

func (*CANAdapter) HandleMessage

func (c *CANAdapter) HandleMessage(f *can.Frame)

HandleMessage is the main entry point for processing incoming CAN bus frames. It accepts a *can.Frame, extracts the NMEA 2000 metadata from the CAN ID, creates a Packet, and processes it through the pipeline.

Processing flow:

  1. Extract PGN, source, priority, and destination from the 29-bit CAN ID.
  2. Create a new Packet and look up candidate decoders.
  3. If there are parse errors (e.g., unknown PGN), forward immediately as-is.
  4. If the PGN is a fast-packet type, pass to MultiBuilder for assembly. Otherwise, mark as Complete immediately (single-frame message).
  5. Once Complete, filter decoders by manufacturer and forward to the handler.

Parameters:

  • f: A *can.Frame from the brutella/can library.

func (*CANAdapter) HandleMessageWithInfo added in v1.0.0

func (c *CANAdapter) HandleMessageWithInfo(f *can.Frame, pInfo pgn.MessageInfo)

HandleMessageWithInfo processes a frame using observation metadata supplied by the source Adapter rather than reconstructing its timestamp and identity.

func (*CANAdapter) SetOutput

func (c *CANAdapter) SetOutput(ph PacketHandler)

SetOutput registers the downstream PacketHandler that will receive complete packets. This must be called before HandleMessage to ensure packets are forwarded.

Parameters:

  • ph: The PacketHandler implementation to receive complete packets.

type MultiBuilder

type MultiBuilder struct {
	// contains filtered or unexported fields
}

MultiBuilder manages the assembly of multi-frame NMEA 2000 fast packets into complete single Packets. NMEA 2000 messages with payloads larger than 8 bytes are transmitted as a series of CAN frames that must be reassembled.

MultiBuilder keys in-progress sequences by network identity, source address, PGN, and sequence ID. Network identity is essential when several physical networks are merged into one read pipeline because their dynamic source addresses and three-bit sequence IDs can overlap.

Each unique (source, PGN, seqId) tuple maps to a sequence that accumulates frames until the message is complete. Once complete, the sequence is deleted to free memory.

This structure is instantiated by CANAdapter and delegates frame-level assembly to the sequence type.

func NewMultiBuilder

func NewMultiBuilder() *MultiBuilder

NewMultiBuilder creates and returns a new MultiBuilder with an initialized (empty) sequences map, ready to receive fast-packet frames.

func (*MultiBuilder) Add

func (m *MultiBuilder) Add(p *decoder.Packet)

Add processes an incoming fast-packet frame by extracting its sequence ID and frame number, locating (or creating) the appropriate sequence, and adding the frame data. If the sequence is now complete (all expected bytes received), the assembled data is copied into the packet, the packet is marked Complete, and the sequence is deleted from the map to free memory.

Parameters:

  • p: A pointer to the Packet containing the raw CAN frame data. On return, if the sequence is complete, p.Data will contain the fully assembled payload and p.Complete will be true.

func (*MultiBuilder) SeqFor

func (m *MultiBuilder) SeqFor(p *decoder.Packet) *sequence

SeqFor returns the existing sequence for the given packet's (source, PGN, seqId) tuple, or creates a new one if it doesn't exist yet. It lazily initializes intermediate map levels as needed.

Parameters:

  • p: The Packet whose Info.SourceId, Info.PGN, and SeqId identify the target sequence.

Returns a pointer to the sequence for this packet's source/PGN/seqId combination.

type PacketHandler

type PacketHandler interface {
	// Decode receives a complete Packet for decoding.
	Decode(decoder.Packet)
}

PacketHandler is the interface for downstream consumers of complete Packets. Implementations receive fully assembled packets (both single-frame and multi-frame) that are ready for decoding into typed PGN structs.

Jump to

Keyboard shortcuts

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