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:
@@ -167,8 +167,12 @@ mpremote repl
|
||||
>>> run_esp32.main() # ohne Helligkeitsregelung
|
||||
>>> run_esp32.main(with_ldr=True) # mit LDR über den ADC
|
||||
>>> run_esp32.main(with_mqtt=False) # ohne MQTT (sonst an, sofern konfiguriert)
|
||||
>>> run_esp32.main(host="192.168.1.115") # feste Adresse, statt der eingestellten
|
||||
```
|
||||
|
||||
Ohne `host` gilt die per MQTT gesetzte Adresse aus `settings.json`, sonst
|
||||
`config.MOUNT_HOST` (siehe *Zwischen Mock und Montierung umschalten*).
|
||||
|
||||
### Dauerbetrieb: Autostart und Watchdog
|
||||
|
||||
`main.py` startet die Anzeige nach jedem Reset von selbst — nach Stromausfall
|
||||
@@ -301,6 +305,8 @@ Mac:
|
||||
- **Netzwerk zur echten Montierung.** Die GM4000 steht in `192.168.1.115`, das
|
||||
Heimnetz des ESP32 ist `192.168.178.x` — der Mac erreicht sie per VPN, der
|
||||
ESP32 so nicht. Muss geklärt werden, bevor es an die echte Montierung geht.
|
||||
Das *Umschalten* zwischen Mock und Montierung ist dagegen erledigt: Es geht
|
||||
über MQTT (`set/mount_host`, siehe dort), ohne Deployen und ohne Neustart.
|
||||
|
||||
## Gradzeichen
|
||||
|
||||
@@ -442,21 +448,25 @@ dazwischen fälschlich dunkel und wachte erst später auf.
|
||||
|
||||
### Die Werte stehen in `settings.json`, nicht im Code
|
||||
|
||||
`config.py` ist Programmcode und ändert sich nur beim Deployen. Die Helligkeiten
|
||||
und die Schwelle sollen dagegen im Betrieb verstellbar sein — **später über MQTT**.
|
||||
Sie liegen deshalb als JSON auf dem Gerät und werden über `settings.py` gelesen und
|
||||
geschrieben:
|
||||
`config.py` ist Programmcode und ändert sich nur beim Deployen. Die Helligkeiten,
|
||||
die Schwelle und die Adresse der Montierung sollen dagegen im Betrieb verstellbar
|
||||
sein — **über MQTT**. Sie liegen deshalb als JSON auf dem Gerät und werden über
|
||||
`settings.py` gelesen und geschrieben:
|
||||
|
||||
```python
|
||||
import settings
|
||||
settings.load() # mit Vorgaben aufgefüllt
|
||||
settings.update({"hell_prozent": 60}) # ändern und speichern
|
||||
settings.update({"mount_host": "192.168.1.115"}) # Montierung umstellen
|
||||
```
|
||||
|
||||
Ein laufender `BrightnessController` übernimmt Änderungen mit `reload()`.
|
||||
|
||||
Jeder Wert wird beim Laden **und** beim Schreiben geprüft (Typ und Bereich:
|
||||
Prozente 0–100, Schwelle 0–4095). Das ist der Grund, warum die Prüfung überhaupt
|
||||
Prozente 0–100, Schwelle 0–4095, `mount_host` nur Zeichen aus IP-Adressen und
|
||||
Hostnamen). Ob eine Einstellung Zahl oder Text ist, entscheidet der Typ ihrer
|
||||
Vorgabe in `settings.DEFAULTS` — so gibt es nur eine Stelle, an der eine neue
|
||||
Einstellung einzutragen ist. Das ist der Grund, warum die Prüfung überhaupt
|
||||
existiert: Sobald MQTT dazukommt, kommen die Werte von außen, und ein
|
||||
Helligkeitswert von 500 % oder eine Schwelle von −1 würde die Anzeige sonst
|
||||
unbrauchbar machen. Fehlt die Datei oder ist sie beschädigt, gelten die Vorgaben
|
||||
@@ -529,7 +539,7 @@ darauf hin und kopiert sie nicht.
|
||||
|
||||
### Topics
|
||||
|
||||
Empfangen (`<PREFIX>/set/<name>`, Nutzlast als Zahl):
|
||||
Empfangen (`<PREFIX>/set/<name>`):
|
||||
|
||||
| Topic | Beispiel | Wirkung |
|
||||
|---|---|---|
|
||||
@@ -537,6 +547,10 @@ Empfangen (`<PREFIX>/set/<name>`, Nutzlast als Zahl):
|
||||
| `grossanzeige/set/dunkel_prozent` | `5` | Helligkeit unter der Schwelle |
|
||||
| `grossanzeige/set/schwelle` | `1800` | Umschaltpunkt (LDR-Wert) |
|
||||
| `grossanzeige/set/hysterese` | `150` | Breite um den Umschaltpunkt |
|
||||
| `grossanzeige/set/mount_host` | `192.168.1.115` | Adresse der Montierung (leer = Vorgabe aus `config.py`) |
|
||||
|
||||
Alle Nutzlasten außer `mount_host` sind ganze Zahlen; `mount_host` ist Text
|
||||
(IP-Adresse oder Hostname).
|
||||
|
||||
Gesendet (`<PREFIX>/status/<name>`, alle *retained*):
|
||||
|
||||
@@ -546,6 +560,7 @@ Gesendet (`<PREFIX>/status/<name>`, alle *retained*):
|
||||
| `grossanzeige/status/dec` | `+38°47'01"` |
|
||||
| `grossanzeige/status/ldr` | `2453` |
|
||||
| `grossanzeige/status/helligkeit` | `50` |
|
||||
| `grossanzeige/status/mount_host` | `192.168.1.115` (Adresse, die gerade abgefragt wird) |
|
||||
| `grossanzeige/status/link` | `1` (Montierung erreichbar) |
|
||||
| `grossanzeige/status/online` | `1` — **Last Will** setzt es auf `0` |
|
||||
|
||||
@@ -566,6 +581,43 @@ raus — eine per MQTT gesetzte Helligkeit bliebe unsichtbar, solange die Stufe
|
||||
dieselbe bleibt. Das ist am Gerät aufgefallen (2026-07-27) und wird von
|
||||
`test_mqtt.py` (`TestHelligkeitWirdSofortSichtbar`) festgehalten.
|
||||
|
||||
### Zwischen Mock und Montierung umschalten (`mount_host`)
|
||||
|
||||
Welche Adresse abgefragt wird, ist im Betrieb umstellbar — ohne Deployen, ohne
|
||||
Neustart:
|
||||
|
||||
```bash
|
||||
mosquitto_pub -h <broker> -t grossanzeige/set/mount_host -m 192.168.1.115 # echte GM4000
|
||||
mosquitto_pub -h <broker> -t grossanzeige/set/mount_host -m 192.168.178.26 # Mock auf dem Mac
|
||||
mosquitto_pub -h <broker> -t grossanzeige/set/mount_host -m '' # zurück zu config.py
|
||||
```
|
||||
|
||||
Die Adresse landet in `settings.json` und **übersteht damit einen Stromausfall**:
|
||||
Nach dem Neustart fragt das Gerät dieselbe Adresse wieder ab. Welche gerade gilt,
|
||||
klärt `mount_client.resolve_host()` in dieser Reihenfolge:
|
||||
|
||||
1. eine beim Aufruf ausdrücklich genannte Adresse (`run_esp32.main(host=...)` an
|
||||
der REPL, `run_display.py --host` auf dem Mac),
|
||||
2. `mount_host` aus `settings.json` (das per MQTT Gesetzte),
|
||||
3. `config.MOUNT_HOST` — was beim Deployen im Code stand.
|
||||
|
||||
**Eine leere Nachricht ist der Weg zurück.** Ohne sie würde eine einmal gesetzte
|
||||
Adresse die Vorgabe aus `config.py` für immer verdecken, auch nach einem Deployen
|
||||
mit geändertem Code. Deshalb heißt „leer" hier nicht „keine Adresse", sondern
|
||||
„nimm die aus dem Code".
|
||||
|
||||
Wirksam wird die Umstellung sofort: Der Rückruf trägt die neue Adresse in den
|
||||
`MountClient` ein und **trennt die bestehende Verbindung** — neu verbunden wird im
|
||||
nächsten Durchlauf der Poll-Schleife, mit der gewohnten Fehlerbehandlung. Antwortet
|
||||
unter der neuen Adresse niemand, steht „KEIN LINK" auf der Anzeige, und eine weitere
|
||||
Nachricht holt das Gerät wieder zurück. Was gerade abgefragt wird, meldet
|
||||
`grossanzeige/status/mount_host` — die Rückmeldung kommt auch dann, wenn dort
|
||||
niemand antwortet.
|
||||
|
||||
Der Wert geht in `socket.getaddrinfo` und kommt von außen, deshalb prüft
|
||||
`settings.py` ihn eng: nur Buchstaben, Ziffern, Punkt und Bindestrich, höchstens
|
||||
63 Zeichen. Alles andere wird verworfen, `settings.json` bleibt unberührt.
|
||||
|
||||
### Was dabei schiefgehen kann, und warum es nichts ausmacht
|
||||
|
||||
**Grundsatz: MQTT darf die Anzeige nie aufhalten.** Die Anzeige ist der Zweck des
|
||||
|
||||
Reference in New Issue
Block a user