Files
Symcon_Belevo_Energiemanage…/DOKUMENTATION_CHATGPT.md
T

33 KiB

Belevo Energiemanagement fuer IP-Symcon

Stand: 2026-05-10

Diese Dokumentation ist als Arbeitsgrundlage fuer ChatGPT/Codex und fuer zukuenftige Software-Erweiterungen gedacht. Sie beschreibt die Funktion, Architektur, Modul-Schnittstellen und die wichtigsten Regeln, um neue Module sauber an den Energiemanager anzubinden.

1. Kurzueberblick

Das Repository ist eine IP-Symcon Modulbibliothek fuer ein Energiemanagementsystem der Belevo AG. Das System verteilt elektrische Leistung dynamisch auf steuerbare Verbraucher wie Ladestationen, Boiler, Pufferspeicher, Batterie, Waermepumpe und externe Schaltgruppen.

Die zentrale Idee:

  1. Der Manager liest den aktuellen Netzbezug.
  2. Der Manager entscheidet zwischen Solarladen und Peak-Shaving.
  3. Jeder Verbraucher meldet seine aktuell moeglichen Leistungsstufen als PowerSteps.
  4. Der Manager verteilt die verfuegbare oder zu reduzierende Leistung nach Prioritaet und Fairness.
  5. Die Verbraucher setzen die zugeteilte Leistung in konkrete Schaltkontakte, API-Aufrufe oder Geraetemodi um.

Das System ist fuer Einzelhaeuser, ZEV/V-ZEV-Anlagen und groessere Lastmanagement-Strukturen ausgelegt. Fuer verteilte Anlagen gibt es neben dem lokalen Manager den HauptManager, der mehrere untergeordnete Manager ueber JSON-Datenpunkte zusammenfassen kann.

2. Repository-Struktur

Jedes IP-Symcon Modul liegt in einem eigenen Ordner und enthaelt typischerweise:

  • module.php: PHP-Klasse mit der eigentlichen Logik.
  • module.json: IP-Symcon Modul-Metadaten, GUID, Name, Typ, Hersteller, Prefix.
  • form.json: Konfigurationsformular fuer IP-Symcon.
  • README.md: Modulbeschreibung, aktuell oft noch Template oder veraltet.

Wichtige Dateien auf Root-Ebene:

  • library.json: Modulbibliothek, aktuell Version 2.001, IP-Symcon-Kompatibilitaet 8.0.
  • README.md: vorhandene Systembeschreibung des Energiemanagers.
  • DOKUMENTATION_CHATGPT.md: diese technische Gesamtuebersicht.

3. Modulgruppen

Modul Rolle Manager-Anbindung
Manager Lokaler Energiemanager, verteilt Leistung an Verbraucher Zentrale Instanz
HauptManager Aggregiert mehrere Manager/Unteranlagen ueber JSON Uebergeordnete Instanz
Ladestation_v2 Moderne Ladestationsanbindung mit Fahrzeugerkennung, Mindeststrom, 1p/3p, Easee/ECarUp/Smart-Me/Go-E Verbraucher
Ladestation_Universal Aeltere/einfachere Ladestation Verbraucher
Batterie Batterie mit Lade-/Entladeleistungssteuerung fuer Goodwe, Solaredge, Sig Energy Verbraucher, bidirektional
Boiler_2_Stufig_Mit_Fueler Boiler mit Teil- und Volllastkontakt, Temperatur- und Legionellenlogik Verbraucher
Boiler_x_Stufig Boiler mit frei konfigurierbaren Leistungsstufen Verbraucher
Ansteuerung_Askoheat Stufenlose/mehrstufige Askoheat-Ansteuerung ueber externe Leistungsvariable Verbraucher
Pufferspeicher Puffer mit Teil-/Volllastkontakt und Aussentemperatur-Funktion Verbraucher
Puffer_Speicher Puffer mit frei konfigurierbaren Leistungsstufen Verbraucher
Verbraucher_1_Stufig Einfacher Ein/Aus-Verbraucher mit Mindestlaufzeit/Nachtlogik Verbraucher
Verbraucher_Sperrbar Verbraucher, der im Peak-Fall gesperrt werden kann Verbraucher
Verbraucher_extern Buendelt externe Schaltverbraucher zu Leistungskombinationen Verbraucher/Adapter
WP_Steuerung Waermepumpe mit Sperr-/Erhoehungskontakten, Wetter-/Sonnenlogik Verbraucher
CC100_HW Hardwarezugriff auf digitale Ein-/Ausgaenge und PT-Fuehler Hilfs-/Hardwaremodul
Shelly_Parser_MQTT MQTT-Parser fuer Shelly-Geraete, legt Variablen dynamisch an Hilfs-/Integrationsmodul
Belevo_Server_Kommunikation Wetterdaten und Influx/Server-Kommunikation Monitoring/Kommunikation
Energy_Pie Visualisierung von Produktion, Netz, Einspeisung, Hausverbrauch Visualisierung
Belevo_Bezahl_Modul Experimentelles Google-Pay/Stripe HTML-Modul Nebenmodul, nicht produktionsreif

4. Grundarchitektur

4.1 Schichten

