32°N Developers Docs Tools Nmea Sim

The nmea CLI simulates a sailing scenario as real NMEA data and decodes a NMEA stream back to readings — the exact wire your chartplotter or nav software already speaks. It’s how you drive and verify the 32°N displays against a faithful synthetic source, and a standalone tool you can point OpenCPN at.

Two subcommands:

  • nmea sim — play a 32°N scenario as NMEA-0183 over TCP (and, with --n2k, NMEA-2000 battery/tank/engine/AIS).
  • nmea decode — read a NMEA-0183 stream (TCP / file / stdin) and print the decoded readings, human-readable or as JSON.

It’s built on the pure, fully-tested serializer/decoder in packages/sim: a ScenarioEngine ticks a physically-coherent world state, and the same codecs that emit the wire also decode it.

Install & run

In the monorepo:

pnpm --filter @32n/nmea-sim start -- sim --scenario coastal-passage
pnpm --filter @32n/nmea-sim start -- decode --tcp 127.0.0.1:10110

Standalone (no clone) — the same model as the mss scanner, via npm or a self-contained binary:

npx @32n/nmea-sim sim --scenario coastal-passage
nmea sim --stdout | nmea decode

nmea sim

nmea sim --scenario coastal-passage

Streams the scenario as NMEA-0183 on tcp://127.0.0.1:10110.

FlagDefaultDescription
--scenario <name>coastal-passagePreset scenario to play
--port <n>10110TCP port
--host <addr>127.0.0.1Bind address (loopback only)
--tick <ms>1000Real ms between engine ticks
--time-scale <n>1Sim-time acceleration (>1 plays faster)
--stdout / --file <path>Also echo each frame to stdout / a file
--loopbackoffDecode the 0183 instrument frame back onto the bus
--n2koffDecode battery/tank/engine/AIS over NMEA-2000 onto the bus

Scenarios: anchor-calm, coastal-passage, battery-deep-discharge, anchor-dragging, passage-squall, motoring-overnight, alternator-fault, engine-overheat, ais-collision.

Connect from OpenCPN: add a Network connection — type TCP, address 127.0.0.1, port 10110, receive NMEA 0183. The boat moves along the scenario track with depth, wind, heading, and (for ais-collision) AIS targets live on the chart.

nmea decode

nmea decode --tcp 127.0.0.1:10110        # a live 0183-over-TCP stream
nmea decode --file capture.nmea --json   # a captured file, as JSON
cat capture.nmea | nmea decode           # stdin

Decodes 0183 instrument sentences and AIS !AIVDM to compact readings (pos … sog … cog …, ais <mmsi> …) or structured JSON. Decoding a live CAN bus (can0) needs OS-level socketcan and is a separate tool; stream decode (TCP / file / stdin) works today.

What it carries

NMEA-0183 (always): RMC/GGA/GLL position, VTG SOG/COG, HDT heading, MWD/MWV wind (true + apparent), DBT/DPT depth, VHW water speed, and AIS targets as !AIVDM. Every line is $<talker><type>,…*HH with an XOR checksum.

NMEA-2000 (with --loopback/--n2k): battery SoC/voltage (PGN 127506/127508), fluid level (127505), engine rpm/coolant/oil (127488/127489), AIS position + static (129038/129039/129794) — fast-packet where the PGN needs it.

A fidelity sweep proves the decoded bus reproduces the simulator’s scenarios — for every scenario, across its full duration — within each wire field’s resolution.

Specs