df484321339bc2d91b90757b805a09f66a8c287c
170
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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> |
||
|
|
0cb1fc635e |
Etage ist Pflicht
Die Auswahlliste im Editor bot ein "-" an. Eine Automatik ohne Etage taucht aber in keinem der drei Reiter auf und ist danach nur noch in der Datenbank zu finden - anlegen und sofort verlieren. Der Eintrag ist weg, und der Zustand ist jetzt an drei Stellen unmoeglich statt nur unwahrscheinlich: die Liste kennt nur noch OG, EG und UG, saveAutomation lehnt alles andere mit einer Meldung ab statt still auf "" zurueckzufallen, und im Enum der Spalte gibt es den leeren Wert nicht mehr. Die Reihenfolge in der Liste ist jetzt OG, EG, UG wie bei den Reitern - damit trifft der Rueckfall auf den ersten Eintrag dieselbe Etage wie die Startseite. Kennt die Liste die Etage eines Datensatzes nicht, faellt sie darauf zurueck, statt leer stehen zu bleiben und beim Speichern "" zu schicken. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
27e5c0d331 |
Sperrzeit je Automatik in drei Stufen
Die steigende Flanke allein schuetzt nicht gegen einen Messwert, der um die Schwelle pendelt: "Temperatur > 22" bei 22,1 / 21,9 / 22,1 Grad ist jedes Mal eine echte Flanke, und ueber MQTT koennen die Werte im Sekundentakt hereinkommen. Gemessen: fuenf Kommandos in einer halben Minute. automations.lockout_secs sagt jetzt, wie lange nach einer Ausloesung nicht wieder geschaltet wird. Der Editor bietet drei Stufen an - ohne, eine Minute, eine Viertelstunde -, weil die passende Wahl am Geraet haengt und nicht an einer Zahl: ein Rollladen soll nicht alle zwanzig Sekunden losfahren, eine Lichtfarbe darf das. Gespeichert werden Sekunden, damit eine vierte Stufe eine Zeile in lockoutChoices() ist und keine Wanderung durch die Datenbank. Vorbelegt ist eine Minute. Eine Flanke in der Sperrzeit wird verworfen, nicht aufgehoben. Ein Rollladen, der eine Viertelstunde spaeter doch noch losfaehrt, weil vor langer Zeit einmal eine Schwelle gestreift wurde, waere unangenehmer als einer, der gar nicht faehrt - und der naechste echte Anlass nach Ablauf der Sperre kommt ohnehin durch. Verworfene Flanken stehen auf DEBUG und nicht in automation_log, sonst waere die Tabelle bei einem zappelnden Sensor voll davon. force_once bleibt unberuehrt: es greift nur, wenn im Fenster gar nichts gelaufen ist - dann ist auch keine Sperre aktiv. Nachgemessen am pendelnden Sensor: mit 60 s Sperre ein Kommando, ohne Sperre fuenf. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
25d3c47bd3 |
Sonnenstand: ueber die Tagesgrenze rechnen statt abschneiden
Ein Versatz, der ueber Mitternacht hinausreicht, wurde bisher am Tagesrand abgeschnitten. Damit liessen sich "sechs Stunden vor Sonnenaufgang" oder "fuenf Stunden nach Sonnenuntergang" gar nicht mehr formulieren - solche Angaben sind aber gewollt und landen eben am Vorabend bzw. nach Mitternacht. Gerechnet wird jetzt modulo Tag. Verglichen wird die Uhrzeit innerhalb des Tages: ein Ziel jenseits von Mitternacht gilt als diese Uhrzeit am selben Tag. Bei "+" und "-" ist das genau der gemeinte Zeitpunkt, bei "ab" und "vor" verschiebt sich der wahre Bereich entsprechend mit - das steht so in der README. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
ee417f302f |
Zeit-Ausloeser: "um" ergaenzt, Sonnenstand vervollstaendigt
Bei Uhrzeit und Datum gab es nur "ab" und "vor". Der haeufigste Fall - eine Aktion genau um 16:30 - liess sich damit gar nicht ausdruecken. "um" ist jetzt der erste Eintrag und damit die Vorbelegung. Der Hinweis von frueher bleibt trotzdem richtig und steht in der README: "um" trifft nur eine einzige Minute, faellt der Runner ausgerechnet in dieser Minute aus, ist die Automatik fuer den Tag verloren. "ab" holt der naechste Takt nach. Wer beides will, hakt force_once an. Beim Sonnenauf- und -untergang fehlte die halbe Tabelle: der Versatz kann davor oder danach liegen, und verglichen werden kann davor, danach oder genau. Statt zwei gibt es jetzt sechs Operatoren - "+", "-", "ab +", "ab -", "vor +", "vor -". Das Vorzeichen steckt im Operator, weil der Editor eine einzige Auswahlliste zeigt und nicht zwei Bedienelemente fuer eine Angabe. Rutscht ein Versatz rechnerisch ueber den Tagesrand (Sonnenaufgang 05:34 minus sechs Stunden), bleibt es beim Tagesrand statt auf die andere Seite von Mitternacht zu springen - "kurz vor Sonnenaufgang" soll nicht ploetzlich gestern abend bedeuten. Der Editor brauchte keine Aenderung: er liest Wert und Beschriftung der Operatoren aus dem Geraetekatalog, statt sie selbst zu kennen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
5f643b9844 |
AutoAction-Runner: Automatiken ausfuehren
Bisher konnte man Automatiken nur anlegen - ausgefuehrt hat sie niemand. restricted/autoActions/autoaction_runner.py holt das nach. Dauerlaeufer statt Cronjob, aus zwei Gruenden: Schwellwert-Ausloeser sollen greifen, wenn die MQTT-Nachricht hereinkommt, und actor_states.current_value wird sonst von niemandem fortgeschrieben - beim Discovery einmal gesetzt und danach nie wieder. Ein zustandsloser Lauf haette gar nichts, womit er vergleichen koennte. Der Runner pflegt den Wert nebenbei mit, wovon auch der Editor profitiert: er zeigt neben jedem Messwert den aktuellen Stand. Ausgeloest wird nur auf der steigenden Flanke (automations.cond_met), sonst wuerde "Temperatur ueber 22 Grad" bei jedem Takt erneut feuern. Aus demselben Grund heissen Zeit-Ausloeser jetzt "ab 16:30" statt "gleich 16:30": ein Gleichheitsvergleich waere nur in einer einzigen Minute wahr, und ein Ausfall in genau dieser Minute kostet den ganzen Tag. Dieselbe Ueberlegung steht hinter den breiten Zeitfenstern in auto_watering.py. Der Weg zum Geraet haengt an der URL des Aktors: mqtt:// abonniert und publiziert, http:// pollt und haengt Parameter an, io:// spricht mit der Tahoma-Box, Logic rechnet Uhrzeit, Datum und Sonnenzeiten. Alle vier stehen in transports.py; eine fuenfte Geraeteart ist eine weitere Klasse mit passt(), zustaende_lesen() und senden(). fetch_calendar.py fuellt calendar_days aus openholidaysapi.org, damit "in den Ferien" und "an Feiertagen" eine Grundlage haben. Einmal jaehrlich per Cron. Die Uebersicht blendet auf schmalen Schirmen Spalten aus, statt sie wegzuschieben - auf dem Handy waren die Knoepfe zum Pausieren und Loeschen sonst nur per Seitwaertsscrollen erreichbar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
eee3a89b4e |
AutoAction-Editor: Speichern, Laden und Loeschen
Der Editor las seine Geraete aus homeMesh, schrieb aber nach solarLog in
Tabellen, deren Fremdschluessel auf solarLog.actors/sensors zeigten. Jedes
INSERT lief damit gegen den Fremdschluessel - autoactionsSensors und
autoactionsActors sind deshalb leer geblieben, und die Aktor-Schleife war
ohnehin nie geschrieben worden.
Die Automatiken liegen jetzt in homeMesh neben dem Geraetemodell
(homeMesh_automations.sql). Eine Bedingung verweist mit einem einzigen
Fremdschluessel auf actor_states statt auf Geraet, State-URL und ein
unklares valID; Kommandoparameter stehen zeilenweise statt in vier festen
Spalten "Wert 1" bis "Wert 4". Verknuepft wird ueber group_no: gleiche
Nummer UND, verschiedene ODER, ausgewertet als any(all(gruppe)).
Im Editor ist eine Gruppe ein gerahmter Block mit eigenem "+ Bedingung",
dazwischen steht ODER - die Klammerung ist damit gezeichnet und nicht
vereinbart, und darunter steht derselbe Satz noch einmal in Worten. Die
Uebersicht zeigt ihn in der Spalte "Ausloeser" und ersetzt die bisher fest
verdrahtete Beispielzeile.
Nebenbei behoben: die Operator-Knoepfe schickten ihr innerHTML ("≠",
">") an eine Whitelist, die "!=" erwartete - jede Bedingung "ungleich"
wurde still zu "gleich". Ausgeblendete Wertfelder sendeten ihren Inhalt
trotzdem mit. Beides entfaellt, weil der Editor jetzt JSON aus einem
Modell schickt statt durchnummerierter Formularfelder.
Die vier Endpunkte fillSensorDD, fillActorDD, sensorDetails und
actorDetails entfallen: der Geraetekatalog reist einmal mit dem Editor
mit, statt je Bedingungszeile zwei Anfragen nachzuladen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
fd27fe168e |
Handy-Darstellung: Diagramme, Meteogramm und Abstaende
Auf dem Handy war die Seite bisher nur mit der Desktopversion des Browsers brauchbar. Drei Ursachen, alle nachgemessen bei 375 px: Die Diagramme standen im Hochformat, 301 x 400 px - die Zeitachse lag auf der kurzen Seite. Die Hoehe kam nicht aus dem Container: .chart-container hatte inline height:100% in einem Elternelement ohne Hoehe, und die Canvas trugen height="400px;", was kein gueltiger Zahlenwert ist. Die Hoehe steht jetzt im Stylesheet, 400 px am Rechner und 250 px unter 768 px Breite, die Beschriftung dort 8 statt 10 px. Das Meteogramm hat sich nicht angepasst, sondern gequetscht. meteoblue legt sein Bild einmal beim Laden fest und zeichnet es bei einer Breitenaenderung nicht neu; unter etwa 600 px ueberlagern sich Wochentage und Stundenachse. Es wird jetzt in mindestens 640 px Breite geladen - auf breiten Karten gleich in Kartenbreite, dort aendert sich nichts - und, wenn die Karte schmaler ist, als Ganzes verkleinert. Zuschnitt und Skalierung setzt das Skript direkt am Element, nicht ueber das Stylesheet: sonst haengt die Darstellung an einer womoeglich veralteten solar.css im Browser-Cache, und der breit geladene Rahmen ragt ungeschnitten aus der Karte. Passend dazu bekommt solar.css eine Versionskennung aus filemtime(), wie sie die Skripte in footer.php und adminlte.min.css laengst tragen. Ohne sie kam auf schon einmal besuchten Geraeten die alte Datei aus dem Cache. Die Statistik-Kacheln lagen in nackten .col ohne Breitenangabe; Bootstrap laesst sie dann nach Textlaenge umbrechen, mal zwei, mal drei je Zeile und unterschiedlich breit. Die Breite kommt jetzt aus row-cols-2/row-cols-md-4, und die Karte fuellt die Zeilenhoehe, damit die Werte trotz ein- oder zweizeiliger Titel auf einer Linie stehen. Zuletzt sind die Abstaende unter 768 px enger gefasst - auf .app-content beschraenkt, damit Seitenleiste, Kopfzeile und Modals unberuehrt bleiben: Spaltenabstand 24 -> 8 px, Kartenabstand 24 -> 12 px, Polsterung 16 -> 8 px. Die nutzbare Breite steigt damit von 301 auf 317 px. Geprueft bei 375 und 1200 px auf Solar, Historie, Heizung, Home und Wetter: kein Querlauf, am Rechner unveraenderte Werte. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |