Weitere NMEA0183 Daten verarbeiten
This commit is contained in:
parent
9e4622aeef
commit
f7337a0c6c
115
nmea0183.py
115
nmea0183.py
|
@ -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
|
||||||
|
|
15
obp60v.py
15
obp60v.py
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue