Datenbankgestützte Erstellung der Energiebilanz einer SMA PV-Anlage mit Überschusseinspeisung: Unterschied zwischen den Versionen

Aus FHEMWiki
Zur Navigation springen Zur Suche springen
K (Gliederungsebenen angepasst (Über_FHEMWiki#Artikelgliederung))
Zeile 1: Zeile 1:
= Zweck und Voraussetzungen =
== Zweck und Voraussetzungen ==


Das Beispiel erläutert, wie aus den in einer DbLog-Datenbank enthaltene Werte genutzt werden können eine flexibel anpassbare tabellarische Übersicht über die Energieerzeugungen, Einspeisungen, Verbräuche sowie Autarkie- und Eigenverbrauchsquoten zu erstellen.
Das Beispiel erläutert, wie aus den in einer DbLog-Datenbank enthaltene Werte genutzt werden können eine flexibel anpassbare tabellarische Übersicht über die Energieerzeugungen, Einspeisungen, Verbräuche sowie Autarkie- und Eigenverbrauchsquoten zu erstellen.
Zeile 22: Zeile 22:




== Kennzahlen ==
=== Kennzahlen ===


Es werden neben der aktuellen PV-Energieezeugung, dem Energieverbrauch, dem Bezug bzw. Einspeisung von Energie auch die aktuellen, Tages- sowie Monatswerte von Autarkiequote und Eingenverbrauchsquote berechnet und ausgegeben.
Es werden neben der aktuellen PV-Energieezeugung, dem Energieverbrauch, dem Bezug bzw. Einspeisung von Energie auch die aktuellen, Tages- sowie Monatswerte von Autarkiequote und Eingenverbrauchsquote berechnet und ausgegeben.
Zeile 37: Zeile 37:
Ausgangswerte zur Berechnung der beispielhaften Tages- und Monatsquoten werden mit Hilfe von DbRep-Devices aus der Datenbank extrahiert und daraus die Quoten ermittelt.
Ausgangswerte zur Berechnung der beispielhaften Tages- und Monatsquoten werden mit Hilfe von DbRep-Devices aus der Datenbank extrahiert und daraus die Quoten ermittelt.


= Einrichtung SMA Energymeter Device =
== Einrichtung SMA Energymeter Device ==


Der SMA Energymeter ist ein Zweiwegezähler und erfasst sowohl die eingespeiste als auch aus dem Netz bezogene Energie.
Der SMA Energymeter ist ein Zweiwegezähler und erfasst sowohl die eingespeiste als auch aus dem Netz bezogene Energie.
Zeile 64: Zeile 64:
Das Logintervall wird mit interval = 60 auf 60s gesetzt, d.h. jede Minute ensteht ein Energymeter-Datensatz.
Das Logintervall wird mit interval = 60 auf 60s gesetzt, d.h. jede Minute ensteht ein Energymeter-Datensatz.


= SMA Wechselrichter mit SMAInverter integrieren =
== SMA Wechselrichter mit SMAInverter integrieren ==


Zum Anschluß des SMA Wechselrichters wird das Modul SMAInverter verwendet.  
Zum Anschluß des SMA Wechselrichters wird das Modul SMAInverter verwendet.  
Zeile 106: Zeile 106:
Nach einem Abfragezyklus des Energymeters wird sofort eine Datenabfrage des Wechselrichters gestartet.
Nach einem Abfragezyklus des Energymeters wird sofort eine Datenabfrage des Wechselrichters gestartet.


= Anlegen Dummy als Energiebilanz-Device =
== Anlegen Dummy als Energiebilanz-Device ==


Nachdem die Datenlieferanten an FHEM angeschlossen sind, werden nun folgende Werte in der DbLog-Datenbank gespeichert bzw. liefern Events die für die Beispielfunktion wichtig sind. Die Definition von DbLog wird als bekannt vorausgesetzt.
Nachdem die Datenlieferanten an FHEM angeschlossen sind, werden nun folgende Werte in der DbLog-Datenbank gespeichert bzw. liefern Events die für die Beispielfunktion wichtig sind. Die Definition von DbLog wird als bekannt vorausgesetzt.
Zeile 227: Zeile 227:
Dazu werden mehrere DbRep-Devices und eine Routine in der 99_myUtils.pm angelegt.
Dazu werden mehrere DbRep-Devices und eine Routine in der 99_myUtils.pm angelegt.


= Definition der benötigten DbRep-Devices =
== Definition der benötigten DbRep-Devices ==


Für die Auswertungsläufe wird jeweils ein DbRep-Device angelegt für:
Für die Auswertungsläufe wird jeweils ein DbRep-Device angelegt für:
Zeile 403: Zeile 403:
</pre>
</pre>


= Auswertungsfunktion in 99_myUtils anlegen =
== Auswertungsfunktion in 99_myUtils anlegen ==


Wie oben beschrieben, wird durch die userExitFn der DbRep-Devices diese Subroutine angesprungen. Diese Subroutine wertet die übergebenen Daten aus, setzt Readings im Energiebilanz-Dummy und startet abhängige Selektionsläufe.
Wie oben beschrieben, wird durch die userExitFn der DbRep-Devices diese Subroutine angesprungen. Diese Subroutine wertet die übergebenen Daten aus, setzt Readings im Energiebilanz-Dummy und startet abhängige Selektionsläufe.
Zeile 520: Zeile 520:


<br>
<br>
= Energiebilanz um das aktuelle Jahr ergänzen =
== Energiebilanz um das aktuelle Jahr ergänzen ==


Wenn man der Anleitung bis hierher gefolgt ist, werden in der Bilanz aktuelle Werte, Werte des aktuellen Tages und des Monats abgebildet.
Wenn man der Anleitung bis hierher gefolgt ist, werden in der Bilanz aktuelle Werte, Werte des aktuellen Tages und des Monats abgebildet.
Um auch Werte des aktuellen Jahres einzufügen, kann die Erweiterung wie nun beschrieben erfolgen.
Um auch Werte des aktuellen Jahres einzufügen, kann die Erweiterung wie nun beschrieben erfolgen.


== DbRep Devices ergänzen ==
=== DbRep Devices ergänzen ===


Es werden drei weitere DbRep-Devices angelegt/kopiert.
Es werden drei weitere DbRep-Devices angelegt/kopiert.
Zeile 589: Zeile 589:




== Erweiterung der Routine setDumEnergy ==
=== Erweiterung der Routine setDumEnergy ===


In 99_myUtils wird die Routine um eine weitere If-Schleife erweitert (einfach unter die letzte If-Schleife eingefügt).
In 99_myUtils wird die Routine um eine weitere If-Schleife erweitert (einfach unter die letzte If-Schleife eingefügt).
Zeile 682: Zeile 682:




== Trigger zum Start der Jahresbilanz anlegen ==
=== Trigger zum Start der Jahresbilanz anlegen ===


Damit die Berechnung der Jahresbilanz regelmäßig erfolgt wird ein weiteres AT ("recalc_Dum.Energy.Quoten.Jahr") zum Starten angelegt:
Damit die Berechnung der Jahresbilanz regelmäßig erfolgt wird ein weiteres AT ("recalc_Dum.Energy.Quoten.Jahr") zum Starten angelegt:

Version vom 1. Juni 2017, 08:38 Uhr

Zweck und Voraussetzungen

Das Beispiel erläutert, wie aus den in einer DbLog-Datenbank enthaltene Werte genutzt werden können eine flexibel anpassbare tabellarische Übersicht über die Energieerzeugungen, Einspeisungen, Verbräuche sowie Autarkie- und Eigenverbrauchsquoten zu erstellen.

Es wird vorausgesetzt, dass es sich um eine SMA-Anlage mit SMA Energymeter und SMA Wechselrichter handelt und das Logging ausschließlich in einer DbLog-Datenbank erfolgt. Für die Umsetzung des Beispiels werden Devices folgender FHEM-Module verwendet:

  • SMAEM
  • SMAInverter
  • DbLog
  • DbRep
  • Dummy
  • Notify
  • At

Wird dieses Beispiel Schritt für Schritt durchgeführt, ist im Ergebnis eine Energiebilanz wie im nebenstehen Screeshot dargestellt nutzbar und kann natürlich durch Anpassungen und Ergänzungen flexibel zugeschnitten werden, da sich alle benötigten Ausgangswerte in der Datenbank befinden.

Energiebilanz

Bei der Beschreibung wird darauf verzichtet auf die jeweiligen Module näher einzugehen, nur die für die hier benötigte Funktion wesentlichen Parameter und Einstellungen werden erwähnt. Die aufgeführten Device-Definitionen entsprechen der Raw definition-Anzeige direkt im FHEMWEB.


Kennzahlen

Es werden neben der aktuellen PV-Energieezeugung, dem Energieverbrauch, dem Bezug bzw. Einspeisung von Energie auch die aktuellen, Tages- sowie Monatswerte von Autarkiequote und Eingenverbrauchsquote berechnet und ausgegeben.

Die Eigenverbrauchsquote und Autarkiequote wird gebildet aus:

Eigenverbrauchsquote (%) = (Erzeugung - Einspeisung) / Erzeugung * 100

Autarkiequote (%) = (Erzeugung - Einspeisung) / (Erzeugung - Einspeisung + Bezug) * 100

Die aktuellen Quoten werden aus den momentanen Readingswerten von SMAEM- bzw. SMAInverter-Devices gebildet. Ausgangswerte zur Berechnung der beispielhaften Tages- und Monatsquoten werden mit Hilfe von DbRep-Devices aus der Datenbank extrahiert und daraus die Quoten ermittelt.

Einrichtung SMA Energymeter Device

Der SMA Energymeter ist ein Zweiwegezähler und erfasst sowohl die eingespeiste als auch aus dem Netz bezogene Energie. Das Device im Beispiel heißt "SMA_Energymeter" und ist wie folgt definiert.

defmod SMA_Energymeter SMAEM
attr SMA_Energymeter DbLogExclude state
attr SMA_Energymeter disableSernoInReading 1
attr SMA_Energymeter event-min-interval state:120
attr SMA_Energymeter event-on-update-reading state,Saldo_Wirkleistung,Bezug_WirkP_Zaehler_Diff,Einspeisung_WirkP_Zaehler_Diff,.\
,Einspeisung_WirkP_Verguet_Diff,Bezug_WirkP_Kosten_Diff,Bezug_Wirkleistung,Einspeisung_Wirkleistung,.\
,Bezug_Wirkleistung_Zaehler,Einspeisung_Wirkleistung_Zaehler
attr SMA_Energymeter feedinPrice 0.1269
attr SMA_Energymeter group SMA Energy Meter
attr SMA_Energymeter icon measure_power@green
attr SMA_Energymeter interval 60
attr SMA_Energymeter powerCost 0.26782
attr SMA_Energymeter room Energie
attr SMA_Energymeter stateFormat state Watt, ToGrid (+) , FromGrid (-)
attr SMA_Energymeter verbose 3

Wichtig für das Beispiel ist das Attribut "disableSernoInReading". Es wird mit verkürzten Readingnamen gearbeitet. Die in "event-on-update-reading" aufgeführten Readings sollen entweder in der DB geloggt werden oder haben im Ablauf eine steuernde Funktion. Für das Logging in der DB werden Differenzwerte verwendet (Readings mit Diff-Zusatz) um nach einem Stromausfall die Datenintegrität zu gewährleisten. Bei Spannungsausfall werden die Summenzähler im Energymeter (z.B. Bezug_Wirkleistung_Zaehler) wieder auf 0 zurück gesetzt. Das Logintervall wird mit interval = 60 auf 60s gesetzt, d.h. jede Minute ensteht ein Energymeter-Datensatz.

SMA Wechselrichter mit SMAInverter integrieren

Zum Anschluß des SMA Wechselrichters wird das Modul SMAInverter verwendet.

defmod STP_5000 SMAInverter <Passwort> <IP-Adresse>
attr STP_5000 DbLogExclude modulstate,state
attr STP_5000 SBFSpotComp 1
attr STP_5000 detail-level 2
attr STP_5000 event-on-change-reading total_pac,etoday,etotal
attr STP_5000 event-on-update-reading state,modulstate
attr STP_5000 group SMA Inverter
attr STP_5000 icon measure_photovoltaic_inst@green
attr STP_5000 interval 60
attr STP_5000 mode manual
attr STP_5000 offset 0
attr STP_5000 room Energie
attr STP_5000 showproctime 1
attr STP_5000 stateFormat { AttrVal("$name","mode", "automatic").\
" - ".ReadingsVal("$name","state", undef)." kW"}
attr STP_5000 suppressSleep 0
attr STP_5000 target-serial <Serial-No>
attr STP_5000 target-susyid <SysID>
attr STP_5000 timeout 30
attr STP_5000 verbose 2

SMAInverter kennt zwei Arbeitsmodi, manual = 0 bzw. 1. Der Wechselrichter soll nicht eigenständig regelmäßig durch das Modul abgefragt werden, sondern dem Interval des SMA Energymeters folgen. Dazu wird das Attribut manual = 1 gesetzt. Mit SBFSpotComp = 1 wird noch auf die zu SBFSpot kompatible Readingsdarstellung geschaltet und mit detail-level = 2 sämliche Readings erstellt.

Das interval = 60 hat in diesem Modus keine direkte Funktion, sollte aber auf den gleichen Wert wie SMA Energymeter gesetzt werden damit statistische Readings wie "avg_power_lastminutes_05" korrekt kalkuliert werden.

Um die Datensynchronität mit dem SMA Energymeter zu gewähleisten, wird ein Notify angelegt.

defmod N.STP_5000.getdata notify SMA_Energymeter:Saldo_Wirkleistung:.* get STP_5000 data
attr N.STP_5000.getdata disable 0
attr N.STP_5000.getdata room Energie

Nach einem Abfragezyklus des Energymeters wird sofort eine Datenabfrage des Wechselrichters gestartet.

Anlegen Dummy als Energiebilanz-Device

Nachdem die Datenlieferanten an FHEM angeschlossen sind, werden nun folgende Werte in der DbLog-Datenbank gespeichert bzw. liefern Events die für die Beispielfunktion wichtig sind. Die Definition von DbLog wird als bekannt vorausgesetzt.

  • Bezug_Wirkleistung - momentaner Leistungsbezug
  • Einspeisung_Wirkleistung - momentane EInspeiseleistung
  • Bezug_WirkP_Zaehler_Diff - Differenzwert Leistungsbezug zur vorherigen Messung
  • Einspeisung_WirkP_Zaehler_Diff - Differenzwert Leistungseinseisung zur vorherigen Messung
  • total_pac - aktuelle PV-Erzeugung
  • etoday - PV-Erzeugung Tageswert
  • etotal - PV Erzeugung seit Inbetriebnahme Wechslrichter

Der Dummy wird alle gewünschten Ergebnisreadings beinhalten und durch entsprechende state-Formatierung als Tabelle darstellen. Im Beispiel werden die aktuellen (60s Aktualisierungsintervall) Werte von:

  • PV-Erzeugung - Reading PV
  • Einspeisung - Reading GridFeedIn
  • Bezug - Reading GridConsumption
  • Energieverbrauch - Reading TotalConsumption
  • Autarkiequote - Reading AutarkyQuote
  • Eigenverbrauchsquote - Reading SelfConsumptionQuote
  • Zeitpunkt der Erfassung/Werteberechnung

erzeugt bzw. errechnet/abgeleitet.

Definition des Dummy:

defmod Dum.Energy dummy
attr Dum.Energy DbLogExclude GridConsumption,GridFeedIn,SelfConsumptionQuote
attr Dum.Energy alias Energiebilanz
attr Dum.Energy event-on-change-reading PV,GridConsumption,GridFeedIn,SelfConsumptionQuote
attr Dum.Energy event-on-update-reading TotalConsumption,AutarkyQuoteDay,SelfConsumptionQuoteDay,AutarkyQuoteMonth,SelfConsumptionQuoteMonth
attr Dum.Energy group Energiebilanz
attr Dum.Energy icon measure_power_meter
attr Dum.Energy room Energie
attr Dum.Energy stateFormat {\
 my $pv   = ReadingsVal("$name","PV", "")." W";;\
 my $pvd  = ReadingsVal("$name","PVDay", "")." kWh";;\
 my $pvm  = ReadingsVal("$name","PVMonth", "")." kWh";;\
 my $gfi  = ReadingsVal("$name","GridFeedIn", "")." W";;\
 my $gfid = ReadingsVal("$name","GridFeedInDay", "")." kWh";;\
 my $gfim = ReadingsVal("$name","GridFeedInMonth", "")." kWh";;\
 my $eb   = ReadingsVal("$name","GridConsumption", "")." W";;\
 my $ebd  = ReadingsVal("$name","GridConsumptionDay", "")." kWh";;\
 my $ebm  = ReadingsVal("$name","GridConsumptionMonth", "")." kWh";;\
 my $et   = ReadingsVal("$name","TotalConsumption", "")." W";;\
 my $etd  = ReadingsVal("$name","TotalConsumptionDay", "")." kWh";;\
 my $etm  = ReadingsVal("$name","TotalConsumptionMonth", "")." kWh";;\
 my $aq   = ReadingsVal("$name","AutarkyQuote", "")." %";;\
 my $aqd  = ReadingsVal("$name","AutarkyQuoteDay", "")." %";;\
 my $aqm  = ReadingsVal("$name","AutarkyQuoteMonth", "")." %";;\
 my $sq   = ReadingsVal("$name","SelfConsumptionQuote", "")." %";;\
 my $sqd  = ReadingsVal("$name","SelfConsumptionQuoteDay", "")." %";;\
 my $sqm  = ReadingsVal("$name","SelfConsumptionQuoteMonth", "")." %";;\
 my $md   = ReadingsTimestamp("$name", "TotalConsumption", "");;\
 my $cd   = ReadingsTimestamp("$name", "AutarkyQuoteDay", "");;\
 my $cm   = ReadingsTimestamp("$name", "AutarkyQuoteMonth", "");;\
"<html><table border=2 bordercolor='darkgreen' cellspacing=0>\
<tr><td style='padding-right:5px;;padding-left:5px;;font-weight:bold'> </td><td style='padding-right:5px;;padding-left:5px;;font-weight:bold'>aktueller Wert</td><td style='padding-right:5px;;padding-left:5px;;font-weight:bold'>Heute</td><td style='padding-right:5px;;padding-left:5px;;font-weight:bold'>dieser Monat</td></tr>\
 <tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>PV-Erzeugung</td><td style='padding-right:5px;;padding-left:5px'>".$pv."</td><td style='padding-right:5px;;padding-left:5px'>".$pvd."</td><td style='padding-right:5px;;padding-left:5px'>".$pvm."</td></tr>\
 <tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>Einspeisung</td><td style='padding-right:5px;;padding-left:5px'>".$gfi."</td><td style='padding-right:5px;;padding-left:5px'>".$gfid."</td><td style='padding-right:5px;;padding-left:5px'>".$gfim."</td></tr>\
 <tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>Bezug</td><td style='padding-right:5px;;padding-left:5px'>".$eb."</td><td style='padding-right:5px;;padding-left:5px'>".$ebd."</td><td style='padding-right:5px;;padding-left:5px'>".$ebm."</td></tr>\
 <tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>Energieverbrauch</td><td style='padding-right:5px;;padding-left:5px'>".$et."</td><td style='padding-right:5px;;padding-left:5px'>".$etd."</td><td style='padding-right:5px;;padding-left:5px'>".$etm."</td></tr>\
 <tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>Autarkiequote</td><td style='padding-right:5px;;padding-left:5px'>".$aq."</td><td style='padding-right:5px;;padding-left:5px'>".$aqd."</td><td style='padding-right:5px;;padding-left:5px'>".$aqm."</td></tr>\
 <tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>Eigenverbrauchsquote</td><td style='padding-right:5px;;padding-left:5px'>".$sq."</td><td style='padding-right:5px;;padding-left:5px'>".$sqd."</td><td style='padding-right:5px;;padding-left:5px'>".$sqm."</td></tr>\
 <tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>Berechnung am</td><td style='padding-right:5px;;padding-left:5px'>".$md."</td><td style='padding-right:5px;;padding-left:5px'>".$cd."</td><td style='padding-right:5px;;padding-left:5px'>".$cm."</td></tr>\
 </table></html>"\
}

Das recht umfangreiche stateFormat dient der tabellarischen Zusammenstellung der Energiebilanz wie weiter oben als Screenshot dargestellt. Da die aktuellen Werte nicht aus der Datenbank gelesen werden, sondern nach Aktualisierung von SMA Energymeter bzw. SMAInverter auf den Dummy übertragen werden sollen, erfolgt dieser Teil mit Notify-Devices.

Die Intervallabfrage des SMA Energymeters initiiert den Zyklus. Mit dem Notify wird dementsprechend der Bezug im Dummy gespeichert.

defmod N.GridConsumption.Dum.Energy notify SMA_Energymeter:Bezug_Wirkleistung:.* { fhem "setreading Dum.Energy GridConsumption "."$EVTPART1"}
attr N.GridConsumption.Dum.Energy room Energie

Ebenso die Eispeisung mit dem Notify:

defmod N.GridFeedIn.Dum.Energy notify SMA_Energymeter:Einspeisung_Wirkleistung:.* { fhem "setreading Dum.Energy GridFeedIn "."$EVTPART1"}
attr N.GridFeedIn.Dum.Energy room Energie

Wie im Punkt "SMA Wechselrichter mit SMAInverter integrieren" beschrieben erfolgt in diesem Zyklus auch die Datenkollektion des Wechselrichters. Mit dem Signal "modulstate" sind die Daten im Wechselrichtermodul vefügbar und werden mit dem folgenden Notify verarbeitet:

defmod N.PV.TotalConsumption.Dum.Energy notify STP_5000:modulstate.* {\
 # Energieverbrauch\
 fhem "setreading Dum.Energy PV ".sprintf("%.1f",(ReadingsVal("STP_5000","total_pac",0)*1000));;\
 my $tc = sprintf("%.1f",ReadingsVal("Dum.Energy","PV",0)+ReadingsVal("Dum.Energy","GridConsumption",0)-ReadingsVal("Dum.Energy","GridFeedIn",0));; \
 if($tc >= 0) { \
     fhem ("setreading Dum.Energy TotalConsumption ".sprintf("%.1f",$tc));;\
 }\
 \
 # Autarkiegrad\
 my $valA = (ReadingsVal("STP_5000", "total_pac",0)*1000)-ReadingsVal("SMA_Energymeter", "Einspeisung_Wirkleistung",0);;\
 my $calcVal = $valA / ($valA + ReadingsVal("SMA_Energymeter", "Bezug_Wirkleistung",0))*100;;\
 fhem ("setreading Dum.Energy AutarkyQuote ".($calcVal?sprintf("%.0f",$calcVal):"0"));;\
  \
 # Eigenverbrauchsquote\
 my $totalpac = ReadingsVal("STP_5000", "total_pac",0)*1000;;\
 if($totalpac > 0) {\
     my $valSelf = $totalpac - ReadingsVal("SMA_Energymeter", "Einspeisung_Wirkleistung",0);;\
     my $calSelf = $valSelf / $totalpac * 100;;\
     fhem ("setreading Dum.Energy SelfConsumptionQuote ".sprintf("%.0f",$calSelf));;\
 } else {\
     fhem ("setreading Dum.Energy SelfConsumptionQuote -");;\
 }\
}
attr N.PV.TotalConsumption.Dum.Energy room Energie

Es wird die aktuelle PV Erzeugung im Dummy gesetzt, der Energieverbrauch berechnet sowie der aktuelle Autarkiegrad und die Eigenverbrauchsquote aus den Daten abgeleitet und in den Dummy-Readings zur Anzeige gesetzt.

Die weiteren Auswertungen der Tages- bzw. Monatswerte erfolgt über Datenselektionen aus der Datenbank um daraus ebenfalls entsprechende Readings im Dummy-Device abzuleiten. Das Prinzip der Datenselektion und Aggregation ist ebenso einfach auf andere Perioden wie aktuelle Woche oder Jahr anwendbar. Dazu werden mehrere DbRep-Devices und eine Routine in der 99_myUtils.pm angelegt.

Definition der benötigten DbRep-Devices

Für die Auswertungsläufe wird jeweils ein DbRep-Device angelegt für:

  • Bezug Monat
  • Bezug Tag
  • Einspeisung Monat
  • Einspeisung Tag
  • Erzeugung Monat
  • Erzeugung Tag

Es ist am einfachsten das erste angelegte DbRep-Device zu kopieren und nur die Attribute Device, Reading und timestamp_begin, timestmp_ende anzupassen bzw. umzukonfigurieren.

Für die Datenkollektion des monatlichen Energiebezuges wäre die Definition:

defmod Rep.SMAEM.Bezug.Monat DbRep LogDB
attr Rep.SMAEM.Bezug.Monat aggregation no
attr Rep.SMAEM.Bezug.Monat devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen
attr Rep.SMAEM.Bezug.Monat device SMA_Energymeter
attr Rep.SMAEM.Bezug.Monat event-on-update-reading state
attr Rep.SMAEM.Bezug.Monat group SMA Energy Meter Auswertung
attr Rep.SMAEM.Bezug.Monat reading Bezug_WirkP_Zaehler_Diff
attr Rep.SMAEM.Bezug.Monat room Energie
attr Rep.SMAEM.Bezug.Monat showproctime 1
attr Rep.SMAEM.Bezug.Monat timeout 180
attr Rep.SMAEM.Bezug.Monat timestamp_begin current_month_begin
attr Rep.SMAEM.Bezug.Monat timestamp_end current_month_end
attr Rep.SMAEM.Bezug.Monat userExitFn setDumEnergy .*:.*
attr Rep.SMAEM.Bezug.Monat verbose 2

Die in der Definition angegeben "LogDB" ist die Definition des maßgeblichen DbLog-Devices und NICHT der Datenbankname selbst. Informationen zu DbRep siehe auch Commandref.

Nach der Definition des Devices kann schon die Funktion mit

Rep.SMAEM.Bezug.Monat sumValue
set Rep.SMAEM.Bezug.Monat sumValue

getestet werden. Es sollte ein Ergebnisreading wie im nebenstehenden Screenshot erscheinen.

Die Attribute Device/Reading enthalten die auszuwertenden Strings in den korrespondierenden Feldern der Datenbank, die timestamp-Angaben bilden die zeitlich Abgrenzung. Dabei wird dynamisch der aktuelle Monat/Tag ermittelt wenn die Angaben wie im obigen Beispiel erfolgen.

Eine besondere Bedeutung kommt dem Attribut userExitFn zu, welches die User-Schnittstelle aktiviert und dem Aufruf der weiter unten beschriebenen Funktion in 99_myUtils dient. Dazu weiter unten mehr.

Das DbRep für den täglichen Bezug:

defmod Rep.SMAEM.Bezug.heute DbRep LogDB
attr Rep.SMAEM.Bezug.heute aggregation no
attr Rep.SMAEM.Bezug.heute devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen
attr Rep.SMAEM.Bezug.heute device SMA_Energymeter
attr Rep.SMAEM.Bezug.heute event-on-update-reading state
attr Rep.SMAEM.Bezug.heute group SMA Energy Meter Auswertung
attr Rep.SMAEM.Bezug.heute reading Bezug_WirkP_Zaehler_Diff
attr Rep.SMAEM.Bezug.heute room Energie
attr Rep.SMAEM.Bezug.heute showproctime 1
attr Rep.SMAEM.Bezug.heute timeout 180
attr Rep.SMAEM.Bezug.heute timestamp_begin current_day_begin
attr Rep.SMAEM.Bezug.heute timestamp_end current_day_end
attr Rep.SMAEM.Bezug.heute userExitFn setDumEnergy .*:.*
attr Rep.SMAEM.Bezug.heute verbose 2

Das DbRep für Einspeisung Monat:

defmod Rep.SMAEM.Einspeisung.Monat DbRep LogDB
attr Rep.SMAEM.Einspeisung.Monat aggregation no
attr Rep.SMAEM.Einspeisung.Monat devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen
attr Rep.SMAEM.Einspeisung.Monat device SMA_Energymeter
attr Rep.SMAEM.Einspeisung.Monat event-on-update-reading state
attr Rep.SMAEM.Einspeisung.Monat group SMA Energy Meter Auswertung
attr Rep.SMAEM.Einspeisung.Monat reading Einspeisung_WirkP_Zaehler_Diff
attr Rep.SMAEM.Einspeisung.Monat room Energie
attr Rep.SMAEM.Einspeisung.Monat showproctime 1
attr Rep.SMAEM.Einspeisung.Monat timeout 180
attr Rep.SMAEM.Einspeisung.Monat timestamp_begin current_month_begin
attr Rep.SMAEM.Einspeisung.Monat timestamp_end current_month_end
attr Rep.SMAEM.Einspeisung.Monat userExitFn setDumEnergy .*:.*
attr Rep.SMAEM.Einspeisung.Monat verbose 2

Das DbRep für Einspeisung Tag:

defmod Rep.SMAEM.Einspeisung.heute DbRep LogDB
attr Rep.SMAEM.Einspeisung.heute aggregation no
attr Rep.SMAEM.Einspeisung.heute devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen
attr Rep.SMAEM.Einspeisung.heute device SMA_Energymeter
attr Rep.SMAEM.Einspeisung.heute event-on-update-reading state
attr Rep.SMAEM.Einspeisung.heute group SMA Energy Meter Auswertung
attr Rep.SMAEM.Einspeisung.heute reading Einspeisung_WirkP_Zaehler_Diff
attr Rep.SMAEM.Einspeisung.heute room Energie
attr Rep.SMAEM.Einspeisung.heute showproctime 1
attr Rep.SMAEM.Einspeisung.heute timeout 180
attr Rep.SMAEM.Einspeisung.heute timestamp_begin current_day_begin
attr Rep.SMAEM.Einspeisung.heute timestamp_end current_day_end
attr Rep.SMAEM.Einspeisung.heute userExitFn setDumEnergy .*:.*
attr Rep.SMAEM.Einspeisung.heute verbose 2

Das DbRep für Erzeugung Monat:

defmod Rep.STP5000.Erzeugung.Monat DbRep LogDB
attr Rep.STP5000.Erzeugung.Monat aggregation no
attr Rep.STP5000.Erzeugung.Monat devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen
attr Rep.STP5000.Erzeugung.Monat device STP_5000
attr Rep.STP5000.Erzeugung.Monat event-on-update-reading state
attr Rep.STP5000.Erzeugung.Monat group SMA Energy Meter Auswertung
attr Rep.STP5000.Erzeugung.Monat reading etotal
attr Rep.STP5000.Erzeugung.Monat room Energie
attr Rep.STP5000.Erzeugung.Monat showproctime 1
attr Rep.STP5000.Erzeugung.Monat timeout 180
attr Rep.STP5000.Erzeugung.Monat timestamp_begin current_month_begin
attr Rep.STP5000.Erzeugung.Monat timestamp_end current_month_end
attr Rep.STP5000.Erzeugung.Monat userExitFn setDumEnergy .*:.*
attr Rep.STP5000.Erzeugung.Monat verbose 2

Das DbRep für Erzeugung Tag:

defmod Rep.STP5000.Erzeugung.heute DbRep LogDB
attr Rep.STP5000.Erzeugung.heute aggregation no
attr Rep.STP5000.Erzeugung.heute devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen
attr Rep.STP5000.Erzeugung.heute device STP_5000
attr Rep.STP5000.Erzeugung.heute event-on-update-reading state
attr Rep.STP5000.Erzeugung.heute group SMA Energy Meter Auswertung
attr Rep.STP5000.Erzeugung.heute reading etoday
attr Rep.STP5000.Erzeugung.heute room Energie
attr Rep.STP5000.Erzeugung.heute showproctime 1
attr Rep.STP5000.Erzeugung.heute timeout 180
attr Rep.STP5000.Erzeugung.heute timestamp_begin current_day_begin
attr Rep.STP5000.Erzeugung.heute timestamp_end current_day_end
attr Rep.STP5000.Erzeugung.heute userExitFn setDumEnergy .*:.*
attr Rep.STP5000.Erzeugung.heute verbose 2

Wie funktioniert die userExitFn ?
DbRep arbeitet nicht-blockierend, was auch bedeutet, dass Programmelemente die Werte eines vorangegangen Selektionslaufes benötigen erst dann loslaufen dürfen, wenn der vorangegangene Selektionlauf seine Daten geliefert hat. DbRep übergibt normalerweise die Selektionsaufgabe einem Hintergrundprozess und kehrt zum Aufrufer zurück der seinen Code fortsetzt, wobei gewöhnlich die angeforderten Daten noch nicht vorliegen werden.

Das Setzen des Attributs

userExitFn setDumEnergy .*:.*

bewirkt nun, dass nach der Erstellung eines Readings die im Attribut angegebene Funktion (hier "setDumEnergy") aufgerufen wird wenn der angegebene Regex (hier ".*:.*", also immer) wahr ist. Der aufgerufenen Funktion wird der Name des aufrufenenden DbRep-Devices, das erzeugte Reading und der Wert übergeben. In der Funktion "setDumEnergy" wird das gelieferte Ergebnis ausgewertet, die relevanten Readings des Energiebilanz-Dummys gesetzt und das nächste DbRep-Device, d.h. die nächste Auswertung aufgerufen. Das aufgerufenen DbRep-Device verzweigt nach der Datenbankselektion wiederum zur userExitFn und der Vorgang wiederholt sich so lange bis alle aufeinander aufbauenden Selektionen abgeschlossen sind und die Ergebnisse in den Dummy-Readings vorliegen.

Der Programmablauf stellt sich für die Tagesauswertung wie folgt dar:

Start Rep.STP5000.Erzeugung.heute -> Datenselektion -> Aufruf "setDumEnergy" und Auswertung -> Start Rep.SMAEM.Einspeisung.heute -> Datenselektion -> Aufruf "setDumEnergy" und Auswertung -> Start Rep.SMAEM.Bezug.heute -> Datenselektion -> Aufruf "setDumEnergy" und Auswertung -> Berechnung Verbrauch, Eigenverbrauchsquote und Autarkiequote -> setzen Dummy Readings

Gleiches gilt für die Monatsauswertung entsprechend.

Für den Start der ersten Datenselektion wird der Lauf von Rep.STP5000.Erzeugung.[Periode} von einem AT Device regelmäßig getriggert. Es wird je ein AT für den Start von Rep.STP5000.Erzeugung.heute bzw. Rep.STP5000.Erzeugung.Monat angelegt:

defmod recalc_Dum.Energy.Quoten.heute at +*00:30:00 {fhem ("set Rep.STP5000.Erzeugung.heute diffValue") }
attr recalc_Dum.Energy.Quoten.heute disable 0
attr recalc_Dum.Energy.Quoten.heute group SMA Energy Meter Auswertung
attr recalc_Dum.Energy.Quoten.heute room Energie

bzw.

defmod recalc_Dum.Energy.Quoten.Monat at +*00:35:00 {fhem ("set Rep.STP5000.Erzeugung.Monat diffValue") }
attr recalc_Dum.Energy.Quoten.Monat disable 0
attr recalc_Dum.Energy.Quoten.Monat group SMA Energy Meter Auswertung
attr recalc_Dum.Energy.Quoten.Monat room Energie

Auswertungsfunktion in 99_myUtils anlegen

Wie oben beschrieben, wird durch die userExitFn der DbRep-Devices diese Subroutine angesprungen. Diese Subroutine wertet die übergebenen Daten aus, setzt Readings im Energiebilanz-Dummy und startet abhängige Selektionsläufe.

############################################################################
# $Id: myUtilsTemplate.pm 7570 2015-01-14 18:31:44Z rudolfkoenig $
#
# Save this file as 99_myUtils.pm, and create your own functions in the new
# file. They are then available in every Perl expression.

package main;

use strict;
use warnings;

sub
myUtils_Initialize($$)
{
  my ($hash) = @_;
}

# Enter you functions below _this_ line.

use Scalar::Util qw(looks_like_number);

############################################################################################################
########   Setzen von Werten in Dum.Energy
########   UserExitFn in Rep.STP5000.Erzeugung.heute, Rep.SMAEM.Einspeisung.heute, Rep.SMAEM.Bezug.heute,
########   Rep.STP5000.Erzeugung.Monat, Rep.SMAEM.Einspeisung.Monat, Rep.SMAEM.Bezug.Monat
############################################################################################################
sub setDumEnergy {
 my ($name,$reading,$value) = @_;
 my $hash   = $defs{$name};
 
 if ($name =~ m/Rep.*heute/) {
   # Werte aktueller Tag 
   if ($reading =~ m/STP_5000__etoday__DIFF/) {
     # Erzeugung aktueller Tag
	 CommandSetReading(undef, "Dum.Energy PVDay ".(looks_like_number($value)?sprintf('%.1f',$value):0.0));
	 # starten Report Eispeisung aktueller Tag 
	 CommandSet(undef,"Rep.SMAEM.Einspeisung.heute sumValue");
   }
   if ($reading =~ m/SMA_Energymeter__Einspeisung_WirkP_Zaehler_Diff__SUM/) {
     # Eispeisung aktueller Tag
	 CommandSetReading(undef, "Dum.Energy GridFeedInDay ".(looks_like_number($value)?sprintf('%.1f',$value):0.0));
	 # starten Report Bezug aktueller Tag 
	 CommandSet(undef,"Rep.SMAEM.Bezug.heute sumValue");
   }
   if ($reading =~ m/SMA_Energymeter__Bezug_WirkP_Zaehler_Diff__SUM/) {
     # Bezug aktueller Tag
	 CommandSetReading(undef, "Dum.Energy GridConsumptionDay ".(looks_like_number($value)?sprintf('%.1f',$value):0.0));
     
	 # Eigenverbrauchsquote aktueller Tag
     my $pvday     = ReadingsVal("Dum.Energy", "PVDay", 0);
     my $feedinday = ReadingsVal("Dum.Energy", "GridFeedInDay", 0);
     my $sqday     = ($pvday - $feedinday) / $pvday * 100 if($pvday > 0);
     CommandSetReading(undef, "Dum.Energy SelfConsumptionQuoteDay ".sprintf('%.0f',$sqday)) if($sqday);

     # Autarkiequote aktueller Tag
     my $consumday = ReadingsVal("Dum.Energy", "GridConsumptionDay", 0);
     my $aqday     = ($pvday - $feedinday) / ($pvday - $feedinday + $consumday) * 100 if($pvday > 0);
     CommandSetReading(undef, "Dum.Energy AutarkyQuoteDay ".sprintf('%.0f',$aqday)) if ($aqday);
	 
	 # Verbrauch aktueller Tag
	 my $tcday = $pvday - $feedinday + $consumday;
	 CommandSetReading(undef, "Dum.Energy TotalConsumptionDay ".sprintf('%.1f',$tcday)) if ($tcday);
   }
 }
 
 if ($name =~ m/Rep.*Monat/) {
   # Werte aktueller Monat
   if ($reading =~ m/STP_5000__etotal__DIFF/) {
     # Erzeugung aktueller Monat
	 CommandSetReading(undef, "Dum.Energy PVMonth ".(looks_like_number($value)?sprintf('%.1f',$value):0.0));
	 # starten Report Eispeisung aktueller Monat
	 CommandSet(undef,"Rep.SMAEM.Einspeisung.Monat sumValue");
   }
   if ($reading =~ m/SMA_Energymeter__Einspeisung_WirkP_Zaehler_Diff__SUM/) {
     # Eispeisung aktueller Monat
	 CommandSetReading(undef, "Dum.Energy GridFeedInMonth ".(looks_like_number($value)?sprintf('%.1f',$value):0.0));
	 # starten Report Bezug aktueller Monat
	 CommandSet(undef,"Rep.SMAEM.Bezug.Monat sumValue");
   }
   if ($reading =~ m/SMA_Energymeter__Bezug_WirkP_Zaehler_Diff__SUM/) {
     # Bezug aktueller Monat
	 CommandSetReading(undef, "Dum.Energy GridConsumptionMonth ".(looks_like_number($value)?sprintf('%.1f',$value):0.0));
     
	 # Eigenverbrauchsquote Monat
     my $pvmonth     = ReadingsVal("Dum.Energy", "PVMonth", 0);
     my $feedinmonth = ReadingsVal("Dum.Energy", "GridFeedInMonth", 0);
     my $sqmonth     = ($pvmonth - $feedinmonth) / $pvmonth * 100 if($pvmonth > 0);
     CommandSetReading(undef, "Dum.Energy SelfConsumptionQuoteMonth ".sprintf('%.0f',$sqmonth)) if($sqmonth);
 
     # Autarkiequote Monat
     my $consummonth = ReadingsVal("Dum.Energy", "GridConsumptionMonth", 0);
     my $aqmonth     = ($pvmonth - $feedinmonth) / ($pvmonth - $feedinmonth + $consummonth) * 100 if($pvmonth > 0);
     CommandSetReading(undef, "Dum.Energy AutarkyQuoteMonth ".sprintf('%.0f',$aqmonth)) if ($aqmonth);
	 
	 # Verbrauch aktueller Monat
	 my $tcmonth = $pvmonth - $feedinmonth + $consummonth;
	 CommandSetReading(undef, "Dum.Energy TotalConsumptionMonth ".sprintf('%.1f',$tcmonth)) if ($tcmonth);
   }
 }
 
return;
}

1;

Sind alle beschrieben Devices und Routinen angelegt, wird die Energiebilanz regelmäßig alle 60s für die aktuellen Werte, alle 30 Minuten für die Tageswerte und alle 35 Minuten für die Monatsaggregationen erstellt. Sollen die Erstellungsperioden geändert werden, kann dies einfach in der Definitionen von recalc_Dum.Energy.Quoten.[Periode] (AT) geschehen.

Für weitere Periodenaggregationen wären weitere DbRep-Devices anzulegen (zu kopieren) in denen die timestamp-Attribute den gewünschten Perioden angepasst werden müssen und ein weiterer IF-Zweig ( z.B. if ($name =~ m/Rep.*Jahr/) {... ) in der Routine "setDumEnergy" angelegt werden. Die Werte stehen dann im Dummy-Device zur Verfügung und können über eine Anpassung des stateFormat in die Ansicht integriert werden.



Energiebilanz um das aktuelle Jahr ergänzen

Wenn man der Anleitung bis hierher gefolgt ist, werden in der Bilanz aktuelle Werte, Werte des aktuellen Tages und des Monats abgebildet. Um auch Werte des aktuellen Jahres einzufügen, kann die Erweiterung wie nun beschrieben erfolgen.

DbRep Devices ergänzen

Es werden drei weitere DbRep-Devices angelegt/kopiert.

"Rep.SMAEM.Bezug.Jahr" für den Bezug über das aktuelle Jahr:

defmod Rep.SMAEM.Bezug.Jahr DbRep LogDB
attr Rep.SMAEM.Bezug.Jahr aggregation no
attr Rep.SMAEM.Bezug.Jahr devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen
attr Rep.SMAEM.Bezug.Jahr device SMA_Energymeter
attr Rep.SMAEM.Bezug.Jahr event-on-update-reading state
attr Rep.SMAEM.Bezug.Jahr group SMA Energy Meter Auswertung
attr Rep.SMAEM.Bezug.Jahr reading Bezug_WirkP_Zaehler_Diff
attr Rep.SMAEM.Bezug.Jahr room Energie
attr Rep.SMAEM.Bezug.Jahr showproctime 1
attr Rep.SMAEM.Bezug.Jahr timeout 180
attr Rep.SMAEM.Bezug.Jahr timestamp_begin current_year_begin
attr Rep.SMAEM.Bezug.Jahr timestamp_end current_year_end
attr Rep.SMAEM.Bezug.Jahr userExitFn setDumEnergy .*:.*
attr Rep.SMAEM.Bezug.Jahr verbose 2


"Rep.SMAEM.Einspeisung.Jahr" für die Einspeisung im aktuellen Jahr:

defmod Rep.SMAEM.Einspeisung.Jahr DbRep LogDB
attr Rep.SMAEM.Einspeisung.Jahr aggregation no
attr Rep.SMAEM.Einspeisung.Jahr devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen
attr Rep.SMAEM.Einspeisung.Jahr device SMA_Energymeter
attr Rep.SMAEM.Einspeisung.Jahr event-on-update-reading state
attr Rep.SMAEM.Einspeisung.Jahr group SMA Energy Meter Auswertung
attr Rep.SMAEM.Einspeisung.Jahr reading Einspeisung_WirkP_Zaehler_Diff
attr Rep.SMAEM.Einspeisung.Jahr room Energie
attr Rep.SMAEM.Einspeisung.Jahr showproctime 1
attr Rep.SMAEM.Einspeisung.Jahr timeout 180
attr Rep.SMAEM.Einspeisung.Jahr timestamp_begin current_year_begin
attr Rep.SMAEM.Einspeisung.Jahr timestamp_end current_year_end
attr Rep.SMAEM.Einspeisung.Jahr userExitFn setDumEnergy .*:.*
attr Rep.SMAEM.Einspeisung.Jahr verbose 2


"Rep.STP5000.Erzeugung.Jahr" ermittelt die Erzeugung des aktuellen Jahres:

defmod Rep.STP5000.Erzeugung.Jahr DbRep LogDB
attr Rep.STP5000.Erzeugung.Jahr aggregation no
attr Rep.STP5000.Erzeugung.Jahr devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen
attr Rep.STP5000.Erzeugung.Jahr device STP_5000
attr Rep.STP5000.Erzeugung.Jahr event-on-update-reading state
attr Rep.STP5000.Erzeugung.Jahr group SMA Energy Meter Auswertung
attr Rep.STP5000.Erzeugung.Jahr reading etotal
attr Rep.STP5000.Erzeugung.Jahr room Energie
attr Rep.STP5000.Erzeugung.Jahr showproctime 1
attr Rep.STP5000.Erzeugung.Jahr timeout 180
attr Rep.STP5000.Erzeugung.Jahr timestamp_begin current_year_begin
attr Rep.STP5000.Erzeugung.Jahr timestamp_end current_year_end
attr Rep.STP5000.Erzeugung.Jahr userExitFn setDumEnergy .*:.*
attr Rep.STP5000.Erzeugung.Jahr verbose 2


Erweiterung der Routine setDumEnergy

In 99_myUtils wird die Routine um eine weitere If-Schleife erweitert (einfach unter die letzte If-Schleife eingefügt). Der letzte Teil der Routine sieht nun so aus:

.....
 if ($name =~ m/Rep.*Jahr/) {
   # Werte aktuelles Jahr
   if ($reading =~ m/STP_5000__etotal__DIFF/) {
     # Erzeugung aktueller Monat
	 CommandSetReading(undef, "Dum.Energy PVYear ".(looks_like_number($value)?sprintf('%.1f',$value):0.0));
	 # starten Report Eispeisung aktuelles Jahr
	 CommandSet(undef,"Rep.SMAEM.Einspeisung.Jahr sumValue");
   }
   if ($reading =~ m/SMA_Energymeter__Einspeisung_WirkP_Zaehler_Diff__SUM/) {
     # Eispeisung aktuelles Jahr
	 CommandSetReading(undef, "Dum.Energy GridFeedInYear ".(looks_like_number($value)?sprintf('%.1f',$value):0.0));
	 # starten Report Bezug aktuelles Jahr
	 CommandSet(undef,"Rep.SMAEM.Bezug.Jahr sumValue");
   }
   if ($reading =~ m/SMA_Energymeter__Bezug_WirkP_Zaehler_Diff__SUM/) {
     # Bezug aktuelles Jahr
	 CommandSetReading(undef, "Dum.Energy GridConsumptionYear ".(looks_like_number($value)?sprintf('%.1f',$value):0.0));
     
	 # Eigenverbrauchsquote Jahr
     my $pvyear     = ReadingsVal("Dum.Energy", "PVYear", 0);
     my $feedinyear = ReadingsVal("Dum.Energy", "GridFeedInYear", 0);
     my $sqyear     = ($pvyear - $feedinyear) / $pvyear * 100 if($pvyear > 0);
     CommandSetReading(undef, "Dum.Energy SelfConsumptionQuoteYear ".sprintf('%.0f',$sqyear)) if($sqyear);
 
     # Autarkiequote Jahr
     my $consumyear = ReadingsVal("Dum.Energy", "GridConsumptionYear", 0);
     my $aqyear     = ($pvyear - $feedinyear) / ($pvyear - $feedinyear + $consumyear) * 100 if($pvyear > 0);
     CommandSetReading(undef, "Dum.Energy AutarkyQuoteYear ".sprintf('%.0f',$aqyear)) if ($aqyear);
	 
	 # Verbrauch aktueller Jahr
	 my $tcyear = $pvyear - $feedinyear + $consumyear;
	 CommandSetReading(undef, "Dum.Energy TotalConsumptionYear ".sprintf('%.1f',$tcyear)) if ($tcyear);
   }
 }
return;
}

1;

Nachdem die neu angelegten DbRep-Devices ihre Werte an den Dummy geliefert haben und dort als Readings zur Vefügung stehen, wird das stateFormat um die neu erzeugten Variablen (Variablen mit Endung "y") ergänzt. Zur Darstellung ist ebenfalls die HTML-Tabelle erweitert. Das komplette stateFormat von "Dum.Energy" baut sich nun so auf:

{
 my $pv   = ReadingsVal("$name","PV", "")." W";
 my $pvd  = ReadingsVal("$name","PVDay", "")." kWh";
 my $pvm  = ReadingsVal("$name","PVMonth", "")." kWh";
 my $pvy  = ReadingsVal("$name","PVYear", "")." kWh";
 my $gfi  = ReadingsVal("$name","GridFeedIn", "")." W";
 my $gfid = ReadingsVal("$name","GridFeedInDay", "")." kWh";
 my $gfim = ReadingsVal("$name","GridFeedInMonth", "")." kWh";
 my $gfiy = ReadingsVal("$name","GridFeedInYear", "")." kWh";
 my $eb   = ReadingsVal("$name","GridConsumption", "")." W";
 my $ebd  = ReadingsVal("$name","GridConsumptionDay", "")." kWh";
 my $ebm  = ReadingsVal("$name","GridConsumptionMonth", "")." kWh";
 my $eby  = ReadingsVal("$name","GridConsumptionYear", "")." kWh";
 my $et   = ReadingsVal("$name","TotalConsumption", "")." W";
 my $etd  = ReadingsVal("$name","TotalConsumptionDay", "")." kWh";
 my $etm  = ReadingsVal("$name","TotalConsumptionMonth", "")." kWh";
 my $ety  = ReadingsVal("$name","TotalConsumptionYear", "")." kWh";
 my $aq   = ReadingsVal("$name","AutarkyQuote", "")." %";
 my $aqd  = ReadingsVal("$name","AutarkyQuoteDay", "")." %";
 my $aqm  = ReadingsVal("$name","AutarkyQuoteMonth", "")." %";
 my $aqy  = ReadingsVal("$name","AutarkyQuoteYear", "")." %";
 my $sq   = ReadingsVal("$name","SelfConsumptionQuote", "")." %";
 my $sqd  = ReadingsVal("$name","SelfConsumptionQuoteDay", "")." %";
 my $sqm  = ReadingsVal("$name","SelfConsumptionQuoteMonth", "")." %";
 my $sqy  = ReadingsVal("$name","SelfConsumptionQuoteYear", "")." %";
 my $md   = ReadingsTimestamp("$name", "TotalConsumption", "");
 my $cd   = ReadingsTimestamp("$name", "AutarkyQuoteDay", "");
 my $cm   = ReadingsTimestamp("$name", "AutarkyQuoteMonth", "");
 my $cy   = ReadingsTimestamp("$name", "AutarkyQuoteYear", "");
"<html><table border=2 bordercolor='darkgreen' cellspacing=0>
<tr><td style='padding-right:5px;padding-left:5px;font-weight:bold'> </td><td style='padding-right:5px;padding-left:5px;font-weight:bold'>aktueller Wert</td><td style='padding-right:5px;padding-left:5px;font-weight:bold'>Heute</td><td style='padding-right:5px;padding-left:5px;font-weight:bold'>dieser Monat</td><td style='padding-right:5px;padding-left:5px;font-weight:bold'>dieses Jahr</td></tr>
 <tr><td style='padding-right:5px;padding-left:5px;text-align:left;font-weight:bold'>PV-Erzeugung</td><td style='padding-right:5px;padding-left:5px'>".$pv."</td><td style='padding-right:5px;padding-left:5px'>".$pvd."</td><td style='padding-right:5px;padding-left:5px'>".$pvm."</td><td style='padding-right:5px;padding-left:5px'>".$pvy."</td></tr>
 <tr><td style='padding-right:5px;padding-left:5px;text-align:left;font-weight:bold'>Einspeisung</td><td style='padding-right:5px;padding-left:5px'>".$gfi."</td><td style='padding-right:5px;padding-left:5px'>".$gfid."</td><td style='padding-right:5px;padding-left:5px'>".$gfim."</td><td style='padding-right:5px;padding-left:5px'>".$gfiy."</td></tr>
 <tr><td style='padding-right:5px;padding-left:5px;text-align:left;font-weight:bold'>Bezug</td><td style='padding-right:5px;padding-left:5px'>".$eb."</td><td style='padding-right:5px;padding-left:5px'>".$ebd."</td><td style='padding-right:5px;padding-left:5px'>".$ebm."</td><td style='padding-right:5px;padding-left:5px'>".$eby."</td></tr>
 <tr><td style='padding-right:5px;padding-left:5px;text-align:left;font-weight:bold'>Energieverbrauch</td><td style='padding-right:5px;padding-left:5px'>".$et."</td><td style='padding-right:5px;padding-left:5px'>".$etd."</td><td style='padding-right:5px;padding-left:5px'>".$etm."</td><td style='padding-right:5px;padding-left:5px'>".$ety."</td></tr>
 <tr><td style='padding-right:5px;padding-left:5px;text-align:left;font-weight:bold'>Autarkiequote</td><td style='padding-right:5px;padding-left:5px'>".$aq."</td><td style='padding-right:5px;padding-left:5px'>".$aqd."</td><td style='padding-right:5px;padding-left:5px'>".$aqm."</td><td style='padding-right:5px;padding-left:5px'>".$aqy."</td></tr>
 <tr><td style='padding-right:5px;padding-left:5px;text-align:left;font-weight:bold'>Eigenverbrauchsquote</td><td style='padding-right:5px;padding-left:5px'>".$sq."</td><td style='padding-right:5px;padding-left:5px'>".$sqd."</td><td style='padding-right:5px;padding-left:5px'>".$sqm."</td><td style='padding-right:5px;padding-left:5px'>".$sqy."</td></tr>
 <tr><td style='padding-right:5px;padding-left:5px;text-align:left;font-weight:bold'>Berechnung am</td><td style='padding-right:5px;padding-left:5px'>".$md."</td><td style='padding-right:5px;padding-left:5px'>".$cd."</td><td style='padding-right:5px;padding-left:5px'>".$cm."</td><td style='padding-right:5px;padding-left:5px'>".$cy."</td></tr>
 </table></html>"
}


Trigger zum Start der Jahresbilanz anlegen

Damit die Berechnung der Jahresbilanz regelmäßig erfolgt wird ein weiteres AT ("recalc_Dum.Energy.Quoten.Jahr") zum Starten angelegt:

defmod recalc_Dum.Energy.Quoten.Jahr at *20:15:00 {fhem ("set Rep.STP5000.Erzeugung.Jahr diffValue") }
attr recalc_Dum.Energy.Quoten.Jahr disable 0
attr recalc_Dum.Energy.Quoten.Jahr group SMA Energy Meter Auswertung
attr recalc_Dum.Energy.Quoten.Jahr room Energie
Energiebilanz mit Jahreswerten

Nun wird täglich um 20:25 die PV-Erzeugung des Jahres ermittelt und über den mehrfachen Durchlauf von "setDumEnergy" ebenfalls die weiteren Jahres-DbRep's ausgeführt um am Ende diese Werte auch im Dummy darstellen zu lassen.

Damit sieht das Ergebnis im Dummy wie rechts im Screenshot aus.