Die Software hat logisch vier Schichten:

  1. Datenquellen:

    • Netzbezug, Batterieladezustand, aktuelle Ladeleistung, Temperaturen, Schaltzustand, Wetterdaten.
    • Meist als IP-Symcon Variablen konfiguriert.
  2. Energiemanagement:

    • Manager fuer lokale Anlagen.
    • HauptManager fuer uebergeordnete Verteilung ueber mehrere Manager.
  3. Verbraucheradapter:

    • Module, die den gemeinsamen Verbraucher-Vertrag umsetzen.
    • Beispiele: Ladestation_v2, Batterie, Boiler_x_Stufig.
  4. Aktoren und externe Systeme:

    • Schaltkontakte, Wallbox HTTP APIs, Cloud APIs, Wechselrichtervariablen, Shelly MQTT, CC100 Linux-Dateisystem.

4.2 Normaler lokaler Ablauf

Ein typischer Zyklus laeuft so:

  1. Manager wird ueber Timer_DistributeEnergy aufgerufen.
  2. Manager liest Netzbezug, Peakleistung, Ueberschussleistung und Verbraucher_Liste.
  3. Der Modus wird bestimmt:
    • Solarladen, wenn der Netzbezug unterhalb des Umschaltbereichs liegt.
    • Peak-Shaving, wenn der Netzbezug ueber dem Umschaltbereich liegt.
  4. Fuer jeden Verbraucher werden die EMS-Variablen gelesen:
    • Power
    • Bezogene_Energie
    • PV_Prio
    • Sperre_Prio
    • Idle
    • PowerSteps
    • Leistung_Delta
  5. Der Manager fordert per IPS_RequestAction($verbraucher, "GetCurrentData", $Is_Peak_Shaving) neue Daten an.
  6. Wenn ein Verbraucher nicht Idle ist oder sich der Modus geaendert hat, bleiben alle aktuellen Leistungen im aktuellen Zyklus stehen.
  7. Sonst sortiert der Manager Verbraucher nach Prioritaet und verteilt die Leistung.
  8. Die Zuteilung wird ueber IPS_RequestAction($verbraucher, "SetAktuelle_Leistung", $leistung) an die Verbraucher gegeben.
  9. Die Verbraucher setzen diese Vorgabe in ihrem eigenen Do_UserCalc-Timer um.

Wichtig: Viele Verbraucher setzen die Leistung nicht direkt im RequestAction("SetAktuelle_Leistung"), sondern speichern den Wert zuerst in der Variable Power. Die reale Umsetzung erfolgt im naechsten Do_UserCalc.

4.3 Modusentscheidung

Der lokale Manager kennt zwei Betriebsarten:

  • Is_Peak_Shaving = false: Solarladen / Nutzung verfuegbarer Leistung.
  • Is_Peak_Shaving = true: Peak-Shaving / Reduktion oder Begrenzung der Leistung.

Wenn UmschaltpunktStatisch = false, nutzt der Manager die Mitte zwischen Peakleistung und Ueberschussleistung:

Schwellwert = (Peakleistung + Ueberschussleistung) / 2
Netzbezug < Schwellwert -> Solarladen
Netzbezug >= Schwellwert -> Peak-Shaving

Wenn UmschaltpunktStatisch = true, werden Umschalt_Solarladen und Umschalt_Peakshaving als Hysterese verwendet. Zwischen den beiden Werten bleibt der bisherige Modus erhalten.

4.4 Leistungsverteilung

Der Manager arbeitet mit diskreten Leistungsstufen. Jeder Verbraucher liefert ein JSON-Array PowerSteps, zum Beispiel:

[0, 1500, 3000, 6000]

oder bei bidirektionalen Verbrauchern:

[-3000, -1000, 0, 1000, 3000]

Die Verteilung laeuft prioritaetsweise:

  1. Prioritaetsschluessel waehlen:
    • Solarladen: PV_Prio
    • Peak-Shaving: Sperre_Prio
  2. Verbraucher sortieren:
    • zuerst nach Prioritaet, niedriger Wert bedeutet hoeher priorisiert.
    • bei gleicher Prioritaet nach Bezogene_Energie / 2000, damit weniger versorgte Verbraucher bevorzugt werden.
  3. Verbraucher gleicher Prioritaet werden gruppiert.
  4. Innerhalb einer Gruppe werden alle moeglichen Schritte sortiert.
  5. Der Manager nimmt nur Schritte, die in die verbleibende Leistung passen.
  6. Verbraucher, die nicht 0 annehmen koennen, werden gesondert behandelt.

Leistung_Delta korrigiert Soll-/Ist-Abweichungen. Das ist besonders wichtig bei Ladestationen, weil die effektive Ladeleistung von der Vorgabe abweichen kann.

5. Der gemeinsame Verbraucher-Vertrag

Jedes neue Modul, das vom Manager gesteuert werden soll, muss mindestens die folgenden Variablen und Actions anbieten.

5.1 Pflichtvariablen

Ident Typ Bedeutung
Sperre_Prio Integer Prioritaet im Peak-Shaving. Niedriger = wichtiger.
PV_Prio Integer Prioritaet im Solarladen. Niedriger = wichtiger.
Idle Boolean true, wenn das Modul fuer eine neue Leistungszuteilung bereit ist.
Aktuelle_Leistung Integer/Float Aktuell umgesetzte oder zuletzt gesetzte Leistung in W.
Bezogene_Energie Float Aufsummierte Energie fuer Fairness. Aktuell in W * h gerechnet, faktisch Wh.
PowerSteps String JSON-Array moeglicher Leistungsstufen in W.
Power Integer/Float Vom Manager gewuenschte Leistung, oft als Zwischenspeicher.
Is_Peak_Shaving Boolean Letzter vom Manager uebergebener Modus.
Leistung_Delta Integer/Float Abweichung zwischen Soll und Ist, damit der Manager die reale Leistung beruecksichtigen kann.
IdleCounter Integer Hilfszaehler bis Idle wieder true wird.

