Discovery: alle Geraete finden und stabil ablegen

Ein Lauf mit allen Modulen brachte 54 Geraete und 441 Messwerte - und fuenf
Fehler ans Licht, die vorher niemand sehen konnte, weil clear_tables die
Tabellen bei jedem Lauf geleert hat.

Vier davon sind Schluessel- und Upsert-Fehler derselben Familie:

 * command_parameters war ueber (command_id, url) eindeutig. WLED-Parameter
   haben keine URL - ihr Name ist der Platzhalter in der Kommando-Vorlage -,
   und eine NULL kollidiert in MySQL nie. ON DUPLICATE KEY UPDATE griff
   also nicht, und jeder Lauf legte dieselben Parameter erneut an: aus 18
   wurden nach drei Laeufen 54. Schluessel jetzt (command_id,
   parameter_name).

 * actor_states war ueber (actor_id, url) eindeutig. Umgekehrtes Problem:
   Messwerte, die sich ein Topic teilen, ueberschrieben einander. Der
   go-eCharger schickt sechzehn Werte als JSON-Feld auf einem Topic - von
   denen kam genau einer in der Datenbank an. Schluessel jetzt (actor_id,
   state_name), das bringt 50 verlorene Messwerte zurueck.

 * Kommandos, Messwerte und Parameter aktualisierten ihre URL beim
   Wiederholungslauf nicht - sie stand nicht im UPDATE-Teil. Eine Korrektur
   in einem Modul kam damit nie in einer bestehenden Datenbank an.

 * Der Typ eines Kommando-Parameters wurde als Text in eine int-Spalte
   geschrieben. MariaDB macht daraus stillschweigend 0, und 0 ist "bool" -
   deshalb bot der Editor fuer die WLED-Helligkeit (0..255) ein Ja/Nein an.

Der fuenfte: die Shelly-Gen1-Relais hatten weder eine Kommando-URL noch eine
URL am Zustand. Ohne die weiss niemand, was zu schicken und wo nachzusehen
ist. Gen1 schaltet ueber ?turn=on|off|toggle und meldet sich in "ison".

Damit entfaellt auch die Uebersetzungstabelle im HTTPTransport: die
Zuordnung gehoert ins Geraetemodell, nicht in den Runner.

Zwei Luecken auf der Runner-Seite, die derselbe Lauf gezeigt hat:

 * WLED liess sich gar nicht ansteuern - es gab keinen Transport dafuer.
   Der neue nutzt die JSON-Vorlage aus command_url, fuellt die Platzhalter
   und schickt sie am Stueck an /json/state.

 * Tahoma wurde am Schema "io://" erkannt. Das Schema beschreibt aber die
   Funkart: dieselbe Box liefert rts:// fuer die Dachfenster und
   internal:// fuer die Alarmanlage. Drei von 22 Geraeten fielen durch.
   Erkannt wird jetzt an der Box-Kennung in der URL.

Nachgemessen: zwei Laeufe hintereinander aendern keine einzige Zeile mehr,
die Geraete-IDs bleiben ueber Laeufe stabil (Voraussetzung fuer die
Fremdschluessel der Automatiken), alle 54 Geraete finden genau einen
Transport, und 440 der 441 Messwerte sind tatsaechlich lesbar.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-31 14:57:29 +02:00
co-authored by Claude Opus 5
parent 0cb1fc635e
commit 631baa7333
6 changed files with 180 additions and 46 deletions
+18 -10
View File
@@ -114,19 +114,27 @@ Fenster gar nichts gelaufen ist — dann ist auch keine Sperre aktiv.
Welcher Weg zum Gerät führt, entscheidet die URL des Aktors in `actors`:
| URL | Messwert (`actor_states.url`) | Kommando |
|-------------|-------------------------------|-------------------------------------|
| `mqtt://…` | vollständiges Topic, abonniert | publiziert auf das Parameter-Topic |
| `http://…` | Feldname in der JSON-Antwort, gepollt | Parameter als Abfrageargumente |
| `io://…` | Tahoma-Statusname, gepollt | `exec/apply` an die Tahoma-Box |
| `Logic` | gerechnet: Uhrzeit, Datum, Sonne | |
| URL | Messwert (`actor_states.url`) | Kommando (`actor_commands.command_url`) |
|---|---|---|
| `mqtt://…` | vollständiges Topic, abonniert | Nutzlast auf das Parameter-Topic |
| `http://…` | Feldname in der JSON-Antwort, gepollt | Abfrageargumente an die Geräte-URL (`turn=on`) |
| `wled://…` | Pfad in `/json/state` (`seg[0].col[0]`), gepollt | JSON-Vorlage mit Platzhaltern, als Ganzes gesendet |
| Tahoma | Statusname (`core:ClosureState`), gepollt | `exec/apply` an die Box |
| `Logic` | gerechnet: Uhrzeit, Datum, Sonne | |
Alle vier stehen in `transports.py`. Eine fünfte Geräteart kommt als weitere
Alle fünf stehen in `transports.py`. Eine sechste Geräteart kommt als weitere
Klasse dazu; sie braucht `passt()`, `zustaende_lesen()` und `senden()`.
Bei HTTP heißen die Schaltbefehle nicht so wie in der Datenbank — dafür gibt es
in `HTTPTransport` eine kleine Übersetzungstabelle (`turn_on``on=true`).
Das ist die Stelle, die beim Anschluss neuer HTTP-Geräte wächst.
Tahoma ist der einzige, der nicht am URL-Schema erkannt wird, sondern an der
**Box-Kennung** in der URL. Das Schema beschreibt dort die Funkart, und
dieselbe Box liefert `io://` für die Jalousien, `rts://` für die Dachfenster
und `internal://` für die Alarmanlage. Ohne `pin` in der `config.ini` ist
niemand zuständig — dann meldet der Runner beim Auslösen „kein Transport",
statt still nichts zu tun.
Bei WLED trägt die Kommando-Vorlage alles: `{"seg":[{"col":[[%red%,%green%,%blue%]]}]}`
wird mit den Parameterwerten gefüllt und am Stück geschickt. Deshalb haben die
Parameter dort keine eigene URL — ihr Name *ist* der Platzhalter.
## Voraussetzungen