Weitere NMEA0183 Daten verarbeiten

This commit is contained in:
Thomas Hooge 2025-07-18 14:40:19 +02:00
parent 9e4622aeef
commit f7337a0c6c
3 changed files with 135 additions and 21 deletions

View File

@ -13,6 +13,23 @@ def DBT(boatdata, msg):
pass pass
#boatdata.setValue("DBT", msg.depth) #boatdata.setValue("DBT", msg.depth)
def GGA(boatdata, msg):
# Time, position, and fix related data
# msg.num_sats
# msg.timestamp
if msg.gps_qual == 0:
# No fix
return
if msg.lat_dir == 'N':
boatdata.setValue("LAT", msg.latitude)
else:
boatdata.setValue("LAT", msg.latitude * -1)
if msg.lon_dir == 'E':
boatdata.setValue("LON", msg.longitude)
else:
boatdata.setValue("LON", msg.longitude * -1)
boatdata.setValue("HDOP", msg.horizontal_dil)
def GLL(boatdata, msg): def GLL(boatdata, msg):
print("-> GLL") print("-> GLL")
boatdata.setValue("LAT", msg.latitude) boatdata.setValue("LAT", msg.latitude)
@ -22,11 +39,32 @@ def GSV(boatdata, msg):
# Satellites in view # Satellites in view
print("-> GSV") print("-> GSV")
def HDG(boatdata, msg):
# UNUSED: Heading - Deviation & Variation
# Magnetic Sensor heading in degrees
# msg.heading
# .deviation, dev_dir E/W
# .variation, var_dir E/W
pass
def HDM(boatdata, msg):
# Heading magnetic
if msg.magnetic == 'M':
boatdata.setValue("HDM", msg.heading)
else:
print("HDM: M not set!")
def HDT(boatdata, msg): def HDT(boatdata, msg):
# Heading True # Heading True
print("-> HDT") print("-> HDT")
print(msg.fields) print(msg.fields)
def HTD(boatdata, msg):
# Heading/Track control data
# e.g. $YDHTD,V,1.5,,R,N,,,,,,,,,A,,,*48
print("-> HTD")
print(msg.fields)
def MWV(boatdata, msg): def MWV(boatdata, msg):
# Windgeschwindigkeit und -winkel # Windgeschwindigkeit und -winkel
print(f"Wind: {msg.wind_angle}° {msg.wind_speed}kt") print(f"Wind: {msg.wind_angle}° {msg.wind_speed}kt")
@ -45,16 +83,37 @@ def RMB(boatdata, msg):
print("-> RMB") print("-> RMB")
def RMC(boatdata, msg): def RMC(boatdata, msg):
print("-> RMC") # Recommended Minimum Navigation Information
#boatdata.setValue("LAT", msg.lat) # print("-> RMC")
#boatdata.setValue("LON", msg.lon) # print(msg.timestamp, msg.datestamp)
# print(msg.status) # V=Warning, P=Precise, A=?
# mag_variation, mag_var_dir E/W
# true_course
if msg.lat_dir == 'N':
boatdata.setValue("LAT", msg.lat)
else:
boatdata.setValue("LAT", msg.lat) * -1
if msg.lon_dir == 'E':
boatdata.setValue("LON", msg.lon)
else:
boatdata.setValue("LON", msg.lon) * -1
boatdata.setValue("SOG", msg.spd_over_grnd)
def ROT(boatdata, msg):
# Rate Of Turn
# print("-> ROT")
if msg.status == 'A':
boatdata.setValue("ROT", msg.rate_of_turn)
def RSA(boatdata, msg): def RSA(boatdata, msg):
# Rudder Sensor Angle # Rudder Sensor Angle
# negative Werte bedeuten Backbord # negative Werte bedeuten Backbord
#print("-> RSA")
# Boatdata: RPOS primär, PRPOS sekundär # Boatdata: RPOS primär, PRPOS sekundär
print("-> RSA") if msg.rsa_starboard_status== 'A':
print(msg.fields) boatdata.setValue("RPOS", msg.rsa_starboard)
if msg.rsa_port_status == 'A':
boatdata.setValue("PRPOS", msg.rsa_port)
def RTE(boatdata, msg): def RTE(boatdata, msg):
# Route # Route
@ -65,9 +124,16 @@ def VBW(boatdata, msg):
print("-> VBW") print("-> VBW")
def VHW(boatdata, msg): def VHW(boatdata, msg):
print("-> VHW")
boatdata.setValue("STW", float(msg.water_speed_knots)) boatdata.setValue("STW", float(msg.water_speed_knots))
def VPW(boatdata, msg):
# UNUSED: Speed - Measured Parallel to Wind
# print(f"-> VPW: {msg.speed_kn} kn")
pass
def VTG(boatdata, msg): def VTG(boatdata, msg):
print("-> VTG")
boatdata.setValue("COG", int(msg.true_track)) boatdata.setValue("COG", int(msg.true_track))
#TODO klären was für Typen hier ankommen können #TODO klären was für Typen hier ankommen können
# bytearray, str, decimal.Decimal? # bytearray, str, decimal.Decimal?
@ -75,10 +141,40 @@ def VTG(boatdata, msg):
#str von OpenCPN: sog = float(msg.spd_over_grnd_kts[:-1]) #str von OpenCPN: sog = float(msg.spd_over_grnd_kts[:-1])
boatdata.setValue("SOG", sog) boatdata.setValue("SOG", sog)
def VWR(boatdata, msg):
# Relative Wind Speed and Angle
#print("-> VWR")
if msg.l_r == "R":
angle = msg.deg_r
else:
angle = 360 - msg.deg_r
boatdata.setValue("AWA", angle)
boatdata.setValue("AWS", msg.wind_speed_ms)
def WPL(boatdata, msg): def WPL(boatdata, msg):
print("-> WPL") print("-> WPL")
print(msg.fields) print(msg.fields)
def VWT(boatdata, msg):
# True Wind Speed and Angle
if msg.direction == "R":
angle = msg.wind_angle_vessel
else:
angle = 360 - msg.wind_angle_vessel
boatdata.setValue("TWA", angle)
boatdata.setValue("TWS", msg.wind_speed_meters)
def XDR(boatdata, msg):
# Extra sensor data / Transducer Measurement
# type, value, units, id
# type: A
# units: D
# id: Yaw
if msg.id.lower() == 'yaw':
boatdata.setValue("YAW", msg.value)
else:
print(f"-> XDR: {msg.type}, {msg.value}, {msg.units}, {msg.id}")
def XTE(boatdata, msg): def XTE(boatdata, msg):
# Cross Track error measured # Cross Track error measured
print("-> XTE") print("-> XTE")
@ -98,18 +194,27 @@ def ZDA(boatdata, msg):
decoder = { decoder = {
"DBS": DBS, "DBS": DBS,
"DBT": DBT, "DBT": DBT,
"GGA": GGA,
"GLL": GLL, "GLL": GLL,
"GSV": GSV, "GSV": GSV,
"HDG": HDG,
"HDM": HDM,
"HTD": HTD,
"MWV": MWV, "MWV": MWV,
"MTW": MTW, "MTW": MTW,
"RMB": RMB, "RMB": RMB,
"ROT": ROT,
"RMC": RMC, "RMC": RMC,
"RSA": RSA, "RSA": RSA,
"RTE": RTE, "RTE": RTE,
"VBW": VBW, "VBW": VBW,
"VHW": VHW, "VHW": VHW,
"VPW": VPW,
"VTG": VTG, "VTG": VTG,
"VWR": VWR,
"VWT": VWT,
"WPL": WPL, "WPL": WPL,
"XDR": XDR,
"XTE": XTE, "XTE": XTE,
"XTR": XTR, "XTR": XTR,
"ZDA": ZDA "ZDA": ZDA

View File

@ -210,7 +210,7 @@ def rxd_0183(devname):
try: try:
msg = pynmea2.parse(raw) msg = pynmea2.parse(raw)
except pynmea2.nmea.ParseError: except pynmea2.nmea.ParseError:
print(f"NMEA0183: Parse-Error: {raw}") print(f"NMEA0183: Parse-Error: {raw}", end='')
continue continue
# sentence_type kann fehlen # sentence_type kann fehlen
try: try:
@ -223,11 +223,16 @@ def rxd_0183(devname):
# if stype in stypefilter: # if stype in stypefilter:
# continue # continue
if stype in nmea0183.decoder: if stype in nmea0183.decoder:
nmea0183.decoder[stype(boatdata, msg)] nmea0183.decoder[stype](boatdata, msg)
else: else:
# Hier unbekannter Satztyp: protokollieren und ignorieren # Hier unbekannter Satztyp: protokollieren und ignorieren
print("Nicht implementiert") """
print(msg) ['checksum', 'data', 'fields', 'identifier', 'name_to_idx', 'parse',
'proprietary_re', 'query_re', 'render', 'sentence_re',
'sentence_type', 'sentence_types', 'talker', 'talker_re']
"""
print(f"Nicht implementiert: '{stype}' from {msg.talker}")
ser.close() ser.close()
def rxd_gps(devname, devspeed): def rxd_gps(devname, devspeed):
@ -608,7 +613,7 @@ def init_profile(config, cfg, boatdata):
cls = getattr(pages, p['type']) cls = getattr(pages, p['type'])
except AttributeError: except AttributeError:
# Klasse nicht vorhanden, Seite wird nicht benutzt # Klasse nicht vorhanden, Seite wird nicht benutzt
print(f"Klasse '{type}' nicht gefunden") print(f"Klasse '{p['type']}' nicht gefunden")
continue continue
c = cls(i, cfg, boatdata, *[v for v in p['values'].values()]) c = cls(i, cfg, boatdata, *[v for v in p['values'].values()])
clist[i] = c clist[i] = c

View File

@ -77,9 +77,9 @@ class Anchor(Page):
self.anchor_set = True self.anchor_set = True
else: else:
self.anchor_set = False self.anchor_set = False
if self.buttonid == 5: if buttonid == 5:
# Bei aktivem Alarm kann mit dieser Taste der Alarm zurückgesetzt # Bei aktivem Alarm kann mit dieser Taste der Alarm zurückgesetzt
# werden # werden. Die Tastenbeschriftung wechselt zwischen ALARM und OFF.
if self.alarm: if self.alarm:
self.alarm = False self.alarm = False
self.buttonlabel[5] = 'ALARM' self.buttonlabel[5] = 'ALARM'
@ -87,6 +87,7 @@ class Anchor(Page):
self.alarm_enabled = False self.alarm_enabled = False
self.buttonlabel[5] = 'ALARM' self.buttonlabel[5] = 'ALARM'
else: else:
self.alarm_enabled = True
self.buttonlabel[5] = 'OFF' self.buttonlabel[5] = 'OFF'
return False return False
@ -114,7 +115,11 @@ class Anchor(Page):
ctx.set_font_size(16) ctx.set_font_size(16)
ctx.move_to(2, 70) ctx.move_to(2, 70)
ctx.show_text("Alarm: off") ctx.show_text("Alarm: ")
if self.alarm_enabled:
ctx.show_text("On")
else:
ctx.show_text("Off")
ctx.move_to(320, 70) ctx.move_to(320, 70)
ctx.show_text(f"{self.chain} m") ctx.show_text(f"{self.chain} m")
ctx.stroke() ctx.stroke()
@ -138,10 +143,9 @@ class Anchor(Page):
# Windpfeil zeichnen # Windpfeil zeichnen
# TWD / TWS if self._bd.awa.value:
# boatdata.value(TWD)
p = ((cx, cy - r + 25), (cx - 12, cy - r - 4), (cx, cy - r + 6), (cx + 12, cy - r - 4), (cx, cy - r + 25)) p = ((cx, cy - r + 25), (cx - 12, cy - r - 4), (cx, cy - r + 6), (cx + 12, cy - r - 4), (cx, cy - r + 25))
wind = self.rotate((cx, cy), p, 62) wind = self.rotate((cx, cy), p, self._bd.awa.value)
ctx.move_to(*wind[0]) ctx.move_to(*wind[0])
for point in wind[1:]: for point in wind[1:]:
ctx.line_to(*point) ctx.line_to(*point)