5.2 Pflicht-Actions

Action Parameter Aufgabe
GetCurrentData Boolean Peak Aktuellen Modus speichern und PowerSteps neu berechnen.
SetAktuelle_Leistung Integer/Float power Neue Leistungsvorgabe entgegennehmen oder direkt umsetzen.
Do_UserCalc leer Interner zyklischer Modulschritt, setzt Power um und aktualisiert PowerSteps.

5.3 Bedeutung der Vorzeichen

Im bestehenden Code gilt implizit:

  • Positive Leistung: Verbraucher bezieht oder laedt Energie.
  • 0: Verbraucher aus oder neutral.
  • Negative Leistung: Einspeisen, Entladen oder Gegenrichtung, aktuell vor allem fuer Batterie relevant.

Neue Module sollten diese Vorzeichenregel konsequent einhalten. Wenn ein Geraet physikalisch anders arbeitet, sollte der Adapter intern umrechnen, aber gegenueber dem Manager diese Semantik behalten.

5.4 Idle-Regel

Idle = false bedeutet: Das Modul hat gerade eine Aenderung bekommen oder wartet auf Mindestlaufzeiten, Hardware-Reaktion oder Stabilisierung. Der Manager soll in dieser Zeit keine neue Verteilung erzwingen.

Typisches Muster:

  1. Wenn neue Leistung ungleich alter Leistung:
    • Idle = false
    • IdleCounter = IdleCounterMax
  2. Pro Zyklus:
    • IdleCounter dekrementieren.
    • Wenn IdleCounter == 0, dann Idle = true.

Dieses Muster verhindert schnelles Takten von Relais, Wallboxen und Wechselrichtervorgaben.

6. Manager im Detail

6.1 Manager

Datei: Manager/module.php

Wichtige Properties:

  • Peakleistung: Sollwert bzw. Obergrenze fuer Peak-Shaving in W.
  • Ueberschussleistung: Sollwert fuer Solarladen in W.
  • Netzbezug: IP-Symcon Variable mit aktuellem Netzbezug.
  • Verbraucher_Liste: Liste der zu steuernden Verbraucher-Instanzen.
  • UmschaltpunktStatisch: aktiviert feste Umschaltpunkte.
  • Umschalt_Solarladen: untere Schwelle bei statischer Hysterese.
  • Umschalt_Peakshaving: obere Schwelle bei statischer Hysterese.
  • HauptmanagerAktiv: aktiviert Kopplung an HauptManager.
  • ManagerID: ID des Untermanagers fuer externe Strukturen.
  • DatenHoch: String-Variable, in die lokale Daten fuer den Hauptmanager geschrieben werden.
  • DatenZuruck: String-Variable, aus der Zuweisungen des Hauptmanagers gelesen werden.
  • Interval: Zykluszeit in Sekunden.

Wichtige Funktionen:

  • DistributeEnergy(): lokale Verteilung.
  • DistributeEnergy_Extern(): JSON-Austausch mit Hauptmanager.
  • RequestAction("DistributeEnergy"): Einstieg des Timers.

6.2 HauptManager

Datei: HauptManager/module.php

Der HauptManager verbindet mehrere lokale Manager oder Teilanlagen. Er liest pro Unteranlage:

  • eine JSON-Variable mit User-/Verbraucherdaten (User_Up)
  • eine JSON-Variable fuer Rueckgabe/Zuweisung (User_Down)

Er aggregiert alle Verbraucher, summiert den Netzbezug, entscheidet global zwischen Solarladen und Peak-Shaving und schreibt pro Untermanager ein JSON mit finalen Set_Leistung-Werten zurueck.

JSON-Erwartung vom Untermanager:

{
  "User": [
    {
      "InstanceID": 12345,
      "Aktuelle_Leistung": 0,
      "Bezogene_Energie": 0,
      "PV_Prio": 1,
      "Sperre_Prio": 1,
      "Idle": true,
      "PowerSteps": [0, 1500, 3000],
      "Leistung_Delta": 0
    }
  ],
  "Netzbezug": 0,
  "Timestamp": 1710000000
}

Rueckgabe an Untermanager:

{
  "Timestamp": 1710000000,
  "Is_Peak_Shaving": false,
  "User": [
    {
      "InstanceID": 12345,
      "Set_Leistung": 1500
    }
  ]
}

Wenn Daten aelter als 30 Sekunden sind, setzt der Hauptmanager fuer diese Unteranlage eine sichere Rueckgabe mit leerer User-Liste.

7. Verbraucher-Module

7.1 Ladestationen

Ladestation_v2

Das wichtigste Ladestationsmodul. Es kann fachlich bereits viele Elemente eines spaeteren OCPP-orientierten Moduls abbilden, aber aktuell noch mit herstellerspezifischer Logik direkt im Modul.

