pgngen

package
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: Mar 25, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package pgngen provides a DSL parser and code generators for NMEA 2000 PGN definitions.

The DSL format defines PGN packet structures with bit-level field layouts, scaling factors, units, and enumerations. Generators produce Go structs with decoders/encoders, Protocol Buffer definitions, and JSON Schema.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GenerateGo

func GenerateGo(s *Schema, pkg string) string

GenerateGo produces Go source code for a parsed schema. It generates:

  • Named enum types with constants
  • Struct definitions for each PGN
  • Decode functions ([]byte -> struct)
  • Encode methods (struct -> []byte)
  • A PGN registry mapping PGN numbers to metadata and decode functions

func GenerateGoHelpers

func GenerateGoHelpers(pkg string) string

GenerateGoHelpers produces the helper functions needed by generated decode/encode code.

func GenerateJSONSchema

func GenerateJSONSchema(s *Schema) string

GenerateJSONSchema produces a JSON Schema document for the schema. Each PGN becomes a definition, and the root schema is a oneOf across all PGNs.

func GenerateProto

func GenerateProto(s *Schema, pkg string) string

GenerateProto produces a Protocol Buffers v3 definition for the schema.

Types

type EnumDef

type EnumDef struct {
	Name   string
	Values []EnumValue
	Line   int // source line for error reporting
}

EnumDef defines a named enumeration used by lookup fields.

type EnumValue

type EnumValue struct {
	Value int
	Name  string
}

EnumValue is a single value in an enumeration.

type FieldDef

type FieldDef struct {
	Name        string    // empty for reserved fields ("_")
	Type        FieldType // base type
	Bits        int       // bit width
	BitStart    int       // computed bit offset from start of packet (set by Resolve)
	Scale       float64   // raw * scale = decoded (0 means no scaling)
	Offset      float64   // decoded = raw * scale + offset (0 means no offset)
	Unit        string    // human-readable unit (e.g. "deg", "m/s")
	Desc        string    // optional description
	EnumRef     string    // enum type name (non-empty when Type == TypeEnum)
	LookupRef   string    // lookup table name (non-empty when lookup= is set)
	StructRef   string    // struct type name (non-empty when Type == TypeStruct)
	RepeatRef   string    // dynamic repeat count field name (e.g. "sats_in_view")
	Trim        string    // characters to right-trim from decoded string (e.g. "@ ")
	Tolerance   *float64  // change detection tolerance (nil = not set, 0 = any change significant)
	Signed      bool      // true for int types
	MatchValue  *int64    // when set, this field must equal this value (dispatch discriminator)
	RepeatCount int       // number of repetitions (0 = not repeated, must be >= 2 when set)
	GroupMode   string    // "" (array, default) or "map" (map[int]T)
	AliasPlural string    // override for auto-pluralized field name (from as= attribute)
	PGNRef      string    // field name holding the target PGN for cross-PGN pair decoding (bytes fields only)
	CountRef    string    // field name holding the number of parameter pairs (bytes fields only)
	Line        int       // source line for error reporting
}

FieldDef defines a single field within a PGN.

func (*FieldDef) HasScaling

func (f *FieldDef) HasScaling() bool

HasScaling returns true if the field has a scale or offset transformation.

func (*FieldDef) IsDynamicRepeat

func (f *FieldDef) IsDynamicRepeat() bool

IsDynamicRepeat returns true if this field uses repeat=<field_ref> (runtime count).

func (*FieldDef) IsRepeated

func (f *FieldDef) IsRepeated() bool

IsRepeated returns true if this field uses a static repeat= count.

func (*FieldDef) IsReserved

func (f *FieldDef) IsReserved() bool

IsReserved returns true if this is a padding/reserved field.

func (*FieldDef) IsSkipped

func (f *FieldDef) IsSkipped() bool

IsSkipped returns true if this field should be excluded from generated structs. Both reserved padding and unknown data fields are skipped.

func (*FieldDef) IsUnknown

func (f *FieldDef) IsUnknown() bool

IsUnknown returns true if this is an unknown data field.

type FieldType

type FieldType int

FieldType classifies the base data type of a field.

