Einstellungen -> Grundriss: Etagen, Raeume und Kacheln am Plan pflegen
Neuer Reiter mit Plan-Editor: Etagen anlegen, umbenennen, sortieren, loeschen und als Standard markieren; Grundrissbild hochladen; Raeume mit Name, Kuerzel und Thermostat-Zweig anlegen und bearbeiten; Kacheln im Plan ziehen oder einen Raum ohne Kachel mit "Platzieren" und einem Klick setzen. Loest tools/kachelpositionen.php ab - Raster, Geisterkachel und die Umrechnung Mitte -> linke obere Ecke sind von dort uebernommen. - restricted/grundriss.php: alle Pruefungen und Schreibzugriffe. Eine Etage mit Raeumen oder Automatiken laesst sich nicht loeschen, die Ablehnung nennt die Namen. Raeume loeschen laesst ihre Geraete ohne Raum. - Grundrissbilder nach tiles/grundriss/ (beschreibbar, nicht im Git), nur PNG/JPEG/WebP, am Inhalt geprueft; SVG bewusst nicht. Prüfsumme im Dateinamen, alte hochgeladene Bilder werden weggeraeumt. - ajax/settings.php: ?action=grundriss und sieben POST-Aktionen, jede antwortet mit dem ganzen neuen Stand. - "Werte" springt in den Reiter Home-Kacheln und oeffnet die Kachel; Home-Kacheln und Geraete laden nach einer Grundriss-Aenderung nach. - Startseite ohne Etage mit platziertem Raum: Hinweis auf die Einstellungen statt einer leeren Zeichenflaeche. - README: Grundriss als Inhalt statt Code, neue Dateien und Endpunkte, Reihenfolge der Schema-Dateien fuer ein neues Haus. Backend mit einer Probe-Etage durchgespielt (auch Fehlerfaelle, Upload, Aufraeumen); Oberflaeche auf einer Probeseite mit echten Daten und Zeiger-Ereignissen geprueft: Ziehen, Antippen, Platzieren, neuer Raum. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -49,9 +49,11 @@ smart/
|
||||
│ ├── header.php footer.php Rahmen jeder Seite, Menü, Skript-Einbindung
|
||||
│ ├── home.php solar.php heat.php history.php
|
||||
│ ├── skoda.php weather.php settings.php logs.php ← die acht Seitenvorlagen
|
||||
│ ├── rooms.php Räume, Etagen, Kachelwerte, Symbole
|
||||
│ ├── rooms.php Etagen und Räume lesen (homeMesh), Kachelvorgabe, Symbole
|
||||
│ ├── grundriss.php Etagen, Räume, Kachelpositionen, Bilder ändern (Reiter Grundriss)
|
||||
│ ├── meshdb.php meshDb(): Verbindung zu homeMesh
|
||||
│ ├── costs.php Preistabellen + solarDb()
|
||||
│ ├── automations.php Automatiken, Gerätekatalog + meshDb()
|
||||
│ ├── automations.php Automatiken, Gerätekatalog
|
||||
│ ├── kacheln.php Anzeigewerte der Home-Kacheln (Modell zur Maske)
|
||||
│ ├── roomControls.php Bedienelemente des Raum-Modals
|
||||
│ ├── commands.php ein Kommando tatsächlich abschicken
|
||||
@@ -68,8 +70,8 @@ smart/
|
||||
├── js/solar/ der eigene JavaScript-Code
|
||||
├── js/ Fremdbibliotheken, alle lokal (kein CDN)
|
||||
├── css/solar.css das eigene Stylesheet (Theme + alle Bauteile)
|
||||
├── assets/img/ Grundriss-Renderings OG/EG/UG/AG, Icons
|
||||
├── tiles/ Kartenkacheln-Zwischenspeicher (nicht im Git)
|
||||
├── assets/img/ mitgelieferte Grundriss-Renderings dieses Hauses, Icons
|
||||
├── tiles/ beschreibbar, nicht im Git: Kartenkacheln, grundriss/ (hochgeladene Grundrisse)
|
||||
└── *.sql Schema-Dateien zum Nachziehen von Hand
|
||||
```
|
||||
|
||||
@@ -185,7 +187,7 @@ genau die Topics, die auf den Kacheln stehen (`tileTopics()` in `rooms.php`).
|
||||
| `history` | `history.php` | `jahresstatistik.js`, `historyMQTT.js` | `energyHistory` (6 ×), `getStats` | — |
|
||||
| `skoda` | `skoda.php` | `skodaMQTT.js` | `skoda.php?was=…`, `skodaCmd.php`, `tile.php` | `solarManager/#` |
|
||||
| `weather` | `weather.php` | `weatherMQTT.js` | nichts — das Meteogramm ist ein fremdes Dokument im `<iframe>` (`js/meteogram.js`) | `weatherStation/#` |
|
||||
| `settings` | `settings.php` | `settings.js` | `settings.php?action=…` | — |
|
||||
| `settings` | `settings.php` | `settings.js`, `grundriss.js` | `settings.php?action=…` | — |
|
||||
| `logs` | `logs.php` | `logs.js` | `logs.php?action=…` | — |
|
||||
|
||||
Und dasselbe als Abhängigkeitsbild — von der Seite bis in den Speicher:
|
||||
@@ -241,8 +243,9 @@ flowchart TB
|
||||
AUTOA --> AUTOM
|
||||
SETA --> COSTS & KACH & AUTOM
|
||||
STATS --> COSTS
|
||||
SETA --> GRM["grundriss.php"]
|
||||
KACH --> ROOMS
|
||||
ROOMS --> COSTS
|
||||
GRM --> ROOMS
|
||||
LOGA --> LOGD
|
||||
|
||||
COSTS --> SOLARLOG
|
||||
@@ -291,7 +294,8 @@ Text wird: Topic oder Wechselrichtersumme lesen, ggf. JSON-Pfad
|
||||
herausgreifen, Vorzeichen drehen (`negativ`), skalieren (`format:
|
||||
"leistung"` für Watt-Quellen, `"leistung_kw"` für Quellen, die schon
|
||||
Kilowatt melden — die Wallboxen), runden (`stellen`), Einheit anhängen. Klick auf eine Kachel
|
||||
öffnet das Raum-Modal über `ajax/room.php?room=EG_Bad`.
|
||||
öffnet das Raum-Modal über `ajax/room.php?room=<Raumnummer>`; Heizsymbol,
|
||||
Regler und Ist-Werte lesen aus dem Thermostat-Zweig des Raums (`mqttZweig()`).
|
||||
|
||||
**`solarMQTT.js`** — die große Anlagenübersicht. `solarSVG` zeichnet den
|
||||
Energiefluss (Breite der Pfeile aus der Leistung), darunter hängen die drei
|
||||
@@ -320,6 +324,10 @@ Anfragen dazu, und die Auswahlfelder füllten sich asynchron. Dazu die
|
||||
Übersicht: Nachfolger einklappen (`toggleAutomationGroup`) und die Rückfrage
|
||||
vor dem Löschen (`frageNachfolger`).
|
||||
|
||||
**`grundriss.js`** — der Reiter Grundriss: Etagen, Räume, Grundrissbilder und
|
||||
der Plan-Editor, in dem Kacheln gezogen und gesetzt werden. Eigene Datei, weil
|
||||
`settings.js` schon für vier Reiter reicht; es nutzt `textSchuetzen()` von dort.
|
||||
|
||||
**`settings.js`** — vier Reiter in einer Datei, deutlich getrennt: Preistabellen,
|
||||
Home-Kacheln, Geräte, Fahrzeug. Jeder Abschnitt hat sein Modell (`kachelModell`,
|
||||
`geraeteModell`, `skodaModell`), seine `zeichne…()`-Funktion und eine `…Binden()`-Funktion,
|
||||
@@ -337,9 +345,9 @@ klein: Diagramme füllen bzw. Logzeilen nachladen und einfärben.
|
||||
|
||||
| Endpunkt | Aufruf | liefert / tut |
|
||||
|---|---|---|
|
||||
| `room.php` | `?room=EG_Bad`, `POST ?action=command\|temp` | Raum-Modal bauen; ein Kommando oder eine Solltemperatur senden |
|
||||
| `room.php` | `?room=<rooms.id>`, `POST ?action=command\|temp\|jalousie` | Raum-Modal bauen; ein Kommando oder eine Solltemperatur senden |
|
||||
| `AutoAction.php` | `?action=editor\|list\|followers\|werte`, `POST save\|delete\|toggle` | Automatik-Editor und -Übersicht |
|
||||
| `settings.php` | `?action=list\|kacheln\|geraete\|skoda-keys`, `POST save\|kacheln-save\|geraete-raeume\|geraet-loeschen\|skoda-keys-save` | Einstellungsseite; `skoda-keys` meldet nur, ob ein Schlüssel hinterlegt ist und worauf er endet |
|
||||
| `settings.php` | `?action=list\|kacheln\|geraete\|grundriss\|skoda-keys`, `POST save\|kacheln-save\|geraete-raeume\|geraet-loeschen\|etage-speichern\|etagen-reihenfolge\|etage-loeschen\|etage-bild\|raum-speichern\|raum-position\|raum-loeschen\|skoda-keys-save` | Einstellungsseite; die Grundriss-Aktionen antworten mit dem ganzen neuen Stand, `skoda-keys` meldet nur, ob ein Schlüssel hinterlegt ist und worauf er endet |
|
||||
| `getStats.php` | `GET` | Jahresstatistik, alle Jahre, mit Metadaten je Kennzahl |
|
||||
| `energyHistory.php` | `?series=prod\|cons&range=month\|year\|decade` | Verbrauchs-/Erzeugungsverlauf (Rohdaten oder Stundenarchiv) |
|
||||
| `getProdData` `getConsData` `getForecastData` `getHeaterData` `getWaterData` | `?FROM=&TO=` | Chart.js-Datensätze für die jeweilige Karte |
|
||||
@@ -362,9 +370,11 @@ Kennzahlen, `energyHistory.php` wählt die Quelle nach Zeitraum,
|
||||
|
||||
| Datei | Zuständig für | Wichtige Funktionen |
|
||||
|---|---|---|
|
||||
| `rooms.php` | Räume, Etagen, Kachelwerte, Symbole | `allRooms()`, `roomsWithTile()`, `tileTopics()`, `kachelVorgabe()`, `kachelUeberschreibungen()`, `bootstrapIcons()`, `kachelIcon()` |
|
||||
| `rooms.php` | Etagen und Räume lesen (`homeMesh`), Kachelvorgabe, Symbole | `grundriss()`, `allRooms()`, `roomsOnFloor()`, `floorsWithPlan()`, `standardEtage()`, `etageBild()`, `roomsWithTile()`, `tileTopics()`, `kachelVorgabe()`, `bootstrapIcons()`, `kachelIcon()` |
|
||||
| `grundriss.php` | Etagen, Räume, Kachelpositionen und Grundrissbilder ändern | `grundrissStand()`, `etageSpeichern()`, `etagenReihenfolge()`, `etageLoeschen()`, `etageBildSpeichern()`, `raumSpeichern()`, `raumPosition()`, `raumLoeschen()` |
|
||||
| `meshdb.php` | Verbindung zu `homeMesh` | `meshDb()` |
|
||||
| `costs.php` | Preistabellen, Verbindung zu `solarLog` | `solarDb()`, `preiseLaden()`, `preiseSpeichern()`, `grundpreisImZeitraum()` |
|
||||
| `automations.php` | Automatiken, Gerätekatalog, Verbindung zu `homeMesh` | `meshDb()`, `deviceCatalog()`, `loadAutomation()`, `saveAutomation()`, `deleteAutomation()`, `automationFollowers()`, `pruefeKreis()`, `kalendertagChoices()`, `tagVorlagen()`, `stateValues()`, `geraeteListe()`, `geraetLoeschen()`, `saveRooms()` |
|
||||
| `automations.php` | Automatiken, Gerätekatalog, Raumzuordnung der Geräte | `deviceCatalog()`, `raumListe()`, `loadAutomation()`, `saveAutomation()`, `deleteAutomation()`, `automationFollowers()`, `pruefeKreis()`, `kalendertagChoices()`, `tagVorlagen()`, `stateValues()`, `geraeteListe()`, `geraetLoeschen()`, `saveRooms()` |
|
||||
| `kacheln.php` | Anzeigewerte der Home-Kacheln (Maskenseite) | `kachelListe()`, `kachelKatalog()`, `kachelWertPruefen()`, `kachelWerteSpeichern()`, `kachelSymbole()` |
|
||||
| `roomControls.php` | Welches Gerät welches Bedienelement bekommt | `bedienform()`, `zeichneBeschattung()`, `zeichneLicht()`, `zeichneMesswerte()` |
|
||||
| `commands.php` | Ein Kommando abschicken (MQTT/WLED/HTTP/Tahoma) | `executeCommand()`, `sendeMqtt()`, `sendeWled()`, `sendeHttp()`, `sendeTahoma()` |
|
||||
@@ -382,11 +392,13 @@ Datenbank folgen kann, ohne zu springen:
|
||||
```mermaid
|
||||
flowchart LR
|
||||
HELPER["helper.php"] --> MYSQL["mysql.php<br/><small>Zugangsdaten</small>"]
|
||||
ROOMS["rooms.php"] --> COSTS["costs.php"] --> MYSQL
|
||||
COSTS["costs.php"] --> MYSQL
|
||||
MESH["meshdb.php<br/><small>meshDb()</small>"] --> MYSQL
|
||||
ROOMS["rooms.php"] --> MESH
|
||||
GRM["grundriss.php"] --> ROOMS
|
||||
KACH["kacheln.php"] --> ROOMS
|
||||
KACH --> COSTS
|
||||
KACH -. "nur wenn vorhanden" .-> AUTOM["automations.php"]
|
||||
AUTOM --> MYSQL
|
||||
AUTOM --> MESH
|
||||
AUTOM --> ROOMS
|
||||
CMD["commands.php"] --> MYSQL
|
||||
CMD --> TAH["tahoma_EG.php"]
|
||||
@@ -441,7 +453,6 @@ erDiagram
|
||||
| `skoda_ladepunkte` | Wallbox-Verlauf während einer Ladung, im Minutentakt, wird nicht ausgedünnt (`solarLog_skoda_ladepunkte.sql`) | `gatherSkodaData.py`; ältere Ladungen `skoda_ladepunkte_nachtragen.py` |
|
||||
| `weatherStation`, `weatherHours`, `weatherDays`, `daylight`, `simPower` | Wetter, Sonnenzeiten, Ertragsprognose | Wetterbrücke, Open-Meteo, Prognose |
|
||||
| `gridCosts`, `gasCosts`, `fuelCosts` | Preiszeitreihen (Stichtag, kein Enddatum) | Einstellungsseite (`costs.php`) |
|
||||
| `kachelWerte` | Überschreibungen der Home-Kacheln, JSON je Raum | Einstellungsseite (`kacheln.php`) |
|
||||
|
||||
**`Logins`** — `users` (Passkeys) und `addUser` (Einmal-Links).
|
||||
|
||||
@@ -449,15 +460,50 @@ erDiagram
|
||||
|
||||
## Vier Bausteine im Detail
|
||||
|
||||
### 1. Die Home-Kacheln
|
||||
### 1. Grundriss und Home-Kacheln
|
||||
|
||||
Was auf einer Kachel steht, hat drei Stufen: die Vorgabe in `rooms.php`, die
|
||||
Überschreibung in `kachelWerte`, und die Anzeige im Browser.
|
||||
Etagen, Räume, Kachelpositionen und Kachelwerte sind **Inhalt, kein Code**.
|
||||
Sie liegen in `homeMesh.floors` und `homeMesh.rooms` (`homeMesh_grundriss.sql`)
|
||||
und werden unter **Einstellungen → Grundriss** und **→ Home-Kacheln** gepflegt.
|
||||
Bis September 2026 standen sie als Tabelle in `rooms.php`; für ein anderes
|
||||
Haus hätte man den Quelltext umschreiben müssen.
|
||||
|
||||
| Tabelle | trägt |
|
||||
|---|---|
|
||||
| `floors` | `code` (fest: URL, SVG-Ids, `automations.floor`), `label`, Reihenfolge, Grundrissbild, Standard-Etage |
|
||||
| `rooms` | feste Nummer `id`, Etage, Name, `kuerzel` (SVG-Ids), Kachel `x`/`y` (leer = keine Kachel), `thermostat` (MQTT-Zweig), `werte` (JSON, leer = Vorgabe) |
|
||||
|
||||
Auf die feste Raumnummer zeigen `actors.room_id` und das Raum-Modal
|
||||
(`room.php?room=12`). Ein umbenannter Raum behält damit Geräte, Regler und
|
||||
Kachel. `automations.floor` ist ein Fremdschlüssel auf `floors`: eine Etage mit
|
||||
Automatiken lässt sich nicht löschen.
|
||||
|
||||
**Die Vorgabe einer Kachel** ist allein das Thermostat: mit `thermostat` Soll,
|
||||
Ist und Feuchte aus diesem Zweig, sonst nur der Name. Derselbe Zweig trägt
|
||||
Heizsymbol und Temperaturregler (`mqttZweig()` in `homeMQTT.js`,
|
||||
`<zweig>/changeSetTemp` in `room.php`) — nichts setzt mehr voraus, dass ein
|
||||
Thermostat unter `Raumtemp/<Etage>/<Raum>` meldet.
|
||||
|
||||
**Grundrissbilder** kommen per Upload nach `tiles/grundriss/` — das einzige
|
||||
Verzeichnis, in das der Webserver schreiben darf, und nicht im Git. PNG, JPEG
|
||||
oder WebP, geprüft am Inhalt; SVG bewusst nicht, es könnte Skript enthalten.
|
||||
Der Name trägt einen Teil der Prüfsumme, ein neues Bild hat also eine neue
|
||||
Adresse. Die mitgelieferten unter `assets/img` bleiben daneben gültig.
|
||||
|
||||
**Der Plan-Editor** (`js/solar/grundriss.js`, Modell `restricted/grundriss.php`)
|
||||
löst `tools/kachelpositionen.php` ab: Kacheln werden gezogen, ein Raum ohne
|
||||
Kachel mit „Platzieren“ und einem Klick gesetzt. Übernommen sind Raster,
|
||||
Geisterkachel und die Umrechnung von der gezeigten Mitte zur gespeicherten
|
||||
linken oberen Ecke. Jede Aktion antwortet mit dem ganzen neuen Stand. Nach
|
||||
einer Änderung laden „Home-Kacheln“ und „Geräte“ beim nächsten Öffnen nach.
|
||||
|
||||
Ohne Etage mit platziertem Raum zeigt die Startseite statt der Zeichenfläche
|
||||
den Weg zu den Einstellungen — der Anfang jeder neuen Installation.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
ROOMS["rooms.php<br/><small>$rooms: Vorgabe je Raum</small>"] --> MIT["mitWerten()"]
|
||||
KW[("kachelWerte<br/><small>je Raum, JSON</small>")] --> MIT
|
||||
DB[("homeMesh.floors<br/>homeMesh.rooms")] --> GR["grundriss()<br/><small>rooms.php</small>"]
|
||||
GR --> MIT["mitWerten()"]
|
||||
MIT --> RWT["roomsWithTile()"]
|
||||
RWT -->|"als JSON in die Seite"| HOMEJS["homeMQTT.js<br/><small>homeRooms</small>"]
|
||||
RWT --> SVG["home.php<br/><small>SVG-Kacheln</small>"]
|
||||
@@ -465,8 +511,10 @@ flowchart LR
|
||||
BROKER --> HOMEJS
|
||||
HOMEJS -->|"kachelWert()"| SVG
|
||||
|
||||
SETJS["settings.js<br/><small>Reiter Kacheln</small>"] --> SETA["ajax/settings.php"]
|
||||
SETA --> KACHM["kacheln.php<br/><small>prüfen, speichern</small>"] --> KW
|
||||
GRJS["grundriss.js<br/><small>Reiter Grundriss</small>"] --> SETA["ajax/settings.php"]
|
||||
SETJS["settings.js<br/><small>Reiter Kacheln</small>"] --> SETA
|
||||
SETA --> GRM["grundriss.php<br/><small>Etagen, Räume, Bilder</small>"] --> DB
|
||||
SETA --> KACHM["kacheln.php<br/><small>Werte prüfen, speichern</small>"] --> DB
|
||||
KACHM -->|"Auswahlliste"| KAT["deviceCatalog()<br/><small>automations.php</small>"]
|
||||
```
|
||||
|
||||
@@ -486,8 +534,6 @@ der Name **irgendeines** Bootstrap-Icons — die Codepunkte liest
|
||||
`bootstrapIcons()` aus `css/bootstrap-icons.min.css`, gezeichnet wird als
|
||||
SVG-Text in der Icon-Schrift.
|
||||
|
||||
Fehlt die Tabelle `kachelWerte`, zeigt jede Kachel ihre Vorgabe: die
|
||||
Startseite ist keine Einstellung, ohne die man das Haus nicht mehr sieht.
|
||||
|
||||
### 2. Das Raum-Modal
|
||||
|
||||
@@ -499,8 +545,8 @@ sequenceDiagram
|
||||
participant C as commands.php
|
||||
participant G as Gerät
|
||||
|
||||
B->>R: GET ?room=EG_Bad
|
||||
R->>RC: Geräte des Raums (actors.room) → Bedienformen
|
||||
B->>R: GET ?room=12 (rooms.id)
|
||||
R->>RC: Geräte des Raums (actors.room_id) → Bedienformen
|
||||
RC-->>B: fertiges Markup (Rollladen, Licht, Messwerte …)
|
||||
B->>R: POST ?action=command {command_id, params}
|
||||
R->>C: executeCommand()
|
||||
@@ -733,8 +779,8 @@ englisch bleibt, was von außen vorgegeben ist (`floor`, `topic`, Chart.js-
|
||||
Optionen, Spaltennamen). Kommentare erklären **warum**, nicht was.
|
||||
|
||||
**Fehlertoleranz vor Vollständigkeit.** Was eine Seite nicht zwingend braucht,
|
||||
wird in `try/catch` geholt: fehlt die Mesh-Datenbank, bleibt die Startseite
|
||||
sichtbar; fehlt `kachelWerte`, gilt die Vorgabe.
|
||||
wird in `try/catch` geholt: fehlt die Mesh-Datenbank oder der Grundriss, zeigt
|
||||
die Startseite einen Hinweis statt eines Fatal Errors.
|
||||
|
||||
**Zugriffsschutz.** `.htaccess` sperrt Punkt-Dateien (allen voran `.git`) und
|
||||
alle Dateitypen, die der Browser nie anfordert (`.py`, `.sql`, `.ini`, `.md`
|
||||
@@ -750,8 +796,9 @@ ausgeliefert.
|
||||
|
||||
| Vorhaben | Anlaufstelle |
|
||||
|---|---|
|
||||
| Ein Raum kommt dazu oder heißt anders | `restricted/rooms.php`, Tabelle `$rooms` — Kachel, Menü und MQTT-Abo ergeben sich daraus |
|
||||
| Andere Werte auf einer Kachel | Einstellungen → Kacheln (keine Codeänderung). Vorgabe für neue Räume: `kachelVorgabe()` in `rooms.php` |
|
||||
| Ein Raum oder eine Etage kommt dazu, heißt anders, bekommt ein neues Grundrissbild | Einstellungen → Grundriss (keine Codeänderung) — Kachel, Menü und MQTT-Abo ergeben sich daraus |
|
||||
| Andere Werte auf einer Kachel | Einstellungen → Home-Kacheln (keine Codeänderung). Vorgabe ohne eigene Werte: `kachelVorgabe()` in `rooms.php` |
|
||||
| Ein anderes Haus einrichten | `homeMesh_DB-layout.sql`, `homeMesh_automations.sql`, `homeMesh_grundriss.sql` in dieser Reihenfolge; dann Einstellungen → Grundriss |
|
||||
| Neues Symbol auf einer Kachel | Name eines Bootstrap-Icons ins Feld tippen. Vorschlagsliste: `kachelSymbole()` in `kacheln.php` |
|
||||
| Neue Kennzahl in der Jahresstatistik | `KENNZAHLEN` **und** `kennzahlenAus()` in `ajax/getStats.php` — sonst nichts |
|
||||
| Neues Diagramm auf einer Seite | Karte in der Vorlage, `<canvas>`, dazu ein Endpunkt nach dem Muster von `getProdData.php`, geladen mit `getData()` |
|
||||
|
||||
Reference in New Issue
Block a user