Adresse der Montierung per MQTT umstellbar und gespeichert
Zwischen Mock und echter GM4000 umschalten, ohne zu deployen und ohne Neustart:
mosquitto_pub -t grossanzeige/set/mount_host -m 192.168.1.115
mosquitto_pub -t grossanzeige/set/mount_host -m 192.168.178.26
mosquitto_pub -t grossanzeige/set/mount_host -m ''
Die Adresse liegt in settings.json auf dem Geraet und uebersteht damit
Stromausfall und Watchdog-Neustart. deploy.sh kopiert die Datei bewusst nicht
mit, die Einstellung ueberlebt also auch ein Deployen.
**Leer heisst: config.MOUNT_HOST gilt.** mount_client.resolve_host loest auf in
der Reihenfolge: ausdruecklich mitgegebener Host (REPL, run_display --host) ->
mount_host aus settings.json -> config.MOUNT_HOST. Ohne diesen Rueckweg wuerde
eine einmal per MQTT gesetzte Adresse die Zeile in config.py fuer immer
verdecken, auch nach einem Deployen mit geaendertem Code.
Pruefung: settings._pruefe unterscheidet jetzt Zahl und Text am Typ der Vorgabe
in DEFAULTS -- eine neue Einstellung wird weiterhin an genau einer Stelle
eingetragen. Fuer mount_host sind nur Buchstaben, Ziffern, Punkt und
Bindestrich erlaubt, hoechstens 63 Zeichen: Der Wert geht ungeprueft in
socket.getaddrinfo, und von MQTT kommt alles Moegliche. Ungueltiges wird
verworfen, settings.json bleibt unberuehrt.
Sofort wirksam: Der Rueckruf traegt die neue Adresse in den MountClient ein und
trennt nur die bestehende Verbindung -- neu verbindet die Poll-Schleife im
naechsten Durchlauf, mit der gewohnten Fehlerbehandlung. Antwortet dort niemand,
steht "KEIN LINK", und eine weitere Nachricht holt das Geraet zurueck.
grossanzeige/status/mount_host meldet, welche Adresse gerade abgefragt wird --
die Rueckmeldung steht direkt hinter bridge.check() und nicht im Erfolgspfad,
kommt also auch dann, wenn die Montierung schweigt.
Der on_change-Rueckruf ist als run_esp32.make_on_change aus main() herausgeloest.
test_mqtt.py prueft ihn bisher als Abschrift ("Dieselbe Logik wie in
run_esp32.main"); jetzt laeuft der echte Code durch die Tests.
201 Tests gruen. Neu, unter anderem:
- TestUmschaltenImLaufendenBetrieb faehrt die ganze Kette an echten Sockets:
erst "KEIN LINK" an einer toten Adresse, nach dem set/mount_host die
Koordinaten vom Mock.
- TestAdresswahl (test_lx200) haelt die Reihenfolge von resolve_host fest.
- test_esp32: main() ohne host nimmt nach einem Neustart, was gespeichert ist.
Nicht angefasst: run_display.py auf dem Mac behaelt config.MOUNT_HOST als
Vorgabe fuer --host. Dort gibt es keine MQTT-Bruecke, und settings.json ist
Zustand des Geraets, nicht des Macs.
Am Geraet bestaetigt (2026-07-29), am Broker mitgeschnitten. Umschalten im
laufenden Betrieb, mit dem Mock auf dem Mac als Ausgangslage:
0.0s status/mount_host 192.168.178.26 Ausgangslage, link = 1
-> set/mount_host = 192.168.178.99
5.1s status/mount_host 192.168.178.99 Rueckmeldung
5.9s status/link 0 dort antwortet niemand
-> set/mount_host = ''
17.8s status/mount_host 192.168.178.26 Vorgabe aus config.py
18.6s status/link 1 Koordinaten laufen wieder
Und ueber den Neustart hinweg -- der eigentliche Zweck des Speicherns:
-> set/mount_host = 192.168.178.99
1.6s status/mount_host 192.168.178.99
settings.json auf dem Geraet:
{"hysterese": 150, "mount_host": "192.168.178.99", "schwelle": 1800, ...}
-> Hardware-Reset
8.6s status/online 0 Last Will
15.5s status/online 1 Autostart durch
15.5s status/mount_host 192.168.178.99 aus der Datei, nicht aus config.py
Die alte settings.json ohne mount_host wird beim Laden einfach um die Vorgabe
ergaenzt; die eingestellten Helligkeiten bleiben unberuehrt. Eine Migration war
nicht noetig.
set/mount_host wird ohne Retain-Flag geschickt: Das ist ein Befehl, kein
Zustand. Retained laege er im Broker und wuerde bei jedem Reconnect erneut
zugestellt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,11 +4,14 @@
|
||||
<PREFIX>/set/dunkel_prozent 5
|
||||
<PREFIX>/set/schwelle 1800
|
||||
<PREFIX>/set/hysterese 150
|
||||
<PREFIX>/set/mount_host 192.168.1.115 Adresse der Montierung; leer =
|
||||
Vorgabe aus config.MOUNT_HOST
|
||||
|
||||
<PREFIX>/status/ra 18h36m56s ausgehend
|
||||
<PREFIX>/status/dec +38°47'01"
|
||||
<PREFIX>/status/ldr 2453
|
||||
<PREFIX>/status/helligkeit 50
|
||||
<PREFIX>/status/mount_host 192.168.1.115 Adresse, die gerade abgefragt wird
|
||||
<PREFIX>/status/link 1 Montierung erreichbar
|
||||
<PREFIX>/status/online 1 retained, mit Last Will auf 0
|
||||
|
||||
@@ -149,11 +152,19 @@ class MqttBridge:
|
||||
if name not in SETZBAR:
|
||||
self._log("MQTT: unbekannte Einstellung %r verworfen" % name)
|
||||
return
|
||||
try:
|
||||
wert = int(roh)
|
||||
except ValueError:
|
||||
self._log("MQTT: %s=%r ist keine ganze Zahl" % (name, roh))
|
||||
return
|
||||
|
||||
# Zahl oder Text? Entscheidet der Typ der Vorgabe -- dieselbe Regel wie
|
||||
# in settings._pruefe. Eine leere Nachricht ist deshalb nur bei
|
||||
# Textwerten sinnvoll: mount_host faellt damit auf config.MOUNT_HOST
|
||||
# zurueck, waehrend int("") wie gehabt als Unsinn abgelehnt wird.
|
||||
if isinstance(settings.DEFAULTS[name], str):
|
||||
wert = roh
|
||||
else:
|
||||
try:
|
||||
wert = int(roh)
|
||||
except ValueError:
|
||||
self._log("MQTT: %s=%r ist keine ganze Zahl" % (name, roh))
|
||||
return
|
||||
|
||||
try:
|
||||
neu = settings.update({name: wert})
|
||||
@@ -161,7 +172,7 @@ class MqttBridge:
|
||||
self._log("MQTT: %s" % e)
|
||||
return
|
||||
|
||||
self._log("MQTT: %s = %d uebernommen" % (name, wert))
|
||||
self._log("MQTT: %s = %r uebernommen" % (name, wert))
|
||||
if self._on_change:
|
||||
try:
|
||||
self._on_change(neu)
|
||||
|
||||
Reference in New Issue
Block a user