Skip to main content

v0.3.1

Released March 10, 2026. GitHub Release | Full Changelog

56 commits since v0.2.0.

Highlights

PGN Code Generator & Decoder Library

A complete NMEA 2000 PGN code generation system (pgngen) that reads .pgn DSL definitions and generates Go structs, decoders, encoders, Protobuf definitions, and JSON Schema. The DSL supports enums, lookup tables, value-based dispatch for proprietary PGNs, repeated fields (repeat=), struct definitions, STRING_LAU, dynamic repeats, string trimming (trim=), name-only PGNs, unknown field markers, and draft annotations.

New PGN definitions:

CategoryPGNs
AIS129038 (Class A Position), 129039 (Class B Position), 129041 (AtoN), 129793 (UTC/Date), 129794 (Static/Voyage), 129809 (Static Part A), 129810 (Static Part B)
Navigation129285 (Route WP Information), 129026 (COG/SOG with change-tracking tolerances)
GNSS129540 (Sats in View), Distance Log, Magnetic Variation, GNSS DOPs
Engine/Electrical127489 (Engine Parameters Dynamic), 127506 (DC Source Status), 127509 (Inverter Status), 127513 (Battery Config), 127750 (Converter Status)
AC Power65010-65016 (Utility Power Monitoring)
Misc126993 (Heartbeat), Binary Switch Bank

Change Tracking

New ChangeTracker with field-level tolerance-aware diffing. Detects meaningful data changes while ignoring noise within configured tolerances. Available in lplex via the --changes flag. Tolerances are defined per-field in the PGN DSL using the tolerance= attribute.

lplex dump --changes --decode

Display Filter Expressions

BPF-inspired display filter expressions for lplex via the --where flag. Supports header fields (pgn, src, dst, prio), decoded struct fields by JSON tag, and lookup sub-accessors (register.name).

lplex dump --where "pgn == 129025"
lplex dump --where "sog > 5.0"
lplex dump --where "register.name == 'Battery Voltage'"

Send Policy & On-Demand Queries

Gated /send and /query endpoints with configurable send policies. The /query endpoint issues ISO Request (PGN 59904) to solicit on-demand PGN responses from devices. Rules support PGN values, ranges, comma-separated lists, and name-based filtering with deny/allow semantics.

Smart Boat Discovery

New --boat flag in lplex for automatic server discovery: tries mDNS on the local network first, falls back to cloud if available.

lplex dump --boat myboat    # mDNS first, cloud fallback

Auto-Reconnecting Subscriptions

Watch API in the Go client library (lplexc) with exponential backoff for automatic reconnection on connection loss.

Monitoring & Health

  • Prometheus metrics endpoint (GET /metrics)
  • Health check endpoint (GET /healthz)
  • Bus silence alerting to detect CAN bus disconnection

Decoded Values Endpoint

GET /values now returns field-level decoded PGN values, not just raw bytes.

Exclusion Filters

  • exclude-pgn and exclude-name filters across the HTTP API, sessions, and lplex
  • Client-side PGN filtering in lplex and lplex.conf

Replication Improvements

  • Configurable resource protections (limits on per-instance memory and goroutines)
  • End-to-end integration test covering boat lplex-server -> cloud lplex-cloud -> SSE

Output Improvements

  • Enum values serialized as JSON strings for known labels, numbers for unknown
  • Lookup fields displayed as {id, name} objects in decoded output
  • Decode errors shown in red, decoded data on same line in lplex

Documentation

Documentation site moved into website/ with Docusaurus, deployed to GitHub Pages.

Bug Fixes

  • Fix cloud journal archival to S3
  • Fix exclude-pgn filter dropped in buffered session creation
  • Fix incorrect padding in PGN 130310 and 130311 definitions
  • Fix WaterDepth PGN definition
  • Fix proprietary PGN registry description for dispatched PGNs
  • Fix broken doc links
  • Fix Docker build for multi-platform images (TARGETARCH)
  • Pad short PGN data with 0xFF instead of erroring
  • Return (nil, nil) for unknown proprietary PGN discriminator values

Security

  • Fix CVE in serialize-javascript dependency
  • Fix uncontrolled slice allocation in EventLog.Recent (multiple rounds of hardening)
  • Break CodeQL taint chain for slice allocation

Install / Upgrade

Homebrew (lplex client only):

brew install sixfathoms/tap/lplex

Debian/Ubuntu (server):

# Download .deb from GitHub Releases
sudo dpkg -i lplex_0.3.1_linux_*.deb
sudo systemctl restart lplex-server

Docker:

docker pull ghcr.io/sixfathoms/lplex:v0.3.1