Appearance
GNSS and gpsd
Most boats get their position from a GPS antenna on the NMEA 2000 bus, and nothing in this chapter applies to them.
Some do not. The Brain may have its own GNSS receiver — a USB dongle, a serial module on the board, an LTE modem with GNSS built in — wired to the Brain and invisible to the bus. Or the boat's only chartplotter GPS has failed and there is a spare receiver in a drawer.
This chapter is about that receiver. muxen-nmea2000 can read it, feed it into the navigation report like any other source, and put it on the NMEA 2000 bus so that every chartplotter and instrument on board sees a position again — including ones from manufacturers that have never heard of MUXEN.
That last part is worth being explicit about: this is how a Brain with a USB GPS becomes the boat's GPS.
gpsd does the talking to the hardware
The daemon does not open serial ports or speak to receivers directly. It talks to gpsd, the standard Linux GPS daemon, over TCP. gpsd owns the device, handles every receiver protocol there is, and hands out a tidy JSON stream.
That means: if gpsd can see your receiver, so can this daemon; if it cannot, this daemon is the wrong place to debug.
sh
sudo apt install gpsd gpsd-clients
gpspipe -w -n 5 localhost:2947 # does gpsd have data?GNSS support is compiled in only when libgps was available at build time. If it was not, none of the --source-gpsd* options exist and the daemon rejects them as unknown. Check with muxen-nmea2000 --help.
Reading a receiver
sh
muxen-nmea2000 --interface=can1 --name=0x11223344FF467788 \
--report-nav --source-gpsd| Option | Default | Effect |
|---|---|---|
--source-gpsd | off | enable the gpsd client |
--source-gpsd-host HOST | localhost | gpsd server |
--source-gpsd-port PORT | 2947 | gpsd port |
--source-gpsd-device PATH | all devices | use only this receiver |
--source-gpsd-device matters when gpsd is managing more than one receiver. Without it the daemon takes whichever device reports first and stays with it.
The daemon subscribes to gpsd's JSON stream and consumes:
| Class | Carries |
|---|---|
VERSION | gpsd's protocol version, logged at connect |
DEVICES | the list of receivers gpsd is managing |
TPV | time, position, altitude, course, speed, fix mode |
SKY | satellites in view and dilution-of-precision figures |
GST | position error estimates |
A lost connection is retried with an exponential backoff starting at 1 second and capping at 60.
Status on MQTT
sh
mosquitto_sub -h 127.0.0.1 -t 'nmea/gpsd' -vRetained, QoS 0, expireAfterSec 10:
json
{
"data": { "connected": true, "device": "/dev/ttyUSB0", "fix": "3d" },
"metadata": { "rxDate": "…", "rxTimestamp": 1736174045, "expireAfterSec": 10 }
}fix is none, 2d or 3d. device and fix are omitted while disconnected — connected: false on its own is the disconnected state.
Into the navigation report
A position from gpsd is fed to the navigation report only once the receiver has a real fix (TPV.mode of 2 or 3). With --nav-high-speed it also feeds the 10 Hz position and course/speed paths.
It arrives under the daemon's own J1939 NAME, because that is the identity the Brain has on the bus. So in muxen-nmea2000-config the gpsd position appears as a source named after the daemon, and it is ranked against the bus GPS receivers with exactly the same priority rules as any other source — see Navigation.
There is no automatic demotion: a gpsd position competes on equal terms unless an installer gives it a priority. If you want the bus GPS preferred, set the priorities.
SKY data is not used by the navigation report; it exists for the transmit path below.
Transmitting onto the bus
This is the part that makes the Brain a GPS for the whole boat.
sh
muxen-nmea2000 … --source-gpsd --source-gpsd-transmitThe flag takes an optional mode:
| Mode | Behaviour |
|---|---|
on (the default when the flag is given bare) | transmit whenever gpsd has data |
failover | transmit only while the bus has no valid GNSS of its own |
Add --source-gpsd-transmit-high-speed for the rapid-update PGNs.
The daemon transmits:
| PGN | Name | Rate | Requires |
|---|---|---|---|
| 129029 | GNSS Position Data | 1 Hz | |
| 129539 | GNSS DOPs | 1 Hz | |
| 129540 | GNSS Satellites in View | 1 Hz | |
| 129025 | Position, Rapid Update | 10 Hz | --source-gpsd-transmit-high-speed |
| 129026 | COG & SOG, Rapid Update | 10 Hz | --source-gpsd-transmit-high-speed |
Transmission is gated on freshness, so a stalled gpsd goes quiet instead of repeating an old fix: 1 Hz PGNs stop after 5 s without a TPV, rapid updates after 1 s, and satellite data after 10 s without a SKY message.
The frames go out under the daemon's claimed address and NAME. The gateway does not acquire a second identity for GNSS — to the rest of the bus, the MUXEN gateway is the thing transmitting position.
Failover mode
failover is the mode for a boat that already has a GPS and wants a standby. The Brain stays silent while another device gives the bus a position, takes over when none does, and hands back when one returns.
What counts as a GNSS on the bus. A position received from another device: GNSS Position Data (129029) whose method field reports a fix, or Position, Rapid Update (129025) carrying a latitude and a longitude. A receiver that transmits without a fix does not count. Neither do the Brain's own frames.
Taking over. The Brain starts transmitting when no such position has been received for --source-gpsd-transmit-failover-delay seconds (default 60) and gpsd has a fix. A single valid position from the bus starts the delay again.
Handing back. The Brain stops once valid positions have been coming from the bus for 10 seconds with no gap longer than 5 seconds. During those 10 seconds both positions are on the wire. A receiver that comes and goes — a fix for a few seconds, then nothing — never completes them, so it does not silence the Brain. After handing back, the Brain needs the whole delay again before it takes over a second time.
At startup. The delay runs from the moment the daemon has claimed its address on the bus, at startup and again after a bus failure. A Brain that starts on a boat with a working GPS therefore never transmits; on a boat without one it starts when the delay has passed.
Sixty seconds is a deliberate default. A GPS receiver that reboots, or whose antenna is briefly shaded, can be silent for tens of seconds and come back on its own; a shorter delay makes the Brain start transmitting into a bus that already has a working GPS, and now there are two positions on the wire.
The shortest delay is 5 seconds, because a receiver is only considered lost after 5 seconds of silence — the rule the navigation report applies to a position source (Navigation). A value of 1 to 4 behaves as 5. 0 is accepted and selects the default of 60 seconds.
Option dependencies
The daemon refuses to start rather than silently ignoring a flag:
Config: --source-gpsd-transmit requires --source-gpsd
Config: --source-gpsd-transmit-high-speed requires --source-gpsd-transmit
Config: --source-gpsd-transmit mode must be 'on' or 'failover', got 'yes'
Config: --source-gpsd-transmit-failover-delay must be non-negativeBefore you turn transmit on
Putting a second GNSS source on an NMEA 2000 bus is a real change to the boat, not a monitoring setting.
- Two GPS sources is a decision, not an accident. Every plotter on the bus will see both and each will choose for itself. Some choose badly. On a boat with a working GPS, prefer
failover. - The bus is 250 kbit/s and shared. 129540 with a full satellite list is a large Fast Packet message; at 1 Hz alongside 10 Hz rapid updates, this is real traffic on a busy bus.
- A USB GPS is not a marine GPS. No differential corrections, no integrity monitoring, no reference-station information, and a timestamp only as good as the dongle. It is a good standby and a poor primary.
- Check what the plotters do. Transmit onto the bus at the dock, and confirm on each display that the position is right and the source is the one you expect, before relying on it.
Diagnostics
sh
journalctl -u muxen-nmea2000 -f
mosquitto_sub -h 127.0.0.1 -t 'nmea/gpsd' -v
candump can1 | grep 19F805 # PGN 129029 leaving the Brain--verbose-gpsd logs the connection, the device and the fix state; without it the gpsd path is nearly silent. --verbose-control logs the transmit lifecycle, including the moment failover takes over and the moment it hands back.
If nmea/gpsd says connected: false, the problem is between the Brain and gpsd, not on the CAN bus. If it says fix: none, the problem is the antenna. See Troubleshooting.
