Die Seite speichert eine Automatik, indem sie deren Bedingungen loescht und
neu einfuegt. Wer nur die Uhrzeit verstellt, aendert damit weder die
Zeilenzahl noch automations.changed - ON UPDATE greift nur, wenn sich in
automations wirklich eine Spalte aendert, und Name, Stockwerk und Fenster
stehen ja noch genauso da. Der Runner prueft aber genau daran, ob er sein
Regelwerk neu laden muss, und lief deshalb bis zum naechsten Neustart mit
der alten Uhrzeit weiter.
Aufgefallen ist es an einer Automatik, die auf 18:16 gestellt war und um
18:24 ausloeste - zur Zeit, die vor der Aenderung dort stand.
changed wird jetzt ausdruecklich mitgeschrieben. Der Runner bekommt
zusaetzlich einen Fingerabdruck ueber den Inhalt, damit er nicht darauf
angewiesen ist, dass die Oberflaeche mitdenkt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Pfade in commands.php und homeMesh_automations.sql zeigten noch ins
Web-Verzeichnis. Dazu die Beschreibung der Zeit-Operatoren im Kopf von
automations.php: "um 16:30" gilt jetzt ab dieser Minute und noch
catchup_minutes lang, damit ein Neustart oder ein langsamer Durchlauf den
Termin nicht mehr verschluckt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Das Modal zeigte jedes Kommando so, wie es in der Datenbank steht: eine
Jalousie kam mit acht Rohbefehlen daher, darunter "Winken", die Farbe einer
Lampe als drei Zahlenfelder 0-255, ein Stromzaehler als abgeschnittene
Textzeile. Die Solltemperatur stand doppelt da - einmal als Schieberegler,
einmal als Zahlenfeld der Thermostat-Karte.
Jetzt entscheidet restricted/roomControls.php, welches Geraet welches
Bedienelement bekommt, und zwar an seinen Faehigkeiten statt am Typnamen:
hat es ein "setClosure"? ein An/Aus-Paar? drei Parameter rot/gruen/blau?
Damit bekommt auch ein neu gefundenes Geraet sein passendes Element, ohne
dass jemand einen Typnamen nachtraegt.
Beschattung Auf/Stop/Zu, darunter Position und Neigung als Schieber
auf dem zuletzt gemeldeten Stand; "Winken" und
"my-Position" im Mehr-Menue
Licht Kippschalter, Helligkeit, Farbwaehler des Browsers,
Effekt und Preset als Auswahl
Schalten ein Kippschalter statt dreier Knoepfe
Messwerte Wertegitter, die sechs wichtigsten sichtbar - beim
Wasserzaehler standen vorher MAC-Adresse und freier
Speicher vorn und der Verbrauch hinter "12 weitere"
Heizung nur noch der Schieberegler, daneben Ist-Temperatur und
Feuchte live aus dem MQTT-Strom
Ab zwei Geraeten einer Art ordnet eine Ueberschrift; darunter waere sie
nur Aufwand. Schieberegler schicken beim Loslassen, nicht beim Ziehen -
sonst bekaeme eine Jalousie bei jedem Pixel ein neues Ziel. Waehrend ein
Kommando unterwegs ist, sperrt sich die Karte sichtbar: ein "Zu" dauert
ueber eine Minute, und ohne Sperre tippt man in der Zeit nach.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Zuordnung der restlichen Geraete lief gegen eine Luecke im Raummodell:
rooms.php kannte nur Raeume, die eine Kachel im Grundriss haben - also
Raeume mit Thermostat. Die Kueche im EG hat keines, und die Stromzaehler
und der Wasserzaehler sitzen in Technikraeumen, die dort ebenfalls fehlten.
Ein Raum ohne x/y ist jetzt trotzdem ein Raum: Geraete lassen sich ihm
zuordnen, er erscheint nur nicht im Grundriss. roomsOnFloor() liefert
weiterhin nur Raeume mit Kachel - alles, was zeichnet oder aktualisiert,
geht darueber -, allRooms() liefert fuer die Zuordnung alle. Die
Aktualisierungsschleife im Browser bekommt ausdruecklich nur die
Kachel-Raeume; ein Raum ohne Position haette dort keine Elemente zu fuellen.
Neu eingetragen: EG/Kueche, EG/Technik, UG/Technik.
Damit sind 49 der 54 Geraete einem Raum zugeordnet. Offen bleiben mit
Absicht: Alarm (hausweit), Zeitpunkt (gerechnet), Thermostat EG
Unkonfiguriert (laut eigenem Namen) und die beiden Dachfenster, deren Raum
noch niemand genannt hat.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Beim Anlegen einer Automatik denkt man in Raeumen ("im Bad soll ..."), nicht
in Geraetearten. Ein Raummodell gibt es schon - restricted/rooms.php, die
einzige Quelle fuer die Home-Ansicht -, nur fehlte die Zuordnung Geraet ->
Raum.
Die neue Spalte actors.room haelt sie als "Etage/Raum" (OG/Bad), dazu
"aussen" fuer Carport, Garage und Regensensor. Etage und Raum zusammen,
weil "Bad" allein auf drei Etagen vorkommt. Discovery fasst die Spalte nicht
an - der Upsert setzt nur type und name -, die Zuordnung ueberlebt also
jeden Suchlauf.
Zugeordnet wird ueber das Haus-Symbol in der Karte "Automatismen". Wo der
Raum aus dem MQTT-Topic hervorgeht ("Raumtemp/OG/Bad/Temp[degC]"), schlaegt
die Ansicht ihn vor und uebernimmt ihn auf Knopfdruck - das sind die
dreizehn Thermostate, ohne jedes Raten. Bei allen anderen wird bewusst nicht
geraten: "Bad Links" sagt nichts darueber, auf welcher der drei Etagen
dieses Bad liegt. Noch nicht zugeordnete Geraete stehen in der Tabelle oben.
Die Geraeteauswahl im Editor gruppiert danach nach Raum, in der Reihenfolge
aus rooms.php. Solange niemand zugeordnet hat, bleibt es bei der Gruppierung
nach Geraeteart - eine einzige Gruppe "Nicht zugeordnet" waere ein
Rueckschritt. Und weil auch nach der ersten Zuordnung noch viel ohne Raum
ist, wird dieser Rest weiter nach Geraeteart unterteilt ("Ohne Raum ·
Aussenjalousie (11)").
Anders als bei den Gerätearten behalten Raeume mit nur einem Geraet ihre
Ueberschrift: "OG · Bad" ist auch mit einem einzigen Thermostat genau die
Zeile, die man sucht - und mehr als eines haengt selten in einem Raum.
Die dreizehn Thermostate sind bereits zugeordnet, weil das ihre eigenen
Topics hergeben; alles andere steht auf "-" und will von Hand vergeben
werden.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nach dem Discovery-Lauf stehen 51 Geraete in der Ausloeser-Liste und 40 in
der Aktions-Liste, flach und alphabetisch. Dreizehn Thermostate und elf
Jalousien sind darin vierundzwanzig gleich aussehende Zeilen.
Die Liste ist jetzt nach Geraeteart gruppiert (optgroup, das koennen auch
die Handy-Browser nativ). Arten mit nur einem Geraet bekommen keine eigene
Ueberschrift - fuenfzehn Gruppen mit je einem Eintrag waeren
unuebersichtlicher als die flache Liste -, sie sammeln sich am Ende unter
"Einzelne".
Dazu ein Namensputz fuer die Anzeige, ohne die Datenbank anzufassen: das
u_-Praefix aus den Tahoma-Beschriftungen faellt weg, ebenso eine
angehaengte einstellige Kanalnummer, und Unterstriche werden zu Leerzeichen.
Aus "u_Wozi Terrassentuer" wird "Wozi Terrassentuer", aus "Power_EG_EM_0"
wird "Power EG EM". Bewusst nur die einstellige Endung - "go-eCharger_270003"
traegt seine Seriennummer und behaelt sie.
Beschriftungen, die danach doppelt waeren, bekommen die Geraeteart dazu: die
Tahoma-Box nennt sowohl den Rollladen als auch den Sonnenenergie-Sensor
"Terasse", in der Liste untereinander waren sie nicht zu unterscheiden.
Daraus wird "Terasse (Rollladen)" und "Terasse (Licht)".
Die Beschriftung entsteht an einer Stelle und wird von Editor und
Uebersicht geteilt - sonst stuende in der Auswahlliste "Wozi Terrassentuer"
und im Satz darunter weiter "u_Wozi Terrassentuer".
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Manche Geraete schicken eine Zahl und meinen einen Zustand - der
go-eCharger etwa 2 fuer "Charging". Welche Zahl welchen Namen hat, steht im
value_template der Home-Assistant-Discovery als Werttabelle:
{{ ['Unknown','Idle','Charging','WaitCar','Complete','Error'][value_json|int] }}
Das ist kein Pfad in die Nutzlast, sondern eine Uebersetzung, und sie wurde
bisher verworfen. Jetzt landet sie in possible_values - in derselben
Schreibweise, die WLED fuer seine Effektliste schon benutzt, naemlich einer
Liste aus {Wert: Bezeichnung}. Damit versteht der Editor sie ohne
Zusatzarbeit und macht eine Auswahlliste daraus. Ein Versatz im Ausdruck
wandert in die Schluessel: aus [value_json|int-3] wird {"3":"Default"}.
Der Runner uebersetzt beim Lesen, eine Bedingung vergleicht also den
Klartext. Steht die Zahl nicht in der Tabelle, bleibt sie stehen - ein
erfundener Name waere schlimmer als ein roher Wert.
Dabei ist ein Folgefehler aufgefallen: Auswahlwerte in dieser Schreibweise
kamen im Editor als "[object Object]" an. Die alte addOptions kannte die
Form, der neue Modell-Aufbau nicht - aufgefallen ist es nie, weil WLED beim
Umbau abgeschaltet war. Der Katalog liefert Auswahlwerte jetzt einheitlich
als {value, label}, und zwar seitenrichtig:
Messwert angezeigt Charging, gespeichert Charging
(der Runner hat schon uebersetzt)
Parameter angezeigt Blink, gespeichert 1
(das Geraet will die Zahl)
Die Uebersicht loest die Bezeichnung ebenfalls auf: "Effekt (Blink)" statt
"Effekt (1)".
Nachgemessen: alle fuenf Werttabellen auf dem Broker richtig erkannt,
einschliesslich des Versatzes, kein Fehltreffer unter den 35 uebrigen
Vorlagen. Live liefert der go-eCharger jetzt Idle, Neutral, Auto, Eco und
None statt 1, 0, 0, 4, 0. Ein weiterer Discovery-Lauf aendert keine Zeile.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Auswahlliste im Editor bot ein "-" an. Eine Automatik ohne Etage taucht
aber in keinem der drei Reiter auf und ist danach nur noch in der Datenbank
zu finden - anlegen und sofort verlieren.
Der Eintrag ist weg, und der Zustand ist jetzt an drei Stellen unmoeglich
statt nur unwahrscheinlich: die Liste kennt nur noch OG, EG und UG,
saveAutomation lehnt alles andere mit einer Meldung ab statt still auf ""
zurueckzufallen, und im Enum der Spalte gibt es den leeren Wert nicht mehr.
Die Reihenfolge in der Liste ist jetzt OG, EG, UG wie bei den Reitern -
damit trifft der Rueckfall auf den ersten Eintrag dieselbe Etage wie die
Startseite. Kennt die Liste die Etage eines Datensatzes nicht, faellt sie
darauf zurueck, statt leer stehen zu bleiben und beim Speichern "" zu
schicken.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die steigende Flanke allein schuetzt nicht gegen einen Messwert, der um die
Schwelle pendelt: "Temperatur > 22" bei 22,1 / 21,9 / 22,1 Grad ist jedes
Mal eine echte Flanke, und ueber MQTT koennen die Werte im Sekundentakt
hereinkommen. Gemessen: fuenf Kommandos in einer halben Minute.
automations.lockout_secs sagt jetzt, wie lange nach einer Ausloesung nicht
wieder geschaltet wird. Der Editor bietet drei Stufen an - ohne, eine
Minute, eine Viertelstunde -, weil die passende Wahl am Geraet haengt und
nicht an einer Zahl: ein Rollladen soll nicht alle zwanzig Sekunden
losfahren, eine Lichtfarbe darf das. Gespeichert werden Sekunden, damit eine
vierte Stufe eine Zeile in lockoutChoices() ist und keine Wanderung durch
die Datenbank. Vorbelegt ist eine Minute.
Eine Flanke in der Sperrzeit wird verworfen, nicht aufgehoben. Ein
Rollladen, der eine Viertelstunde spaeter doch noch losfaehrt, weil vor
langer Zeit einmal eine Schwelle gestreift wurde, waere unangenehmer als
einer, der gar nicht faehrt - und der naechste echte Anlass nach Ablauf der
Sperre kommt ohnehin durch. Verworfene Flanken stehen auf DEBUG und nicht in
automation_log, sonst waere die Tabelle bei einem zappelnden Sensor voll
davon.
force_once bleibt unberuehrt: es greift nur, wenn im Fenster gar nichts
gelaufen ist - dann ist auch keine Sperre aktiv.
Nachgemessen am pendelnden Sensor: mit 60 s Sperre ein Kommando, ohne Sperre
fuenf.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Bei Uhrzeit und Datum gab es nur "ab" und "vor". Der haeufigste Fall - eine
Aktion genau um 16:30 - liess sich damit gar nicht ausdruecken. "um" ist
jetzt der erste Eintrag und damit die Vorbelegung.
Der Hinweis von frueher bleibt trotzdem richtig und steht in der README:
"um" trifft nur eine einzige Minute, faellt der Runner ausgerechnet in
dieser Minute aus, ist die Automatik fuer den Tag verloren. "ab" holt der
naechste Takt nach. Wer beides will, hakt force_once an.
Beim Sonnenauf- und -untergang fehlte die halbe Tabelle: der Versatz kann
davor oder danach liegen, und verglichen werden kann davor, danach oder
genau. Statt zwei gibt es jetzt sechs Operatoren - "+", "-", "ab +",
"ab -", "vor +", "vor -". Das Vorzeichen steckt im Operator, weil der
Editor eine einzige Auswahlliste zeigt und nicht zwei Bedienelemente fuer
eine Angabe.
Rutscht ein Versatz rechnerisch ueber den Tagesrand (Sonnenaufgang 05:34
minus sechs Stunden), bleibt es beim Tagesrand statt auf die andere Seite
von Mitternacht zu springen - "kurz vor Sonnenaufgang" soll nicht ploetzlich
gestern abend bedeuten.
Der Editor brauchte keine Aenderung: er liest Wert und Beschriftung der
Operatoren aus dem Geraetekatalog, statt sie selbst zu kennen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Bisher konnte man Automatiken nur anlegen - ausgefuehrt hat sie niemand.
restricted/autoActions/autoaction_runner.py holt das nach.
Dauerlaeufer statt Cronjob, aus zwei Gruenden: Schwellwert-Ausloeser sollen
greifen, wenn die MQTT-Nachricht hereinkommt, und actor_states.current_value
wird sonst von niemandem fortgeschrieben - beim Discovery einmal gesetzt und
danach nie wieder. Ein zustandsloser Lauf haette gar nichts, womit er
vergleichen koennte. Der Runner pflegt den Wert nebenbei mit, wovon auch der
Editor profitiert: er zeigt neben jedem Messwert den aktuellen Stand.
Ausgeloest wird nur auf der steigenden Flanke (automations.cond_met), sonst
wuerde "Temperatur ueber 22 Grad" bei jedem Takt erneut feuern. Aus
demselben Grund heissen Zeit-Ausloeser jetzt "ab 16:30" statt "gleich
16:30": ein Gleichheitsvergleich waere nur in einer einzigen Minute wahr,
und ein Ausfall in genau dieser Minute kostet den ganzen Tag. Dieselbe
Ueberlegung steht hinter den breiten Zeitfenstern in auto_watering.py.
Der Weg zum Geraet haengt an der URL des Aktors: mqtt:// abonniert und
publiziert, http:// pollt und haengt Parameter an, io:// spricht mit der
Tahoma-Box, Logic rechnet Uhrzeit, Datum und Sonnenzeiten. Alle vier stehen
in transports.py; eine fuenfte Geraeteart ist eine weitere Klasse mit
passt(), zustaende_lesen() und senden().
fetch_calendar.py fuellt calendar_days aus openholidaysapi.org, damit "in
den Ferien" und "an Feiertagen" eine Grundlage haben. Einmal jaehrlich per
Cron.
Die Uebersicht blendet auf schmalen Schirmen Spalten aus, statt sie
wegzuschieben - auf dem Handy waren die Knoepfe zum Pausieren und Loeschen
sonst nur per Seitwaertsscrollen erreichbar.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Editor las seine Geraete aus homeMesh, schrieb aber nach solarLog in
Tabellen, deren Fremdschluessel auf solarLog.actors/sensors zeigten. Jedes
INSERT lief damit gegen den Fremdschluessel - autoactionsSensors und
autoactionsActors sind deshalb leer geblieben, und die Aktor-Schleife war
ohnehin nie geschrieben worden.
Die Automatiken liegen jetzt in homeMesh neben dem Geraetemodell
(homeMesh_automations.sql). Eine Bedingung verweist mit einem einzigen
Fremdschluessel auf actor_states statt auf Geraet, State-URL und ein
unklares valID; Kommandoparameter stehen zeilenweise statt in vier festen
Spalten "Wert 1" bis "Wert 4". Verknuepft wird ueber group_no: gleiche
Nummer UND, verschiedene ODER, ausgewertet als any(all(gruppe)).
Im Editor ist eine Gruppe ein gerahmter Block mit eigenem "+ Bedingung",
dazwischen steht ODER - die Klammerung ist damit gezeichnet und nicht
vereinbart, und darunter steht derselbe Satz noch einmal in Worten. Die
Uebersicht zeigt ihn in der Spalte "Ausloeser" und ersetzt die bisher fest
verdrahtete Beispielzeile.
Nebenbei behoben: die Operator-Knoepfe schickten ihr innerHTML ("≠",
">") an eine Whitelist, die "!=" erwartete - jede Bedingung "ungleich"
wurde still zu "gleich". Ausgeblendete Wertfelder sendeten ihren Inhalt
trotzdem mit. Beides entfaellt, weil der Editor jetzt JSON aus einem
Modell schickt statt durchnummerierter Formularfelder.
Die vier Endpunkte fillSensorDD, fillActorDD, sensorDetails und
actorDetails entfallen: der Geraetekatalog reist einmal mit dem Editor
mit, statt je Bedingungszeile zwei Anfragen nachzuladen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>