48dc2b896aa94406e00e4095123a5e88a24c31a0
127
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
fad6d5ab34 |
Wechselrichter ueber ihren Namen, Symbole auf den Kacheln
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> |
||
|
|
a5920ac7cc |
Raum-Modal fuer Raeume mit Leerzeichen, Messwerte im Aussengelaende
Das Raum-Modal fand die Geraete von "Carport EG" und den fuenf anderen AG-Raeumen mit Leerzeichen nicht - es meldete stattdessen, dem Raum sei nichts zugeordnet. ajax/room.php bereinigte den Schluessel mit [^A-Za-z0-9_] und warf dabei das Leerzeichen weg: aus "AG_Carport EG" wurde "AG_CarportEG", der Vergleich gegen die gespeicherte Zuordnung "AG/Carport EG" ging ins Leere. Aufgefallen ist es erst jetzt, weil sechs von neun AG-Raeumen ein Leerzeichen im Namen haben und keiner der achtzehn auf den anderen Etagen. Durchgespielt: vorher 6 von 27 Raeumen kaputt, danach 0. Messwerte auf den AG-Kacheln, wo es etwas zu messen gibt: Garage solarManager/evPower - die Wattpilot der EG-Partei Carport OG solarManager/evPowerOG - der go-e Charger Garten Wetter/Regen [tage1] - Regen des laufenden Tages Veranda, Terrasse und Pergola behalten ihren Namen: dort haengen Licht und Rollladen, und die zeigt das Raum-Modal. Carport EG bleibt vorerst ohne - die Hoymiles liegen auf solarManager/invertersN, positionsnummeriert, und welcher Strang der Carport ist, steht nirgends im Code. Geraten wird das nicht. tileTopics() zieht Wetter/# von selbst nach, das Abonnement folgt aus dem Topic. Ausserdem der weisse Saum am freigestellten Rendering. Die feste Schwelle liess den ein bis zwei Punkte breiten Uebergang stehen - gemessen 247, 250, 241, 204, 145, und die 241 blieb knapp haengen und leuchtete vor dem schwarzen Grund. Die Flutfuellung frisst jetzt entlang der Kante in immer dunklere Punkte nach und legt zuletzt einen Punkt mit halber Deckung an, damit die Kante nicht treppig wird. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
93fb054b66 |
Zeilenenden vereinheitlichen: LF ueberall ausser im Fremdcode
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> |
||
|
|
abdf6880eb |
Aussengelaende als vierte Etage einhaengen
Das Rendering des Grundstuecks tritt an die Stelle des Vektorplans. Es kommt aus derselben Art Quelle wie die drei Geschossbilder und passt damit besser zu ihnen, als der Plan es je koennte; der hat seinen Zweck erfuellt, indem er die Geometrie sortiert hat. Freigestellt wird mit einer Flutfuellung vom Rand her, nicht mit einem Farbtausch: Weiss kommt auch im Bild selbst vor - Hauswand, Grundstuecksmauer -, und nur was vom Rand aus zusammenhaengend erreichbar ist, ist wirklich Hintergrund. Aufgefuellt statt beschnitten auf 4:3, weil 1024x792 etwas hoeher ist und Wegschneiden das Bild selbst treffen wuerde. Etagenbilder und Schalter in home.php kommen jetzt aus einer Schleife. Ausgeschrieben waren die Blenden bei drei Etagen neun Zeilen und bei vier schon sechzehn, und jede neue Etage haette alle anderen mit angefasst. Die Schalter ruecken ab der vierten Etage von 100 auf 78 Einheiten zusammen, sonst faellt der unterste aus der 300 hohen viewBox. Die Kachelpositionen sind ein Startwert, kein Endstand: Richtung aus dem Modell gerechnet - Westen liegt links unten, Sueden rechts unten -, Lage per Auge im Raster. Der erste Wurf hatte die Terrasse an der falschen Fassade; im Modell liegt sie an der Suedwestecke. Lange Raumnamen brechen jetzt um. "Terrasse OG" stand einzeilig ueber die 24 Einheiten breite Kachel hinaus - sichtbar wurde das erst hier, weil im Aussengelaende jeder Raumname aus zwei Woertern besteht. Nebenbei: xcursor="pointer" am OG-Schalter war ein Tippfehler, der Kreis hatte als einziger keinen Zeiger. Das tote border-Attribut am OG-Bild ist mit weggefallen, SVG kennt es nicht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
182b5b66b4 |
Aussenplan an die Farbgebung der Geschoss-Renderings angleichen
Aus OG.png gemessen, nicht geschaetzt: die hellste Stufe ist genau neutral und liegt bei 200 - heller wird dort nichts -, und je dunkler eine Flaeche wird, desto blauer wird sie. Beides steckt jetzt in aussenSchatten(), das bisher farbtreu gegen Schwarz gerechnet hat. Damit allein fehlte dem Plan aber immer noch das obere Drittel der Helligkeitsskala, das die Renderings haben. Grund war, dass jede Aussenwand denselben Faktor bekam, egal wohin sie zeigte - der Plan hatte gar kein gerichtetes Licht. aussenBeleuchtung() liefert es jetzt aus einer Sonne im Westsuedwesten und ersetzt nebenbei die grobe Zweistufung am Dach. Waagerechte Flaechen bleiben knapp unter der besonnten Wand. Mit vollem Licht waren Boden und Terrassen das Hellste im Bild; im Vorbild sind es die Waende. Die Deckflaeche lief bisher an aussenSchatten() vorbei, sonst haette der Deckel die flachen Flaechen nie erreicht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
f29ed5abfa |
Wandflaechen von hinten nach vorn malen, nicht in Kantenreihenfolge
Der OG-Carport sah aus wie ein Tisch auf vier Beinen: seine Westwand fehlte
scheinbar, man schaute an ihrer Stelle in den Innenraum. Gezeichnet wurde sie
die ganze Zeit - die Kennungen der Flaechen zeigen sie als "Wand W aussen".
Der Fehler lag in der Reihenfolge. Die Flaechen einer Wand entstehen in
Kantenreihenfolge, und die Nordwand ist Kante 3, die Westwand Kante 2. Die
Innenseite der hinteren Nordwand wurde damit nach der Aussenseite der
vorderen Westwand gemalt und uebermalte sie. Bei einem geschlossenen Koerper
faellt das nie auf, weil dort keine Innenseiten sichtbar sind; erst mit
Oeffnungen und Wandstaerke kam es heraus.
Jetzt werden die Wandflaechen eines Koerpers gesammelt, nach Tiefe sortiert
und dann gemalt. Das Tiefenmass ist die Projektion des Flaechenmittelpunkts
auf die Blickrichtung - bei dieser Projektion faellt genau eine Raumrichtung
auf einen Bildpunkt zusammen, ihre Komponenten sind sin(Winkel), cos(Winkel)
und Stauchung/Ueberhoehung. Die projizierte Y-Koordinate taugt dafuer nicht:
in ihr steckt auch die Hoehe, ein hoher Punkt saehe damit weiter hinten aus.
Boden und Dach bleiben ausserhalb der Sortierung - der eine liegt immer
unten, das andere immer oben.
Dazu tragen die Flaechen jetzt eine Kennung ("Carport OG: Wand W aussen").
aussenSvg() liest sie nicht, sie kostet also nichts und macht die Fehlersuche
moeglich, ohne den Zeichner umzubauen - ohne sie waere dieser Fehler
Farbraten geblieben.
Die Schnittkanten sind nebenbei von 0,84 auf 0,66 abgedunkelt. Heller als die
Wand liessen sie die Ecken wie Pfosten aussehen, was den Tischeindruck noch
verstaerkt hat.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
bcc685dcfa |
Der Keil zwischen Garage und Haus ist Garten
Der Gartenumriss laeuft als Schluesselloch um Haus und Veranda herum. In seiner westlichen Ausbuchtung sprang er von [22.7, 24.2] gleich weiter nach [19.9, 25.6] und liess damit den Keil zwischen der Ostkante der Garage, der Westseite der Veranda und der Nordkante des Hofs aus. Dort lag ueberhaupt keine Flaeche, und der schwarze Hintergrund schien durch. Vier Punkte fuehren den Rand jetzt um diesen Keil herum: an der Veranda hinauf, ueber die Nordkante der Garage und an deren Ostkante wieder herunter zum Hof. Der Umriss bleibt dabei ueberschneidungsfrei - nachgerechnet ueber alle 17 Kantenpaare, denn ein Schluesselloch, das sich selbst kreuzt, wuerde die Fuellregel an unerwarteter Stelle aussparen und den Fehler nur verschieben. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
1c80ec588e |
PV aufs Haus, Dachdicke fuer die Carports, Sonnensegel auf zwei Meter
Auf dem OG-Carport liegt keine Anlage - die Module gehoeren aufs Hausdach. Dafuer kann der Zeichner jetzt auch Module auf einer Dachschraege und nicht nur auf einer waagrechten Deckflaeche: "pv" nimmt eine Himmelsrichtung. Auf dem Haus ist es die Suedschraege, und weil die Wiederkehr danach gezeichnet wird, deckt sie die Mitte ab - genau wie auf dem Luftbild, wo die Module links und rechts von ihr liegen. Eingezogen wird dort im Bild und nicht in Metern: die Schraege ist schon projiziert, und auf ihrer Ebene bleibt ein Einzug auch nach der Projektion ein Einzug. Die Carportdaecher haben eine Dicke, mit 30 cm etwas mehr als die 20 cm der Waende. Das brauchte zwingend einen Ueberstand: buendig aufliegend sind Stirnflaeche und Wandflaeche deckungsgleich, die Dicke waere gerechnet und trotzdem unsichtbar. Genau daher kam auch der Eindruck, dem OG-Carport fehle die Westwand - sie war die ganze Zeit da und wurde auch gezeichnet, sie hatte nur keine Kante, an der sie aufgehoert haette. Mit 25 cm Ueberstand steht sie jetzt sichtbar unter dem Dach. Die Pergola ist ein Sonnensegel: eine Bahn Tuch auf zwei Metern, heller und ohne Bauwerk darunter. Dass sie zu schweben scheint, ist richtig so - die Masten waeren bei diesem Massstab duenner als ein Strich. Der Hof laeuft vor dem EG-Carport gerade bis an den Garten weiter; der Carport steht damit auf ihm. Seine suedliche Kante sind dieselben beiden Punkte, die auch im Gartenumriss stehen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
8119645123 |
Waende bekommen Dicke, Carportdaecher werden flacher
Vier Korrekturen am Aussenplan: Die Waende sind Kaesten und keine Flaechen mehr. An einer Oeffnung stand sonst ein Blatt Papier im Raum - Innenseite, Oberkante und die beiden Schnittkanten fehlten, und genau das sah seltsam aus. Die Dicke wird nur gerechnet, wo ein Koerper ueberhaupt offen ist; bei einer geschlossenen Wand sieht man sie nie. Der First der Garage lief vorher schon richtig, Nord-Sued. Die Drehung um 90 Grad war ein Missverstaendnis und ist zurueckgenommen - jetzt steht die Achse ausgeschrieben da, damit bei diesem fast quadratischen Grundriss nicht wieder die zweite Nachkommastelle entscheidet. Die halb offenen Nord- und Suedwaende des EG-Carports sind wieder zu. Die Faehigkeit bleibt im Zeichner, sie wird hier nur nicht mehr gebraucht. Beide Pultdaecher sind auf ein Drittel abgeflacht: 0,27 m statt 0,8 beim OG-Carport, 0,23 statt 0,7 beim EG-Carport - rund vier Prozent Neigung. Beim OG-Carport ist die Wandhoehe dafuer auf 2,23 m gesetzt, damit die hohe Seite bei 2,50 m herauskommt und dort an die Traufe des Garagendachs anschliesst. Nachgerechnet: beide bei 2,50 m. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
d30f4ac0ab |
Aussenplan bekommt Daecher, Oeffnungen und die Farbgebung der Renderings
Der Zeichner konnte bisher nur Klotz mit Satteldach. Jetzt:
* Pultdaecher mit Fallrichtung. Die Richtung kommt aus der Aussennormalen
der genannten Kante und nicht aus einem festen Nord-Sued-Vektor - das
Grundstueck steht zehn Grad schief, und eine Traufe soll parallel zum
Gebaeude laufen und nicht fast parallel.
* Offene und halb offene Seiten. Genannt werden Himmelsrichtungen, die
Kanten sagen selbst, welche gemeint ist. Bei einer halb offenen Seite
bleibt die Haelfte stehen, die von der Oeffnung weiter weg liegt.
* Ein Tor, mittig in seiner Wand.
* Module, die plan auf der Dachflaeche liegen.
* Rueckflaechen fallen weg. Bei positivem Umlauf der Grundflaeche haben die
zugewandten Seiten eine positive projizierte Flaeche - damit verschwinden
die Kanten, die man sonst durch einen Koerper hindurch gesehen haette,
ohne sie einzeln benennen zu muessen.
* Der First laeuft nicht mehr an festen Eckennummern entlang, sondern
zwischen den Mitten zweier benannter Kanten. "achse" ueberschreibt das -
bei der fast quadratischen Garage entschiede sonst die zweite
Nachkommastelle, welche Seite die laengere ist.
Damit steht am Grundstueck: das Haus bekommt seine Wiederkehr auf der
Suedseite (als eigener Koerper auf derselben Grundflaeche - sie liegt
suedlich und damit weiter vorn, deckt das Hauptdach also von selbst richtig
ab; Breite und Tiefe sind vom Luftbild geschaetzt). Die Garage hat ein
begruentes Dach, ihr First liegt quer und ihr Tor nach Sueden. Der OG-Carport
ist nach Sueden offen und faellt zur Strasse hin ab, der EG-Carport ist nach
Westen offen, seine Nord- und Suedwand stehen nur hinten, und er faellt nach
Sueden ab. Auf beiden liegen die Module.
Die Farben folgen den Innenansichten: Weiss und Grau, dazu ein blaeulicher
Grauton fuer die Boeden von Veranda und Terrasse, OG etwas heller als EG.
Rot war ohnehin falsch, seit das Garagendach begruent ist.
Drei Fehler kamen beim Zeichnen heraus:
* Die Dachflaechen nahmen die Firstenden in fester Reihenfolge. Eine der
beiden wurde damit zur Schleife und zeichnete einen Zacken quer ueber das
Haus. Jetzt bekommt jedes Traufende den Firstpunkt, der bei ihm liegt.
* Die Wiederkehr zog ihre Ost- und Westwand mitten durch das Haus. Sie hat
jetzt gar keine Waende: sie sitzt als reines Dach auf sechs Metern.
* Wo eine Seite offen ist, schaute man durch den Koerper auf den schwarzen
Hintergrund - ein Loch, kein Unterstand. Solche Koerper bekommen jetzt
einen Boden.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
ff74ec3c68 |
Der Lageplan des Aussengelaendes ist gezeichnet
Die elf Flaechen sind am Luftbild abgeklickt und danach gerichtet worden: von Hand trifft man keine rechten Winkel, und Ecken, die derselbe Punkt sein sollten, lagen ein paar Dezimeter auseinander. Gerichtet wurde im Bezugssystem des Grundstuecks. Dessen Ausrichtung steckt in den Hauskanten - laengengewichtet gemittelt ueber den vierfachen Winkel, weil vier Kanten in vier Richtungen desselben Rasters zeigen und erst der vierfache Winkel sie zusammenfallen laesst. Ergebnis: -9,77 Grad. In diesem System sind die Gebaeude achsparallel. Sie durch ihr umschliessendes Rechteck zu ersetzen macht sie damit genau rechtwinklig, und das anschliessende Zusammenschnappen der Koordinaten - u und v getrennt - laesst sie Rechtecke bleiben. Andersherum waere das nicht gegangen: schnappt man vorher, stehen die Winkel wieder schief. Hof, Garten und Pergola bleiben, wie sie abgeklickt wurden. Die ersten beiden sind gewachsene Formen, und am dritten haengt ein Sonnensegel - die sind selten rechteckig. Ihre Ecken schnappen trotzdem mit, sonst klafften Luecken zu den Gebaeuden. Ergebnis, alle acht Gebaeude auf 90,0 Grad: Haus 15,3 x 14,2 m Veranda EG/OG 2,4 x 11,5 m Garage 6,5 x 6,4 m Terrasse EG/OG 2,6 x 5,0 m Carport OG 4,0 x 6,4 m Carport EG 9,0 x 4,3 m Die groesste Verschiebung einer Ecke betrug 0,92 m, die meisten lagen unter einem halben Meter. Dazu zwei Fehler am Dach, die erst die Zeichnung zeigte: die Giebel standen offen, sodass an den Schmalseiten die Wand durchschien, und der First lag fest an den Ecken 0/3 und 1/2 - bei einem quer stehenden Gebaeude waere er damit ueber die kurze Achse gelaufen. Jetzt schliessen zwei Giebeldreiecke das Dach, und der First richtet sich nach der laengeren Seite. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
e2b97c049e |
Aussengelaende in Schraegsicht von Suedwesten
Veranda und Terrasse gibt es zweimal, je Wohnpartei eine. In der Draufsicht
laege das obere Paar genau auf dem unteren: nicht auseinanderzuhalten und
schon gar nicht getrennt anzuklicken. Deshalb wird AG nicht flach von oben
gezeichnet, sondern schraeg von Suedwesten - von dort sieht man den Hof, auf
den die Veranden zeigen, und die Ostseite des Hauses traegt nichts, was
vorkommen muesste.
restricted/aussenplan.php haelt die Projektion und die Geometrie. Gezeichnet
wird in Militaerprojektion, nicht in echter Perspektive:
X = x·cos φ − y·sin φ
Y = (x·sin φ + y·cos φ)·STAUCHUNG − z·UEBERHOEHUNG
Der Grundriss bleibt dabei masshaltig - Geraden bleiben gerade, Rechtecke
Rechtecke. Genau deshalb diese und keine perspektivische: die Flaechen lassen
sich am Luftbild von oben abklicken, und dieselben Zahlen ergeben ohne Umweg
die Schraegsicht. Eine echte Perspektive muesste man neu vermessen.
Das Vorzeichen des Winkels bestimmt die Himmelsrichtung. Bei +35° zeigt der
Y-Gradient nach Osten und Sueden, die naechste Ecke waere die suedoestliche;
fuer Suedwesten muss er negativ sein. Was die Paare trennt, ist ohnehin nicht
die Drehung, sondern Stauchung und Ueberhoehung - bei 1,4 stehen Terrasse EG
und Terrasse OG rund 34 Einheiten auseinander, eine Kachel ist 19 hoch.
Hoehen: Traufe 6 m, First 9 m, Carport 2,5 m. Die OG-Ebene ist mit 3 m
angenommen - die halbe Traufhoehe bei zwei Geschossen.
tools/lageplan.php nimmt dafuer jetzt je Flaeche eine Hoehe entgegen und
zeigt die Schraegsicht live neben dem Luftbild: nur dort sieht man beim
Abklicken, ob die Paare wirklich auseinandergehen. Die Vorschau rechnet
dieselben Formeln im Browser nach; massgeblich bleibt der PHP-Code, von dem
spaeter die gezeichnete Etage und die Kachelpositionen kommen.
Dazu die Raeume: aus "Veranda" und "Terrasse" werden je zwei, eine pro
Partei. Welche der vier Geraete zu welcher gehoeren, sagt kein Name - die
beiden Wechselrichter tragen immerhin "OG" ("Veranda OG2-4", "Veranda
UG/OG1"), Licht und Rollladen der Terrasse gar nichts. Sie stehen deshalb
vorlaeufig auf Veranda OG und Terrasse EG.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
3c67303acf |
Zwei Carports, einer je Wohnpartei
Es gibt nicht einen Carport, sondern zwei - einen fuer die EG-Partei und
einen fuer die OG-Partei. Damit heissen sie "Carport EG" und "Carport OG"
und benutzen dieselben Kuerzel wie die Etagen; das Haus hat dieses Vokabular
ohnehin ueberall.
Der go-e Charger steht am OG-Carport: restricted/config.php haelt fest, dass
"og" der go-e ist und "eg" die Wattpilot - und die steht in der Garage, nicht
am Carport.
Welcher der fuenf Wechselrichter auf welchem Carport sitzt, sagt weder sein
Name ("Carport 1-6", "Carport 7-12" ...) noch die OpenDTU, aus der die Namen
stammen. Sie stehen deshalb vorlaeufig zusammen auf dem EG-Carport - ein
benannter Raum ist besser als ein Schluessel, den es nicht mehr gibt. Die
Aufteilung ist ein Klick im Zuordnungsdialog, sobald sie feststeht.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
762af074e8 |
Messblatt fuer den Lageplan des Aussengelaendes
OG, EG und UG haben je ein Rendering in assets/img, Puppenhausschnitt von schraeg oben. Fuer AG gibt es so ein Bild nicht: die Planungssoftware kennt nur das einzelne Gebaeude, nicht das Grundstueck. Der Plan fuer das Aussengelaende entsteht deshalb als Vektor direkt im SVG von home.php. Diese Seite liefert die Koordinaten dafuer. Als Hintergrund liegt das amtliche Luftbild - DOP20 mit 20 cm Bodenaufloesung, live vom WMS der Bayerischen Vermessungsverwaltung, CC BY 4.0. Es liegt also keine Kopie im Repository, und weil es ein True Orthophoto ist, sitzen die Dachkanten ueber dem Grundriss statt perspektivisch daneben - bei Google zeichnet man sonst den Dachueberstand ab. Abgeklickt wird Flaeche fuer Flaeche; unten fallen die fertigen <polygon>-Zeilen fuer home.php heraus und dazu die x/y-Zeilen fuer rooms.php, deren Kachelmitte aus den Ecken gerechnet wird. Welche Flaechen es gibt, sagt die Raumtabelle - ein neuer AG-Raum taucht hier von selbst auf. Das Haus steht davor, obwohl es kein Raum ist: es ist der Umriss, an dem sich beim Zeichnen alles andere ausrichtet, und bekommt folgerichtig keine Kachelzeile. Der Ausschnitt laesst sich ueber ?lat=, ?lon= und ?breite= verschieben, ohne die Datei anzufassen. Die Umrechnung nach UTM32 steckt in der Seite, weil ein quadratischer Ausschnitt in Laengen- und Breitengraden keiner waere: ein Grad Laenge ist auf dieser Breite nur zwei Drittel so lang wie ein Grad Breite. Bauart und Aussehen wie tools/kachelpositionen.php, und aus demselben Grund kein Eintrag im Menue: die Seite wird einmal gebraucht und danach nie wieder. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
d3c1cb4682 |
Aussengelaende wird die vierte Etage AG
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>
|
||
|
|
71f2f844c8 |
gartenwasser_module.py mit CRLF wie seine Nachbarn
Git fuer Windows setzt core.autocrlf=input in seiner System-Konfiguration, die Synology-Seite hat das nicht. Dieselbe Arbeitskopie liegt auf beiden Systemen - unter /volume1/web/smart und als Z:\ -, und die Datei war deshalb im Arbeitsverzeichnis CRLF, im Repository aber LF: Windows sah sie sauber, die NAS dauerhaft geaendert. Ein "git pull" dort waere daran haengengeblieben. Jetzt liegt sie so im Repository, wie sie im Arbeitsverzeichnis steht - und wie die uebrigen Discovery-Module, die ebenfalls mit CRLF eingecheckt sind. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
7b9c9362a6 |
Discovery loescht keine laufenden Messwerte mehr
Die Upserts schrieben current_value = VALUES(current_value). Ein Modul, das keinen Startwert kennt - das Gartenwasser-Modul zum Beispiel, dessen Werte ausschliesslich per MQTT hereinkommen -, liefert dort NULL, und damit ueberschrieb jeder Discovery-Lauf den laufenden Wert mit NULL. Der Runner holte das nicht zurueck. Er merkt sich in `geschrieben`, was er zuletzt in die Datenbank geschrieben hat, und `regelwerk_laden` uebernimmt diesen Merker beim Neuladen per setdefault - der naechste hereinkommende Wert war damit "unveraendert" und wurde nicht erneut geschrieben. Im Editor stand danach "Regen heute (= )" statt "(= 0,0 mm)", und zwar bis sich der Wert zufaellig einmal aenderte. Bei "Bewaessert heute" koennen das Tage sein. Jetzt COALESCE: ein NULL aus dem Modul heisst "kein Startwert" und laesst stehen, was da ist. Module, die beim Suchen wirklich einen Wert ablesen - Tahoma, Shelly, WLED -, schreiben ihn weiterhin. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
03f823ae39 |
Bewaesserung meldet retained, ob sie gerade laeuft
Die Firmware der Ventilsteuerungen liefert seit heute ein retained Gartenwasser/<x>/Running mit "running", "running<Ventil>" und "mode", dazu das schon vorbereitete "daysSinceWatering<Ventil>" in LastWatering. Der Messwert "Laufende Automatik" las diese Angabe bisher aus Timers und weicht deshalb. Timers ist nicht retained und wird nur im Sekundentakt gesendet, solange etwas laeuft: der Runner sah im Ruhezustand gar nichts und behielt nach einem Lauf den zuletzt gesehenen Wert - also genau das Gegenteil von verlaesslich. Running ist retained und faellt ueber eine Last-Will-Nachricht auch dann auf false, wenn die Steuerung mitten im Giessen wegbricht. Neu sind damit je Steuerung "Bewaesserung laeuft" und "Laufender Modus", dazu je Zone ein eigener Laufmerker - aber nur, wo eine Steuerung mehr als eine Zone bedient. Bei "hinten" waere er derselbe Wert wie der Merker der Steuerung, und ein Messwert, der nie etwas anderes sagt, macht die Auswahl nur laenger. "Bewaesserung laeuft = NEIN" ist der Waechter fuer jede Regel, die hier etwas anstossen will: die Zonen einer Steuerung haengen an derselben Leitung, zwei gleichzeitig gibt es nicht. Die beiden alten Zeilen "Laufende Automatik" muessen von Hand aus actor_states verschwinden - das Discovery schreibt nur mit ON DUPLICATE KEY UPDATE und loescht nie. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
128acae48e |
Bewaesserung und Regen werden Geraete im Automatik-Editor
Erster Teil der Ablosung von restricted/gartenbewaesserung/auto_watering.py.
Das Skript holt heute stuendlich den Regen, vergleicht ihn mit Schwellen
aus einer ZONES-Tabelle im Quelltext und schaltet selbst. Kuenftig
entscheidet der AutoAction-Runner, und die Schwellen stehen im Editor.
Dafuer legt ein neues Discovery-Modul drei Geraete an. Es sucht nichts,
sondern schreibt sie fest hin - wie das Logic-Modul auch:
* Die beiden ESP32-Ventilsteuerungen sprechen zwar MQTT, aber ohne
Home-Assistant-Discovery; das MQTT-Modul findet sie deshalb nicht.
* "Regen" ist gar kein Geraet, sondern das, was gatherRainData.py im
SolarManager von Open-Meteo holt und nach Wetter/Regen legt.
Je Steuerung entsteht ein Kommando "Automatik" mit dem Modus als
Parameter - ein Kommando ohne Parameter schickt im Runner eine leere
Nutzlast, der Klartext ("Hoch", "Trog", "Vorn") muss also der Parameter
sein. Dazu je Zone zwei Messwerte:
Bewaessert heute ersetzt die Zwoelf-Stunden-Sperre des Skripts;
"heute noch nicht" heisst hier "= 0". Die
Steuerung setzt den Wert um Mitternacht zurueck,
der Runner kann den mitgelieferten "wateringDay"
naemlich nicht pruefen.
Tage seit Bewaesserung ersetzt max_dry_days. Ein Zeitstempel nuetzte
nichts: der Runner vergleicht Datumsangaben nur
gegen einen festen Wert, "laenger als fuenf Tage
her" ist damit nicht formulierbar. Die Firmware
liefert deshalb gleich die Anzahl Tage.
Die Regensummen kommen als tage1 bis tage7 herein; welche davon als
Messwert auftauchen, entscheidet allein dieses Modul. Der Sammler
veroeffentlicht immer alle sieben, damit sich die beiden Repositorien
nicht ueber eine Fensterliste einigen muessen.
Die Logseite kennt rainOutput.log jetzt ebenfalls.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
37962224c1 |
Geraeteauswahl im Automatik-Editor gruppiert nach Etage
Bisher stand ueber jedem Raum eine eigene Ueberschrift - bei neunzehn Raeumen aus rooms.php also neunzehn Stueck, jede mit der Etage davor: "OG - Bad", "EG - Bad", "UG - Bad". In einer Liste, die fuenfzehn Zeilen hoch ist, sah man dadurch mehr Ueberschrift als Geraet. Jetzt gruppiert nur die Etage, und der Raum steht klein und rechtsbuendig an jeder Zeile. Sortiert wird innerhalb der Etage nach Raum (Reihenfolge wie in rooms.php), sodass die Geraete eines Raums trotzdem beisammen stehen; aus zwanzig Ueberschriften werden fuenf. Ein Raum, den es in rooms.php nicht mehr gibt, bekommt eine eigene Ueberschrift, statt stillschweigend unter den Unzugeordneten zu verschwinden. Die Suche laeuft zusaetzlich ueber den Raum: "bad" findet damit auch den Handtuchtrockner, der im Bad haengt, ohne es im Namen zu tragen. In der Trefferliste steht keine Ueberschrift darueber, deshalb traegt dort jede Zeile die volle Angabe "OG - Bad". Dafuer nennt raumListe() Etage und Raum jetzt auch einzeln, und der Geraetekatalog reicht beides durch - der Schluessel "Etage/Raum" muss so nicht im JavaScript wieder auseinandergenommen werden. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
77651a860a |
Verwaistes wattpilot.py heisst jetzt wattpilot_unused.py
Seit der Umstellung auf MQTT ruft es niemand mehr auf - kein PHP, kein Startskript, kein Aufgabenplaner. Der neue Name macht das sichtbar, bevor die Datei irgendwann geloescht wird; das Wallbox-Passwort steht darin weiterhin im Klartext. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
4bbc7ee7a7 |
Enyaq mit 77 kWh statt 79
Von der Skoda-Website abgelesen. Datenbanken im Netz nennen fuer den RS des Modelljahrs 2026 teils 79 kWh nutzbar - der Hersteller ist die verlaesslichere Quelle. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
2ef946c732 |
Akkugroessen der beiden Autos stimmen und stehen in der Konfiguration
Der Schieberegler "Zusaetzlich benoetigte Ladung" rechnet Prozent in Wattstunden um. Dafuer standen bisher drei verschiedene Zahlen im Code: 140 Wh/% beim Schreiben der EG-Wallbox, 90 Wh/% beim go-e und feste 14000 Wh beim Zurueckrechnen im Browser - fuer beide Autos dieselbe. Eine Einstellung von 50 % am go-e schrieb 4500 Wh und las sich beim naechsten Oeffnen als 32 % zurueck. Jetzt kommt die Zahl aus einer Quelle: restricted/config.php nennt Auto und nutzbare Akkukapazitaet je Wallbox, carForm.php gibt die Wattstunden je Prozent als data-Attribut an den Schieberegler weiter, und das JavaScript rechnet damit zurueck statt mit einer festen Konstanten. EG: Skoda Enyaq RS, Modelljahr 2026, 84 kWh brutto / 79 kWh nutzbar OG: Jeep Compass 4xe, 11,4 kWh Das Lademodal zeigt Auto und Kapazitaet jetzt unter dem Regler an - damit sichtbar ist, worauf sich die Prozente beziehen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
61ea98db1d |
Beide Wallboxen werden gleich bedient
carEG.php und carOG.php waren fast identisch und unterschieden sich nur im Transportweg: der go-e bekam seine Kommandos per HTTP, die Wattpilot ueber einen eigenen Python-Prozess je Klick, der sich einen Websocket aufbaute, anmeldete, ein Feld setzte und wieder starb. Beide haengen laengst am selben MQTT-Broker - der go-e mit eigenem Client (mce=true, mcr=false), die Wattpilot ueber wattpilot_bruecke.py. Beide nehmen Kommandos auf <praefix><schluessel>/set entgegen. Die Steuerung steht deshalb jetzt einmal in carSteuerung.php; was die Wallboxen wirklich trennt - Topic-Praefix, die Namen ate/att gegen ftt/fte und die Wattstunden je Prozent - steht als Tabelle in restricted/wallboxen.php. Nebenbei faellt damit /volume1/homes/wagner/wattpilot.py weg, das das Passwort der Wallbox im Klartext enthaelt und ausserhalb jedes Repos liegt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
b4b5e59cb4 |
Tooltip der MQTT-Bruecke sagt, was sie tatsaechlich tut
"Reicht die Messwerte an den Browser weiter" verschwieg die Quelle und den Weg. wsMQTTbridge.py haengt am Websocket der Wetterstation (ws://192.168.179.42/ws) und veroeffentlicht die Werte unter dem MQTT-Topic weatherStation; der Browser holt sie erst von dort. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
cbc9353f0a |
Protokollseite: die Logs der Hintergrundprozesse im Dashboard
Bisher kam man an die Ausgabe von solarManager.py, dem Runner und den uebrigen Dauerprozessen nur per SSH heran. Die neue Seite unter "Protokolle" zeigt sie: links die fuenf Dateien mit Groesse und Alter - eine, die seit Tagen nicht gewachsen ist, faellt so auf, ohne dass man sie oeffnet -, rechts die Zeilen mit Volltextsuche, Level-Filter und optionalem Nachladen. Nicht in die Datenbank geschrieben, obwohl das naheliegt: ein Log muss genau dann noch funktionieren, wenn die Datenbank es nicht tut. Ein Handler, der nach MySQL schreibt, verschluckt ausgerechnet die Meldung "Datenbank nicht erreichbar" - also die, wegen der man nachsieht. Was strukturiert ausgewertet werden soll, steht ohnehin in automation_log. Gelesen wird rueckwaerts in Bloecken: 5000 Zeilen aus der 329 MB grossen Datei der Wallbox kosten 46 ms, weil nur das Ende angefasst wird. Sucht man ins Leere, bricht der Server nach 4 MB ab und sagt es auch. Die beiden Prozesse formatieren unterschiedlich - der eine stellt das Level voran, der andere den Zeitstempel -, deshalb wird beides gesucht statt an fester Stelle erwartet. Zeilen ohne eigenes Level erben das der Zeile darueber, sonst filterte "nur Fehler" die Tracebacks weg, die den Fehler erklaeren. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
abfa84dff8 |
Geaenderte Bedingungen erreichen den Runner wieder
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> |
||
|
|
d285ec27a0 |
Einstellungsseite, Skoda-Seite und Karte
Sammelstand der offenen Arbeit im Dashboard. Einstellungen: eine Eingabemaske fuer die Energiepreise unter restricted/settings.php, dazu costs.php als Modell und ajax/settings.php als Endpunkt. Die Preise stehen jetzt in gridCosts, gasCosts und fuelCosts statt fest im Quelltext von getStats.php; die Jahresstatistik rechnet ueber LEAD() den jeweils gueltigen Zeitraum aus und schlaegt den anteiligen Grundpreis auf. Eingegeben wird in gewohnten Einheiten - l/100 km, kWh/100 km, Euro je Liter -, umgerechnet wird beim Speichern. solarLog_costs.sql beschreibt die Umstellung der Tabellen. Skoda: eigene Seite mit Live-Werten ueber MQTT und Historie ueber ajax/skoda.php, Kommandos ueber ajax/skodaCmd.php. Karte: Leaflet mit einem eigenen Kachel-Zwischenspeicher (ajax/tile.php), dessen Ablage unter tiles/ nicht ins Repository gehoert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
c9a9e16b21 |
Verweise auf den Runner nachgezogen
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> |
||
|
|
cbddd664e3 |
Runner zieht zum SolarManager um
Der AutoAction-Runner ist ein Hintergrundprozess und gehoert damit zu den anderen, nicht ins Web-Verzeichnis. Er liegt jetzt unter /volume1/homes/wagner/SolarManager/autoActions und wird von dort zusammen mit dem Manager gestartet; versioniert ist er im Repository SolarManager. Browser und Runner reden ohnehin nur ueber die Datenbank homeMesh miteinander - das Web-UI kennt den Pfad nicht und muss ihn nicht kennen. Die Verweise in commands.php und homeMesh_automations.sql zeigen bereits auf den neuen Ort. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
79a55aeafd |
Kacheln zeigen frei gewaehlte Messwerte, Heizung nur wo eine haengt
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> |
||
|
|
9f52b095b3 |
Kachelpositionen: Messblatt unter tools/, fuenf neue Kacheln
Wo eine Kachel im Grundriss hingehoert, liess sich bisher nur schaetzen - und der Bezugspunkt ist auch noch die linke obere Ecke, nicht die Mitte, die man im Auge hat. tools/kachelpositionen.php nimmt beides ab: Grundriss mit Raster, die vorhandenen Kacheln in Originalgroesse samt einem Punkt an ihrem Bezugspunkt, eine Geisterkachel am Zeiger und darunter die Zeile, die in rooms.php gehoert. Ein Klick friert sie ein. Als PHP-Seite im Webverzeichnis, nicht als erzeugte HTML-Datei: so liest sie ihre Raeume live aus restricted/rooms.php und veraltet nicht, wenn ein Raum dazukommt. Geprueft an bekannten Werten - auf die Mitte einer vorhandenen Kachel gezeigt kommt genau ihre gespeicherte Koordinate heraus. Damit haben jetzt alle Raeume eine Kachel: EG Kueche und Technik, UG Technik, dazu OG Kueche und Technik als neue Raeume. Sie zeigen vorerst die Platzhalter der Temperaturvorlage - was auf ihnen stehen soll (Leistung, Wasserverbrauch), ist der naechste Schritt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
08e8e68a61 |
Raum-Modal: Solltemperatur wirkt sofort, kein Speichern-Knopf mehr
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> |
||
|
|
e8612bebb8 |
Raum-Modal: Heizung in einen eigenen Reiter, Spalten buendig
Die Heizung stand ueber den Tabs und war in jedem Raum sichtbar, auch wenn man wegen der Rollladen gekommen war. Sie ist jetzt eine Gruppe wie die anderen - nur baut sie sich nicht aus einer Geraeteliste, sondern ist ein Regler fuer den Raum. zeichneGruppen() nimmt dafuer fertige Inhalte entgegen. Bei einem Raum mit nur einem Thermostat bleibt die Leiste weg, dort sieht es aus wie vorher. Aus den Pillen sind Reiter geworden - sie sehen jetzt aus wie das, was sie sind, und nicht wie eine Knopfreihe. Position und Neigung standen um 0,35 rem versetzt: die Regel fuer gestapelte Regler (Helligkeit ueber Farbe) griff auch auf die zweite Spalte, die aber danebensteht. Sie gilt jetzt nur noch fuer Regler, die keine Spalte sind - nachgemessen stehen beide Bahnen auf 181/104. Das Fensterbild ist von "so breit wie moeglich" auf 5 rem zurueckgenommen; der uebrige Platz verteilt sich auf die Zwischenraeume, statt das Bild breitzuziehen. Zwischen ihm und den Bedienelementen liegt jetzt Luft. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
18557021b0 |
Raum-Modal: Fensterbild zeigt Hoehe und Neigung, Regler nach rechts
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> |
||
|
|
e7fd7715ef |
Raum-Modal: Regler gedreht statt writing-mode, eigenes Aussehen
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>
|
||
|
|
f6e0414866 |
Raum-Modal: Gruppen als Tabs, Jalousien senkrecht bedienen
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> |
||
|
|
17f972d081 |
Raum-Modal: Bedienelemente statt Kommandoliste
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>
|
||
|
|
131d7cc46d |
Jalousien: Zu heisst zweifach schwenken, Versand laeuft im Hintergrund
Die Kugelschreiber-Mechanik betrifft jedes Kommando, nicht nur
setOrientation, und sie betrifft auch das Schliessen: ein "Zu" faehrt die
Jalousie zwar herunter, die Lamellen bleiben aber bei etwa 30 % offen
stehen. Dicht wird sie erst durch das zweifache Schwenken.
Die Regel lautet jetzt einheitlich: derselbe Befehl zweimal - erst mit
Neigung 0, dann warten, bis die Fahrt steht, dann mit dem gewuenschten Wert.
Die Position bleibt dabei erhalten, die Jalousie faehrt also nur einmal.
Zu -> [100,0] warten [100,100]
Neigung 20 -> direkt, unter der Schwelle
Neigung 80 -> [0] warten [80]
Position 40 Neigung 50 -> [40,0] warten [40,50]
"Zu" wird dabei nur umgeschrieben, wenn das Geraet Position und Neigung
zusammen setzen kann - der einfache Rollladen "Terasse" hat keine Lamellen
und bekommt weiter das rohe down.
Gewartet wird auf zwei Auskuenfte zusammen, weil einzeln keine traegt:
core:MovingState trug die lange Fahrt (gemessen 61 s), wird bei kurzen
Neigungsfahrten aber nie gesetzt; die Zustandswerte sind die Wahrheit,
zeigen direkt nach dem Kommando aber noch den alten Stand. Fertig heisst:
nichts faehrt mehr, die Ziele stimmen, und es wurde entweder ein "faehrt"
gesehen oder der Vorlauf von acht Sekunden ist um.
Und weil ein "Zu" damit ueber eine Minute dauert, schickt der Runner nicht
mehr selbst: der neue Versand nimmt die Kommandos entgegen und arbeitet sie
in eigenen Faeden ab - je Geraet der Reihe nach, ueber Geraete hinweg
nebeneinander. Sonst haette eine einzige Jalousie die ganze Auswertung fuer
eine Minute angehalten: keine Zeit-Ausloeser, keine Messwerte, und mehrere
Rollladen in einer Automatik haetten sich aufaddiert. Die Datenbank bleibt
dabei im Hauptfaden - die Faeden melden nur ihr Ergebnis zurueck, eine
pymysql-Verbindung ist nicht fuer mehrere Faeden gedacht.
Nachgemessen: Einreihen kehrt sofort zurueck, zwei Kommandos an dasselbe
Geraet laufen nacheinander (6 s, dann 12 s), drei an verschiedene Geraete
gleichzeitig, Fehler kommen zurueck, und die Schleife lief in 20 Sekunden
20 Takte durch.
Die Bedienung im Modal wartet weiterhin - dort sitzt ein Mensch vor einem
Fortschritt und klickt einmal. ajax/room.php hebt dafuer die Zeitgrenze auf
180 Sekunden an, wie es ajax/tahoma.php an derselben Stelle auch tut.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
d557a1651f |
Neigungs-Umweg gilt fuer jedes Kommando, nicht nur setOrientation
Die Kugelschreiber-Mechanik haengt nicht am Kommando, sondern an der Neigung selbst - "Position+Neigung" braucht den Umweg ueber 0 % genauso wie "Neigung". Erkannt wird er deshalb am Parameter und nicht am Kommandonamen: beide Kommandos nennen ihren Neigungsparameter "Neigung", das Geraetemodell liefert die Zuordnung also mit. Geprueft im Probelauf in beiden Versendern: Position+Neigung mit 20 % geht direkt raus, mit 90 % mit vorgeschaltetem Umweg. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
1b9bbc9857 |
Jalousien: Neigung ueber 30 % nur mit Umweg ueber 0 %
Die Aussenjalousien haben eine Kugelschreiber-Mechanik: beim Herunterfahren stehen die Lamellen bei etwa 30 %. In Richtung 0 % laesst sich von jeder Stellung aus direkt neigen; darueber hinaus rastet die Mechanik nur um, wenn sie vorher einmal auf 0 % war. Ein "Neigung 80 %" ohne diesen Umweg bleibt wirkungslos. Beide Versender wissen das jetzt: restricted/commands.php fuer die Bedienung im Raum-Modal, transports.py fuer den Runner. Bei setOrientation mit einem Ziel ueber 30 % geht erst eine 0 raus, dann wird gewartet, bis die Box diese 0 auch meldet, und erst danach der eigentliche Wert. Der Umweg gehoert dorthin und nicht in die Bedienung - sonst muesste ihn jeder kennen, der eine Jalousie anspricht, auch beim Anlegen einer Automatik. Gewartet wird auf core:SlateOrientationState und nicht auf core:MovingState: bei Neigungsfahrten meldet die Box waehrend der ganzen Bewegung "faehrt nicht". Genau darauf war ich vorher hereingefallen. Zwei Messungen aus der Erprobung stecken in den Konstanten: von 100 % auf 0 % braucht eine Jalousie gut fuenfzehn Sekunden, deshalb die Grenze von 25 s. Im Versuch ging ein "Neigung 100 %" von 79 % aus nach 14 s durch - echtes Warten, nicht die Notbremse. Dabei ein Fehler, den ausgerechnet das Ziel 0 verdeckt haette: die PHP-Leseroutine liefert null, wenn die Abfrage fehlschlaegt, und intval(null) ist 0. Die Warteschleife hielt einen fehlgeschlagenen Lesevorgang damit fuer "Ziel erreicht" und brach sofort ab - der Umweg fand also gar nicht statt, es sah nur so aus. In der Python-Fassung ist dieselbe Stelle jetzt ebenfalls ausdruecklich gegen ein fehlendes Feld abgesichert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
98a1da6cd5 |
Raum-Modal: Heizung, Rollladen und Licht auf einer Seite
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>
|
||
|
|
bed1884b04 |
Raeume ohne Kachel: Kueche EG und die beiden Technikraeume
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> |
||
|
|
4b47372015 |
Geraete den Raeumen zuordnen
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>
|
||
|
|
2ac504ca29 |
Geraeteauswahl: Suchfeld statt Auswahlliste
Die Gruppierung nach Geraeteart hat die Liste geordnet, aber nicht kuerzer
gemacht: elf Jalousien bleiben elf Zeilen. Statt der Auswahlliste steht
jetzt ein Knopf in der Zeile, der eine durchsuchbare Liste ueber die volle
Breite aufklappt.
Gesucht wird ueber Beschriftung UND Geraeteart zugleich, also quer zur
Gruppierung: "bad" findet die drei Thermostate im Bad und die zwei
Jalousien "Bad Links"/"Bad Rechts", "jalousie" alle elf auf einmal. Ohne
Suchtext bleiben die Zwischenueberschriften stehen; sobald gefiltert wird,
faellt die Gruppierung weg, weil die Treffer dann quer ueber alle Arten
stehen und die Art ohnehin an jeder Zeile mitlaeuft.
Die aufgeklappte Liste haengt unter der ganzen Zeile und nicht in ihr - in
einer input-group stuende sie sonst als weitere Spalte daneben. Escape
schliesst, Enter nimmt den ersten Treffer, ein Klick daneben schliesst
ebenfalls. Es ist immer hoechstens eine offen.
Dabei zwei Sachen mitgenommen:
Eine neue Zeile beginnt jetzt ohne Geraet ("Gerät wählen …"). Bisher stand
dort das erste Geraet mit seinem ersten Messwert - nach dem
Geraete-Discovery also "Bad Links: Gesperrt = ", eine Bedingung, die
niemand gemeint hat und die man erst wegklicken musste. Der Satz darunter
sagt in dem Fall "Noch kein Ausloeser", und der Server lehnt eine
unvollstaendige Bedingung ohnehin ab.
Auf dem Handy quetschten sich Geraet, Messwert, Vergleich, Wert, Einheit
und Papierkorb in eine Zeile - uebrig blieben "Therm OG Bad" und "te".
Unter 576 px bekommen Geraet und Messwert jetzt je eine eigene Zeile. Die
Regel braucht die input-group-Klasse im Selektor: solar.css wird vor
AdminLTE geladen, und Bootstraps ".input-group > .form-select" haette sonst
dasselbe Gewicht und wuerde als spaeteres Blatt gewinnen.
Geprueft bei 375 px und am Rechner.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
00f5944a7a |
Geraeteauswahl: nach Art gruppiert, Namen geputzt
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> |
||
|
|
9f8c9016c2 |
Gartenbewaesserung: Morgenfenster, Trockenheits-Notlauf, Regen von heute
Vier Aenderungen an auto_watering.py: Zeitfenster morgens statt nur abends. Ueber --schedule laesst sich "morning", "evening" oder "both" waehlen; morgens reicht das Fenster vom Sonnenaufgang bis SUNRISE_FOLLOW_MINUTES danach, abends wie bisher von WATERING_LEAD_MINUTES vor Sonnenuntergang bis zum Sonnenuntergang. Im Modus "both" haelt die 12-Stunden-Sperre aus RECENT_WATERING_LOOKBACK_HOURS das Ganze selbstregulierend: zweimal am Tag wird nur bei langen Sommertagen wirklich bewaessert. Eigener Ausloesezeitpunkt je Fenster. Die Fenster sind mit 70 Minuten breiter als das stuendliche Cron-Raster, es fallen also je nach Sonnenzeit zwei Laeufe hinein. Auf das LastWatering-Topic der Ventilsteuerung ist als Schutz kein Verlass - es wird unter Umstaenden erst spaeter aktualisiert, und zu kurze Laeufe werden bewusst ignoriert. Das Skript merkt sich seinen Auslusezeitpunkt deshalb selbst im retained RainStatus der Zone und loest pro Fenster und Kalendertag nur einmal aus. Nachrichten der Vorversion, die nur ein "last_trigger" kannten, werden konservativ fuer beide Fenster uebernommen, damit am Umstellungstag nicht doppelt bewaessert wird. Der heutige Regen zaehlt mit. Bisher wurden nur abgeschlossene Tage summiert - hatte es seit dem Morgen geschuettet, half das der Entscheidung am Abend nicht. Jetzt kommt der bereits gefallene Regen des laufenden Tages aus den stuendlichen Werten dazu, ohne die Vorhersage fuer die restlichen Stunden. Das Fenster verschiebt sich entsprechend: threshold_days zaehlt heute als letzten Tag mit. Trockenheits-Notlauf. Unabhaengig vom Regen wird bewaessert, wenn die letzte Bewaesserung laenger als max_dry_days zurueckliegt - fuer die Hochbeete auf fuenf Tage gesetzt, fuer Troege und Garten vorn aus. Ist kein Zeitpunkt bekannt, wird nicht ausgeloest: sonst erzwaenge jeder Broker-Neustart eine Bewaesserung. Geprueft mit --dry-run in beiden Modi: die Fenster werden richtig gerechnet (06:36-07:46 und 18:52-20:02), und die Zonen entscheiden wie erwartet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
17678da824 |
Zahlencodes als Klartext
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>
|
||
|
|
56b2ab1648 |
Mehrere Messwerte auf einem Topic auseinanderhalten
Der go-eCharger schickt sechzehn Zahlen als JSON-Feld auf einem einzigen
Topic, die Wechselrichter und die WLAN-Felder machen es aehnlich. Welcher
Teil der Nutzlast gemeint ist, steht im value_template der
Home-Assistant-Discovery - das Modul las es bisher nur, um den Datentyp zu
raten, und warf es dann weg. Alle sechzehn Messwerte bekamen denselben
Rohtext.
actor_states hat jetzt eine Spalte value_path: ein Pfad in die Nutzlast, in
derselben Schreibweise, die WLED schon benutzt ("[4]", "ssid",
"seg[0].col[0]"). NULL heisst weiterhin: die ganze Nutzlast.
Gelesen wird aus dem Template nur der einfache Fall - ein Zugriff auf
value_json und was danach an Punkten und Klammern folgt. Von den 40
Vorlagen, die hier auf dem Broker liegen, sind 28 genau das. Die uebrigen
zwoelf sind entweder die ganze Nutzlast (dann ist NULL richtig) oder
Werttabellen wie ['Idle','Charging'][value_json|int] - das ist kein Pfad,
sondern eine Uebersetzung von Zahl nach Text, und dort bleibt es beim
bisherigen Verhalten. Kein einziger Fehltreffer: die Werttabellen liefern
sauber None statt eines erfundenen Pfades.
Die Pfad-Auswertung stand schon im WLED-Transport; sie ist jetzt eine
gemeinsame Funktion, die sich beide teilen. MQTT wertet die Nutzlast einmal
je Nachricht aus und verteilt sie danach an alle Messwerte des Topics.
Nachgemessen: die sechzehn nrg-Werte liefern jetzt sechzehn eigene Zahlen
statt sechzehnmal dasselbe, die Leseabdeckung bleibt bei 440 von 441, und
ein weiterer Discovery-Lauf aendert keine Zeile.
Die restlichen geteilten Topics sind kein Fehler: bei den Wechselrichtern
lesen "Limit Persistent" und "Limit NonPersistent" wirklich denselben Wert
und unterscheiden sich nur im Kommando-Topic, und beim Thermostat liest die
Klima-Entity dieselbe Temperatur wie der Sensor.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
631baa7333 |
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> |