const (
	TypeUint      FieldType = iota // unsigned integer
	TypeInt                        // signed integer
	TypeFloat                      // IEEE 754 float
	TypeString                     // fixed-length ASCII string
	TypeEnum                       // lookup enum (references an EnumDef)
	TypeReserved                   // reserved/padding bits
	TypeUnknown                    // unknown data (observed but undocumented)
	TypeStringLAU                  // variable-length NMEA 2000 STRING_LAU
	TypeStruct                     // reference to a StructDef (generates a slice)
	TypeBytes                      // remaining raw bytes (captures packet tail)
)

type LookupDef

type LookupDef struct {
	Name    string // e.g. "VictronRegister"
	KeyType string // Go type: "uint8", "uint16", "uint32", "uint64"
	Values  []LookupValue
	Line    int // source line for error reporting
}

LookupDef defines a named lookup table mapping integer keys to human-readable names. Unlike enums, lookups don't change the field's Go type; the field stays its raw integer type and gets a Name() method for human-readable display.

type LookupValue

type LookupValue struct {
	Key  int64
	Name string
}

LookupValue is a single entry in a lookup table.

type PGNDef

type PGNDef struct {
	PGN         uint32
	Description string
	FastPacket  bool
	Interval    time.Duration // 0 = unspecified
	OnDemand    bool
	Draft       bool // definition is incomplete or uncertain
	Fields      []FieldDef
	Line        int // source line for error reporting
}

PGNDef defines a single PGN packet layout.

Fields semantics:

  • nil: name-only PGN (we know it exists but not its field layout)
  • []: PGN with zero user-visible fields (only reserved/unknown bits)
  • [...]: PGN with a full field definition

func (*PGNDef) HasVariableWidth

func (p *PGNDef) HasVariableWidth() bool

HasVariableWidth returns true if any field is variable-length (TypeStringLAU, TypeStruct with dynamic repeat, or TypeBytes), making the packet size unknowable at compile time.

func (*PGNDef) IsNameOnly

func (p *PGNDef) IsNameOnly() bool

IsNameOnly returns true if the PGN has no field layout defined.

func (*PGNDef) MinBytes

func (p *PGNDef) MinBytes() int

MinBytes returns the minimum number of bytes needed to decode this PGN.

func (*PGNDef) TotalBits

func (p *PGNDef) TotalBits() int

TotalBits returns the total number of bits across all fields. Repeated fields contribute Bits * RepeatCount. Variable-width fields (TypeStringLAU, TypeStruct, TypeBytes) contribute 0 bits.

type ResolveError

type ResolveError struct {
	Line    int
	Message string
}

ResolveError reports a validation error during schema resolution.

func (*ResolveError) Error

func (e *ResolveError) Error() string

type Schema

type Schema struct {
	Enums   []EnumDef
	Lookups []LookupDef
	Structs []StructDef
	PGNs    []PGNDef
}

Schema is the top-level AST node containing all parsed definitions.

func Parse

func Parse(src string) (*Schema, error)

Parse parses DSL source text into a Schema.

DSL syntax:

# line comment

enum WindReference {
  0 = "true_north"
  1 = "magnetic_north"
  2 = "apparent"
}

pgn 130306 "Wind Data" {
  sid             uint8           :8
  wind_speed      uint16          :16  scale=0.01   unit="m/s"
  wind_angle      uint16          :16  scale=0.0001 unit="rad"
  wind_reference  WindReference   :3
  _                               :5
}

func ParseFiles

func ParseFiles(sources map[string]string) (*Schema, error)

ParseFile is a convenience wrapper that reads a file and parses it. The caller is responsible for reading the file contents.

func (*Schema) Resolve

func (s *Schema) Resolve() error

Resolve computes BitStart offsets for all fields in all PGNs and validates enum references, struct references, and dispatch groups. Call after parsing, before code generation.

type StructDef

type StructDef struct {
	Name   string     // snake_case (e.g. "satellite_in_view")
	Fields []FieldDef // field layout within each entry
	Line   int        // source line for error reporting
}

StructDef defines a named sub-structure used by repeated variable-length groups. Analogous to EnumDef but for composite types referenced by struct-typed fields.

func (*StructDef) FixedEntryBytes

func (sd *StructDef) FixedEntryBytes() int

FixedEntryBytes returns the total bytes per entry for fixed-width structs. Only valid when HasVariableWidth() returns false.

func (*StructDef) HasVariableWidth

func (sd *StructDef) HasVariableWidth() bool

HasVariableWidth returns true if any field in the struct is variable-width (TypeStringLAU), making entry size unknowable at compile time.

Jump to

Keyboard shortcuts

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