Audio, Erkennung Regattaende
This commit is contained in:
parent
adb1b4e63a
commit
fd5b2c96b9
|
@ -306,12 +306,18 @@ class RaceTracker(Page):
|
||||||
ctx.move_to(8, 260)
|
ctx.move_to(8, 260)
|
||||||
ctx.show_text(f"!!! Time drift of {self.app.track.hero_timedelta} seconds")
|
ctx.show_text(f"!!! Time drift of {self.app.track.hero_timedelta} seconds")
|
||||||
|
|
||||||
|
|
||||||
x0 = 8
|
x0 = 8
|
||||||
x1 = 96
|
x1 = 96
|
||||||
y0 = 150
|
y0 = 150
|
||||||
yoffset = 18
|
yoffset = 18
|
||||||
ctx.select_font_face("Ubuntu", cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD)
|
ctx.select_font_face("Ubuntu", cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD)
|
||||||
ctx.set_font_size(16)
|
ctx.set_font_size(16)
|
||||||
|
|
||||||
|
# Debug: Phase anzeigen
|
||||||
|
ctx.move_to(360, 35)
|
||||||
|
ctx.show_text(str(self.app.track.hero_racephase))
|
||||||
|
|
||||||
ctx.move_to(x0, y0)
|
ctx.move_to(x0, y0)
|
||||||
ctx.show_text("Type")
|
ctx.show_text("Type")
|
||||||
ctx.move_to(x1, y0)
|
ctx.move_to(x1, y0)
|
||||||
|
|
97
tracker.py
97
tracker.py
|
@ -98,11 +98,13 @@ class Tracker():
|
||||||
|
|
||||||
self.hero_raceid = None # Aktuell ausgewählte Regatta
|
self.hero_raceid = None # Aktuell ausgewählte Regatta
|
||||||
self.hero_racephase = 0 # Bei Änderung Event auslösen
|
self.hero_racephase = 0 # Bei Änderung Event auslösen
|
||||||
|
self.hero_shortened = False # Bahnverkürzung aktiv
|
||||||
|
|
||||||
# MQTT
|
# MQTT
|
||||||
self.client = mqtt.Client()
|
self.client = mqtt.Client()
|
||||||
self.client.on_connect = self.mqtt_on_connect
|
self.client.on_connect = self.mqtt_on_connect
|
||||||
self.client.on_message = self.mqtt_on_message
|
self.client.on_message = self.mqtt_on_message
|
||||||
|
self.client_race_age = 0 # Age of last mqtt race data in seconds
|
||||||
|
|
||||||
self.hero_orgstatus = None
|
self.hero_orgstatus = None
|
||||||
self.hero_racestatus = None
|
self.hero_racestatus = None
|
||||||
|
@ -251,21 +253,21 @@ class Tracker():
|
||||||
else:
|
else:
|
||||||
return math.degrees(2 * math.pi - azimut + math.pi * 3 / 2)
|
return math.degrees(2 * math.pi - azimut + math.pi * 3 / 2)
|
||||||
|
|
||||||
def hero_query_org(self):
|
def hero_query(self, raceid):
|
||||||
"""
|
"""
|
||||||
Abfrage des Datenservers / Basisdaten
|
Query Regatta Hero HTTP-Server
|
||||||
- Namen der Regatten und Kurse
|
|
||||||
"""
|
"""
|
||||||
ssl_context = ssl.create_default_context()
|
ssl_context = ssl.create_default_context()
|
||||||
conn = http.client.HTTPSConnection(self.hero_host, self.hero_port, context=ssl_context)
|
conn = http.client.HTTPSConnection(self.hero_host, self.hero_port, context=ssl_context)
|
||||||
endpoint = '/mapupdate'
|
endpoint = '/mapupdate'
|
||||||
payload = self.http_payload_template
|
payload = self.http_payload_template
|
||||||
payload['raceid'] = '[No race]'
|
payload['raceid'] = raceid
|
||||||
json_data = json.dumps(payload)
|
json_data = json.dumps(payload)
|
||||||
headers = {
|
headers = {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Content-Length': str(len(json_data))
|
'Content-Length': str(len(json_data))
|
||||||
}
|
}
|
||||||
|
data = {} # empty
|
||||||
try:
|
try:
|
||||||
conn.request("POST", endpoint, body=json_data, headers=headers)
|
conn.request("POST", endpoint, body=json_data, headers=headers)
|
||||||
response = conn.getresponse()
|
response = conn.getresponse()
|
||||||
|
@ -274,13 +276,21 @@ class Tracker():
|
||||||
data = json.loads(response.read().decode())
|
data = json.loads(response.read().decode())
|
||||||
else:
|
else:
|
||||||
self.log.warning(f"HTTP: Failed to retrieve data. Status code: {response.status}")
|
self.log.warning(f"HTTP: Failed to retrieve data. Status code: {response.status}")
|
||||||
return
|
return data
|
||||||
except http.client.HTTPException as e:
|
except http.client.HTTPException as e:
|
||||||
self.log.warning(f"HTTP error occurred: {e}")
|
self.log.warning(f"HTTP error occurred: {e}")
|
||||||
except ssl.SSLError as ssl_error:
|
except ssl.SSLError as ssl_error:
|
||||||
self.log.warning(f"SSL error occurred: {ssl_error}")
|
self.log.warning(f"SSL error occurred: {ssl_error}")
|
||||||
finally:
|
finally:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
return data
|
||||||
|
|
||||||
|
def hero_query_org(self):
|
||||||
|
"""
|
||||||
|
Abfrage des Datenservers / Basisdaten
|
||||||
|
- Namen der Regatten und Kurse
|
||||||
|
"""
|
||||||
|
data = self.hero_query('[No race]')
|
||||||
self.viewerpass = data['org']['viewerPasscode']
|
self.viewerpass = data['org']['viewerPasscode']
|
||||||
self.courses = []
|
self.courses = []
|
||||||
for c in data['org']['courses']:
|
for c in data['org']['courses']:
|
||||||
|
@ -294,32 +304,10 @@ class Tracker():
|
||||||
self.hero_raceid = self.races[0]
|
self.hero_raceid = self.races[0]
|
||||||
|
|
||||||
def hero_query_course(self, raceid):
|
def hero_query_course(self, raceid):
|
||||||
# Bojen und Kurs für ein gegebenes Rennen
|
"""
|
||||||
ssl_context = ssl.create_default_context()
|
Bojen und Kurs für ein gegebenes Rennen
|
||||||
endpoint = '/mapupdate'
|
"""
|
||||||
conn = http.client.HTTPSConnection(self.hero_host, self.hero_port, context=ssl_context)
|
data = self.hero_query(raceid)
|
||||||
payload = self.http_payload_template
|
|
||||||
payload['raceid'] = raceid
|
|
||||||
json_data = json.dumps(payload)
|
|
||||||
headers = {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Content-Length': str(len(json_data))
|
|
||||||
}
|
|
||||||
try:
|
|
||||||
conn.request("POST", endpoint, body=json_data, headers=headers)
|
|
||||||
response = conn.getresponse()
|
|
||||||
if response.status == 200:
|
|
||||||
self.log.info("HTTP: Response received successfully!")
|
|
||||||
data = json.loads(response.read().decode())
|
|
||||||
else:
|
|
||||||
self.log.warning(f"HTTP: Failed to retrieve data. Status code: {response.status}")
|
|
||||||
return
|
|
||||||
except http.client.HTTPException as e:
|
|
||||||
self.log.warning(f"HTTP error occurred: {e}")
|
|
||||||
except ssl.SSLError as ssl_error:
|
|
||||||
self.log.warning(f"SSL error occurred: {ssl_error}")
|
|
||||||
finally:
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
print(self.hero_orgdata)
|
print(self.hero_orgdata)
|
||||||
|
|
||||||
|
@ -334,6 +322,23 @@ class Tracker():
|
||||||
print(self.buoys)
|
print(self.buoys)
|
||||||
|
|
||||||
# Kurse
|
# Kurse
|
||||||
|
self.courses = []
|
||||||
|
for c in data['org']['courses']:
|
||||||
|
self.courses.append(c)
|
||||||
|
self.races = []
|
||||||
|
for r in data['org']['races'].values():
|
||||||
|
if not r['hiderace']:
|
||||||
|
self.races.append(r['raceid'])
|
||||||
|
|
||||||
|
def hero_query_race(self, raceid):
|
||||||
|
"""
|
||||||
|
Aktuelle Regattadaten vom HTTP-Server holen, ggf. weil MQTT nichts mehr sendet
|
||||||
|
"""
|
||||||
|
data = self.hero_query(raceid)
|
||||||
|
self.hero_racestatus = data['race']['racestatus']
|
||||||
|
print(self.hero_racestatus)
|
||||||
|
# 'raceactive': False
|
||||||
|
# 'racefinished': True
|
||||||
|
|
||||||
def get_position(self):
|
def get_position(self):
|
||||||
# Positionsabfrage für die Payload
|
# Positionsabfrage für die Payload
|
||||||
|
@ -407,6 +412,7 @@ class Tracker():
|
||||||
elif msg.topic.startswith(f"regattahero/racestatus/{self.hero_orgid}"):
|
elif msg.topic.startswith(f"regattahero/racestatus/{self.hero_orgid}"):
|
||||||
# kommt alle 1s
|
# kommt alle 1s
|
||||||
# dem Topic angehängt ist noch die raceid
|
# dem Topic angehängt ist noch die raceid
|
||||||
|
self.client_race_age = 0
|
||||||
payload = json.loads(msg.payload)
|
payload = json.loads(msg.payload)
|
||||||
self.hero_racestatus = payload['racestatus']
|
self.hero_racestatus = payload['racestatus']
|
||||||
racephase = payload['racestatus']['racephase']
|
racephase = payload['racestatus']['racephase']
|
||||||
|
@ -431,9 +437,11 @@ class Tracker():
|
||||||
elif self.hero_racephase == 2:
|
elif self.hero_racephase == 2:
|
||||||
if racephase == 3:
|
if racephase == 3:
|
||||||
self.hero_play_audio('vierMin')
|
self.hero_play_audio('vierMin')
|
||||||
|
elif racephase == 4:
|
||||||
|
self.hero_play_audio('dreiMin')
|
||||||
elif self.hero_racephase == 3:
|
elif self.hero_racephase == 3:
|
||||||
if racephase == 4:
|
if racephase == 4:
|
||||||
pass
|
self.hero_play_audio('dreiMin')
|
||||||
if racephase == 1:
|
if racephase == 1:
|
||||||
self.hero_play_audio('startVerschiebung')
|
self.hero_play_audio('startVerschiebung')
|
||||||
|
|
||||||
|
@ -449,6 +457,9 @@ class Tracker():
|
||||||
elif racephase == 6:
|
elif racephase == 6:
|
||||||
# Blauer Peter runter
|
# Blauer Peter runter
|
||||||
pass
|
pass
|
||||||
|
elif self.hero_racephase == 6:
|
||||||
|
if racephase == 1:
|
||||||
|
self.hero_play_audio('startVerschiebung')
|
||||||
elif self.hero_racephase == 7:
|
elif self.hero_racephase == 7:
|
||||||
if racephase == 8:
|
if racephase == 8:
|
||||||
# Gestartet
|
# Gestartet
|
||||||
|
@ -457,8 +468,10 @@ class Tracker():
|
||||||
if racephase == 2:
|
if racephase == 2:
|
||||||
if payload['racestatus']['recallgeneral']:
|
if payload['racestatus']['recallgeneral']:
|
||||||
self.hero_play_audio('allgmRueck')
|
self.hero_play_audio('allgmRueck')
|
||||||
else:
|
elif payload['racestatus']['racecancelled']:
|
||||||
self.hero_play_audio('abbruch')
|
self.hero_play_audio('abbruch')
|
||||||
|
elif payload['racestatus']['racefinished']:
|
||||||
|
self.hero_play_audio('endeWettfahrt')
|
||||||
self.hero_racephase = racephase
|
self.hero_racephase = racephase
|
||||||
|
|
||||||
# TODO Einzelrückruf, keine Änderung in der Phase!
|
# TODO Einzelrückruf, keine Änderung in der Phase!
|
||||||
|
@ -482,6 +495,13 @@ class Tracker():
|
||||||
|
|
||||||
# payload['racestatus']['racestarted']
|
# payload['racestatus']['racestarted']
|
||||||
# payload['racesettings']
|
# payload['racesettings']
|
||||||
|
|
||||||
|
# Bahnverkürzung
|
||||||
|
if payload['racestatus']['shortend'] and not self.hero_shortened:
|
||||||
|
self.hero_shortened = True
|
||||||
|
self.hero_play_audio('bahnVerk')
|
||||||
|
self.log.info("Bahnverkürzung: Zu Bahnmarke {}".format(payload['racestatus']['shortendsel']))
|
||||||
|
|
||||||
"""
|
"""
|
||||||
time: negativ: Zeit vor dem Start, positiv: Zeit nach dem Start
|
time: negativ: Zeit vor dem Start, positiv: Zeit nach dem Start
|
||||||
in Sekunden
|
in Sekunden
|
||||||
|
@ -579,8 +599,19 @@ class Tracker():
|
||||||
self.client.loop_start()
|
self.client.loop_start()
|
||||||
while not appdata.shutdown:
|
while not appdata.shutdown:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
self.client_race_age += 1
|
||||||
if self.activated and self.hero_raceid is not None:
|
if self.activated and self.hero_raceid is not None:
|
||||||
self.mqtt_publish(topic, payload, bv_lat, bv_lon, bv_sog)
|
self.mqtt_publish(topic, payload, bv_lat, bv_lon, bv_sog)
|
||||||
|
if self.client_race_age > 15:
|
||||||
|
# Server sendet keine Daten mehr oder Verbindung verloren
|
||||||
|
# TODO Frage den http-Server nach den letzten Racestatus
|
||||||
|
self.log.warning(f"Keine Daten vom MQTT-Sever seit ca. {self.client_race_age} Sekunden")
|
||||||
|
self.log.warning("Hole Daten vom HTTP-Server")
|
||||||
|
self.hero_query_race(self.hero_raceid)
|
||||||
|
if self.hero_racestatus['racefinished'] == True:
|
||||||
|
self.hero_racephase = 0
|
||||||
|
self.hero_play_audio('endeWettfahrt')
|
||||||
|
self.activated = False
|
||||||
self.client.loop_stop()
|
self.client.loop_stop()
|
||||||
self.client.disconnect()
|
self.client.disconnect()
|
||||||
if cfg['trace']:
|
if cfg['trace']:
|
||||||
|
|
Loading…
Reference in New Issue