From 2e155ea4a7d7596e545f7dcecc5c82c497c9cc39 Mon Sep 17 00:00:00 2001 From: Moirtz Wagner Date: Sat, 5 Sep 2026 11:54:42 +0200 Subject: [PATCH] README mit dem Datenfluss der Hintergrundprozesse Bisher gab es nur ein README zum Runner. Wer wissen wollte, welches Skript eine Zahl liefert und wer sie weiterverwendet, musste sich das aus Importen, Topic-Namen und Startskripten zusammensuchen - und hatte am Ende trotzdem nicht gesehen, dass fuer einen Teil der Messwerte gar kein Skript zustaendig ist. Zwei Mermaid-Diagramme, geteilt am MQTT-Broker: das erste zeigt, woher die Zahlen kommen, das zweite, wer sie benutzt. Dazu Tabellen, wem welches Topic und welche Datenbank gehoert und was wann startet. Co-Authored-By: Claude Opus 5 --- README.md | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..ea51085 --- /dev/null +++ b/README.md @@ -0,0 +1,182 @@ +# SolarManager + +Die Hintergrundprozesse des Hauses: Messwerte einsammeln, Wallbox und Heizung +regeln, die Automatiken auswerten. Gegenstück ist das Web-Repo +`admin/Smart-Dashboard` unter `/volume1/web/smart` — dort liegt die Anzeige, +hier liegt alles, was ohne offenen Browser weiterlaufen muss. + +Beide Seiten reden über zwei Dinge miteinander: den **MQTT-Broker** für alles +Aktuelle und die **Datenbanken** für alles, was bleiben soll. Kein Prozess +ruft einen anderen direkt auf. + +## Woher die Zahlen kommen + +```mermaid +flowchart LR + + WR["Wechselrichter
GoodWe · OpenDTU · DTU-BI"] + EM3["Stromzähler
2× Shelly EM3"] + HEIZ["Heizung"] + GOE["go-eCharger"] + WPILOT["Wattpilot"] + SKODA["MySkoda-API"] + STATION["Wetterstation"] + METEO["Open-Meteo"] + VENTILE["Ventilsteuerungen
2× ESP32"] + HAUSGER["Thermostate · Shellys · Schalter
melden sich per
Home-Assistant-Discovery
"] + + MGR["solarManager.py
gatherModbusData · gatherOpenDTUData
gatherDTUBIData · gatherShellyEM3Data EG/UG
gatherHeaterData · gatherSkodaData
gatherWaterData · charger_goE
"] + WPB["wattpilot_bruecke.py"] + WSB["wsMQTTbridge.py"] + RAIN["gatherRainData.py"] + + BROKER{{"MQTT-Broker"}} + SOLARLOG[("solarLog")] + + WR -->|Modbus · HTTP| MGR + EM3 -->|HTTP| MGR + HEIZ -->|HTTP| MGR + GOE -->|HTTP| MGR + WPILOT -->|WebSocket| MGR + SKODA -->|HTTPS| MGR + WPILOT -->|WebSocket| WPB + STATION -->|WebSocket| WSB + METEO -->|HTTPS| RAIN + + SOLARLOG -->|zisterne| MGR + MGR -->|"EnergyFlow · skoda"| SOLARLOG + + MGR -->|"solarManager/#"| BROKER + WPB -->|"wattpilot/#"| BROKER + WSB -->|"weatherStation/#"| BROKER + RAIN -->|"Wetter/Regen"| BROKER + GOE -->|"go-eCharger/#"| BROKER + VENTILE -->|"Gartenwasser/#"| BROKER + HAUSGER -->|"Raumtemp/# · Power_EG/#
Power_UG/# · wasser/#"| BROKER + + classDef quelle fill:#eef4fb,stroke:#7f9dc0 + classDef skript fill:#fff6e5,stroke:#d0a548 + classDef speicher fill:#eaf5ee,stroke:#6fa981 + class WR,EM3,HEIZ,GOE,WPILOT,SKODA,STATION,METEO,VENTILE,HAUSGER quelle + class MGR,WPB,WSB,RAIN skript + class BROKER,SOLARLOG speicher +``` + +Vier Prozesse holen aktiv etwas ab. Alles andere meldet sich von selbst: die +Ventilsteuerungen, die Wallbox und jedes Gerät, das +Home-Assistant-Discovery spricht, schreiben ohne Umweg auf den Broker. Für +deren Messwerte ist also **kein Skript** zuständig — wer sie sucht, sucht am +Gerät, nicht im Quelltext. + +`solarManager.py` ist der Sonderfall: ein Prozess, aber acht +Sammler-Module, jedes für eine Anlage. Sie laufen nicht einzeln, sondern +werden importiert; ihr gemeinsames Ergebnis geht als ein Baum nach +`solarManager/#`. + +Die Zisterne fällt aus der Reihe — ihr Stand steht in `solarLog`, und +`gatherWaterData` liest ihn von dort. Die Daten laufen also durch die +Datenbank hindurch von einem Prozess zum nächsten. + +## Wer sie benutzt + +```mermaid +flowchart TB + + BROKER{{"MQTT-Broker"}} + SOLARLOG[("solarLog
Verlauf")] + HOMEMESH[("homeMesh
Geräte · Automatiken")] + ALARM[("alarm
Weckzeiten")] + + RUNNER["autoaction_runner.py
SolarManager"] + WECKER["wecker.py
SolarManager"] + KALENDER["fetch_calendar.py
SolarManager · Cronjob, jährlich"] + DISCOVERY["device_discovery.py
Web · von Hand gestartet"] + AJAX["ajax/*.php
Web"] + BROWSER["js/solar/*.js
Web · im Browser"] + + HAUS["Rollläden · Licht · Schalter
Tahoma · WLED · Shelly"] + VENTILE["Ventilsteuerungen"] + FERIEN["openholidaysapi.org"] + + BROKER <-->|"Messwerte ↓ Kommandos ↑"| RUNNER + HOMEMESH <-->|"Regelwerk ↓ Verlauf ↑"| RUNNER + RUNNER -.->|"HTTP · WLED · Tahoma"| HAUS + BROKER -.->|"Gartenwasser/…/set"| VENTILE + + ALARM --> WECKER + FERIEN --> KALENDER + KALENDER -->|"calendar_days"| HOMEMESH + WECKER -.->|HTTP| HAUS + + BROKER -->|"homeassistant/#"| DISCOVERY + HAUS -->|"mDNS · Tahoma"| DISCOVERY + DISCOVERY -->|"Geräte, Messwerte, Befehle"| HOMEMESH + + SOLARLOG --> AJAX + HOMEMESH --> AJAX + AJAX <--> BROWSER + AJAX -.->|Kommandos| BROKER + BROKER -->|wss| BROWSER + + classDef skript fill:#fff6e5,stroke:#d0a548 + classDef speicher fill:#eaf5ee,stroke:#6fa981 + classDef geraet fill:#eef4fb,stroke:#7f9dc0 + class RUNNER,WECKER,DISCOVERY,AJAX,BROWSER,KALENDER skript + class BROKER,SOLARLOG,HOMEMESH,ALARM speicher + class HAUS,VENTILE,FERIEN geraet +``` + +**Durchgezogen fließen Daten, gestrichelt gehen Befehle.** + +Der Browser bekommt seine laufenden Werte direkt vom Broker über +`wss://mqtt.nas.el-wa.org`, nicht über PHP. Über PHP läuft nur, was der +Broker nicht weiß: der Verlauf aus `solarLog` und alles aus `homeMesh` — und +umgekehrt jeder Knopfdruck, denn schalten darf nur der Server. + +`device_discovery.py` ist kein Dauerläufer. Es sucht per mDNS nach Shellys +und WLEDs, hört die Discovery-Nachrichten auf `homeassistant/#` mit, fragt +die Tahoma-Box und legt daraus die Geräte in `homeMesh` an. Gestartet wird es +von Hand, wenn sich am Bestand etwas geändert hat. + +## Wem welche Daten gehören + +| Daten | wird gefüllt von | wird gelesen von | +|---|---|---| +| `solarManager/#` | `solarManager.py` | Browser, Runner | +| `wattpilot/#` | `wattpilot_bruecke.py` | Browser, Runner | +| `weatherStation/#` | `wsMQTTbridge.py` | Browser, Runner | +| `Wetter/Regen` | `gatherRainData.py` | Runner, Browser | +| `go-eCharger/#` | die Wallbox selbst | Browser, Runner | +| `Gartenwasser/#` | die beiden ESP32 | Browser, Runner | +| `Raumtemp/#`, `Power_*/#`, `wasser/#` | die Geräte selbst | Browser, Runner | +| `homeassistant/#` | die Geräte selbst | `device_discovery.py` | +| **`solarLog`** | `solarManager.py` | `ajax/*.php`, `gatherWaterData` | +| **`homeMesh`** | `device_discovery.py`, Runner, Web-Editor | Runner, `ajax/*.php` | +| **`alarm`** | Web-Oberfläche | `wecker.py` | + +## Was wann startet + +| Prozess | gestartet von | +|---|---| +| `solarManager.py` | `startSolarServer.sh` (Aufgabenplaner, beim Hochfahren) | +| `autoActions/autoaction_runner.py` | dito | +| `gatherRainData.py` | dito | +| `wsMQTTbridge.py` | `startMQTTbridge.sh` | +| `wattpilot_bruecke.py` | `startWattpilotMQTT.sh` | +| `wecker.py` | `startWecker.sh` | +| `autoActions/fetch_calendar.py` | Cronjob, einmal im Jahr | +| `device_discovery.py` (Web-Repo) | von Hand | + +`startSolarServer.sh` beendet eine schon laufende Instanz, bevor es neu +startet — beim Runner ist das wichtig, zwei Instanzen würden jedes Kommando +doppelt schicken. + +## Konfiguration + +Zugangsdaten und Standort stehen in `config.ini` (Vorlage: +`config.ini.example`), gelesen über `konfig.py`; der Runner hat seine eigene +unter `autoActions/`. Beide sind per `.gitignore` ausgenommen — nichts davon +gehört in den Quelltext. + +Mehr zum Runner selbst, zum Aufbau einer Automatik und zu den Transporten +steht in [autoActions/README.md](autoActions/README.md).