Field Guide · term

Also known as: NMEA 0183, NMEA-0183, NMEA sentence

NMEA 0183 is the plain-text sentence format GPS receivers speak — a $, a five-character talker-and-type tag, comma-separated fields, and an optional trailing *hh checksum.1 It is not a radio protocol itself, but several trunked-radio GPS schemes (P25 Motorola Unit GPS, Tait CCDI, many MOTOTRBO GPS profiles) transport a verbatim NMEA sentence as their payload, so GopherTrunk parses it as the protocol-agnostic core that per-protocol decoders feed once they have extracted a GPS message’s text.2

$ GP RMC ,field,field,field,… * hh XOR every byte between $ and * → hh
An NMEA sentence is a dollar sign, a talker + type tag, comma-separated fields, and a trailing asterisk with a two-hex-digit checksum that is the XOR of every byte in between.

How it works

GopherTrunk’s ParseNMEA trims the sentence, requires the leading $, and — when a *hh suffix is present — verifies the checksum before parsing any fields. It then splits on commas and dispatches on the last three characters of the first field (the sentence type), ignoring the two-character talker ID so any of GP, GN, GL and friends are accepted. Only two sentence types carry a usable fix and are handled; anything else returns an “unsupported sentence” error rather than a wrong guess.

GGA and RMC

The two supported sentences place their coordinate fields at fixed positions:

Sentence Meaning Latitude field Longitude field Extra
GGA Fix data 2 (N/S in 3) 4 (E/W in 5)
RMC Recommended minimum 3 (N/S in 4) 5 (E/W in 6) status (2), speed (7), course (8)

RMC additionally carries a status letter — A for a valid fix, V for “void” — and GopherTrunk returns ErrNoFix on a void sentence. When present, RMC’s speed (knots) and course (degrees) fields are parsed into the position. A (0,0) result is treated as invalid: it is the overwhelmingly common “no fix yet” placeholder, and Null Island is open ocean.

Coordinate decoding and checksum

NMEA reports coordinates as ddmm.mmmm for latitude and dddmm.mmmm for longitude — degrees concatenated with decimal minutes — so nmeaDegrees splits off the leading degree digits (two for latitude, three for longitude) and adds minutes / 60, then applies the hemisphere letter as the sign. The checksum is deliberately trivial: the exclusive-OR of every byte of the sentence body, the text strictly between $ and *.

// nmeaChecksum XORs every byte of an NMEA sentence body (between '$' and '*').
func nmeaChecksum(body string) byte {
    var c byte
    for i := 0; i < len(body); i++ {
        c ^= body[i]
    }
    return c
}

That one-byte XOR is enough to catch the odd character corruption that a text-transport GPS link introduces, without the weight of a full cyclic redundancy check — appropriate for a format whose fields are already human-readable and self-delimiting.

Sources

  1. NMEA 0183 — Wikipedia, on the sentence structure, talker IDs, GGA/RMC content and the XOR checksum. 

  2. Global Positioning System — Wikipedia, on the GPS fixes NMEA sentences report. 

See also