Unterstuetzte Typen laut Formular:

  • Go-E Wallbox alte Version
  • Go-E Gemini/Gemini Flex
  • Smart-Me Pico
  • Dummy Station
  • Easee nur Solarladen
  • Easee

Zentrale Eigenschaften:

  • IP_Adresse, ID, Seriennummer, Username, Password
  • Token_Easee, Token_ECarUp
  • Max_Current_abs
  • Ein_Zeit, Aus_Zeit
  • Mindestaldestrom als Variable mit Action

Zentrale Betriebsvariablen:

  • Ladebereit: Freigabe.
  • Solarladen: PV-Lademodus.
  • Car_detected: Fahrzeug erkannt.
  • Car_is_full: Fahrzeug voll.
  • Is_1_ph: erkannter 1-phasiger Betrieb.
  • Max_Current: intern berechneter Maximalstrom.
  • Fahrzeugstatus: herstellerspezifischer Status.
  • Ladeleistung_Effektiv: gemessene Ladeleistung.
  • Pending_Counter: Zaehler fuer ausbleibende Ist-Leistung.
  • IsTimerActive, IsTimerActive_Null_Timer: Mindestlaufzeit-/Null-Timer.
  • Letzer_User: Benutzerbezug fuer Easee/ECarUp-Logik.

Wichtige Funktionen:

  • Detect_Car(): Fahrzeugerkennung je Stationstyp.
  • Get_Car_Status(): Statusabfrage je Stationstyp.
  • Calc_Max_Current(): dynamische Ermittlung des maximalen Stroms aus effektiver Ladeleistung.
  • Get_Current_From_Power(): Umrechnung W -> A fuer 1p/3p.
  • Get_Array_From_Current(): erzeugt moegliche Leistungsstufen aus Stromstufen.
  • SetAktuelle_Leistung(): setzt EMS-Vorgabe und sendet Stromvorgabe an Station.
  • GetCurrentData(): erzeugt PowerSteps je Modus, Freigabe, Fahrzeugzustand und Timer.
  • sendPowerToStation(): setzt Strom ueber Go-E, Smart-Me, Easee oder Dummy.
  • Refresh_Token(): Easee Login und Token-Pufferung.

Ladestation_Universal

Aelteres, einfacheres Ladestationsmodul. Es arbeitet staerker mit Leistungsgrenzen in W statt mit dynamischer Strom-/Fahrzeuglogik.

Zentrale Unterschiede zu Ladestation_v2:

  • Konfiguriert MinLeistung, MaxLeistung, MinLeistung_1ph, MaxLeistung_1ph.
  • Hat Lademodus statt Is_1_ph.
  • Unterstuetzt Go-E, Smart-Me Pico und Dummy.
  • Weniger ausgebaute Timer-/Pending-/Tokenlogik.

7.2 Batterie

Datei: Batterie/module.php

Das Batteriemodul ist bidirektional im Sinne des Managers: Es erzeugt positive und negative PowerSteps.

Eigenschaften:

  • MaxBatterieleistung: Variable fuer maximale Entladeleistung.
  • MaxNachladen: Variable fuer maximale Ladeleistung.
  • Batterieladezustand: SoC-Variable.
  • AufdasNachladen: Zielwert fuer Nachladen.
  • MinimumEntladen: untere SoC-Grenze.
  • Batteriemanagement: 1 = Wechselrichter, 2 = Symcon EMS.
  • Batterietyp: 1 = Goodwe, 2 = Solaredge, 3 = Sig Energy.
  • Netzbezug: Netzbezug fuer Sonderlogik.

Besonderheiten:

  • GeneratePowerSteps() erzeugt ein Raster aus groben 250-W-Schritten und feinen 50-W-Schritten um die aktuelle Leistung.
  • Im Wechselrichter-Modus (Batteriemanagement = 1) meldet das Modul nur [0].
  • Im EMS-Modus werden je nach SoC, Hysterese und Modus Lade-/Entladestufen freigegeben.
  • SetAktuelle_Leistung() schreibt je Batterietyp andere Steuerwerte:
    • Goodwe: Goodwe_EntLadeleistung, Laden_Entladen.
    • Solaredge: Ladeleistung, Entladeleistung, Laden_Entladen.
    • Sig Energy: Leistung in kW und andere Moduswerte.

7.3 Boiler

Boiler_2_Stufig_Mit_Fueler

Boiler mit zwei Schaltkontakten:

  • Kontakt_Teillast
  • Kontakt_Volllast

Leistungsstufen:

[0, BoilerLeistungTeillast, BoilerLeistungVolllast]

Die PowerSteps werden aus Temperatur, Mindesttemperatur, Maximaltemperatur, Legionellenlogik, Zeitplan und Modus erzeugt.

Boiler_x_Stufig

Boiler mit frei konfigurierbarer Liste LeistungsStufen. Jede Stufe hat:

  • Stufe
  • Leistung
  • Schaltkontakt_Stufe

Das Modul erzeugt daraus ein sortiertes Leistungsarray und schaltet genau die passende Stufe.

Ansteuerung_Askoheat

Askoheat-Modul mit 7-stufiger Leistungslogik:

  • BoilerLeistung ist die Maximalleistung.
  • Calc_Seven_Steps() erzeugt 8 Werte von 0 bis Volllast.
  • SetAktuelle_Leistung() schreibt eine Stufe in Variable_Leistung.
  • Temperatur kommt aus Variable_Temperatur_Ist.

