adminandClaude Opus 5 cc96e990fa Messwerte je Wert zuteilen, damit Gen2-Shellys ueber MQTT gelesen werden
Das Discovery-Modul adressiert die neueren Shellys neu: ihre Messwerte
stehen nicht mehr als Feldname zu einer HTTP-Adresse in actor_states,
sondern als Topic mit dem Feld in value_path. Geschaltet werden sie weiter
ueber HTTP - das Geraet bleibt also ein http://-Aktor, waehrend seine Werte
ueber den Broker kommen.

Der Runner teilte Messwerte bisher allein nach der Geraete-URL zu. Die
umgestellten Werte waeren damit beim HTTP-Transport gelandet, der in der
JSON-Antwort nach einem Feld namens "Power_EG/status/em:0" gesucht und nie
gefunden haette: die Werte waeren still auf ihrem letzten Stand
eingefroren. Zugeteilt wird deshalb je Messwert - was wie ein Topic
aussieht (ist_topic()), liest der MQTT-Transport, alles andere geht den
alten Weg. Fuer die aelteren Shellys aendert sich nichts, sie koennen kein
MQTT und bleiben ganz bei HTTP.

Zweitens haette der Runner den Wechsel gar nicht bemerkt. Sein
Fingerabdruck fuers Neuladen zaehlt die Zeilen von actor_states, und ein
Discovery-Lauf schreibt die Zeilen um, statt neue anzulegen - gleiche
Zeilenzahl, keine Reaktion, bis zum naechsten Neustart. Jetzt gehen url und
value_path als CRC-Summe mit ein, ebenso die command_url der Kommandos.

Nach dem naechsten Suchlauf faellt damit das Polling fuer vier Geraete weg:
34 der 35 HTTP-Messwerte wandern zum Broker, gefragt wird nur noch der
Handtuchtrockner.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 00:07:04 +02:00
2026-09-02 20:46:59 +02:00

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

flowchart LR

  WR["Wechselrichter<br/><small>GoodWe · OpenDTU · DTU-BI</small>"]
  EM3["Stromzähler<br/><small>2× Shelly EM3</small>"]
  HEIZ["Heizung"]
  GOE["go-eCharger"]
  WPILOT["Wattpilot"]
  SKODA["MySkoda-API"]
  STATION["Wetterstation"]
  METEO["Open-Meteo"]
  VENTILE["Ventilsteuerungen<br/><small>2× ESP32</small>"]
  HAUSGER["Thermostate · Shellys · Schalter<br/><small>melden sich per<br/>Home-Assistant-Discovery</small>"]

  MGR["<b>solarManager.py</b><br/><small>gatherModbusData · gatherOpenDTUData<br/>gatherDTUBIData · gatherShellyEM3Data EG/UG<br/>gatherHeaterData · gatherSkodaData<br/>gatherWaterData · charger_goE</small>"]
  WPB["<b>wattpilot_bruecke.py</b>"]
  WSB["<b>wsMQTTbridge.py</b>"]
  RAIN["<b>gatherRainData.py</b>"]

  BROKER{{"<b>MQTT-Broker</b>"}}
  SOLARLOG[("<b>solarLog</b>")]

  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/#<br/>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

flowchart TB

  BROKER{{"<b>MQTT-Broker</b>"}}
  SOLARLOG[("<b>solarLog</b><br/><small>Verlauf</small>")]
  HOMEMESH[("<b>homeMesh</b><br/><small>Geräte · Automatiken</small>")]
  ALARM[("<b>alarm</b><br/><small>Weckzeiten</small>")]

  RUNNER["<b>autoaction_runner.py</b><br/><small>SolarManager</small>"]
  WECKER["<b>wecker.py</b><br/><small>SolarManager</small>"]
  KALENDER["<b>fetch_calendar.py</b><br/><small>SolarManager · Cronjob, jährlich</small>"]
  DISCOVERY["<b>device_discovery.py</b><br/><small>Web · von Hand gestartet</small>"]
  AJAX["<b>ajax/*.php</b><br/><small>Web</small>"]
  BROWSER["<b>js/solar/*.js</b><br/><small>Web · im Browser</small>"]

  HAUS["Rollläden · Licht · Schalter<br/><small>Tahoma · WLED · Shelly</small>"]
  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.

S
Description
No description provided
Readme
3 MiB
Languages
Python 87%
C 11.1%
Cython 0.9%
JavaScript 0.6%
Shell 0.2%
Other 0.2%