NMEA 0183 Driver
Overview
An in-house Java implementation of NMEA 0183 v4.x, the standard ASCII protocol used in the marine / shipboard / GNSS domains. Based on the publicly available NMEA association spec, Wikipedia, and general manuals. No external libraries or copied GitHub code.
| Item | Value |
|---|---|
opc_type | NMEA |
| Implementation class | plantpulse.driver.protocol.nmea.NMEADriver |
| Library | (none — in-house implementation, NMEA 0183 v4) |
| read | Good (based on the receive cache) |
| write | ❌ (isWriteSupported() = false, receive-only) |
| Default port | 10110 (NMEA over IP de-facto) |
| Security | None |
The NMEA 0183 standard specifies RS-232/RS-422 serial (4800 / 38400 baud), but in actual operation it is common for a multiplexer/gateway to forward the data over TCP or UDP as NMEA over IP. This driver accepts the TCP variant.
Classes / structure
NMEADriver (BaseProtocolDriver)
├── Socket / BufferedReader (US-ASCII)
├── receiverThread — daemon, "NMEA-Receiver-<opc_id>"
├── lastByType — ConcurrentHashMap<sentenceType, parsed map>
├── readLine() — CR/LF 분리 + MAX_LINE_LEN(256) 가드
├── processLine(line) — '$' / checksum 검증 / talker 제거 / 필드 split
├── addAliases(type, fields) — RMC/GGA/GLL/VTG/GSA/GSV/HDT/HDM/MWV/DBT/DPT/MTW/VHW/ZDA/XDR
└── xorChecksum(payload) — '$' 와 '*' 사이 XOR
socket.setSoTimeout(0) — provided for serial emulation / low-speed equipment.
Wire format summary
$<talker><sentence>,f1,f2,...,fN*<CC><CR><LF>
예) $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A
- 2-character talker ID (GP/GL/GN/GA/HC/II/AI ...) + 3-character sentence type.
- A proprietary
Pprefix is used as the cache key as-is, without talker separation. *<CC>checksum = XOR of every char between$and*(2-digit uppercase hex).- Length limit is 82 characters (NMEA 0183 v4 standard); this implementation guards with
MAX_LINE_LEN=256.
Cache / read format
Messages that pass processLine() are stored in lastByType under the sentence type (e.g. RMC) key:
parsed = {
"__raw__": "$GPRMC,...",
"__type__": "RMC",
"1": "123519", // utc
"2": "A", // status
...
// alias
"utc": "123519",
"lat": "4807.038",
...
}
read("RMC.7") → field 7 (speed). read("RMC.lat") → alias.
OPC registration options
If options.nmea.port is present, it overrides the OPC opc_agent_port.
No connect-timeout / read-timeout options — CONNECT_TIMEOUT_MS = 5000, soTimeout = 0.
Tag address format
| Notation | Meaning |
|---|---|
RMC.7 | Field 7 of the RMC sentence |
GGA.2 | Field 2 of GGA (latitude) |
RMC.utc / RMC.lat / RMC.lon / RMC.speed | alias |
RMC | Raw string (no field index / alias specified) |
Supported sentences + aliases
Defined by addAliases():
| type | alias examples |
|---|---|
RMC | utc, status, lat, ns, lon, ew, speed, course, date, magvar, magvarew, mode |
GGA | utc, lat, ns, lon, ew, fix, sats, hdop, alt, altunit, geoidsep, sepunit, dgpsage, dgpsid |
GLL | lat, ns, lon, ew, utc, status, mode |
VTG | cogtrue, cogmag, speed, speedkn, speedkm, mode |
GSA | mode1, mode2, pdop, hdop, vdop |
GSV | totalmsgs, msgnum, satsinview |
HDT / HDM | heading, t / m |
MWV | angle, ref, speed, units, status |
DBT / DPT | depthft, depthm, depth, depthfa / depth, offset, max |
MTW | temp, units |
VHW | headingt, headingm, speed, speedkm |
ZDA | utc, day, month, year, tzh, tzm |
XDR | type, value, units, id (first group only) |
Undefined sentences can still be accessed by 1..N index.
Supported / not supported
- ✅ Checksum verification (
$~*XOR); lines are discarded on mismatch - ✅ Automatic talker ID removal (e.g.
GPRMC→RMC) - ✅ Aliases for the 16 most commonly used sentences
- ✅ Proprietary
$P...lines preserved as-is - ❌
!encapsulation (AIVDM and other AIS) — currently only$is accepted - ❌ Multi-message GSV accumulation
- ❌ write / sentence transmission
Test coverage
test/java/plantpulse/driver/protocol/nmea/
| Class | Test count |
|---|---|
NMEADriverTest | 15 |
NMEASpecTest | 22 |
37 tests in total — checksum, talker separation, alias mapping, index access, length limit.
References
- NMEA 0183 v4 standard (publicly available NMEA association items)
- Code:
src/plantpulse/driver/protocol/nmea/NMEADriver.java