Zum Hauptinhalt springen

NMEA 0183 Treiber

Überblick

Eigene Java-Implementierung des ASCII-Standardprotokolls NMEA 0183 v4.x aus dem Bereich Marine / Schiffbau / GNSS. Basierend auf der öffentlichen Spezifikation der NMEA-Vereinigung, Wikipedia und allgemeinen Handbüchern. Keine externen Bibliotheken, kein kopierter GitHub-Code.

PunktWert
opc_typeNMEA
Implementierungsklasseplantpulse.driver.protocol.nmea.NMEADriver
Bibliothek(keine — Eigenimplementierung. NMEA 0183 v4)
readgut (basierend auf Empfangs-Cache)
write❌ (isWriteSupported() = false, nur Empfang)
Standardport10110 (NMEA over IP de facto)
Sicherheitkeine
Ursprüngliches Medium

Für NMEA 0183 ist RS-232/RS-422 seriell (4800 / 38400 Baud) der Standard, im realen Betrieb ist jedoch NMEA over IP üblich, bei dem Multiplexer/Gateways die Daten über TCP oder UDP weiterleiten. Dieser Treiber verarbeitet die TCP-Variante.


Klassen / Struktur

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) — für serielle Emulation / langsame Geräte.


Zusammenfassung des Wire-Formats

$<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
  • Talker ID 2 Zeichen (GP/GL/GN/GA/HC/II/AI ...) + Sentence Type 3 Zeichen.
  • Das proprietäre Präfix P wird ohne Talker-Abtrennung direkt als Cache-Key verwendet.
  • *<CC> Checksum = XOR aller Zeichen zwischen $ und * (2-stelliger Hex-Wert, Großbuchstaben).
  • Längenbegrenzung 82 Zeichen (Standard NMEA 0183 v4), diese Implementierung nutzt eine MAX_LINE_LEN=256-Guard.

Cache- / read-Format

Nachrichten, die processLine() passiert haben, werden unter dem Sentence Type (z. B. RMC) als Key in lastByType abgelegt:

parsed = {
"__raw__": "$GPRMC,...",
"__type__": "RMC",
"1": "123519", // utc
"2": "A", // status
...
// alias
"utc": "123519",
"lat": "4807.038",
...
}

read("RMC.7") → Feld 7 (speed). read("RMC.lat") → Alias.


OPC-Registrierungsoptionen

Ist options.nmea.port vorhanden, wird opc_agent_port des OPC überschrieben.

Keine Optionen connect-timeout / read-timeoutCONNECT_TIMEOUT_MS = 5000, soTimeout = 0.


Tag-Adressformat

NotationBedeutung
RMC.7Feld 7 des Sentence RMC
GGA.2Feld 2 von GGA (Breitengrad)
RMC.utc / RMC.lat / RMC.lon / RMC.speedAlias
RMCRoh-String (kein Feldindex / Alias angegeben)

Unterstützte Sentences + Alias

addAliases() definiert:

typeAlias-Beispiele
RMCutc, status, lat, ns, lon, ew, speed, course, date, magvar, magvarew, mode
GGAutc, lat, ns, lon, ew, fix, sats, hdop, alt, altunit, geoidsep, sepunit, dgpsage, dgpsid
GLLlat, ns, lon, ew, utc, status, mode
VTGcogtrue, cogmag, speed, speedkn, speedkm, mode
GSAmode1, mode2, pdop, hdop, vdop
GSVtotalmsgs, msgnum, satsinview
HDT / HDMheading, t / m
MWVangle, ref, speed, units, status
DBT / DPTdepthft, depthm, depth, depthfa / depth, offset, max
MTWtemp, units
VHWheadingt, headingm, speed, speedkm
ZDAutc, day, month, year, tzh, tzm
XDRtype, value, units, id (nur erste Gruppe)

Auch bei nicht definierten Sentences ist der Indexzugriff 1..N möglich.


Unterstützt / nicht unterstützt

  • ✅ Checksum-Prüfung (XOR von $ bis *), bei Abweichung wird die Zeile verworfen
  • ✅ Automatisches Entfernen der Talker ID (z. B. GPRMCRMC)
  • ✅ Aliase für 16 häufig verwendete Sentences
  • ✅ Proprietäre $P...-Zeilen bleiben unverändert erhalten
  • ! Encapsulation (AIVDM u. a. AIS) — derzeit wird nur $ verarbeitet
  • ❌ Akkumulation von Multi-Message-GSV
  • ❌ write / Sentence-Versand

Testabdeckung

test/java/plantpulse/driver/protocol/nmea/

KlasseAnzahl Tests
NMEADriverTest15
NMEASpecTest22

Insgesamt 37 Tests — Checksum, Talker-Abtrennung, Alias-Mapping, Indexzugriff, Längenbegrenzung.


Referenzen

  • Standard NMEA 0183 v4 (öffentliche Angaben der NMEA-Vereinigung)
  • Code: src/plantpulse/driver/protocol/nmea/NMEADriver.java