Lokaler Tracker funktionsfähig. Bugfixes.
This commit is contained in:
parent
f0ebdd0201
commit
e7a96390f2
9
TODO
9
TODO
|
@ -5,7 +5,14 @@ Aufgaben, Planungs- und Ideenliste
|
|||
python3-paho-mqtt benötigt
|
||||
b) lokal
|
||||
c) Server
|
||||
|
||||
|
||||
- Internationalisierung
|
||||
1. EN (Standardsprache)
|
||||
2. DE
|
||||
3. FR
|
||||
4. ES
|
||||
5. IT
|
||||
|
||||
- Satelliten: SatelliteList verwenden und dieses auch in
|
||||
nmea2000 implementieren
|
||||
- Satellitenübersicht / SkyView
|
||||
|
|
14
obp60v.py
14
obp60v.py
|
@ -115,7 +115,7 @@ import pages
|
|||
|
||||
__author__ = "Thomas Hooge"
|
||||
__copyright__ = "Copyleft 2024-2025, all rights reversed"
|
||||
__version__ = "0.2"
|
||||
__version__ = "0.3"
|
||||
__email__ = "thomas@hoogi.de"
|
||||
__status__ = "Development"
|
||||
|
||||
|
@ -128,7 +128,7 @@ cfg = {
|
|||
'loglevel': 3,
|
||||
'imgpath': os.path.join(sys.path[0], 'images'),
|
||||
'audiopath': os.path.join(sys.path[0], 'audio'),
|
||||
'histpath' = '~/.local/lib/obp60v',
|
||||
'histpath': '~/.local/lib/obp60v',
|
||||
'deviceid': 100,
|
||||
'manufcode': 2046, # Open Boat Projects (OBP)
|
||||
'devfunc': 120, # Display
|
||||
|
@ -749,6 +749,7 @@ if __name__ == "__main__":
|
|||
cfg['tracker']['mqtt_pass'] = config.get('tracker', 'mqtt_pass')
|
||||
cfg['tracker']['logdir'] = cfg['logdir']
|
||||
cfg['tracker']['trace'] = config.getboolean('tracker', 'trace')
|
||||
cfg['tracker']['interval'] = config.getint('tracker', 'interval')
|
||||
|
||||
# Boat data
|
||||
cfg['boat']['name'] = config.get('boat', 'name')
|
||||
|
@ -806,14 +807,15 @@ if __name__ == "__main__":
|
|||
log.info("Networking enabled")
|
||||
t_rxd_net = threading.Thread(target=rxd_network, args=(cfg['net_port'],cfg['net_addr']))
|
||||
t_rxd_net.start()
|
||||
if cfg['tracker']['type'] == 'NONE':
|
||||
if cfg['tracker']['type'] != 'NONE':
|
||||
log.info(f"Tracking enabled, mode {cfg['tracker']['type']}")
|
||||
#appdata.track.set_type( cfg['tracker']['type'])
|
||||
if cfg['tracker']['type'] == 'HERO':
|
||||
t_tracker = threading.Thread(target=appdata.track.mqtt_tracker, args=(cfg['tracker'],cfg['boat'],appdata,boatdata))
|
||||
elif cfg['tracker']['type'] IN ['LOCAL', 'SDCARD']:
|
||||
t_tracker = threading.Thread(target=appdata.track.local_tracker, args=(cfg['tracker'],cfg['boat'],appdata,boatdata))
|
||||
t_tracker.start()
|
||||
t_tracker.start()
|
||||
elif cfg['tracker']['type'] in ['LOCAL', 'SDCARD']:
|
||||
t_tracker = threading.Thread(target=appdata.track.local_tracker, args=(cfg,appdata,boatdata))
|
||||
t_tracker.start()
|
||||
if not cfg['simulation']:
|
||||
if cfg['bme280']:
|
||||
log.info("Environment sensor enabled")
|
||||
|
|
|
@ -45,7 +45,10 @@ class Barograph(Page):
|
|||
# Meßwert alle 15 Minuten:
|
||||
# 84 Stunden * 4 Werte je Stunde = 336 Meßwerte
|
||||
self.bd = boatdata
|
||||
self.source = 'I' # (I)ntern, e(X)tern
|
||||
if not cfg['bme280']:
|
||||
self.source = None # keine Datenquelle!
|
||||
else:
|
||||
self.source = 'I' # (I)ntern, e(X)tern, None=Disabled
|
||||
self.zoom = (1, 2, 3, 6, 12)
|
||||
self.zoomindex = 4
|
||||
self.series = (75, 150, 300, 600, 900)
|
||||
|
@ -65,6 +68,7 @@ class Barograph(Page):
|
|||
self.buttonlabel[2] = '-'
|
||||
self.buttonlabel[5] = 'SRC'
|
||||
|
||||
self.data = None
|
||||
self.refresh = time.time() - 30
|
||||
|
||||
def handle_key(self, buttonid):
|
||||
|
@ -113,6 +117,9 @@ class Barograph(Page):
|
|||
Transfer data from history to page buffer
|
||||
set y-axis according to data
|
||||
"""
|
||||
if self.source == None:
|
||||
# TODO hier muß noch Arbeit reingesteckt werden!
|
||||
return False
|
||||
self.data = []
|
||||
self.vmin = 9999
|
||||
self.vmax = 0
|
||||
|
@ -363,8 +370,13 @@ class Barograph(Page):
|
|||
ctx.stroke()
|
||||
|
||||
# Meßdaten
|
||||
for v in self.data:
|
||||
x0 -= 1
|
||||
if v > 0:
|
||||
ctx.rectangle(x0, y0 - (v - ysmin) * dy, 1.5, 1.5)
|
||||
ctx.fill()
|
||||
if self.data:
|
||||
for v in self.data:
|
||||
x0 -= 1
|
||||
if v > 0:
|
||||
ctx.rectangle(x0, y0 - (v - ysmin) * dy, 1.5, 1.5)
|
||||
ctx.fill()
|
||||
else:
|
||||
# Keine Daten vorhanden!
|
||||
# TODO iregndwas nettes anzeigen
|
||||
pass
|
||||
|
|
|
@ -33,14 +33,16 @@ class RaceTracker(Page):
|
|||
self.bv_lat = boatdata.getRef("LAT")
|
||||
self.bv_lon = boatdata.getRef("LON")
|
||||
self.bv_sog = boatdata.getRef("SOG")
|
||||
self.bv_hdop = boatdata.getRef("HDOP")
|
||||
self.races = None
|
||||
self.raceid = None
|
||||
if self.ttype == 'HERO':
|
||||
self.raceid = self.app.track.hero_raceid # Ausgewählte Regatta
|
||||
self.buttonlabel[1] = 'MODE'
|
||||
self.buttonlabel[2] = 'INFO'
|
||||
self.buttonlabel[5] = 'ABORT'
|
||||
else:
|
||||
self.raceid = None
|
||||
elif self.ttype in ('LOCAL','SDCARD'):
|
||||
self.buttonlabel[5] = 'ON'
|
||||
self.menupos = 0
|
||||
self.mode = 'N' # (N)ormal, (C)onfiguration, (M)itteilung
|
||||
self.query_active = False
|
||||
|
@ -92,6 +94,8 @@ class RaceTracker(Page):
|
|||
self.buttonlabel = self.savebuttons.copy()
|
||||
return True
|
||||
if buttonid == 1:
|
||||
if not self.ttype == 'HERO':
|
||||
return False
|
||||
# Modus umschalten
|
||||
if self.mode == 'N':
|
||||
self.mode = 'C'
|
||||
|
@ -110,6 +114,8 @@ class RaceTracker(Page):
|
|||
self.buttonlabel[5] = 'ABORT'
|
||||
return True
|
||||
elif buttonid == 2:
|
||||
if not self.ttype == 'HERO':
|
||||
return False
|
||||
if self.mode == 'N':
|
||||
self.mode = 'M' # Nachrichten der Wettfahrtleitung
|
||||
self.buttonlabel[2] = ''
|
||||
|
@ -140,15 +146,26 @@ class RaceTracker(Page):
|
|||
return True
|
||||
elif buttonid == 5:
|
||||
if self.mode == 'N':
|
||||
self.query_active = True;
|
||||
self.savebuttons = self.buttonlabel.copy()
|
||||
self.buttonlabel[1] = ""
|
||||
self.buttonlabel[2] = "YES"
|
||||
self.buttonlabel[3] = ""
|
||||
self.buttonlabel[4] = ""
|
||||
self.buttonlabel[5] = "NO"
|
||||
self.buttonlabel[6] = ""
|
||||
# Taste 2 = JA, Taste 5 = NEIN
|
||||
if self.ttype in ('LOCAL','SDCARD'):
|
||||
# Tracking ein/-ausschalten
|
||||
if self.app.track.is_active():
|
||||
self.app.track.set_active(False)
|
||||
self.buttonlabel[5] = 'ON'
|
||||
else:
|
||||
self.app.track.set_active(True)
|
||||
self.buttonlabel[5] = 'OFF'
|
||||
else:
|
||||
if self.ttype == ('HERO'):
|
||||
# Rennabbruch verarbeiten
|
||||
self.query_active = True;
|
||||
self.savebuttons = self.buttonlabel.copy()
|
||||
self.buttonlabel[1] = ""
|
||||
self.buttonlabel[2] = "YES"
|
||||
self.buttonlabel[3] = ""
|
||||
self.buttonlabel[4] = ""
|
||||
self.buttonlabel[5] = "NO"
|
||||
self.buttonlabel[6] = ""
|
||||
# Taste 2 = JA, Taste 5 = NEIN
|
||||
elif self.mode == 'C':
|
||||
# Tracking ein/-ausschalten
|
||||
if self.app.track.is_active():
|
||||
|
@ -180,16 +197,22 @@ class RaceTracker(Page):
|
|||
ctx.set_font_size(16)
|
||||
ctx.move_to(x, y)
|
||||
ctx.show_text("Disabled by 'NONE in configuration'.")
|
||||
y += 40
|
||||
y += 30
|
||||
ctx.move_to(x, y)
|
||||
ctx.show_text("Currently only tracker type 'HERO' is")
|
||||
ctx.show_text("Currently only tracker types 'HERO' and 'LOCAL'")
|
||||
y += 20
|
||||
ctx.move_to(x, y)
|
||||
ctx.show_text("implemented. Please visit the Regatta")
|
||||
ctx.show_text("are implemented.")
|
||||
y += 30
|
||||
ctx.move_to(x, y)
|
||||
ctx.show_text("'LOCAL' tracks positions in file system.")
|
||||
y += 30
|
||||
ctx.move_to(x, y)
|
||||
ctx.show_text("For 'HERO' pleast visit the Regatta Hero")
|
||||
y += 20
|
||||
ctx.move_to(x, y)
|
||||
ctx.show_text("Hero web page for detailed description.")
|
||||
y += 40
|
||||
ctx.show_text("web page for detailed description.")
|
||||
y += 20
|
||||
ctx.move_to(x, y)
|
||||
ctx.show_text("Additionally you should contact your local")
|
||||
y += 20
|
||||
|
@ -198,19 +221,61 @@ class RaceTracker(Page):
|
|||
|
||||
def draw_local(self, ctx):
|
||||
x = 8
|
||||
x1 = 130
|
||||
y = 50
|
||||
ctx.select_font_face("Ubuntu", cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD)
|
||||
ctx.set_font_size(24)
|
||||
ctx.move_to(x, y)
|
||||
ctx.show_text("Local Tracking")
|
||||
|
||||
ctx.select_font_face("Ubuntu", cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD)
|
||||
ctx.set_font_size(16)
|
||||
|
||||
y += 30
|
||||
ctx.move_to(x, y)
|
||||
ctx.show_text("Activated: ")
|
||||
ctx.show_text("Yes" if self.app.track.is_active() else "No")
|
||||
y += 20
|
||||
ctx.move_to(x, y)
|
||||
ctx.show_text(f"Log interval: {self.app.track.local_dt} seconds")
|
||||
#ctx.show_text(str(self.app.track.local_dt))
|
||||
y += 20
|
||||
ctx.move_to(x, y)
|
||||
ctx.show_text("Log entries written: ")
|
||||
ctx.show_text(str(self.app.track.local_lfdno))
|
||||
|
||||
# Anzeige
|
||||
# - LAT, LON
|
||||
# - bisher gespeicherte Anzahl Positionen
|
||||
# - Zeitabstand zwischen den einzelnen Messungen
|
||||
# - Hinweis wo gespeichert wird
|
||||
y += 30
|
||||
ctx.move_to(x, y)
|
||||
ctx.show_text("Latitude: ")
|
||||
ctx.move_to(x1, y)
|
||||
ctx.show_text(self.bv_lat.format())
|
||||
y += 20
|
||||
ctx.move_to(x, y)
|
||||
ctx.show_text("Longitude: ")
|
||||
ctx.move_to(x1, y)
|
||||
ctx.show_text(self.bv_lon.format())
|
||||
y += 20
|
||||
ctx.move_to(x, y)
|
||||
ctx.show_text("HDOP: ")
|
||||
ctx.move_to(x1, y)
|
||||
ctx.show_text(self.bv_hdop.format() or '---')
|
||||
y += 20
|
||||
ctx.move_to(x, y)
|
||||
ctx.show_text("Speed: ")
|
||||
ctx.move_to(x1, y)
|
||||
ctx.show_text(self.bv_sog.format())
|
||||
|
||||
def draw_normal(self, ctx):
|
||||
def draw_hero(self, ctx):
|
||||
"""
|
||||
Regatta Hero Normalansicht
|
||||
TODO
|
||||
racephase anzeige zu Debuggingzwecken
|
||||
"""
|
||||
|
||||
ctx.select_font_face("DSEG7 Classic")
|
||||
ctx.set_font_size(80)
|
||||
|
@ -448,10 +513,12 @@ class RaceTracker(Page):
|
|||
|
||||
def draw(self, ctx):
|
||||
if self.mode == 'N':
|
||||
if self.ttype == 'NONE':
|
||||
self.draw_none(ctx)
|
||||
if self.ttype in ('LOCAL', 'SDCARD'):
|
||||
self.draw_local(ctx)
|
||||
elif self.ttype == 'HERO':
|
||||
self.draw_hero(ctx)
|
||||
else:
|
||||
self.draw_normal(ctx)
|
||||
self.draw_none(ctx)
|
||||
elif self.mode == 'C':
|
||||
self.draw_config(ctx)
|
||||
else:
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
"""
|
||||
Wind / Windlupe
|
||||
|
||||
TODO
|
||||
- Windlupe:
|
||||
Wenn der Wind achterlich kommt, dann andere Ansicht / Skala verwenden
|
||||
|
||||
"""
|
||||
import os
|
||||
import cairo
|
||||
import math
|
||||
|
|
32
tracker.py
32
tracker.py
|
@ -48,6 +48,9 @@ class Tracker():
|
|||
raise TypeError("Invalid tracker type: '{}'. Only supported: {}".format(cfg['tracker']['type'], ','.join(validtypes)))
|
||||
self.ttype = cfg['tracker']['type']
|
||||
|
||||
self.local_lfdno = 0
|
||||
self.local_dt = cfg['tracker']['interval'] # Eintrag alle <n> Sekunden schreiben
|
||||
|
||||
self.trace = cfg['tracker']['trace'] # Debugging
|
||||
self.trace_fh = None # File Handle der Tracedatei
|
||||
|
||||
|
@ -127,9 +130,11 @@ class Tracker():
|
|||
def set_active(self, newval):
|
||||
self.activated = newval
|
||||
|
||||
def local_tracker(self, cfg, boat, appdata, boatdata):
|
||||
# TODO / WIP
|
||||
def local_tracker(self, cfg, appdata, boatdata):
|
||||
self.log.info("Local tracker enabled")
|
||||
if not os.path.exists(cfg['histpath']):
|
||||
os.makedirs(cfg['histpath'])
|
||||
self.log.info(f"History path created: '{cfg['histpath']}'")
|
||||
|
||||
# Zugriff auf Boatdata: Referenzen für leichten schnellen Zugriff
|
||||
bv_lat = boatdata.getRef("LAT")
|
||||
|
@ -137,20 +142,25 @@ class Tracker():
|
|||
bv_hdop = boatdata.getRef("HDOP")
|
||||
bv_tspos = boatdata.getRef("TSPOS")
|
||||
|
||||
self.local_dt = 15
|
||||
self.local_lfdno = 0
|
||||
trackerfile = "/tmp/test.log" # TODO Konfiguration lesen
|
||||
trackerfile = os.path.join(cfg['histpath'], "localtrack.log")
|
||||
fh = open(trackerfile, 'a+')
|
||||
n = 0
|
||||
while not appdata.shutdown:
|
||||
time.sleep(self.local_dt)
|
||||
time.sleep(1)
|
||||
if not self.activated:
|
||||
continue
|
||||
n += 1
|
||||
if n % self.local_dt != 0:
|
||||
continue
|
||||
self.local_lfdno += 1
|
||||
data = f"{},{},{},{}\n".format(
|
||||
data = "{},{}Z,{},{},{}\n".format(
|
||||
self.local_lfdno,
|
||||
bv_tspos.getValueRaw(),
|
||||
bv_lat.getValueRaw(),
|
||||
bv_lon.getValueRaw(),
|
||||
bv_hdop.getValueRaw())
|
||||
bv_tspos.getValue(),
|
||||
bv_lat.getValue(),
|
||||
bv_lon.getValue(),
|
||||
bv_hdop.getValue())
|
||||
fh.write(data)
|
||||
fh.flush()
|
||||
fh.close()
|
||||
|
||||
def set_hero_raceid(self, newraceid):
|
||||
|
|
Loading…
Reference in New Issue