# 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).