Documentation
¶
Overview ¶
Package n2k decodes NMEA 2000 marine network messages from CAN bus hardware into strongly-typed Go structs.
Index ¶
- func Receive(ctx context.Context, opts ...Option) iter.Seq2[pgn.Message, error]
- type Client
- type DeviceName
- type Option
- func CAN(iface string) Option
- func Filter(expr string) Option
- func IncludeUnknown() Option
- func Replay(frames []can.Frame) Option
- func USB(port string) Option
- func WithBus(bus canbus.Interface) Option
- func WithClaimTimeout(d time.Duration) Option
- func WithLogger(l *slog.Logger) Option
- func WithName(name DeviceName) Option
- func WithSourceAddress(addr uint8) Option
- type Scanner
- type WriteResult
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is the central integration point for NMEA 2000 communication. It composes address claiming, transport protocol, encoding, and framing into a single type that can both read and write PGN messages.
func NewClient ¶
NewClient creates a Client that can read and write NMEA 2000 messages. At least one source option (CAN, USB, Replay, or Bus) must be provided.
func (*Client) Close ¶
Close shuts down the client, cancels the context, and releases resources. It is safe to call Close multiple times.
func (*Client) Receive ¶
Receive returns an iterator of decoded NMEA 2000 messages. For bus clients it reads from the internal message channel; for replay clients it delegates to the top-level Receive function.
func (*Client) Scanner ¶
Scanner creates a new Scanner that reads from this client. For bus clients it reads from the internal message channel; for replay clients it delegates to NewScanner.
func (*Client) Write ¶
func (c *Client) Write(msg pgn.Message) *WriteResult
Write asynchronously encodes and transmits a PGN message. The message must be a pointer to a PGN struct (e.g. *pgn.VesselHeading). The returned WriteResult can be used to wait for completion and check for errors. Writes are serialized through a single goroutine to guarantee FIFO ordering.
func (*Client) WrittenFrames ¶
WrittenFrames returns a copy of all CAN frames written through this client. This is primarily useful in replay/testing mode to inspect what was sent.
type DeviceName ¶
type DeviceName struct {
IdentityNumber uint32 // 21 bits (0-20)
ManufacturerCode uint16 // 11 bits (21-31)
DeviceInstance uint8 // 8 bits: lower 3 (32-34) + upper 5 (35-39)
DeviceFunction uint8 // 8 bits (40-47)
DeviceClass uint8 // 7 bits (49-55), bit 48 is reserved
SystemInstance uint8 // 4 bits (56-59)
IndustryGroup uint8 // 3 bits (60-62)
}
DeviceName represents the ISO 11783 / NMEA 2000 64-bit NAME that uniquely identifies a device on a CAN bus network. The NAME is used during address claiming (PGN 60928) to arbitrate bus addresses.
func DefaultDeviceName ¶
func DefaultDeviceName() DeviceName
DefaultDeviceName returns a DeviceName pre-configured for a PC-based software gateway operating on an NMEA 2000 marine network. The identity number is randomized so that multiple processes using the same binary can coexist on the same bus without NAME collisions during address claiming.
func UnpackDeviceName ¶
func UnpackDeviceName(name uint64) DeviceName
UnpackDeviceName extracts a DeviceName from the 64-bit NAME integer defined by ISO 11783. The arbitraryAddressCapable flag (bit 63) is not stored in the struct; callers can check it directly via (name >> 63) & 1.
func (DeviceName) Pack ¶
func (d DeviceName) Pack(arbitraryAddressCapable bool) uint64
Pack encodes the DeviceName into the 64-bit NAME integer defined by ISO 11783. The arbitraryAddressCapable flag sets bit 63, indicating the device can participate in dynamic address negotiation.
64-bit NAME layout (LSB-first):
Bits 0-20: Identity Number (21 bits) Bits 21-31: Manufacturer Code (11 bits) Bits 32-34: Device Instance Lower (3 bits) Bits 35-39: Device Instance Upper (5 bits) Bits 40-47: Device Function (8 bits) Bit 48: Reserved (0) Bits 49-55: Device Class (7 bits) Bits 56-59: System Instance (4 bits) Bits 60-62: Industry Group (3 bits) Bit 63: Arbitrary Address Capable (1 bit)
func (DeviceName) Validate ¶
func (d DeviceName) Validate() error
Validate checks that each field fits within its bit width as defined by the ISO 11783 NAME specification. DeviceInstance and DeviceFunction are uint8 and always fit their 8-bit fields.
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option configures the behavior of Receive and NewScanner.
func Filter ¶
Filter sets a CEL expression to filter messages. The expression is automatically partitioned into pre-decode (metadata) and post-decode (struct field) stages.
func IncludeUnknown ¶
func IncludeUnknown() Option
IncludeUnknown includes undecodable messages as *pgn.UnknownPGN in the output stream. By default, unknown PGNs are dropped and logged at debug level.
func WithBus ¶
WithBus provides a pre-constructed canbus.Interface for the client to use. This is primarily for testing with mock buses. When set, the client uses this bus directly instead of constructing one from CAN/USB sources.
func WithClaimTimeout ¶
WithClaimTimeout sets how long NewClient blocks waiting for address claiming to complete on a real CAN bus. Default is 1500ms. This allows time for the initial 250ms claim window plus several rounds of contention renegotiation.
func WithLogger ¶
WithLogger overrides the default slog.Default() logger.
func WithName ¶
func WithName(name DeviceName) Option
WithName sets the ISO 11783 device NAME used for address claiming. The NAME is a 64-bit identifier that uniquely identifies this device on the NMEA 2000 network. In address contention, the device with the lower NAME wins. When not set, a default NAME is used (see DefaultDeviceName).
func WithSourceAddress ¶
WithSourceAddress sets an explicit NMEA 2000 source address for the client. When set, the client uses this address and treats contention as a fatal error. When not set (default), the client uses auto mode — starting at address 253 and working downward if contention occurs.
type Scanner ¶
type Scanner struct {
// contains filtered or unexported fields
}
Scanner reads decoded NMEA 2000 messages one at a time. Call Next() to advance, Message() to get the current message, and Err() for errors.
func NewScanner ¶
NewScanner creates a Scanner that reads from the configured sources.
type WriteResult ¶
type WriteResult struct {
// contains filtered or unexported fields
}
WriteResult represents the outcome of an asynchronous write operation. The zero value is safe to use and behaves as a completed, successful write.
func (*WriteResult) Done ¶
func (r *WriteResult) Done() <-chan struct{}
Done returns a channel that is closed when the write is complete. On a zero-value WriteResult, Done returns an already-closed channel.
func (*WriteResult) Wait ¶
func (r *WriteResult) Wait() error
Wait blocks until the write is complete, then returns the error (or nil). On a zero-value WriteResult, Wait returns nil immediately.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
internal
|
|
|
adapter
Package adapter implements the adapter for raw CAN bus frame endpoints.
|
Package adapter implements the adapter for raw CAN bus frame endpoints. |
|
canbus
Package canbus is built around the Channel structure, which represents a single canbus channel for sending/receiving CAN frames.
|
Package canbus is built around the Channel structure, which represents a single canbus channel for sending/receiving CAN frames. |
|
claiming
Package claiming implements the NMEA 2000 / ISO 11783 address claiming protocol (PGN 60928).
|
Package claiming implements the NMEA 2000 / ISO 11783 address claiming protocol (PGN 60928). |
|
decoder
Package decoder converts input messages to an intermediate (Packet) form, and outputs equivalent golang structs.
|
Package decoder converts input messages to an intermediate (Packet) form, and outputs equivalent golang structs. |
|
framer
Package framer builds CAN frames from encoded PGN payloads.
|
Package framer builds CAN frames from encoded PGN payloads. |
|
transport
Package transport implements ISO 11783 Transport Protocol for NMEA 2000 messages that exceed 8 bytes and cannot use fast-packet encoding.
|
Package transport implements ISO 11783 Transport Protocol for NMEA 2000 messages that exceed 8 bytes and cannot use fast-packet encoding. |
|
Package pgn uses data from canboat.json to convert NMEA 2000 messages to strongly-typed golang data.
|
Package pgn uses data from canboat.json to convert NMEA 2000 messages to strongly-typed golang data. |
|
Package units provides type-safe unit conversion for physical quantities commonly encountered in marine (NMEA 2000) and general-purpose sensor systems.
|
Package units provides type-safe unit conversion for physical quantities commonly encountered in marine (NMEA 2000) and general-purpose sensor systems. |