NMEA sentences: GxRMC and GxGGA#

Why#

The PPS provides a second-boundary pulse accurate to around a microsecond, but it doesn’t say which second just ticked (GNSS constellations chapter). That information (the calendar date and time) arrives over the receiver’s second stream: the NMEA sentences, read by gpsd and handed to chrony via shared memory (Chrony chapter). A receiver spontaneously emits a whole family of sentences (GGA, GSA, GSV, VTG, GLL, ZDA…); this project deliberately uses only two: GxRMC and GxGGA.

This choice isn’t just about saving serial-link bandwidth. It rests above all on a principle of reproducibility. NMEA 0183 is a public, vendor-neutral standard, originally published for marine electronics: every GNSS receiver on the market speaks it, from a u-blox module to any SiRF or MediaTek chip. By contrast, the binary UBX protocol of the receiver used here (u-blox NEO-M9N) is richer but proprietary, tied to a single manufacturer’s tooling. By depending only on GxRMC and GxGGA, two sentences any standard receiver can produce, the entire method of this guide transposes as-is to any other hardware, with nothing to rewrite.

How#

Anatomy of an NMEA sentence#

An NMEA 0183 sentence is a plain ASCII text line:

$ GN RMC ,field,field,... *HH
│ │  │                    │
│ │  │                    └─ checksum (XOR of everything
│ │  │                       that precedes it, in hexadecimal)
│ │  └──────────────────── sentence type (3 letters: RMC, GGA...)
│ └─────────────────────── talker ID (2 letters)
└───────────────────────── start of sentence

The talker ID is the “Gx” of the title: those two letters name the constellation that produced the solution.

Talker IDSource
GPGPS only
GLGLONASS only
GAGalileo only
GBBeiDou only
GNcombined solution (several constellations at once)

A multi-constellation receiver like this project’s most often emits GN sentences (e.g. $GNRMC), since it computes a single solution from several systems. That’s why we write GxRMC with a generic x rather than GPRMC: hard-coding GP in a configuration would miss the sentences actually emitted.

GxRMC: date, time, and validity#

RMC stands for Recommended Minimum specific GNSS data, the minimum sentence recommended by the standard. It is the only common sentence that carries the calendar date:

$GNRMC,182017.00,A,xxxx.xxxxx,N,xxxxx.xxxxx,E,0.002,,260726,,,A,V*hh
       │         │                                   │
       │         │                                   └─ date: 26/07/26 (DDMMYY)
       │         └─────────────────────────────────── status: A = valid,
       │                                              V = invalid
       └───────────────────────────────────────────── UTC time: 18:20:17

The position fields (latitude, longitude) and the checksum are masked (xxxx.xxxxx, *hh): only the time, date, and status matter here. The last two letters before the checksum (A,V) are the mode indicator and navigational status added by the NMEA 4.1 standard, unused by this project.

Two fields are decisive for a time server:

  • The UTC time + date: this is the complete pair that resolves the PPS’s second ambiguity. The PPS says “it’s now, an exact second boundary”; GxRMC says “and that now is 26 July 2026 at 18:20:17 UTC”.
  • The A/V status: A (Active) signals a valid navigation fix, V (Void) a receiver with no usable fix. This field is what distinguishes “I’m receiving sentences” from “I have a reliable time”: it underpins chrony’s lock GPS directive (Chrony chapter), which refuses to discipline the clock as long as the status isn’t A.

GxGGA: fix quality#

GGA stands for Global Positioning System Fix Data. It does not carry the date (only the time of day), but it provides the quality indicators GxRMC lacks:

$GNGGA,182017.00,xxxx.xxxxx,N,xxxxx.xxxxx,E,1,12,0.87,xx.x,M,xx.x,M,,*hh
       │                                    │ │  │
       │                                    │ │  └─ HDOP: 0.87 (geometric quality)
       │                                    │ └── satellites used: 12
       │                                    └──── fix quality: 1 = GPS fix
       └──────────────────────────────────── UTC time: 18:20:17

The number of satellites used and the HDOP are the metrics watched to judge reception health (Final verification chapter), and the fix quality field distinguishes a standard fix from a degraded one. gpsd relies on GxGGA to populate the fix mode and satellite count shown by cgps.

What each sentence provides#

InformationGxRMCGxGGA
UTC time (of day)yesyes
Calendar dateyesno
A/V validity statusyesno
Fix qualitynoyes
Number of satellites usednoyes
HDOP, altitudenoyes

Reading the table gives the reason for the pair: GxRMC provides the complete timestamp and the validity lock chrony needs, GxGGA provides the reception diagnostics. Neither is enough on its own: a receiver emitting only GxGGA would deprive gpsd of the date, and thus of any complete UTC timestamp.

Reducing the receiver to these two sentences#

Emitting only GxRMC and GxGGA lightens the serial link and drops sentences the project doesn’t need (the GSV sentences, which list every satellite in view, are the most verbose). Selecting the active sentences is done on the receiver side; gpsd itself simply uses whatever arrives and extracts the time from any standard dated sentence. The principle stays deliberately generic: on a u-blox you tune the rates via UBX-CFG-MSG, but the idea (“keep only the dated sentence and the quality sentence”) holds for any receiver, whatever its configuration tool.

Pitfalls to avoid#

  • Relying on GxGGA alone. Without GxRMC (or ZDA), no sentence carries the date: gpsd can’t rebuild a complete UTC timestamp, and the second reading fails silently.
  • Hard-coding the talker ID to GP. A multi-constellation receiver emits GN sentences; a filter or test that literally looks for $GPRMC will never see anything go by. Always reason in terms of GxRMC.
  • Taking NMEA time for a precision source. The sentence arrives over the serial link with a latency on the order of ±10 ms, non-deterministic (Hardware and wiring chapter). It serves only to say which second; the precision comes from the PPS. That is exactly why the corresponding source is declared noselect on the chrony side.
  • Ignoring the checksum. A sentence truncated or corrupted on the serial link has a wrong checksum; a consumer that doesn’t verify it may read a wrong time. gpsd performs this check, but any home-grown parsing must redo it.

Verify#

# Raw NMEA stream: RMC and GGA sentences should scroll by, once per
# second. The talker ID (GN, GP...) depends on the receiver.
gpspipe -r -n 20 | grep -E '(RMC|GGA)'

# Isolate the RMC validity status (3rd comma-column): expect A
gpspipe -r -n 20 | grep -m1 'RMC' | cut -d, -f3
# A = valid fix, V = no usable fix

# Number of satellites used, read from the GGA sentence (8th comma-column)
gpspipe -r -n 20 | grep -m1 'GGA' | cut -d, -f8

As long as the GxRMC status stays V, the receiver has no usable fix yet (antenna obstructed, or a cold start in progress): chronyd will not discipline the clock, per lock GPS.


📚 Going further

  • The sentence format is defined by the NMEA 0183 standard (Standard for Interfacing Marine Electronic Devices), National Marine Electronics Association. The standard is paywalled, but the subset of common GNSS sentences (RMC, GGA, GSA, GSV, ZDA) is abundantly documented in receiver manuals and in the gpsd documentation.
  • The exact list of sentences gpsd recognizes, field by field, is kept up to date in its gpsd_json man page and in the gpsd project’s NMEA.txt file.
  • Related chapters: GNSS constellations (how the receiver obtains time), GNSS/PPS acquisition (setting up gpsd), Chrony (consuming the sentence via refclock SHM).