Skip to main content

Enums and Lookup Tables

The DSL provides two mechanisms for named values: enums and lookups. They serve different purposes.

Enums

Enums define a new Go type with a String() method. Use them when the field has a small, dense set of possible values.

Definition

enum WindReference {
0 = "true_north"
1 = "magnetic_north"
2 = "apparent"
3 = "true_boat"
4 = "true_water"
}

Generated Go code

type WindReference uint8

const (
WindReferenceTrueNorth WindReference = 0
WindReferenceMagneticNorth WindReference = 1
WindReferenceApparent WindReference = 2
WindReferenceTrueBoat WindReference = 3
WindReferenceTrueWater WindReference = 4
)

func (v WindReference) String() string {
switch v {
case 0: return "true_north"
case 1: return "magnetic_north"
case 2: return "apparent"
case 3: return "true_boat"
case 4: return "true_water"
default: return "unknown"
}
}

Usage in PGN

pgn 130306 "Wind Data" {
wind_reference WindReference :3
}

The Go struct field becomes WindReference WindReference, and JSON serialization uses the string value.

When to use enums

  • The value set is small (fits in the bit width)
  • Values are dense (0, 1, 2, ... with few gaps)
  • You want type safety (a distinct Go type)
  • You want String() for human-readable output

Lookup tables

Lookups map sparse integer keys to human-readable names without creating a new type. Use them when the key space is large and sparse.

Definition

lookup VictronRegister uint16 {
0x0100 = "Product ID"
0x0200 = "Device Mode"
0x0201 = "Device State"
0xED8D = "DC Channel 1 Voltage"
0xED8E = "DC Channel 1 Power"
0xEDD3 = "Yield Today"
}

The type after the name (uint16) specifies the key type.

Generated Go code

var victronRegisterNames = map[uint16]string{
0x0100: "Product ID",
0x0200: "Device Mode",
0x0201: "Device State",
0xED8D: "DC Channel 1 Voltage",
0xED8E: "DC Channel 1 Power",
0xEDD3: "Yield Today",
}

func VictronRegisterName(v uint16) string {
if name, ok := victronRegisterNames[v]; ok {
return name
}
return ""
}

Usage in PGN

pgn 61184 "Victron Battery Register" {
register_id uint16 :16 lookup=VictronRegister
}

The Go struct field stays uint16 (no new type), but gains a RegisterIDName() string helper method on the struct.

When to use lookups

  • The key space is large or sparse (e.g., 0x0100, 0xED8D)
  • You want to keep the raw integer type for arithmetic
  • You're mapping register IDs, product codes, or other identifiers
  • Adding new entries shouldn't require a new Go constant

Comparison

EnumLookup
Go typeNew named typeOriginal integer type
String()Yes (on the type)Name() function
Type safetyYesNo
Key spaceDense (0, 1, 2, ...)Sparse (any values)
JSON outputString valueInteger (with name available)
Use caseSmall finite setsLarge/sparse mappings