NMEA0183 in eigenes Modul ausgelagert

This commit is contained in:
Thomas Hooge 2025-07-12 07:26:32 +02:00
parent b1fdb592b0
commit df04c9ad8e
4 changed files with 102 additions and 27 deletions

3
TODO
View File

@ -1,5 +1,8 @@
Aufgaben- und Planungs- und Ideenliste
- datareader für mehrere I²C-Sensoren. History muß entsprechend
eine Liste sein.
- Barograph
- Ankeralarm

69
nmea0183.py Normal file
View File

@ -0,0 +1,69 @@
"""
NMEA0183 verarbeiten
"""
def DBS(boatdata, msg):
# Wassertiefe unter der Oberfläche
pass
def DBT(boatdata, msg):
# Wassertiefe unter Geber
pass
def GLL(boatdata, msg):
print("-> GLL")
boatdata.setValue("LAT", msg.latitude)
boatdata.setValue("LON", msg.longitude)
def HDT(boatdata, msg):
# Heading True
print("-> HDT")
print(msg.fields)
def MWV(boatdata, msg):
# Windgeschwindigkeit und -winkel
print(f"Wind: {msg.wind_angle}° {msg.wind_speed}kt")
boatdata.setValue("AWA", msg.wind_angle)
boatdata.setValue("AWS", msg.wind_speed)
def RSA(boatdata, msg):
# Rudder Sensor Angle
# negative Werte bedeuten Backbord
# Boatdata: RPOS primär, PRPOS sekundär
print("-> RSA")
print(msg.fields)
def RTE(boatdata, msg):
# Route
print("-> RTE")
print(msg.fields)
def VHW(boatdata, msg):
boatdata.setValue("STW", float(msg.water_speed_knots))
def VTG(boatdata, msg):
boatdata.setValue("COG", int(msg.true_track))
#TODO klären was für Typen hier ankommen können
# bytearray, str, decimal.Decimal?
sog = float(msg.spd_over_grnd_kts)
#str von OpenCPN: sog = float(msg.spd_over_grnd_kts[:-1])
boatdata.setValue("SOG", sog)
def WPL(boatdata, msg):
print("-> WPL")
print(msg.fields)
# Aus Performancegründen eine direkte Sprungtabelle, ggf. können
# zukünftig außer der Funktion noch weitere Daten gespeichert werdeb
decoder = {
"DBS": DBS,
"DBT": DBT,
"GLL": GLL,
"MWV": MWV,
"RSA": RSA,
"RTE": RTE,
"VHW": VHW,
"VTG": VTG,
"WPL": WPL
}

View File

@ -102,6 +102,7 @@ import time
from datetime import datetime
from nmea2000 import Device, BoatData, History, HistoryBuffer
from nmea2000 import parser
import nmea0183
import pages
import struct
@ -203,8 +204,10 @@ def rxd_0183(devname):
return
setthreadtitle("0183listener")
while not shutdown:
raw = ser.readline().decode('ascii')
if len(raw) == 0:
continue
try:
raw = ser.readline().decode('ascii')
msg = pynmea2.parse(raw)
except pynmea2.nmea.ParseError:
print(f"NMEA0183: Parse-Error: {raw}")
@ -215,25 +218,15 @@ def rxd_0183(devname):
except:
print(f"NMEA0183: Sentence type missing: {raw}")
continue
if stype == 'GLL':
boatdata.setValue("LAT", msg.latitude)
boatdata.setValue("LON", msg.longitude)
elif stype == 'VTG':
boatdata.setValue("COG", int(msg.true_track))
#TODO klären was für Typen hier ankommen können
# bytearray, str, decimal.Decimal?
sog = float(msg.spd_over_grnd_kts)
#str von OpenCPN: sog = float(msg.spd_over_grnd_kts[:-1])
boatdata.setValue("SOG", sog)
elif stype == 'VHW':
boatdata.setValue("STW", float(msg.water_speed_knots))
elif stype == 'WPL':
# Wegepunkt
print(msg.fields)
elif stype == 'RTE':
# Route
print(msg.fields)
# WIP Neuer Code aus Modul
# TODO Filter mit gewünschen Satztypen
# if stype in stypefilter:
# continue
if stype in nmea0183.decoder:
nmea0183.decoder[stype(boatdata, msg)]
else:
# Hier unbekannter Satztyp: protokollieren und ignorieren
print("Nicht implementiert")
print(msg)
ser.close()
@ -258,7 +251,7 @@ def rxd_gps(devname, devspeed):
print(msg.fields)
ser.close()
def datareader(histpath, history):
def datareader(cfg, history):
"""
Daten zu fest definierten Zeitpunkten lesen
@ -272,9 +265,9 @@ def datareader(histpath, history):
setthreadtitle("datareader")
# Speicherpfad für Meßwertdaten
if not os.path.exists(histpath):
os.makedirs(histpath)
history.basepath = histpath
if not os.path.exists(cfg['histpath']):
os.makedirs(cfg['histpath'])
history.basepath = cfg['histpath']
# Serien initialisieren
history.addSeries("BMP280-75", 336 ,75)
history.addSeries("BMP280-150", 336 , 150)
@ -687,17 +680,23 @@ if __name__ == "__main__":
# Schnittstellen aktivieren
if cfg['can']:
print("CAN enabled")
t_rxd_n2k = threading.Thread(target=rxd_n2k, args=(cfg['can_intf'],))
t_rxd_n2k.start()
if cfg['nmea0183']:
print("NMEA0183 enabled")
t_rxd_0183 = threading.Thread(target=rxd_0183, args=(cfg['0183_port'],))
t_rxd_0183.start()
if cfg['gps']:
print("GPS enabled (local)")
t_rxd_gps = threading.Thread(target=rxd_gps, args=(cfg['gps_port'],))
t_rxd_gps.start()
if not cfg['simulation']:
t_data = threading.Thread(target=datareader, args=(cfg['histpath'], history))
t_data.start()
if cfg['bme280']:
t_data = threading.Thread(target=datareader, args=(cfg, history))
t_data.start()
else:
print("Simulation mode enabled")
app = Frontend(cfg, owndevice, boatdata, profile)
app.run()
@ -708,6 +707,6 @@ if __name__ == "__main__":
t_rxd_0183.join()
if cfg['gps']:
t_rxd_gps.join()
if not cfg['simulation']:
if not cfg['simulation'] and cfg['bme280']:
t_data.join()
print("Another fine product of the Sirius Cybernetics Corporation.")

View File

@ -28,6 +28,10 @@ Damit eine saubere Skala auf der Y-Achse erreicht wird, gibt einige
feste Skalierungen.
Standard: 20hPa von unten nach oben, z.B. 1015, 1020, 1025, 1030, 1035
TODO
- wenn keine Luftdruckdaten vorliegen, dann eine entsprechende
Meldung anzeigen
"""
import time