7.4 Pufferspeicher

Pufferspeicher

Puffer mit zwei festen Leistungsstufen:

  • PufferTeilLeistung
  • PufferLeistung

Schaltkontakte:

  • Heizkontakt_Puffer_Teillast
  • Heizkontakt_Puffer

Die Zieltemperatur wird als lineare Funktion der Aussentemperatur berechnet:

VT = f(AT)

mit den Parametern:

  • MinVT_Temp
  • MaxVT_Temp
  • MinAT_Temp
  • MaxAT_Temp

Im Peak-Modus meldet der Puffer normalerweise [0]. Im Solarlade-Modus gibt er Stufen frei, wenn die Puffertemperatur unter dem berechneten Zielwert liegt.

Puffer_Speicher

Variante mit frei konfigurierbaren Leistungsstufen analog zu Boiler_x_Stufig.

7.5 Einfache und externe Verbraucher

Verbraucher_1_Stufig

Ein Ein/Aus-Verbraucher mit:

  • BoilerLeistung
  • Schaltkontakt1
  • Mindesttlaufzeit
  • Nachtlogik 22:00 bis 07:00
  • DailyOnTime
  • Mindestzeit zwischen Zustandswechseln

Im Solarlade-Modus kann er [0, BoilerLeistung] melden. Bei Nacht und nicht erreichter Mindestlaufzeit kann er Leistung erzwingen.

Verbraucher_Sperrbar

Ein Verbraucher, der im Peak-Fall gesperrt werden kann.

Eigenschaften:

  • Leistung: Variable mit aktueller Verbraucherleistung.
  • Schaltkontakt1: Sperrkontakt.
  • Mindestsperrleistung: Mindestwert, ab dem Sperre relevant wird.
  • MaxSperrZeit: maximale Sperrzeit pro Tag.

Im Peak-Modus meldet das Modul je nach aktueller Leistung [0, Letzte_Sperrleistung]. Im Solarlade-Modus meldet es [0].

Verbraucher_extern

Adapter fuer mehrere externe Verbraucher. Es liest eine Liste von Paaren:

  • Read_Var: anfragende/aktive Variable.
  • Write_Var: zu schaltende Variable.
  • P_Nenn: Nennleistung.

Aus aktiven Einzelverbrauchern werden alle moeglichen Leistungskombinationen berechnet. Bei einer Manager-Zuweisung wird eine passende Kombination gesucht und die zugehoerigen Write_Var geschaltet.

7.6 Waermepumpe

Datei: WP_Steuerung/module.php

Die Waermepumpe nutzt:

  • Sperrkontakt
  • Kontakt_Erhoeung
  • WP_Leistung
  • Wetter-/Wolkenvariable
  • Aussentemperatur
  • Referenzzeit fuer Sonnenaufgang
  • optionale Warmwasser-Schwellwertlogik

Sie hat interne Zustaende:

  • Zustand_WP = 1: Normalbetrieb.
  • Zustand_WP = 2: Sperre.
  • Zustand_WP = 3: Erhoehung.

GetCurrentData() meldet normalerweise [0, WP_Leistung], kann aber bei Mindestlaufzeit oder Warmwasser-Schwellwert auf einen festen Zustand begrenzen.

8. Hilfs- und Integrationsmodule

8.1 CC100_HW

Dieses Modul greift direkt auf Linux-Dateipfade eines CC100-Systems zu:

  • Digitale Ausgaenge: /sys/kernel/dout_drv/DOUT_DATA
  • Digitale Eingaenge: /sys/devices/platform/soc/44009000.spi/spi_master/spi0/spi0.0/din
  • PT-Fuehler: /sys/bus/iio/devices/iio:device2/...

Es stellt bereit:

  • Bit1 bis Bit4 als digitale Ausgaenge.
  • DI1 bis DI8 als digitale Eingaenge.
  • PT1, PT2 als Temperaturwerte.

Dieses Modul kann als Hardware-Abstraktion fuer Schaltkontakte und Sensorwerte dienen.

8.2 Shelly_Parser_MQTT

Das Shelly-Modul verbindet sich mit der IP-Symcon MQTT-Server-Instanz und subscribed auf #.

Es verarbeitet:

  • <device>/online
  • <device>/events/rpc

Pro Shelly-Geraet wird ein Kategorieordner angelegt. Darin werden Variablen erzeugt:

  • Online
  • Typ
  • Output x
  • Input x
  • Temperatur

Outputs erhalten ein gemeinsames Action-Script. Beim Schalten wird ein RPC Switch.Set an <device>/rpc publiziert.

Die Parserlogik liegt in Shelly_Parser_MQTT/libs/ShellyParser.php.

8.3 Belevo_Server_Kommunikation

Aufgaben:

  • Wetterdaten von https://brain.belevo.ch/v2wetter abfragen.
  • Temperatur und Wolkenwarscheinlichkeit setzen.
  • Zusatzvariablen als JSON sammeln.
  • Daten an BaseURL, standardmaessig https://brain.belevo.ch/storedata, senden.

Die Aufzeichnung wird ueber InfluxJaNein aktiviert. Der Timer laeuft dann alle 5 Minuten.

8.4 Energy_Pie

Visualisierungsmodul fuer Produktions-/Verbrauchsdaten.

Konfigurierte Quellvariablen:

  • VarProduction
  • VarConsumption
  • VarFeedIn
  • VarGrid

Das Modul liest geloggte Archivwerte, berechnet Differenzen fuer Tag, Woche, Monat, Jahr oder Total und schiebt ein JSON an das HTML-Tile module.html.

8.5 Belevo_Bezahl_Modul

Experimentelles Zahlungsmodul fuer Google Pay/Stripe. Es schreibt HTML in eine konfigurierte HTMLBox.

Aktueller Zustand:

  • enthaelt einen Stripe Test-Publishable-Key.
  • Backend-Pfad ist Platzhalter (/path-to-your-backend.php).
  • keine produktive Zahlungslogik im Modul.

Dieses Modul sollte nicht als produktionsreif betrachtet werden.

9. Neue Module an den Energiemanager anbinden

9.1 Entscheidung: Verbraucher, Manager, Hilfsmodul oder Visualisierung?

Vor der Umsetzung klaeren:

  • Muss das Modul vom Energiemanager Leistung zugeteilt bekommen? Dann ist es ein Verbraucher.
  • Liefert es nur Daten oder Schaltkontakte? Dann ist es ein Hilfsmodul.
  • Soll es mehrere Verbraucher aggregieren? Dann ist es ein Adapter oder Manager-nahes Modul.
  • Zeigt es nur Daten an? Dann ist es eine Visualisierung.

Nur Verbraucher muessen den vollen Manager-Vertrag umsetzen.

9.2 Minimaler Verbraucher-Aufbau

Ein neues Verbraucher-Modul sollte in Create() mindestens registrieren:

$this->RegisterVariableInteger("Sperre_Prio", "Sperre_Prio");
$this->RegisterVariableInteger("PV_Prio", "PV_Prio");
$this->RegisterVariableBoolean("Idle", "Idle", "", true);
$this->RegisterVariableInteger("Aktuelle_Leistung", "Aktuelle_Leistung", "", 0);
$this->RegisterVariableFloat("Bezogene_Energie", "Bezogene_Energie", "", 0);
$this->RegisterVariableString("PowerSteps", "PowerSteps");
$this->RegisterVariableInteger("Power", "Power", "", 0);
$this->RegisterVariableBoolean("Is_Peak_Shaving", "Is_Peak_Shaving", "", false);
$this->RegisterVariableInteger("Leistung_Delta", "Leistung_Delta", "", 0);
$this->RegisterPropertyInteger("IdleCounterMax", 2);
$this->RegisterVariableInteger("IdleCounter", "IdleCounter", "", 0);
$this->RegisterPropertyInteger("Interval", 5);
$this->RegisterTimer(
    "Timer_Do_UserCalc",
    $this->ReadPropertyInteger("Interval") * 1000,
    "IPS_RequestAction(" . $this->InstanceID . ', "Do_UserCalc", "");'
);

RequestAction() sollte mindestens diese Faelle enthalten:

public function RequestAction($Ident, $Value)
{
    switch ($Ident) {
        case "SetAktuelle_Leistung":
            $this->SetValue("Power", (int)$Value);
            break;

        case "GetCurrentData":
            $this->SetValue("Is_Peak_Shaving", (bool)$Value);
            break;

        case "Do_UserCalc":
            $this->SetAktuelle_Leistung($this->GetValue("Power"));
            $this->GetCurrentData($this->GetValue("Is_Peak_Shaving"));
            break;

        default:
            throw new Exception("Invalid Ident");
    }
}

9.3 GetCurrentData() richtig implementieren

GetCurrentData(bool $Peak) muss:

  1. den aktuellen Betriebsmodus beruecksichtigen.
  2. interne Sensoren/Statuswerte aktualisieren.
  3. die erlaubten Leistungsstufen als JSON in PowerSteps schreiben.
  4. Leistung_Delta setzen, falls Soll und Ist abweichen.
  5. bei Mindestlaufzeiten oder Sperrzeiten nur die aktuelle Leistung melden.

Beispiel:

public function GetCurrentData(bool $Peak)
{
    $this->SetValue("Is_Peak_Shaving", $Peak);

    if (!$this->GetValue("Idle")) {
        $this->SetValue("PowerSteps", json_encode([$this->GetValue("Aktuelle_Leistung")]));
        return;
    }

    if ($Peak) {
        $steps = [0, 1000];
    } else {
        $steps = [0, 1000, 2000, 3000];
    }

    $this->SetValue("PowerSteps", json_encode($steps));
    $this->SetValue("Leistung_Delta", 0);
}

9.4 SetAktuelle_Leistung() richtig implementieren

SetAktuelle_Leistung() muss:

  1. Aenderung erkennen und IdleCounter setzen.
  2. Die physische Ansteuerung durchfuehren.
  3. Aktuelle_Leistung setzen.
  4. Bezogene_Energie fortschreiben.
  5. IdleCounter weiterverarbeiten.

Beispiel:

