Tide: Anzeige erster Testdaten
This commit is contained in:
parent
e9d473fd10
commit
e7a2f4bb54
|
@ -4,6 +4,7 @@ Generische Applikationsdaten
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from web import WebInterface
|
||||||
from tracker import Tracker
|
from tracker import Tracker
|
||||||
from navtex import NAVTEX
|
from navtex import NAVTEX
|
||||||
|
|
||||||
|
@ -14,6 +15,13 @@ class AppData():
|
||||||
self.log = logger
|
self.log = logger
|
||||||
if cfg['navtex']:
|
if cfg['navtex']:
|
||||||
self.navtex = NAVTEX(logger, cfg)
|
self.navtex = NAVTEX(logger, cfg)
|
||||||
|
else:
|
||||||
|
self.navtex = None
|
||||||
|
if cfg['tide']:
|
||||||
|
self.web = WebInterface(logger, cfg)
|
||||||
|
self.web.refresh()
|
||||||
|
else:
|
||||||
|
self.web = None
|
||||||
self.track = Tracker(logger, cfg)
|
self.track = Tracker(logger, cfg)
|
||||||
self.frontend = None
|
self.frontend = None
|
||||||
self.bv_lat = None
|
self.bv_lat = None
|
||||||
|
|
|
@ -26,6 +26,9 @@ B2: Subject indicator character
|
||||||
Y Special services — allocation by IMO NAVTEX Panel
|
Y Special services — allocation by IMO NAVTEX Panel
|
||||||
Z No message on hand
|
Z No message on hand
|
||||||
|
|
||||||
|
Für Konfiguration: subjects = ABCDEFGHIJKLTVWXYZ
|
||||||
|
|
||||||
|
|
||||||
B3, B4: Serial number 01-99, 00: immediate printout
|
B3, B4: Serial number 01-99, 00: immediate printout
|
||||||
|
|
||||||
Timecode: DDHHmm UTC MMM YY
|
Timecode: DDHHmm UTC MMM YY
|
||||||
|
@ -38,6 +41,7 @@ Sqlite database schema
|
||||||
content TEXT
|
content TEXT
|
||||||
received TEXT
|
received TEXT
|
||||||
|
|
||||||
|
siehe auch: https://www.icselectronics.co.uk/support/info/navtexdb
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import http.client
|
import http.client
|
||||||
|
|
|
@ -36,6 +36,8 @@ port = /dev/ttyACM0
|
||||||
[navtex]
|
[navtex]
|
||||||
enabled = false
|
enabled = false
|
||||||
source = net
|
source = net
|
||||||
|
navarea = I
|
||||||
|
subjects = ABDEFKLXYZ
|
||||||
housekeeping = 72
|
housekeeping = 72
|
||||||
refresh = 30
|
refresh = 30
|
||||||
|
|
||||||
|
|
18
obp60v.py
18
obp60v.py
|
@ -6,7 +6,7 @@ Virtuelles Multifunktionsgerät OBP60v
|
||||||
Zwei Displayvarianten
|
Zwei Displayvarianten
|
||||||
1. Fliegendes OBP60 auf großem Bildschirm. 400x300 Display
|
1. Fliegendes OBP60 auf großem Bildschirm. 400x300 Display
|
||||||
2. Fullscreen Display skaliert mit 1,6 ergibt 640x480
|
2. Fullscreen Display skaliert mit 1,6 ergibt 640x480
|
||||||
mit Platz für große Touch-Flächen am rechten Rand
|
mit Platz für große Touch-Flächen (160px) am rechten Rand
|
||||||
|
|
||||||
Das Gerät kann Daten von NMEA2000 und NMEA0183 empfangen, sowie von
|
Das Gerät kann Daten von NMEA2000 und NMEA0183 empfangen, sowie von
|
||||||
einem lokal angeschlossenen GPS-Empfänger.
|
einem lokal angeschlossenen GPS-Empfänger.
|
||||||
|
@ -141,6 +141,7 @@ cfg = {
|
||||||
'gps': False,
|
'gps': False,
|
||||||
'bme280': False,
|
'bme280': False,
|
||||||
'tracker': { 'type': 'NONE' },
|
'tracker': { 'type': 'NONE' },
|
||||||
|
'tide': False,
|
||||||
'boat': { }
|
'boat': { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -798,13 +799,21 @@ if __name__ == "__main__":
|
||||||
config.write(fh)
|
config.write(fh)
|
||||||
log.info("Created new boat UUID: {}".format(cfg['boat']['uuid']))
|
log.info("Created new boat UUID: {}".format(cfg['boat']['uuid']))
|
||||||
|
|
||||||
# Globale Daten, u.a. auch Shutdown-Indikator
|
|
||||||
appdata = AppData(log, cfg)
|
|
||||||
|
|
||||||
# Ggf. Simulationsdaten einschalten
|
# Ggf. Simulationsdaten einschalten
|
||||||
if cfg['simulation']:
|
if cfg['simulation']:
|
||||||
boatdata.enableSimulation()
|
boatdata.enableSimulation()
|
||||||
|
|
||||||
|
# Tide wird aktiviert wenn mindestens eine Tidenseite angezeigt wird
|
||||||
|
for s in config.sections():
|
||||||
|
if s == 'pages':
|
||||||
|
continue
|
||||||
|
if s.startswith('page'):
|
||||||
|
if config.get(s, "type") == 'Tide':
|
||||||
|
cfg['tide'] = True
|
||||||
|
|
||||||
|
# Globale Daten, u.a. auch Shutdown-Indikator
|
||||||
|
appdata = AppData(log, cfg)
|
||||||
|
|
||||||
# Gerät initialisieren u.a. mit den genutzten Seiten
|
# Gerät initialisieren u.a. mit den genutzten Seiten
|
||||||
profile = init_profile(config, cfg, boatdata)
|
profile = init_profile(config, cfg, boatdata)
|
||||||
|
|
||||||
|
@ -834,6 +843,7 @@ if __name__ == "__main__":
|
||||||
elif cfg['tracker']['type'] in ['LOCAL', 'SDCARD']:
|
elif cfg['tracker']['type'] in ['LOCAL', 'SDCARD']:
|
||||||
t_tracker = threading.Thread(target=appdata.track.local_tracker, args=(cfg,appdata,boatdata))
|
t_tracker = threading.Thread(target=appdata.track.local_tracker, args=(cfg,appdata,boatdata))
|
||||||
t_tracker.start()
|
t_tracker.start()
|
||||||
|
|
||||||
if not cfg['simulation']:
|
if not cfg['simulation']:
|
||||||
if cfg['bme280']:
|
if cfg['bme280']:
|
||||||
log.info("Environment sensor enabled")
|
log.info("Environment sensor enabled")
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
NAVTEX
|
Tide Vorausschau
|
||||||
- Meldungen anzeigen
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import cairo
|
import cairo
|
||||||
|
@ -25,6 +24,9 @@ class Tide(Page):
|
||||||
ctx.set_font_size(16)
|
ctx.set_font_size(16)
|
||||||
ctx.set_line_width(2)
|
ctx.set_line_width(2)
|
||||||
|
|
||||||
|
ctx.move_to(220, 40)
|
||||||
|
ctx.show_text("Schulau, Elbe")
|
||||||
|
|
||||||
x0 = 40 # links unten
|
x0 = 40 # links unten
|
||||||
y0 = 250
|
y0 = 250
|
||||||
x1 = 380 # rechts oben
|
x1 = 380 # rechts oben
|
||||||
|
@ -48,3 +50,28 @@ class Tide(Page):
|
||||||
self.draw_text_center(ctx, x0 + (x1 - x0) / 2, y0 + 12, "Zeit, h")
|
self.draw_text_center(ctx, x0 + (x1 - x0) / 2, y0 + 12, "Zeit, h")
|
||||||
ctx.stroke()
|
ctx.stroke()
|
||||||
|
|
||||||
|
ymin, ymax = self.app.web.get_tide_minmax()
|
||||||
|
rawdata = self.app.web.get_tide()
|
||||||
|
|
||||||
|
ctx.move_to(x0 - 32, y0 + 8)
|
||||||
|
ctx.show_text(str(ymin))
|
||||||
|
|
||||||
|
ctx.move_to(x0 - 32, y1 + 8)
|
||||||
|
ctx.show_text(str(ymax))
|
||||||
|
|
||||||
|
ctx.move_to(x0 + 16, y0 + 16)
|
||||||
|
ctx.show_text(f"n = {len(rawdata)}")
|
||||||
|
|
||||||
|
dx = (x1 - x0) / len(rawdata)
|
||||||
|
x = x0
|
||||||
|
while rawdata[0][0] is None:
|
||||||
|
x += dx
|
||||||
|
del rawdata[0]
|
||||||
|
y = (rawdata[0][0] - ymin) / (ymax - ymin) * (y0 - y1)
|
||||||
|
ctx.move_to(x, y0 - (rawdata[0][0] - ymin))
|
||||||
|
del rawdata[0]
|
||||||
|
x += dx
|
||||||
|
for val in rawdata:
|
||||||
|
y = (val[0] - ymin) / (ymax - ymin) * (y0 - y1)
|
||||||
|
ctx.line_to(x, y0 - y)
|
||||||
|
x += dx
|
||||||
|
|
50
web.py
50
web.py
|
@ -1,7 +1,7 @@
|
||||||
"""
|
"""
|
||||||
Web Interface
|
Web Interface
|
||||||
|
|
||||||
Regelmäßiges Abfragen von Daten im Internet
|
Regelmäßiges Abfragen von Daten aus dem Internet
|
||||||
- NAVTEX
|
- NAVTEX
|
||||||
- DWD
|
- DWD
|
||||||
- Pegelstände
|
- Pegelstände
|
||||||
|
@ -13,7 +13,7 @@ Regelmäßiges Abfragen von Daten im Internet
|
||||||
import os
|
import os
|
||||||
import http.client
|
import http.client
|
||||||
import ssl
|
import ssl
|
||||||
import re
|
import json
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import datetime
|
import datetime
|
||||||
from gi.repository import GLib
|
from gi.repository import GLib
|
||||||
|
@ -35,7 +35,14 @@ class WebInterface():
|
||||||
if self.cur.fetchone() == None:
|
if self.cur.fetchone() == None:
|
||||||
sql = ("CREATE TABLE IF NOT EXISTS station ("
|
sql = ("CREATE TABLE IF NOT EXISTS station ("
|
||||||
"uuid TEXT PRIMARY KEY NOT NULL,"
|
"uuid TEXT PRIMARY KEY NOT NULL,"
|
||||||
"name TEXT"
|
"name TEXT)"
|
||||||
|
)
|
||||||
|
self.cur.execute(sql)
|
||||||
|
sql = ("CREATE TABLE IF NOT EXISTS data ("
|
||||||
|
"timestamp TEXT PRIMARY KEY NOT NULL,"
|
||||||
|
"astro NUMBER NOT NULL,"
|
||||||
|
"forecast NUMBER,"
|
||||||
|
"measurement NUMBER)"
|
||||||
)
|
)
|
||||||
self.cur.execute(sql)
|
self.cur.execute(sql)
|
||||||
self.log.info(f"Created tide database: {dbpath}")
|
self.log.info(f"Created tide database: {dbpath}")
|
||||||
|
@ -44,6 +51,7 @@ class WebInterface():
|
||||||
#GLib.timeout_add_seconds(cfg['tide_refresh'] * 60, self.on_timer)
|
#GLib.timeout_add_seconds(cfg['tide_refresh'] * 60, self.on_timer)
|
||||||
GLib.timeout_add_seconds(60 * 60, self.on_timer)
|
GLib.timeout_add_seconds(60 * 60, self.on_timer)
|
||||||
self.running = True
|
self.running = True
|
||||||
|
self.log.info(f"Web interface started")
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.conn.close()
|
self.conn.close()
|
||||||
|
@ -62,7 +70,7 @@ class WebInterface():
|
||||||
"""
|
"""
|
||||||
if local:
|
if local:
|
||||||
# Für Tests um nicht permanent die Webseite abzufragen
|
# Für Tests um nicht permanent die Webseite abzufragen
|
||||||
with open("DE__714P.json", "r") as fh:
|
with open("/tmp/DE__714P.json", "r") as fh:
|
||||||
content = fh.read()
|
content = fh.read()
|
||||||
else:
|
else:
|
||||||
ssl_context = ssl.create_default_context()
|
ssl_context = ssl.create_default_context()
|
||||||
|
@ -88,18 +96,26 @@ class WebInterface():
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
self.log.info("Data refresh")
|
self.log.info("Data refresh")
|
||||||
data = self.bsh_get_data(True)
|
data = self.bsh_get_data(False)
|
||||||
"""
|
#tmpfile = open("/tmp/DE__714P.json", "w")
|
||||||
sql = "INSERT INTO message (msgid, station, content) VALUES (?, ?, ?)"
|
#tmpfile.write(data)
|
||||||
for m in messages:
|
#tmpfile.close()
|
||||||
msg = self.parse_message(m)
|
wvdata = json.loads(data)
|
||||||
self.cur.execute("SELECT COUNT(*) FROM message WHERE msgid=?", (msg['id'],))
|
sql = "INSERT OR REPLACE INTO data (timestamp, astro, forecast, measurement) VALUES (?, ?, ?, ?)"
|
||||||
result = self.cur.fetchone()
|
for wv in wvdata["curve_forecast"]["data"]:
|
||||||
if result[0] == 0:
|
self.cur.execute(sql, (wv['timestamp'], wv['astro'], wv['curveforecast'], wv['measurement']))
|
||||||
self.log.debug(f"NAVTEX: insert new message '{msg['id']}'")
|
self.conn.commit()
|
||||||
self.cur.execute(sql, (msg['id'], msg['station'], m))
|
|
||||||
self.conn.commit()
|
|
||||||
"""
|
|
||||||
|
|
||||||
def housekeeping(self):
|
def housekeeping(self):
|
||||||
self.log.info("Housekeeping")
|
self.log.info("Housekeeping")
|
||||||
|
|
||||||
|
def get_tide(self):
|
||||||
|
# 12 Stunden
|
||||||
|
sql = "select forecast from data where timestamp > '2025-10-05 12:00' and timestamp < '2025-10-06 22:00'"
|
||||||
|
self.cur.execute(sql)
|
||||||
|
return self.cur.fetchall()
|
||||||
|
|
||||||
|
def get_tide_minmax(self):
|
||||||
|
sql = "select min(forecast), max(forecast) from data where timestamp > '2025-10-05 12:00' and timestamp < '2025-10-06 22:00'"
|
||||||
|
self.cur.execute(sql)
|
||||||
|
return self.cur.fetchone()
|
||||||
|
|
Loading…
Reference in New Issue