Die Einstellungen bestanden aus einer einzigen langen Spalte mit den
Preistabellen. Sie bekommt Reiter, und darin zwei neue Flaechen: was die
Kacheln der Startseite anzeigen, und welche Geraete es ueberhaupt gibt.
Reiter gab es vorher dreimal in drei Ausfuehrungen - die Etagen ueber den
Automatismen mit eigenem switchTab(), die Geraetegruppen im Raum-Modal mit
eigener CSS-Klasse, und die Einstellungsseite noch einmal anders. Jetzt baut
restricted/reiter.php alle drei; umgeschaltet wird von Bootstrap, den offenen
Reiter merkt reiterMerken() in der Adresse.
Kachelwerte: was auf einer Kachel steht, stand fest in rooms.php. Die neue
Tabelle kachelWerte (solarLog_kacheln.sql) ueberschreibt das je Raum, die
Maske waehlt die Messwerte aus demselben Katalog wie der Automatik-Editor -
nach Etage sortiert, die Geraete des eigenen Raums oben. Fehlt die Tabelle,
zeigt jede Kachel weiter ihre Vorgabe.
Geraete: die Zuordnung Geraet -> Raum war ein Modal, erreichbar ueber ein
Zahnrad neben den Automatismen. Sie ist eine Einstellung und steht jetzt dort,
zusammen mit dem, was fehlte: seit wann ein Geraet nichts mehr meldet, in
welchen Automatiken es steckt, und ein Loeschknopf. Letzterer ist noetig, weil
der Suchlauf nichts loescht - er legt an und frischt auf, damit die Automatiken
ihre Zustands-Ids behalten; ein abgebautes Geraet bliebe sonst fuer immer
stehen. Geloescht wird nur, was in keiner Automatik vorkommt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zwei Sachen, beide an der Anlage aufgefallen.
Abgebrochen wurde auf "core:MovingState ist false". Das ist nicht
dasselbe wie "steht": die Box meldet das Ende der Fahrt, bevor Hoehe und
Neigung darauf nachgezogen haben, und der festgehaltene Wert war dann der
von kurz davor. Statt einer festen Wartezeit zaehlt jetzt Stabilitaet -
fertig ist es, wenn zwei Abfragen hintereinander dasselbe sagen. Damit
faellt auch die Bestaetigungsrunde weg, sie war genau dieser Gedanke in
schlechter.
Der Umweg der Kugelschreiber-Mechanik hing am Neigungswert (ueber 30 %).
Er gehoert an die Hoehe: eine Hoehenfahrt rastet die Lamellen um, danach
muss die Neigung ueber 0 % wieder angefahren werden - bei jedem Winkel,
nicht erst bei grossen. Wird dagegen nur die Neigung verstellt, steht die
Mechanik schon richtig und es geht direkt. NEIGUNG_DIREKT_MAX faellt
damit weg.
Der Hoehenregler im Raum-Modal schickt deshalb jetzt das kombinierte
Kommando mit der Stellung des Neigungsreglers daneben - ohne
Neigungsziel gaebe es nichts, was der Umweg anfahren koennte.
Geprueft an der Wozi-Schiebetuer: Hoehe von 48 auf 60 bei Neigung 76, und
die 76 standen danach wieder da. Vorher htte die Mechanik sie auf einen
beliebigen Wert umgerastet. Dazu elf Faelle im Browser und sieben gegen
transports.py, darunter "Position+Neigung 10" (Umweg) gegen "nur Neigung
80" (direkt).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Wer eine Jalousie faehrt, das Modal zumacht und gleich wieder aufmacht,
sah weiter den alten Stand - und zwar dauerhaft. Zwei Gruende, die sich
uebereinandergelegt haben: die Box meldet die neue Hoehe erst am Ende der
Fahrt (gemessen rund zwanzig Sekunden), und das Modal zeichnet sich nur
beim Oeffnen. Was in diesen zwanzig Sekunden aufgemacht wurde, blieb
falsch stehen, bis jemand es noch einmal aufmachte.
Beim Oeffnen wird jetzt jede Jalousie des Raums einmal an der Box
nachgefragt. Faehrt sie gerade, bleibt die Verfolgung dran, bis sie steht.
Ohne Auftrag gibt es keinen Vorlauf abzuwarten und nichts nachzureichen,
deshalb genau eine Abfrage je Jalousie - drei fuer das Wohnzimmer.
Damit stimmt die Anzeige in beiden Richtungen: der Server schreibt nach
jedem Fahrbefehl nach (67c2a77), das Modal holt sich beim Aufmachen den
Stand.
Geprueft an der Wozi-Schiebetuer, genau der gemeldete Ablauf: Regler auf
10, Modal nach 1,2 s zu, nach weiteren 0,6 s wieder auf. Es zeigte 60,
verfolgte weiter und sprang nach 28 Sekunden auf 10. Ein ruhiges Oeffnen
kostet drei Abfragen fuer drei Jalousien. Dazu dreizehn Faelle gegen die
echte Datei.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Am echten Geraet ausprobiert - drei Sachen stimmten nicht.
Die PHP-Warnung. Nicht jeder Tahoma-Zustand ist eine Zahl oder ein Wort,
manche sind Listen. strval() darauf ist eine Warnung, und die stand mitten
in der JSON-Antwort. response.json() scheiterte, raumRequest() lieferte
{error}, die Verfolgung brach still ab - genau das Bild, das der Bericht
"kommt noch nicht" beschreibt. Nicht-Skalare werden jetzt uebergangen, und
ein Fehler wird gemeldet statt verschluckt.
Das Mitziehen waehrend der Fahrt. Gemessen: die Hoehe steht die ganzen
zwanzig Sekunden auf dem alten Wert und springt erst am Ende um. Wer das
anzeigte, holte den Regler vom eingestellten Ziel auf den alten Stand
zurueck, um ihn danach wieder vorzuschieben. Angezeigt wird deshalb erst,
was am Ende dasteht.
Das vorzeitige Aufhoeren. Zwischen den beiden Befehlen der
Kugelschreiber-Mechanik steht die Jalousie still und meldet die
Zwischenstellung. Die Verfolgung hielt das fuer das Ende und schrieb
"Neigung 0" fest, wo 62 gemeint war. Sie laeuft jetzt mindestens, bis der
Auftrag zurueck ist, und danach noch vierzehn Sekunden - so lange dauert
eine Neigungsfahrt von Anschlag zu Anschlag.
Gegengeprueft an der Wozi-Schiebetuer: Position 49 -> 20 -> 100 -> 49,
Neigung 62 -> 80 -> 62. Die Neigung wanderte beim Herunterfahren von
selbst auf 100 und stand sofort richtig im Modal. Waehrend des zehn
Sekunden langen Kugelschreiber-Auftrags liefen drei Verfolgungsanfragen
durch - die Sitzungssperre ist also wirklich weg.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
actor_states.current_value schrieb bisher nur der AutoAction-Runner fort,
und der fragt die Tahoma-Box alle fuenf Minuten ab (poll_tahoma). Nach
einem Fahrbefehl stand im Raum-Modal deshalb bis zu fuenf Minuten lang
der Stand von vor der Fahrt.
Das Modal verfolgt die Jalousie jetzt selbst: alle zwei Sekunden fragt es
ueber ajax/room.php?action=jalousie genau dieses eine Geraet, zieht die
beiden Regler und das Lamellenbild nach und hoert auf, sobald die Box
keinen Fahrbefehl mehr meldet. Der gelesene Stand landet dabei gleich in
actor_states, damit auch das naechste Oeffnen und der Automatik-Editor
ihn haben. Wer gerade selbst am Schieber zieht, behaelt ihn.
Drei Dinge mussten dafuer aus dem Weg:
- Die Sitzung. helper.php startet sie und schliesst sie nie, PHP sperrt
ihre Datei bis zum Ende der Anfrage. Ein "Zu" wartet ueber eine Minute
auf das Ende der Fahrt - solange stand jede weitere Anfrage desselben
Browsers still. ajax/room.php gibt sie jetzt frei, sobald checkLogin()
durch ist; danach wird $_SESSION nur noch gelesen.
- Drei Abfragen je Warterunde. warteAufJalousie() holte MovingState,
Neigung und Position einzeln, obwohl eine Abfrage die ganze Liste
liefert. Jetzt eine.
- Kein Ort, an dem der frische Stand haengenbleibt. Dafuer
tahomaZustaende(), tahomaZustaendeSchreiben() und tahomaAktorUrl().
Wahrheitswerte werden dabei als "True"/"False" geschrieben - so macht es
der Runner mit str(), und zwei Schreibweisen fuer denselben Zustand
waeren schlimmer als eine schraege.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nicht nachgebaut, sondern powerToString() aus common.js benutzt. Sie macht
genau das schon, und die Solarseite formatiert dieselben Zahlen damit - eine
eigene Regel hier haette bedeutet, dass dieselbe Wallbox an zwei Stellen
verschieden gerundet dasteht. common.js wird im Fuss vor den seitenweisen
Skripten geladen, steht homeMQTT.js also zur Verfuegung.
Ersetzt wird nur das Trennzeichen: auf der Kachel steht ein schmales
Leerzeichen zwischen Zahl und Einheit, im Rest der Anwendung ein
gewoehnliches.
Betroffen sind Garage, Carport OG und Carport EG. Der Regen im Garten bleibt
bei Einheit und Nachkommastelle - Millimeter skalieren nicht.
Nebenbei: mein Einschub von wechselrichterWert() hatte den Kommentarblock
von kachelWert() von seiner Funktion getrennt, er stand seitdem ueber der
falschen. Zurueckgesetzt und um die beiden neuen Schluessel ergaenzt.
Geprueft mit dem echten Code im Browser: 0 -> "0 W", 999 -> "999 W",
1234 -> "1.23 kW", 12340 -> "12.3 kW"; die Summe der vier Carport-Hoymiles
ergibt 1.23 kW und laesst einen fuenften Wechselrichter richtigerweise
draussen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Das Rendering des Grundstuecks fuellt seinen Rahmen aus, die drei
Geschossbilder haben dagegen breiten schwarzen Rand - deshalb lagen die
Etagenschalter nur beim Aussengelaende auf dem Bild. Der Rand gehoert ins
Bild und nicht in home.php: dort einzurechnen haette auch OG, EG und UG
verschoben, und deren Kacheln sind auf die heutige Lage eingemessen. AG.png
bekommt links 114 durchsichtige Punkte, die sieben Kacheln sind mit
derselben Abbildung umgerechnet.
Die Schalter selbst waren ein duenner Ring in einem Amber (#aa7713), das in
css/solar.css nirgends vorkommt - und alle vier sahen immer gleich aus, die
aktive Etage war an ihnen nicht zu erkennen. Jetzt tragen sie dieselbe
Scheibe wie die Kacheln im Grundriss, die aktive bekommt die Akzentfarbe der
Schieberegler (#00788F), und switchFloor() zieht den Zustand mit. Dort
classList und nicht die Helfer addClass/removeClass weiter oben: deren
"el.className +=" wirkt auf SVG-Elementen nicht, className ist dort
schreibgeschuetzt.
Ausserdem sind sie kleiner. Mit halber Groesse beherrschten sie die linke
Seite, und das Bild musste umso weiter einruecken, um sie freizuhalten - bei
0,38 statt 0,50 bleibt mehr Plan uebrig. Die Groesse steht als eine Zahl in
home.php, Abstand und Bildrand folgen daraus.
Die Beschriftung sitzt jetzt ueber text-anchor und dominant-baseline im
Kreismittelpunkt. Vorher stand je Etage ein von Hand gesuchter Versatz im
Markup (62, 63, 64), und jede neue Etage haette einen neuen gebraucht.
Weggefallen: die Definition #floorBtn, die nur einmal benutzt wurde, und die
Animationen showOG/showEG/showUG, die ein bereits sichtbares Element von 0
auf 1 blendeten.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Carport EG und Veranda OG zeigen jetzt ihre PV-Leistung. Der SolarManager
legt die Hoymiles unter solarManager/inverters0, /inverters1 und so fort ab
- die Nummer ist eine Position in einer Liste und sagt nichts darueber,
welches Dach gemeint ist. Ein fest eingetragenes "inverters3" waere
stillschweigend falsch, sobald sich die Reihenfolge aendert.
Deshalb sucht wechselrichterWert() ueber invertersN/name und summiert die
genannten auf. Das ist eine dritte Art, an einen Wert zu kommen - neben
Topic und JSON-Pfad -, aber sie bleibt auf einen Schluessel und eine
Funktion beschraenkt, und der gewoehnliche Weg ist unberuehrt. Findet sie
keinen der Namen, schreibt sie die vorhandenen in die Konsole; sonst stuende
nur ein Strich auf der Kachel und niemand wuesste, woran es liegt.
tileTopics() unterschied bisher nicht und machte aus dem fehlenden Topic ein
"/#" - eine Anmeldung auf einen leeren Zweig.
Dazu Symbole vor den Zahlen. "0 W" allein sagt nicht, ob geladen, erzeugt
oder verbraucht wird, und die Einheit beantwortet das nicht. Die Icons
kommen als Schrift und nicht als Pfad: css/bootstrap-icons.min.css ist
ohnehin eingebunden, und SVG-Text darf dieselbe Schriftfamilie benutzen wie
HTML. Die Codepunkte stehen in kachelIcon() mit dem Namen daneben,
abgeschrieben aus genau dieser CSS.
Wegen font-display:block bleiben die Symbole bis zum Laden der Schriftdatei
unsichtbar - die Werte stehen so lange ohnehin auf einem Strich.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Bisher entschied jede Arbeitsstation fuer sich, welche Zeilenenden ein
Commit bekommt: Git fuer Windows setzt core.autocrlf=input in seiner
System-Konfiguration, die NAS setzt nichts. Weil der Bestand ausserdem in
sich gemischt war - 34 PHP-Dateien mit LF, 30 mit CRLF -, gab es gar kein
richtiges Zeilenende, an das ein Werkzeug sich haette halten koennen. Jede
Ergaenzung mit LF in einer CRLF-Datei ergab eine gemischte Datei; helper.php
und js/solar/homeMQTT.js waren bereits so entstanden.
.gitattributes macht die Zeilenenden zur Eigenschaft des Repositorys. LF,
weil dieses Verzeichnis der Web-Ordner der NAS ist und von Linux
ausgeliefert wird - und weil Git fuer Windows mit "input" ohnehin schon
dorthin zeigt.
restricted/WebAuthn bleibt ausgenommen und damit byteweise so, wie die
Bibliothek geliefert wurde; darunter liegen 292 Zertifikate.
Von den 47 geaenderten Dateien wurde nachgerechnet keine einzige im Inhalt
angefasst - der Vergleich HEAD-ohne-CR gegen Index ist ueberall gleich.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Was draussen haengt, stand als Pseudo-Raum "aussen" in automations.php:
"Geraete, die zu keinem Raum der Wohnung gehoeren - Carport, Garage,
Regensensor". Das waren inzwischen sechzehn Geraete in einem einzigen Topf,
der groesste ueberhaupt - in der Geraeteauswahl des Editors standen die fuenf
Carport-Wechselrichter, das Sonnensegel und das Garagentor unsortiert
nebeneinander.
Jetzt ist das Aussengelaende eine Etage wie OG, EG und UG, mit eigenen
Raeumen: Carport, Veranda, Pergola, Terrasse, Garage und Garten. Die Namen
stammen von den Geraeten selbst - die Hoymiles heissen seit jeher "Carport
1-6" und "Veranda OG2-4". Die achtzehn Geraete sind verteilt (die beiden
Ventilsteuerungen hatten noch gar keinen Raum und stehen jetzt im Garten,
zusammen mit dem Regensensor, der ihre Automatiken ausloest); "Ohne Raum"
faellt damit von acht auf sechs, und die sind es zu Recht.
AG ist eine Etage ohne Grundriss. Ihre Raeume haben kein x/y, es gibt ja
kein Bild, auf das eine Kachel zeigen koennte - ein Raum ohne Position war
schon immer vorgesehen. Das Menue und das SVG richten sich deshalb nach der
neuen floorsWithPlan(), die Zuordnung und die Automatiken nach $floors.
Bekommt der erste AG-Raum eine Kachel, erscheint die Etage von selbst auch
im Menue; es gibt keine zweite Liste, die man nachziehen muesste.
Die Etagen standen bisher an sechs Stellen noch einmal im Code. Jetzt gibt
es genau eine Liste, $floors in rooms.php, und alles andere leitet sich ab:
* automations.php prueft gegen $floors statt gegen eine eigene Whitelist
* ajax/AutoAction.php baut seine Etagen-Auswahl daraus
* home.php baut Reiter und Inhaltsbereiche in einer Schleife statt
dreimal fast dasselbe HTML
* header.php baut die Menuepunkte daraus
* switchTab() in homeMQTT.js liest die Reiter aus der Seite, statt OG, EG
und UG sechsmal aufzuzaehlen
* refreshAutomations() ebenso - eine feste Liste haette die vierte Etage
still ausgelassen, die Tabelle waere ohne Fehlermeldung leer geblieben
Dazu die ausgeschriebenen Namen in $floorLabels: das Kuerzel steht in URLs,
SVG-Ids und im MQTT-Baum, "Aussengelaende" nur als Titel am Menuepunkt und
am Reiter.
In der Datenbank ist das Enum um 'AG' erweitert; header.php laedt rooms.php
jetzt selbst, weil es vor home.php eingebunden wird.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Drei Sachen an den Kacheln und am Raum-Modal.
Die Platzhalter sind nur noch Striche. Vorher stand dort "---- hPa",
gefuellt wurde die Zeile aber mit der Solltemperatur - eine Einheit, die
nie kam, an einer Stelle, die etwas anderes zeigt.
Der Heizungs-Reiter erscheint nur noch, wo auch ein Thermostat haengt.
Frueher entschied das "hat der Raum eine Kachel" - das stimmte, solange
nur Raeume mit Thermostat eine bekamen. Seit auch Kueche und Technik eine
haben, bekamen sie einen Regler fuer eine Heizung, die es dort nicht gibt.
Jetzt zaehlt, ob im Raum ein Geraet der Bedienform "heizung" steht.
Und eine Kachel zeigt jetzt ein bis drei frei gewaehlte Messwerte. In
restricted/rooms.php steht je Raum unter "werte", welche das sind: topic,
optional pfad (Schluessel in einer JSON-Nachricht), einheit, stellen. Ohne
Angabe bleibt es bei den drei Thermostatwerten samt Heizsymbol, also genau
wie bisher - nur diese Raeume zeichnen die Symbole ueberhaupt noch.
Alles kommt live ueber MQTT, auch die beiden Shelly-Zaehler: sie schicken
ihre sechzehn Werte als eine JSON-Nachricht auf Power_EG/status/em:0, aus
der "pfad" den gesuchten Schluessel greift. Der Browser meldet nicht mehr
fest "Raumtemp/#" an, sondern die Zweige, die die Raumtabelle nennt -
derzeit vier statt vierzig einzelner Topics.
Damit steht auf EG Technik die Leistung (gemessen 293 W), auf UG Technik
Leistung und Wasserzaehler (78 W, 400,4 m3). Raeume ohne Messwert tragen
ihren Namen und oeffnen den Raum; ein leeres Rechteck saehe aus wie ein
Fehler.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Im Raum-Modal wirkt jedes Bedienelement sofort - der Rollladen faehrt, der
Schalter schaltet, die Lampe leuchtet. Nur die Solltemperatur wartete auf
"Save changes". Sie schickt jetzt beim Loslassen des Reglers, wie die
Rollladenregler daneben, und der Knopf ist im Raum-Modal weg. Einer, der
nur fuer einen der Reiter gilt, waere in allen anderen eine Falle.
Das Modal bleibt nach dem Schicken offen; frueher schloss es sich, weil
der Knopf das Ende der Bedienung war. Wer dreimal nachjustiert, will nicht
dreimal neu aufmachen. Die Heizungskarte traegt dafuer dieselbe Sperre wie
die Geraetekarten - waehrend das Kommando unterwegs ist, ist sie gesperrt.
Dabei einen Fehler mitgenommen: der Speichern-Knopf gehoert allen Modals
gemeinsam, und wer ihn versteckt, versteckt ihn fuer alle. Ein Raum ohne
Thermostat liess ihn schon bisher verschwinden - danach hatten der
AutoAction-Editor und die Raumzuordnung bis zum Neuladen keinen
Speichern-Knopf mehr. Beide holen ihn jetzt wieder hervor. Nachgemessen:
im Raum-Modal versteckt, im Editor und in der Raumzuordnung sichtbar.
Die Fahrknoepfe sind von 34 auf 50 Pixel gewachsen - sie sind das, was man
im Vorbeigehen antippt, die Regler daneben braucht man seltener.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Regler standen neben den Fahrknoepfen - beim Antippen von "Auf" fand
der Daumen leicht den Schieber daneben. Jetzt stehen sie rechts aussen,
zwischen ihnen und den Knoepfen liegt das Fensterbild.
Das Bild zeigt jetzt beides. Die Hoehe schneidet ab: gezeichnet wird nur
der Teil des Fensters, den die Jalousie bedeckt, mit der Endschiene an
seiner Unterkante; darunter sieht man hinaus. Die Neigung bestimmt wie
bisher, wie dick eine Lamelle von vorn erscheint. Ein Rollladen ohne
Neigung bekommt volle Lamellenhoehe - er ist ja ein geschlossener Panzer.
Die Prozentzahl unter den Reglern ist weg; die Bahn ist dafuer von 5 auf
6,5 rem gewachsen. Was der Regler bewirkt, zeigt das Bild ohnehin besser
als eine Zahl.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der senkrechte Positionsregler liess sich am Handy kaum anfassen. Gebaut
war er mit writing-mode: vertical-rl - dem neueren Weg, aber einem, bei
dem der Browser das Ziehen als Wischen liest und die Seite blaettert,
statt den Griff mitzunehmen.
Jetzt liegt ein gewoehnlicher waagerechter Regler um 90 Grad gedreht in
seinem Kasten. Er bewegt sich in seinen eigenen Koordinaten waagerecht,
wird von jedem Browser unterstuetzt, traegt dieselbe Gestaltung wie die
liegenden Regler, und touch-action: none haelt die Seite still, solange
der Finger auf ihm liegt. Die Trefferflaeche ist 1,6 rem breit statt der
sichtbaren 0,375 rem Bahn. Nachgemessen: oben angeklickt 8 %, unten 93 %.
Die Neigung steht jetzt ebenfalls senkrecht, daneben das Lamellenbild -
Regler und Bild bilden ein Paar, das Bild sagt, was der Regler bedeutet.
Beide Spalten sind mit Namen und den Worten an ihren Enden beschriftet
("oben"/"unten", "auf"/"zu"); die Zahl darunter ist das, was sich beim
Ziehen aendert.
Die Regler im Raum-Modal haben ein eigenes Aussehen bekommen: Bootstraps
weisse Bahn mit blauem Griff stach auf den dunklen Karten heraus, und in
einem Raum mit drei Jalousien waren das sechs helle Balken. Bahn und Griff
tragen jetzt dasselbe Blaugruen wie der Temperaturregler, der ungefuellte
Teil ein Grau, das in beiden Themes traegt. Die Regler in den Modals fuer
Autoladung und Heizstab bleiben unberuehrt.
Die Regel fuer die Bahn steht zweimal da, einmal fuer -webkit- und einmal
fuer -moz-: als Liste notiert wirft der Browser beim unbekannten Selektor
die ganze Regel weg, und dann bliebe die Bahn ungestaltet.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Gruppenueberschriften sind Tabs geworden, Beschattung zuerst - das ist
es, was man in einem Raum am haeufigsten anfasst. Vorher scrollte man an
drei Rollladen vorbei, um zum Licht zu kommen. Bei nur einer Gruppe bleibt
die Leiste weg; auf schmalen Schirmen scrollt sie seitwaerts, statt die
Namen umzubrechen.
Bei den Jalousien stehen Auf, Stop und Zu jetzt untereinander - so zeigen
die Knoepfe in die Richtung, in die sie fahren. Die Hoehe daneben ist ein
senkrechter Regler mit "oben" und "unten" an den Enden: der Griff steht
dort, wo der Rollladen steht, und niemand muss "100 %" uebersetzen.
Die Neigung hat ein Bild dazubekommen. "30 %" oder "70 %" sagt nicht, ob
man noch hinaussieht; vier Streifen sagen es. Gezeichnet wird die Hoehe,
die eine gekippte Lamelle von vorn zeigt (w * sin(Winkel)) - bei "auf"
sieht man nur ihre Kante und viel Luft dazwischen, bei "zu" deckt sie den
Abstand zur naechsten vollstaendig ab. Genau das, was das Licht abhaelt.
Die Regler faerben ihre Bahn jetzt mit, wie es der Temperaturregler seit
jeher tut - dieselbe Eigenschaft --background-size, nur beim senkrechten
von oben nach unten.
css/solar.css hatte gemischte Zeilenenden und ist dabei durchgehend auf LF
gebracht worden; das erklaert den grossen Diff bei kleiner Aenderung.
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>
Der Grundriss zeigt Raeume, ein Klick darauf zeigte aber nur den
Temperaturregler. Die Rollladen im selben Zimmer waren von dort gar nicht
erreichbar, obwohl die Karte genau sagt, wo sie haengen.
Das Modal zeigt jetzt alles, was dem Raum zugeordnet ist: die
Solltemperatur wie bisher, dazu je Geraet seine Kommandos. Kommandos ohne
Parameter werden Knoepfe nebeneinander - "Auf", "Zu", "Stop" will man
antippen und nicht erst einstellen -, Kommandos mit Parametern bekommen
ihre Eingabefelder und einen Ausloeser. Geraete ohne Kommandos zeigen ihre
Messwerte. Die Reihenfolge der Knoepfe kommt nicht mehr aus dem
Geraete-Suchlauf: die haeufig gebrauchten stehen vorn.
Ausgefuehrt wird ueber restricted/commands.php - das Gegenstueck zu
transports.py, nur fuer den Browser. Dieselbe Zuordnung "welche URL gehoert
zu welchem Weg", nur eben in PHP:
mqtt:// Nutzlast auf das Topic des Parameters
wled:// JSON-Vorlage mit Platzhaltern an /json/state
http:// Abfrageargumente an die Geraete-URL
Tahoma exec/apply, erkannt an der Box-Kennung in der URL
Zwei Umsetzungen derselben Sache sind nicht schoen. Die Alternative waere,
den Runner um eine HTTP-Schnittstelle zu erweitern - dann haengt die
Bedienung daran, dass er laeuft - oder das Web-UI Python aufrufen zu
lassen. Beides waere teurer als diese Datei; der Kommentar sagt das an
beiden Stellen.
Der Endpunkt kennt einen Probelauf: mit "probe" beschreibt er, was er
schicken wuerde, ohne es zu schicken. Damit sind alle vier Wege geprueft,
ohne einen Rollladen in Bewegung zu setzen - Tahoma mit und ohne Parameter,
WLED mit gefuellter Vorlage, Shelly Gen1 und MQTT.
ajax/roomtemp.php entfaellt, es ging darin ausschliesslich um den Regler,
den das Raum-Modal jetzt enthaelt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zusammenlegung
- Die sechs Endpunkte getConsData_/getProdData_{month,year,decade}.php sind
ajax/energyHistory.php?series=&range= gewichen, der gemeinsame Aufbau der
Chart-Daten steht in ajax/chartData.php. Die erzeugte SQL wurde gegen alle
sechs Originale abgeglichen.
- Die 13 Raeume der Home-Ansicht stehen nur noch in restricted/rooms.php.
home.php rendert die SVG-Kacheln daraus, homeMQTT.js bekommt dieselbe
Tabelle als JSON (346 -> 222 bzw. 428 -> 197 Zeilen).
- Gemeinsame JS-Helfer in js/solar/common.js; geteilte Bausteine fuer
Wetterkacheln, Chart-Skripte und das Formular der Ladesteuerung.
- Seitenvorlagen sind jetzt .php und werden eingebunden, statt per
file_get_contents zusammengesetzt zu werden.
Fehlerbehebungen
- ?action=weather fuehrte auf eine leere Seite, es gibt jetzt weather.php.
- homeMQTT.js griff auf ein #meteogram zu, das home.php nie hatte, und brach
damit den readystatechange-Handler ab.
- Die Heizungsseite abonnierte weatherStation/#, zeigte die Werte aber nie an.
Ladelast
- Chart.js, MQTT und Meteogramm werden nur noch auf den Seiten geladen, die
sie brauchen; die Seitentabelle dafuer steht in index.php.
- mqtt.js durch die minifizierte Fassung ersetzt (859 -> 359 KB). MQTT.js
5.14.1, byte-identisch mit dem signierten npm-Tarball.
- Rund 3,1 MB ungenutzte Vendor-Reste und AdminLTE-Demobilder entfernt.
- Solar 1796 -> 1240 KB, Home 1796 -> 873 KB, Historie 1796 -> 843 KB.
Speicher im Browser
- Chart.defaults.devicePixelRatio auf 1.5 gedeckelt. Die Zeichenpuffer der
Diagramme waren mit 20-45 MB der groesste Posten der Seite.
- Das Meteogramm-iframe laedt erst beim Hinscrollen.
Realtime-SVG
- Filterbereiche auf das noetige Mass verkleinert und den wirkungslosen
feOffset-Durchgang entfernt: 60 % weniger gerasterte Filterflaeche bei
pixelgleichem Ergebnis.
- Die Fluss-Animation laeuft ueber transform statt stroke-dashoffset, mit
Punkten statt Strichmuster; sie ruht, wo kein Fluss anliegt.
- Der Wertupdate schreibt nur noch bei echter Aenderung und benutzt
textContent statt innerHTML: 9 statt 86 Elemente pro Update, davon keines
mit Filter. describeArc rundet auf volle Grad.
- waterInfo auf scale(0.90) wie die uebrigen Info-Gruppen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>