public function SetAktuelle_Leistung(int $power)
{
    $lastPower = $this->GetValue("Aktuelle_Leistung");

    if ($lastPower !== $power) {
        $this->SetValue("Idle", false);
        $this->SetValue("IdleCounter", $this->ReadPropertyInteger("IdleCounterMax"));
    }

    // Hier Geraet ansteuern, z.B. Relais, HTTP API oder Wechselrichtervariable.
    // SetValue($this->ReadPropertyInteger("Schaltkontakt"), $power > 0);

    $this->SetValue("Aktuelle_Leistung", $power);
    $this->SetValue(
        "Bezogene_Energie",
        $this->GetValue("Bezogene_Energie") + ($power * ($this->ReadPropertyInteger("Interval") / 3600))
    );

    $this->ProcessIdleCounter();
}

9.5 Checkliste fuer neue Verbraucher

  • module.json mit neuer GUID, Name, Vendor und Prefix erstellen.
  • form.json mit allen benoetigten Einstellungen erstellen.
  • Alle Pflichtvariablen des Verbraucher-Vertrags registrieren.
  • RequestAction mit SetAktuelle_Leistung, GetCurrentData, Do_UserCalc implementieren.
  • PowerSteps immer als gueltiges JSON-Array schreiben.
  • PowerSteps immer numerisch sortierbar halten.
  • 0 als Stufe anbieten, wenn das Geraet wirklich ausgeschaltet/neutral sein darf.
  • Negative Stufen nur verwenden, wenn das Modul Einspeisung/Entladung sauber unterstuetzt.
  • Idle bei Schaltvorgaengen und Mindestlaufzeiten korrekt auf false setzen.
  • Geraetefehler und Kommunikationsfehler abfangen.
  • Bei Fehlern sichere PowerSteps setzen, meist [0] oder aktuelle Leistung.
  • Im Manager unter Verbraucher_Liste eintragen.

10. Empfehlungen fuer zukuenftige Verbesserungen

10.1 Gemeinsame Basisklasse oder Trait fuer Verbraucher

Der gleiche EMS-Vertrag ist in fast allen Verbrauchern mehrfach implementiert. Sinnvoll waere eine gemeinsame Datei, zum Beispiel:

  • libs/EmsConsumerTrait.php
  • libs/EmsPowerStepHelper.php

Diese koennte bereitstellen:

  • Registrierung der Standardvariablen.
  • Einheitliche IdleCounter-Logik.
  • Energiezaehlung.
  • JSON-Validierung fuer PowerSteps.
  • Hilfen fuer Sortierung und Minimalstufen.

10.2 Manager-Zyklus robuster machen

Im aktuellen Manager::DistributeEnergy() werden Verbraucherdaten gelesen und danach GetCurrentData aufgerufen. Dadurch kann der Manager im selben Zyklus noch alte PowerSteps verwenden, sofern die Verbraucher nicht ohnehin ueber ihren eigenen Timer aktuell sind.

Robuster waere:

  1. Alle Verbraucher per GetCurrentData($Is_Peak_Shaving) aktualisieren.
  2. Danach PowerSteps, Idle, Leistung_Delta neu lesen.
  3. Dann verteilen.

Alternativ koennte GetCurrentData() synchron Daten zurueckgeben statt nur Variablen zu schreiben.

10.3 Validierung und Fail-Safe

Viele Properties sind Variable-IDs. Hauefig ist 0 Default. Vor GetValue(0) oder SetValue(0) sollte konsequent geprueft werden:

$id = $this->ReadPropertyInteger("Netzbezug");
if ($id <= 0 || !IPS_VariableExists($id)) {
    $this->SetStatus(201); // oder eigener Fehlerstatus
    return;
}

Empfehlung:

  • Konfigurationspruefung in ApplyChanges().
  • Statuscodes fuer unvollstaendige Konfiguration.
  • sichere PowerSteps bei Kommunikationsfehlern.

10.4 Einheitliche Logging- und Diagnosevariablen

Aktuell gibt es viele IPS_LogMessage()-Eintraege, teils sehr haeufig in Schleifen. Besser waeren:

  • Letzter_Fehler als String.
  • Letzte_Aktion als String.
  • Letzte_Kommunikation als Timestamp.
  • Kommunikation_OK als Boolean.
  • Debug-Logging nur optional per Property.

10.5 Ladestation v3 / OCPP-orientierte Architektur

Ladestation_v2 enthaelt bereits viele Funktionen, die fuer ein OCPP-Modul relevant sind:

  • Freigabe
  • Solarladen
  • Fahrzeugerkennung
  • Statusabfrage
  • effektive Ladeleistung
  • Stromvorgabe
  • Mindeststrom
  • 1p/3p-Erkennung
  • externe Leistungszuweisung
  • PowerSteps
  • Peak-Shaving-Einfluss
  • Idle-/Pending-/Timer-Logik
  • Token-/Login-Mechanismen

Fuer eine neue OCPP-orientierte Version sollte diese Logik fachlich erhalten bleiben, aber in Adapter aufgeteilt werden:

  • ChargePointModel: internes Datenmodell.
  • ChargingSession: Ladevorgang, Benutzer, Energie.
  • MeterValues: Messwerte.
  • SmartCharging: Sollstrom/Sollleistung.
  • ConnectorState: Status pro Ladepunkt.
  • VendorAdapterInterface: Herstelleradapter.
  • Ocpp16Adapter, Ocpp201Adapter, GoEAdapter, EaseeAdapter, SmartMeAdapter, ECarUpAdapter.

Die EMS-Schnittstelle zum Manager sollte gleich bleiben: PowerSteps, SetAktuelle_Leistung, GetCurrentData, Idle.

10.6 Tests und Simulation

Das Projekt hat aktuell keine automatisierten Tests. Sinnvoll waere ein Simulationsmodus:

  • Fake-Verbraucher mit frei definierbaren PowerSteps.
  • Fake-Netzbezug.
  • Testfaelle fuer Solarladen und Peak-Shaving.
  • Testfaelle fuer Verbraucher mit und ohne 0.
  • Testfaelle fuer negative PowerSteps.
  • Testfaelle fuer gleiche Prioritaet/Fairness.
  • Testfaelle fuer Hauptmanager-JSON.

11. Bekannte technische Risiken und Auffaelligkeiten

Diese Punkte sind aus dem aktuellen Code abgeleitet und sollten vor groesseren Erweiterungen geprueft werden:

  • Mehrere Dateien zeigen Encoding-Probleme in deutschen Texten. Das deutet auf UTF-8/ANSI-Mischung hin.
  • Manager::DistributeEnergy() aktualisiert Verbraucher mit GetCurrentData, liest aber vorher bereits viele Verbraucherdaten. Das kann zu veralteten PowerSteps fuehren.
  • Viele Module pruefen konfigurierte Variablen-IDs nicht konsequent vor GetValue() oder SetValue().
  • Ansteuerung_Askoheat registriert Boilertemperatur doppelt, einmal Float und spaeter Integer.
  • Boiler_x_Stufig nutzt in der Zeitplanpruefung offenbar $vollLeistung, ohne diese Variable vorher eindeutig zu setzen.
  • Ladestation_v2::GetCurrentData() verwendet in einem Zweig fuer solarladen && Peak die Variable $is_1_ph, die dort nicht definiert ist. Gemeint ist wahrscheinlich $this->GetValue("Is_1_ph").
  • Pufferspeicher prueft in der Glaettungslogik teilweise GetIDForIdent("Boilertemperatur"), obwohl die Variable Puffertemperatur heisst.
  • Batterie::CheckIdle() verwendet GetValue("Aktuelle_Leistung") mit String statt Variablen-ID. Die Funktion scheint aktuell nicht zentral genutzt zu werden, sollte aber korrigiert werden.
  • Verbraucher_Sperrbar::ist_nachts() nutzt 24:00 als Startzeit. Das ist fachlich ungewoehnlich und sollte geprueft werden.
  • Mehrere Module setzen date_default_timezone_set("Europe/Berlin"); fuer Schweizer Anlagen waere Europe/Zurich konsistenter.
  • Belevo_Bezahl_Modul ist nur Prototyp/Teststand und enthaelt noch Platzhalter.
  • Logging in Schleifen kann im Dauerbetrieb sehr viele Meldungen erzeugen.

12. Arbeitsanweisung fuer ChatGPT/Codex bei zukuenftigen Aenderungen

Wenn ChatGPT/Codex spaeter an dieser Software weiterarbeitet, sollte es so vorgehen:

  1. Zuerst DOKUMENTATION_CHATGPT.md, README.md, Manager/module.php und das betroffene Modul lesen.
  2. Vor jeder Aenderung pruefen, ob das Modul ein Verbraucher ist und den EMS-Vertrag einhalten muss.
  3. Bestehende Variablen-Idents nicht ohne Migrationsplan umbenennen, weil IP-Symcon Installationen davon abhaengen.
  4. Neue Module mit eigenem Ordner, module.php, module.json, form.json anlegen.
  5. Bei neuen Verbrauchern die Pflichtvariablen exakt gleich benennen.
  6. PowerSteps und Leistung_Delta besonders sorgfaeltig testen.
  7. Bei Hardware/API-Modulen immer Fehlerfaelle abfangen und sichere Werte setzen.
  8. Keine bestehenden Benutzer- oder Anlagenkonfigurationen brechen.
  9. Bei Ladestationen die EMS-Schnittstelle stabil halten, auch wenn intern OCPP oder Herstelleradapter eingefuehrt werden.
  10. Nach Aenderungen mindestens PHP-Syntax pruefen und, wenn moeglich, mit einer simulierten Manager-Konfiguration testen.

13. Kurzreferenz fuer neue ChatGPT-Prompts

Wenn ein neues ChatGPT-Fenster mit dieser Software weiterarbeiten soll, kann folgender Kontext verwendet werden:

Dies ist eine IP-Symcon Modulbibliothek fuer das Belevo Energiemanagement.
Der zentrale Manager verteilt Leistung an Verbraucher ueber einen gemeinsamen Vertrag:
Variablen: Sperre_Prio, PV_Prio, Idle, Aktuelle_Leistung, Bezogene_Energie,
PowerSteps, Power, Is_Peak_Shaving, Leistung_Delta, IdleCounter.
Actions: GetCurrentData(bool Peak), SetAktuelle_Leistung(power), Do_UserCalc.
PowerSteps ist ein JSON-Array moeglicher Leistungsstufen in Watt.
Positive Werte bedeuten Verbrauch/Laden, negative Werte Entladen/Einspeisen.
Der Manager entscheidet zwischen Solarladen und Peak-Shaving und verteilt nach Prioritaet.
Neue steuerbare Module muessen diesen Vertrag exakt umsetzen.
Wichtige Dateien: Manager/module.php, HauptManager/module.php,
Ladestation_v2/module.php, Batterie/module.php, DOKUMENTATION_CHATGPT.md.