<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>http://wiki.fhem.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Dracolein</id>
	<title>FHEMWiki - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.fhem.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Dracolein"/>
	<link rel="alternate" type="text/html" href="http://wiki.fhem.de/wiki/Spezial:Beitr%C3%A4ge/Dracolein"/>
	<updated>2026-04-14T23:05:56Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung&amp;diff=38509</id>
		<title>SolarForecast - Solare Prognose (PV Erzeugung) und Verbrauchersteuerung</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung&amp;diff=38509"/>
		<updated>2023-07-21T08:06:27Z</updated>

		<summary type="html">&lt;p&gt;Dracolein: /* Praxisbeispiele und Lösungsansätze für Steuerungen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Hinweis|Das Modul 76_SolarForecast ist im Stadium &amp;quot;Testing&amp;quot; und ist zur Zeit noch nicht im offiziellen FHEM Repository verfügbar. Die vorliegende Wiki-Seite befindet sich im Aufbau.}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Solarprognose und Verbrauchersteuerung&lt;br /&gt;
|ModType=x&lt;br /&gt;
|ModCmdRef=76_SolarForecast&lt;br /&gt;
|ModFTopic=117864&lt;br /&gt;
|ModForumArea=Solaranlagen&lt;br /&gt;
|ModTechName=76_SolarForecast.pm&lt;br /&gt;
|ModOwner=DS_Starter ({{Link2FU|16933|Forum}}/[[Benutzer Diskussion:DS_Starter|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
[[SolarForecast - Solare Prognose (PV Erzeugung) und Verbrauchersteuerung|SolarForecast]] ist ein integratives Modul zur Gewinnung solarer Vorhersagedaten, deren Verarbeitung und grafischen Darstellung. Desweiteren bietet es die Möglichkeit, in FHEM definierte Verbraucher in einem SolarForecast-Device zu registrieren und eine PV Prognose basierte Steuerung der Verbraucher vom Modul übernehmen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Das Modul ist insbesondere durch folgende Eigenschaften gekennzeichnet:&lt;br /&gt;
[[Datei:sfc1.png|right|thumb|300px|grafische Ansicht SolarForecast]]&lt;br /&gt;
&lt;br /&gt;
::* zur Gewinnung solarer Strahlungswerte werden die SolCast API oder alternativ DWD Stahlungswerte-Stationen integriert&lt;br /&gt;
&lt;br /&gt;
::* es wird sowohl die Erzeugungsprognose als auch eine Verbrauchsprognose erstellt&lt;br /&gt;
&lt;br /&gt;
::* Wetterdaten werden über DWD Wetter-Stationen integriert&lt;br /&gt;
&lt;br /&gt;
::* Sprachensupport EN | DE&lt;br /&gt;
&lt;br /&gt;
::* die Prognosedaten, Wetterdaten, Verbraucherplanungen und die aktuellen Energieflüsse werden in umfangreich anpassbaren integrierten Grafiken dargestellt&lt;br /&gt;
&lt;br /&gt;
::* es wird keine externe SQL-Datenbank benötigt, die Datenhaltung erfolgt in einer Memory basierten Cachedatenbank inkl. einer Filesystempersistenz zur Datensicherung und Wiederherstellung beim Restart&lt;br /&gt;
&lt;br /&gt;
::* die Integration von Geräten wie Wechselrichter, Energy Meter, Batterien, Wetterstationen oder Verbrauchern ist offen und universell gestaltet und bietet dem Anwender maximale Freiheiten bei der Einrichtung seines individuellen Solardatensystems.&lt;br /&gt;
&lt;br /&gt;
::* eine integrierte und umfangreich anpassbare Verbrauchersteuerung vereint die PV Prognose basierte Einplanung der Verbraucher mit der Möglichkeit die Verbraucher durch das Modul schalten zu lassen und dadurch auf PV Erzeugungsschwankungen automatisch dynamisch zu reagieren&lt;br /&gt;
&lt;br /&gt;
::* trotz der hohen Komplexität wird dem Anwender durch eine &amp;quot;Guided Procedure&amp;quot; bei der Gerätedefinition der Einstieg erleichtert und damit ein optimales Benutzerlebnis geboten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Abgrenzung:&#039;&#039;&#039; Das Modul 76_SolarForecast ist nicht zu verwechseln mit der SQL-basierten (DbLog) Prognose-Lösung mit Kostal Plenticore Wechselrichtern, die auf der eigenen Seite &#039;&#039;&#039;[[Kostal_Plenticore_10_Plus]]&#039;&#039;&#039; behandelt wird. Diese Lösung beschreibt kein monolithisches Modul, sondern basiert auf einer orchestrierbaren Zusammenstellung individueller Perl Programmbausteine. &lt;br /&gt;
&lt;br /&gt;
Im vorliegenden Wiki-Beitrag wird ausschließlich das Modul 76_SolarForecast behandelt.&lt;br /&gt;
&lt;br /&gt;
== Rahmenbedingungen und Voraussetzungen ==&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Die Hilfe zu dem Modul ist über &amp;quot;help SolarForecast de&amp;quot; aufrufbar.&lt;br /&gt;
&lt;br /&gt;
== Konfigurationsbeispiele ==&lt;br /&gt;
=== Beispiel 1 ===&lt;br /&gt;
Dies ist eine Konfiguration mit &lt;br /&gt;
&lt;br /&gt;
SummenDummy für 2 BatterieWR (Namen : SBS25 / SBS25_2)&lt;br /&gt;
&lt;br /&gt;
SummenDummy für 3 PV-Wechselrichter (Namen : SB25 / SB30 / SB40)&lt;br /&gt;
&lt;br /&gt;
            mit verschiedenen InverterStrings / ModulDirection / ModulTiltAngle, ModulPeakString&lt;br /&gt;
&lt;br /&gt;
und auch mit den notwendigen zugehörigen anderen Modul-Konfigs.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ACHTUNG:&#039;&#039;&#039; Zusätzlich enthalten ist bei dem Beispiel-Notify eine Sonderkonstellation für eine Brennstoffzelle &amp;quot;FCU&amp;quot; als weitere bzw. zusätzliche Stromerzeugungsquelle. Diese &amp;quot;FCU&amp;quot; wird dadurch mit in der Grafik mit deren Erzeugungsleistung Tag und Nacht in der Erzeugersumme (am Symbol = Sonne) berücksichtigt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;(ReadingsVal(&amp;quot;FCU&amp;quot;,&amp;quot;FCU-Strom-aktuelle-Leistung&amp;quot;,0)/1000)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== DWD ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
define DWD DWD_OpenData&lt;br /&gt;
attr DWD DbLogExclude .*&lt;br /&gt;
attr DWD forecastDays 7&lt;br /&gt;
attr DWD forecastProperties SunUp, SunRise, SunSet, Rad1h, R101, TTT, Tx, Tn, Tg, DD, FX1, RR6c, R600, RRhc, Rh00, ww, wwd, Neff&lt;br /&gt;
attr DWD forecastResolution 1&lt;br /&gt;
attr DWD forecastStation H568&lt;br /&gt;
attr DWD forecastWW2Text 1&lt;br /&gt;
attr DWD group Umwelt&lt;br /&gt;
attr DWD icon rc_WEB&lt;br /&gt;
attr DWD room 021_DWD&lt;br /&gt;
attr DWD stateFormat Tomorrow Tmax fc1_Tx °C on fc1_date at Blintrop&lt;br /&gt;
attr DWD verbose 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== InverterDummy ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
define InverterDummy dummy&lt;br /&gt;
attr InverterDummy DbLogExclude .*&lt;br /&gt;
attr InverterDummy DbLogInclude Today_PVforecast,etoday&lt;br /&gt;
attr InverterDummy event-on-change-reading .*&lt;br /&gt;
attr InverterDummy group Energy Meter&lt;br /&gt;
attr InverterDummy icon measure_photovoltaic_inst@green&lt;br /&gt;
attr InverterDummy room 020_PV,Energie&lt;br /&gt;
attr InverterDummy stateFormat {sprintf(&amp;quot;current %9.3f kW    Today_PVforecast  %9.3f kWh      Today_PV %9.3f kWh      Total_PV %9.3f kWh&amp;quot;,\&lt;br /&gt;
ReadingsVal($name,&amp;quot;total_pac&amp;quot;,0)/1,\&lt;br /&gt;
ReadingsNum(&amp;quot;Forecast&amp;quot;,&amp;quot;Today_PVforecast&amp;quot;,0)/1000,\&lt;br /&gt;
ReadingsVal($name,&amp;quot;etoday&amp;quot;,0)/1,\&lt;br /&gt;
ReadingsVal($name,&amp;quot;etotal&amp;quot;,0)/1,)}&lt;br /&gt;
attr InverterDummy verbose 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== SMA_Energymeter ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
define SMA_Energymeter SMAEM&lt;br /&gt;
attr SMA_Energymeter DbLogExclude state&lt;br /&gt;
attr SMA_Energymeter diffAccept 50&lt;br /&gt;
attr SMA_Energymeter disable 0&lt;br /&gt;
attr SMA_Energymeter disableSernoInReading 1&lt;br /&gt;
attr SMA_Energymeter event-on-update-reading state,Saldo_Wirkleistung,Bezug_Wirkleistung,Einspeisung_Wirkleistung,Bezug_Wirkleistung_Zaehler,Einspeisung_Wirkleistung_Zaehler&lt;br /&gt;
attr SMA_Energymeter group Energy Meter&lt;br /&gt;
attr SMA_Energymeter icon measure_power@green&lt;br /&gt;
attr SMA_Energymeter interval 15&lt;br /&gt;
attr SMA_Energymeter room 020_PV,Energie&lt;br /&gt;
attr SMA_Energymeter serialNumber XXXXXXXXXX    &lt;br /&gt;
attr SMA_Energymeter stateFormat state W (IN -) P1: L1_Saldo_Wirkleistung P2: L2_Saldo_Wirkleistung P3:L3_Saldo_Wirkleistung&lt;br /&gt;
attr SMA_Energymeter verbose 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== BatteryDummy ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
define BatteryDummy dummy&lt;br /&gt;
attr BatteryDummy DbLogExclude .*&lt;br /&gt;
attr BatteryDummy event-on-change-reading .*&lt;br /&gt;
attr BatteryDummy group Energy Meter&lt;br /&gt;
attr BatteryDummy icon batterie@green&lt;br /&gt;
attr BatteryDummy room 020_PV,Energie&lt;br /&gt;
attr BatteryDummy stateFormat {ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;total_pac&amp;quot;, undef).&amp;quot; kW &amp;quot;.\&lt;br /&gt;
&amp;quot; - total &amp;quot;.ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;bat_loadtotal&amp;quot;, undef).&amp;quot; kWh (-in)&amp;quot;.\&lt;br /&gt;
&amp;quot; - &amp;quot;.ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;bat_unloadtotal&amp;quot;, undef).&amp;quot; kWh (out)&amp;quot;.\&lt;br /&gt;
&amp;quot; - charged &amp;quot;.ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;chargestatus&amp;quot;, undef).&amp;quot; %&amp;quot;}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;quot;Berechnungs&amp;quot;-Notify der Werte für Batterie- und InverterDummy ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
define N.PV.TotalConsumption.Dum.Energy notify SMA_Energymeter:Saldo_Wirkleistung:.* {\&lt;br /&gt;
 # Forecast Invertererzeugung InverterDummy \&lt;br /&gt;
fhem &amp;quot;setreading InverterDummy Today_PVforecast &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(ReadingsNum(&amp;quot;Forecast&amp;quot;,&amp;quot;Today_PVforecast&amp;quot;,0)));;\&lt;br /&gt;
 # Invertererzeugung InverterDummy \&lt;br /&gt;
fhem &amp;quot;setreading InverterDummy etotal &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(ReadingsNum(&amp;quot;SB25&amp;quot;,&amp;quot;etotal&amp;quot;,0))+(ReadingsNum(&amp;quot;SB30&amp;quot;,&amp;quot;etotal&amp;quot;,0))+(ReadingsNum(&amp;quot;SB40&amp;quot;,&amp;quot;etotal&amp;quot;,0)));;\&lt;br /&gt;
 # Invertererzeugung InverterDummy \&lt;br /&gt;
fhem &amp;quot;setreading InverterDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(ReadingsVal(&amp;quot;FCU&amp;quot;,&amp;quot;FCU-Strom-aktuelle-Leistung&amp;quot;,0)/1000)+(ReadingsNum(&amp;quot;SB25&amp;quot;,&amp;quot;total_pac&amp;quot;,0))+(ReadingsNum(&amp;quot;SB30&amp;quot;,&amp;quot;total_pac&amp;quot;,0))+(ReadingsNum(&amp;quot;SB40&amp;quot;,&amp;quot;total_pac&amp;quot;,0)));;\&lt;br /&gt;
 # Invertererzeugung InverterDummy \&lt;br /&gt;
my $wert1234 = &amp;quot;0&amp;quot; ;;\&lt;br /&gt;
$wert1234 = sprintf(&amp;quot;%.3f&amp;quot;,(ReadingsNum(&amp;quot;SB25&amp;quot;,&amp;quot;etoday&amp;quot;,0))+(ReadingsNum(&amp;quot;SB30&amp;quot;,&amp;quot;etoday&amp;quot;,0))+(ReadingsNum(&amp;quot;SB40&amp;quot;,&amp;quot;etoday&amp;quot;,0)));; \&lt;br /&gt;
fhem (&amp;quot;setreading InverterDummy etoday &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert1234));;\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme InverterDummy\&lt;br /&gt;
fhem &amp;quot;setreading BatteryDummy power_out &amp;quot;.sprintf(&amp;quot;%.0f&amp;quot;,(ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;power_out&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung InverterDummyBatterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading BatteryDummy power_in &amp;quot;.sprintf(&amp;quot;%.0f&amp;quot;,(ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;power_in&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Bezug -bat_loadtotal Batterieentnahme InverterDummy\&lt;br /&gt;
fhem &amp;quot;setreading BatteryDummy bat_unloadtotal &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_unloadtotal&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_unloadtotal&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung bat_loadtotal InverterDummyBatterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading BatteryDummy bat_loadtotal &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_loadtotal&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_loadtotal&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus InverterDummy\&lt;br /&gt;
my $wert5 = sprintf(&amp;quot;%.2f&amp;quot;,(((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0))/2) + ((ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0))/2)));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy chargestatus &amp;quot;.sprintf(&amp;quot;%.2f&amp;quot;,$wert5));;\&lt;br /&gt;
 # Batterie-total_pac  InverterDummy\&lt;br /&gt;
my $wert6 = sprintf(&amp;quot;%.3f&amp;quot;,((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;total_pac&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;total_pac&amp;quot;,0))));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert6));;\&lt;br /&gt;
}&lt;br /&gt;
attr N.PV.TotalConsumption.Dum.Energy DbLogExclude .*&lt;br /&gt;
attr N.PV.TotalConsumption.Dum.Energy room Energie&lt;br /&gt;
attr N.PV.TotalConsumption.Dum.Energy verbose 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== SolarForecast ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
define Forecast SolarForecast&lt;br /&gt;
attr Forecast DbLogExclude .*&lt;br /&gt;
attr Forecast affect70percentRule 0&lt;br /&gt;
attr Forecast comment update per &amp;quot;wget -qO /opt/fhem/FHEM/76_SolarForecast.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/76_SolarForecast.pm&amp;quot;&lt;br /&gt;
attr Forecast ctrlInterval 10&lt;br /&gt;
attr Forecast disable 0&lt;br /&gt;
attr Forecast event-on-change-reading .*&lt;br /&gt;
attr Forecast flowGraphicAnimate 1&lt;br /&gt;
attr Forecast flowGraphicShowConsumer 1&lt;br /&gt;
attr Forecast flowGraphicShowConsumerDummy 1&lt;br /&gt;
attr Forecast flowGraphicShowConsumerPower 1&lt;br /&gt;
attr Forecast flowGraphicShowConsumerRemainTime 1&lt;br /&gt;
attr Forecast flowGraphicSize 400&lt;br /&gt;
attr Forecast graphicBeam1Color 3C14FF&lt;br /&gt;
attr Forecast graphicBeam1Content pvForecast&lt;br /&gt;
attr Forecast graphicBeam2Color 19FF29&lt;br /&gt;
attr Forecast graphicBeam2Content pvReal&lt;br /&gt;
attr Forecast graphicHeaderDetail all&lt;br /&gt;
attr Forecast graphicHistoryHour 4&lt;br /&gt;
attr Forecast graphicLayoutType double&lt;br /&gt;
attr Forecast graphicShowDiff top&lt;br /&gt;
attr Forecast graphicShowNight 0&lt;br /&gt;
attr Forecast group Energy Meter&lt;br /&gt;
attr Forecast room 020_PV,Energie&lt;br /&gt;
attr Forecast stateFormat Current_PV&lt;br /&gt;
attr Forecast verbose 2&lt;br /&gt;
&lt;br /&gt;
setstate Forecast 2023-03-03 19:35:46 currentBatteryDev BatteryDummy pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus&lt;br /&gt;
setstate Forecast 2023-02-27 19:53:12 currentForecastDev DWD&lt;br /&gt;
setstate Forecast 2023-02-27 22:42:02 currentInverterDev InverterDummy pv=total_pac:kW etotal=etotal:kWh capacity=9500&lt;br /&gt;
setstate Forecast 2022-03-29 08:44:11 currentMeterDev SMA_Energymeter gcon=Bezug_Wirkleistung:W contotal=Bezug_Wirkleistung_Zaehler:kWh gfeedin=Einspeisung_Wirkleistung:W feedtotal=Einspeisung_Wirkleistung_Zaehler:kWh&lt;br /&gt;
setstate Forecast 2022-03-06 20:12:10 currentRadiationDev DWD&lt;br /&gt;
setstate Forecast 2023-04-05 16:44:50 inverterStrings Garage_SE,Garage_NW,Haus_NW,Haus_SW&lt;br /&gt;
setstate Forecast 2023-04-05 16:44:32 moduleDirection Garage_SE=SE Garage_NW=NW Haus_NW=NW Haus_SW=SW&lt;br /&gt;
setstate Forecast 2023-04-05 16:45:13 modulePeakString Garage_SE=2.75 Garage_NW=3.2 Haus_NW=2.230 Haus_SW=2.230&lt;br /&gt;
setstate Forecast 2023-04-05 16:45:39 moduleTiltAngle Garage_SE=35 Garage_NW=35 Haus_NW=45 Haus_SW=45&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So sollte es dann als Ergebnis aussehen:&lt;br /&gt;
[[Datei:Solarforecast Beispiel Screenshot.png|zentriert|mini|Ergebnis nach dieser Konfiguration]]&lt;br /&gt;
&lt;br /&gt;
== Einbinden / Registrieren von Verbrauchern ==&lt;br /&gt;
&lt;br /&gt;
Das Modul gestattet es beliebige Verbraucher (Devices) über die Attribute &#039;&#039;&#039;consumerXX&#039;&#039;&#039; zu registrieren. Durch die Registrierung wird dem Modul der Namen des Devices sowie dessen Eingenschaften durch die Angabe von Schlüssel-Wert Paaren bekannt gemacht.&lt;br /&gt;
&lt;br /&gt;
Nach der Registrierung können die Verbraucher durch das Modul genutzt werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* es erfolgt eine Planung der Ein- und Ausschaltzeiten abhängig von der solaren Prognose in Bezug zu den Leistungsdaten des Verbrauchers sowie der anderen registrierten Consumer&lt;br /&gt;
* das Modul kann die Ein- und Ausschaltsteuerung der Consumer übernehmen (optional)&lt;br /&gt;
* die aktuellen Status (Verbrauchsdaten) werden in der Energiefußgrafik dargestellt&lt;br /&gt;
* das Modul lernt mit der Zeit das Verbrauchsverhalten der registrierten Verbraucher&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um einen Verbaucher zu registrieren, wird ein freies &#039;&#039;&#039;consumerXX&#039;&#039;&#039; Attribut, zum Beispiel consumer01, gesetzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Beispiel Registrierung eines Shelly Devices ===&lt;br /&gt;
&lt;br /&gt;
Nachfolgendes Beispiel zeigt eine Registrierung eines Heizlüfters der an einem Shelly Zwischenstecker angeschlossen ist und durch das Modul gesteuert werden soll. Dabei soll die Steuerung nicht nur von der Solarprognose, sondern auch von der Raumtemperatur abhängig erfolgen. Im Beispiel wird das Attribut consumer03 verwendet.&lt;br /&gt;
&lt;br /&gt;
Zwingende Angaben sind&lt;br /&gt;
&lt;br /&gt;
 consumerXX &amp;lt;Device Name&amp;gt; type=&amp;lt;type&amp;gt; power=&amp;lt;power&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Alle Angaben können mehrzeilig eingegeben werden. Die Schlüssel-Werte Paare sind jeweils durch ein Leerzeichen getrennt.&lt;br /&gt;
&lt;br /&gt;
 consumerXX Shelly.shellyplug3 type=heater power=1700 &lt;br /&gt;
&lt;br /&gt;
In dem Beispiel ist Shelly.shellyplug3 der Devicename des Shellies in FHEM. Der Schlüssel &#039;&#039;&#039;type&#039;&#039;&#039; definiert die Art des Verbrauchers. In der Hilfe sind die möglichen Typen aufgeführt. Den richtigen Typ anzugeben hat Einfluß auf die spätere Einschätzung des Leistungsverhaltens über die Laufzeit. So wird von einem &#039;&#039;&#039;heater&#039;&#039;&#039; gleich nach dem Einschalten die angegebene Nominalleistung abgerufen und wird über die Zeit gleichbleiben. &lt;br /&gt;
Eine Waschmaschine oder ein Trockner rufen über ihre Laufzeit die Leistung nicht gleichbleibend ab und ändern die Leistungsaufnahme sich über die Einschaltdauer.&lt;br /&gt;
&lt;br /&gt;
Die Angabe von &#039;&#039;&#039;power&#039;&#039;&#039; definiert die Nominalleistung (Watt) die für den Verbraucher laut Typenschild vom Hersteller angegeben wird. Diese Angabe wird vom Modul bei der Planung der Einschaltzeiten verwendet indem die Nominalleistung in das Verhältnis zur Solarprognose bzw. Verbrauchsprognose des Netzes gesetzt wird. Weiterhin ist dieser Wert auch wichtig um später den tatsächlichen Einschaltzeitpunkt auszuführen wenn ein realer PV Überschuss festgestellt wird.&lt;br /&gt;
&lt;br /&gt;
Es ist möglich &#039;&#039;&#039;power=0&#039;&#039;&#039; zu setzen. Das führt dazu, dass die Planung und letztendlich auch der Schaltvorgang unabhängig von der Solarprognose bzw. einem realen PV Überschuss vorgenommen wird.  &lt;br /&gt;
&lt;br /&gt;
Es werden weitere Schlüsseleingaben vorgenommen:&lt;br /&gt;
:&amp;lt;code&amp;gt;Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit dem Schlüssel &#039;&#039;&#039;icon&#039;&#039;&#039; legt man ein Icon fest welches in der Grafik für den Verbraucher verwendet wird. Der &#039;&#039;&#039;mode&#039;&#039;&#039; definiert die Art und Weise der Einplanung:&lt;br /&gt;
&lt;br /&gt;
;can: Die Einplanung erfolgt zum Zeitpunkt mit wahrscheinlich genügend verfügbaren PV Überschuss. Der Start des Verbrauchers zum Planungszeitpunkt unterbleibt bei ungenügendem PV-Überschuss.&lt;br /&gt;
&lt;br /&gt;
;must: Der Verbaucher wird optimiert eingeplant auch wenn wahrscheinlich nicht genügend PV Überschuss vorhanden sein wird. Der Start des Verbrauchers erfolgt auch bei ungenügendem PV-Überschuss.  &lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;notbefore&#039;&#039;&#039; wird festgelegt, dass die Einplanung nicht vor neun Uhr morgens erfolgen soll auch falls schon genügend PV Überschuss vorhanden wäre. Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; definiert die Einplanungsdauer des Verbrauchers in Minuten im einfachsten Fall. Die hier verwendete Angabe &#039;&#039;&#039;SunPath&#039;&#039;&#039; ist ein Spezialfall. Der Verbraucher soll von Sonnenaufgang bis Sonnenuntergang eingeschaltet werden, wobei die Angabe von 60 bzw. -60 ein relative Verschiebung bewirken. Dadurch wird das Einschalten 60 Mintuen nach Sonnenaufgang bis 60 Minuten vor Sonnenuntergang geplant.&lt;br /&gt;
&lt;br /&gt;
Die Schlüssel &#039;&#039;&#039;on&#039;&#039;&#039; und &#039;&#039;&#039;off&#039;&#039;&#039; teilen dem Modul die jeweiligen gültigen Ein- und Aus-Kommandos mit, mit dem das (Shelly)Device geschaltet werden kann. Werden diese Schlüssel nicht oder &amp;quot;leer&amp;quot; (on= off=) angegeben, erfolgt kein Schalten durch das Modul, nur die Planungsdaten werden erzeugt.&lt;br /&gt;
&lt;br /&gt;
Die Verbraucherregistrierung wird mit weiteren Angaben ergänzt um das gewünschte Verhalten zu erreichen:&lt;br /&gt;
&lt;br /&gt;
 Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off etotal=relay_0_energy_Wh:Wh  &lt;br /&gt;
                    pcurr=relay_0_power:W auto=automatic interruptable=og.bad.wandthermostat:diff-temp:[0-9]\.[0-9]:0.2&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;etotal&#039;&#039;&#039; wird der Readingname des Shelly Devices angegeben welches die Summe der verbrauchten Energie (Wh/kWh) des Consumer Device liefert. D.h. es muß ein sich stetig erhöhender Wert sein. Durch die Auswertung dieses Readings ermittelt das Modul die in bestimmten Zeiteinheiten verbrauchte Energie zur weiteren Verwendung. &lt;br /&gt;
&lt;br /&gt;
In dem Shelly Device ist per default ein solches Reading nicht vorhanden. Über userReadings kann in dem Device Shelly.shellyplug3 ein Reading für etotal erzeugt werden:&lt;br /&gt;
&lt;br /&gt;
 userReadings relay_0_energy_Wh:relay_0_energy.* monotonic { sprintf &amp;quot;%.0f&amp;quot;, ReadingsVal ($name, &#039;relay_0_energy&#039;, 0) / 60 } &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;pcurr&#039;&#039;&#039; enthält das Reading in Shelly.shellyplug3 welches den aktuellen Energieverbrauch liefert. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;auto&#039;&#039;&#039; enthält das Reading in Shelly.shellyplug3 welches zur Freigabe/Sperrung der autmatischen Schaltung durch das Modul dienen soll. Ist das angegebene Reading (im Beispiel &amp;quot;automatic&amp;quot;) im Shelly.shellyplug3 nicht vorhanden, wird es vom Modul automatisch mit dem Wert &amp;quot;1&amp;quot; angelegt.&lt;br /&gt;
Dadurch ist per default das automatische Schalten von Shelly.shellyplug3 durch das Modul freigegeben. &lt;br /&gt;
Der User kann durch Setzen des Readings &#039;&#039;&#039;automatic=0&#039;&#039;&#039; das automatische Schalten durch das Modul sperren und mit &amp;quot;1&amp;quot; wieder freigeben. Dadurch kann man zu bestimmten Zeiten (Urlaub, Feiertage, etc.) die Schaltung temporär deaktivieren.&lt;br /&gt;
&lt;br /&gt;
Wie oben beschrieben, soll der Heizlüfter als weitere Schaltbedingung die Abhängigkeit von der Raumtemperatur beachten. Konkret soll der Heizlüfter mit einer Hysterese von 0.2 (Grad) bei Erreichen einer Soll-Raumtemperatur ausschalten und bei Unterschreiten einer bestimmten Temperatur einschalten.&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; übernimmt diese temporäre Schaltsequenzen.&lt;br /&gt;
&lt;br /&gt;
Zunächst wird in dem Sensordevice (In dem Beispiel ein Homatic Wandthermostat HM-TC-IT-WM-W-EU) ein Reading erstellt welches dann im Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; angegeben wird. Dieses Reading soll einen Wert enthalten auf den der angegebene Regex ([0-9]\.[0-9]) matchen soll um Shelly.shellyplug3 temporär auszuschalten.&lt;br /&gt;
Im Wandthermostat wird dazu ein userReading angelegt:&lt;br /&gt;
&lt;br /&gt;
 userReadings diff-temp:desired-temp.* { &lt;br /&gt;
     sprintf &amp;quot;%.1f&amp;quot;, ReadingsVal ($name, &#039;measured-temp&#039;, 0) - ReadingsVal ($name, &#039;desired-temp&#039;, 0) &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das bedeutet, wenn die Raumtemperatur die Solltemperatur erreicht oder höher ist, wird diff-temp &amp;gt;= 0.&lt;br /&gt;
In diesem Fall matcht der angebene Regex in:&lt;br /&gt;
&lt;br /&gt;
 interruptable=og.bad.wandthermostat:diff-temp:&#039;&#039;&#039;[0-9]\.[0-9]&#039;&#039;&#039;:0.2&lt;br /&gt;
&lt;br /&gt;
und Shelly.shellyplug3 wird ausgeschaltet. &lt;br /&gt;
Unterschreitet der Wert von diff-temp 0, matcht der Regex nicht mehr und der Verbraucher wird wieder eingeschaltet. Dabei wird die angegebene Hysterese berücksichtigt, d.h der Verbraucher wird erst ausgeschaltet wenn &amp;quot;diff-temp - 0.2 &amp;gt;= 0&amp;quot; wahr ist.&lt;br /&gt;
&lt;br /&gt;
Für das Wiedereinschalten des Heizlüfters ist außerdem Voraussetzung, dass ein entsprechender PV-Überschuss vorliegt. Diese Bedingung wird durch die Angabe von &#039;&#039;&#039;power=1700&#039;&#039;&#039; bewirkt. Soll der zwangsweise PV Überschuss ignoriert werden, kann &#039;&#039;&#039;power=0&#039;&#039;&#039; angegeben werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Praxisbeispiele und Lösungsansätze für Steuerungen ==&lt;br /&gt;
&lt;br /&gt;
=== dynamische Ladestromsteuerung eines Victron MultiPlus II Chargers mit Pylontech Batterie ===&lt;br /&gt;
&lt;br /&gt;
Die nachfolgend beschriebene Lösung soll als Anregung für eigene Optimierungen verstanden werden und ist weiter ausbaufähig bzw. erweiterbar um zum Beipiel jahreszeitliche Anpassungen des Verfahrens.&lt;br /&gt;
&lt;br /&gt;
Die MultiPlus II Batteriewechselrichter von Victron sollten die Batterien nicht mit dem maximal möglichen Ladestrom beladen, da sich die Effizienz deutlich verschlechtert wenn sich die Ströme den jeweiligen Grenzwerten nähern ([https://www.victronenergy.com/upload/documents/Output-rating-operating-temperature-and-efficiency.pdf Lesestoff]). &lt;br /&gt;
Andererseits sollen die Ladeleistungen so gewählt werden, dass die verfügbare Solarenergie eine volle Aufladung der Akkus ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Das Victron System ermöglicht das Auslesen und die Steuerung der Anlage via MQTT. Die Einbindung in FHEM über MQTT soll hier nicht beschrieben werden.&lt;br /&gt;
Aber wenn dies erfolgt ist, kann der Ladestrom z.B. mit dem Kommando:&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;Device&amp;gt; MaxChargeCurrent &amp;lt;Wert&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
eingestellt bzw. variiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Modul bietet dem Nutzer die Möglichkeit, im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltetene Code wird am Ende jedes Zyklus (siehe Attribut &#039;&#039;ctrlInterval&#039;&#039;) ausgeführt.&lt;br /&gt;
In dem Attribut wird dieser Code eingetragen dessen Funktion und Zusammenspiel nachfolgend erläutert wird:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  ## Vars&lt;br /&gt;
  ########&lt;br /&gt;
  my $batdev  = (split &amp;quot; &amp;quot;, ReadingsVal ($name, &#039;currentBatteryDev&#039;, &#039;&#039;))[0];  # Batteriedevice&lt;br /&gt;
  my $vebus   = &#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;;                            # Victron Vebus Device&lt;br /&gt;
  my $maxcspc = 35;                                                            # max. Ladesollstrom (A) nominal&lt;br /&gt;
  my $spcorr  = 0.7;                                       # Korrekturfaktor Überschuss 70%&lt;br /&gt;
  my $sch     = 3;                                         # Minuend des Sonnenuntergangs             &lt;br /&gt;
  my $cclvl1  = 10;                                        # Ladestrom Level 1 max. 10 A (500 W)&lt;br /&gt;
  my $cclvl2  = 20;                                        # Ladestrom Level 2 max. 20 A (1000 W)&lt;br /&gt;
  my $cclvl3  = 29;                                        # Ladestrom Level 3 max. 29 A (1400 W)&lt;br /&gt;
  &lt;br /&gt;
  ###############&lt;br /&gt;
  my $pvfc   = ReadingsNum ($name, &#039;RestOfDayPVforecast&#039;,            0);&lt;br /&gt;
  my $cofc   = ReadingsNum ($name, &#039;RestOfDayConsumptionForecast&#039;,   0);&lt;br /&gt;
  my $cpv    = ReadingsNum ($name, &#039;Current_PV&#039;,                     0);&lt;br /&gt;
  &lt;br /&gt;
  my $solh   = ReadingsNum ($name, &#039;statistic_SunHours_Remain&#039;,      0) - $sch; # verbleibende h bis SunSet-3&lt;br /&gt;
  $solh      = $solh &amp;lt; 0 ? 0 : $solh;&lt;br /&gt;
  &lt;br /&gt;
  my $ahrem  = ReadingsNum ($batdev, &#039;EnergyRemain&#039;,                 0) / 48;   # Ladung Batterie verbleibend&lt;br /&gt;
  $ahrem     = sprintf &amp;quot;%.0f&amp;quot;, $ahrem;&lt;br /&gt;
  &lt;br /&gt;
  my $fcdiff = ($pvfc - $cofc) * $spcorr;     # Korrektur der noch aktuell prognostizierten Überschussenergie &lt;br /&gt;
  $fcdiff    = $fcdiff &amp;lt; 0 ? 0 : $fcdiff;     # Wh&lt;br /&gt;
  &lt;br /&gt;
  my $splah  = $fcdiff / 48;                  # Wh -&amp;gt; Ah auf 48 V bezogen&lt;br /&gt;
  &lt;br /&gt;
  if ($cpv &amp;amp;&amp;amp; $solh &amp;amp;&amp;amp; $ahrem &amp;amp;&amp;amp; $ahrem &amp;lt; $fcdiff) {  # Ladeanforderung und Überschuss übersteigt Lademenge&lt;br /&gt;
      my $cspc = $ahrem / $solh;              # A = Ah / h&lt;br /&gt;
	  &lt;br /&gt;
      $maxcspc = $cspc &amp;lt;= $cclvl1 ? $cclvl1 : # Ladung mit Level 1 Leistung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl2 ? $cclvl2 : # Ladung mit Level 2 Leistung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl3 ? $cclvl3 : # Ladung mit Level 3 Leistung&lt;br /&gt;
                 $maxcspc;                    # max. Ladesollstrom         &lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($defs{$batdev}, &#039;SolCast_userFn_MaxChargeCurrent&#039;, $maxcspc, 1);&lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent&#039;, $maxcspc, 1);&lt;br /&gt;
  CommandSet           (undef, &amp;quot;$vebus MaxChargeCurrent $maxcspc&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2023-05-03 201457.png|right|thumb|300px|Vorhersage PV Erzeugung und Energieverbrauch des (restlichen) Tages]]&lt;br /&gt;
Zunächst wird der am aktuellen Tag zu erwartende Totalüberschuss solarer Energie ermittelt. Das erfolgt aus der Differenz von &#039;&#039;RestOfDayPVforecast&#039;&#039; und &#039;&#039;RestOfDayConsumptionForecast&#039;&#039; unter Berücksichtigung eines Sicherheitsabschlages (&#039;&#039;Korrekturfaktor Überschuss 70%&#039;&#039;). Das Ergebnis liegt in Wh vor und wird bezogen auf 48 V (die Spannung des Batteriesystems) in Ah umgerechnet. &lt;br /&gt;
&lt;br /&gt;
Die noch benötigte Ladung der Batterie zur Erreichung des Soll SOC-Wertes ermittelt das ReadingsNum &#039;&#039;statistic_SunHours_Remain&#039;&#039; aus dem Batteriedevice, welches vom Modulreading &#039;&#039;currentBatteryDev&#039;&#039; ausgelesen wird.&lt;br /&gt;
&lt;br /&gt;
Sofern der so ermittelte solare Überschuss des (Rest)Tages die benötigte Lademenge der Batterie übersteigt, wird der DC Ladestrom so verringert, dass er sich in einem effizienten Bereich des MultiPlus II bewegt und dennoch rechnerisch ausreicht auf den Soll SOC-Wert zu laden.  &lt;br /&gt;
&lt;br /&gt;
Zu diesem Zweck wird im Modul über die Auswahl von &#039;&#039;SunHours_Remain&#039;&#039; im Attribut &#039;&#039;ctrlStatisticReadings&#039;&#039; das zusätzliche Reading &#039;&#039;statistic_SunHours_Remain&#039;&#039; erzeugt. Aus dem (noch) erforderlichen Ladungswert &#039;&#039;&#039;EnergyRemain&#039;&#039;&#039; (Ah) und der um eine Sicherheitszeit (&#039;&#039;Minuend des Sonnenuntergangs&#039;&#039;) reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche Mindestladestromstärke ermittelt.&lt;br /&gt;
&lt;br /&gt;
Dieser Wert wird auf die zu Anfang des Codeblocks definierten Ladelevel (&#039;&#039;Ladestrom Level X&#039;&#039;) abstrahiert und ein passender &#039;&#039;&#039;effizienter&#039;&#039;&#039; Ladestrom-Bereich ausgewählt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2023-05-03 201719.png|right|thumb|300px|Vorhersage PV Erzeugung und Energieverbrauch des (restlichen) Tages]]&lt;br /&gt;
&lt;br /&gt;
In allen anderen Fällen, wenn z.B. rechnerisch nicht genügend oder keine Solarenergie erzeugt wird (nachts) oder der Speicher gefüllt ist, wird der maximale (Sollwert) des Ladestroms &#039;&#039;$maxcspc = 35&#039;&#039; eingestellt. Dieser Wert entspricht dem maximalen Ladestrom gemäß Herstellerunterlagen Pylontech.&lt;br /&gt;
&lt;br /&gt;
Die Einstellung erfolgt per Set-Kommando im Victron vebus MQTT Device &#039;&#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;&#039;. Dieses Device wurde ebenfalls während der MQTT Integration des Victron Systems angelegt und wird hier nicht näher diskutiert.&lt;br /&gt;
Zur Kontrolle des kalkulierten Wertes werden noch die Readings &#039;&#039;SolCast_userFn_MaxChargeCurrent&#039;&#039; im Batteriedevice und &#039;&#039;userFn_Bat_MaxChargeCurrent&#039;&#039; im SolarForecast Device generiert.&lt;br /&gt;
&lt;br /&gt;
Neben der Effizienzoptimierung hat dieses Verfahren auch den Vorteil einer möglichst schonenden Batterieaufladung was der Lebensdauer der Komponenten zugute kommen sollte.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Poolheizung in Abhängigkeit von vorhandenenm Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren)&#039;&#039;&#039; ===&lt;br /&gt;
Eine (Whirl-)Poolheizung soll bei ausreichend überschüssiger Energie aus einer Photovoltaikanlage dynamisch gesteuert werden (Eigenverbrauchsoptimierung). Im folgenden Beispiel ist ein Device mit der Bezeichnung &#039;&#039;Forecast&#039;&#039; des Typs &#039;&#039;SolarForecast bereits&#039;&#039; angelegt und konfiguriert. Ein freies Consumer-Attribut &#039;&#039;consumer1&#039;&#039; wird beispielhaft wie folgt definiert:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr Forecast consumer1 MQTT2_layzspa type=other power=1950 mode=can on=&amp;quot;heater on&amp;quot; off=&amp;quot;heater off&amp;quot; pcurr=WATT interruptable=1 swstate=heaterstate:1:0 auto=Automatiksteuerung mintime=SunPath spignorecond=EVCharger22:LadungMitPVUeberschussActive:1 icon=scene_pool notbefore=8 notafter=20&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Poolheizung ist innerhalb FHEM bereits im Device &#039;&#039;MQTT2_layzspa&#039;&#039; integriert und lässt sich normalerweise per FHEM-Befehl &amp;quot;set &#039;&#039;MQTT2_layzspa heater on&amp;quot;&#039;&#039; oder &#039;&#039;&amp;quot;set MQTT2_layzspa heater off&amp;quot;&#039;&#039; steuern. Entsprechend werden die Schlüssel-Wert-Paare &#039;&#039;&amp;quot;on=&amp;quot;&#039;&#039; und &#039;&#039;&amp;quot;off=&amp;quot;&#039;&#039; definiert. Der Stromverbrauch einer aktiven Poolheizung ist uns bekannt und wird im Schlüssel &#039;&#039;&amp;quot;power=1950&amp;quot;&#039;&#039; definiert. Die Heizfunktion soll nur bei ausreichend Überschuss aktiviert werden dürfen und muss bei Unterschreitung sofort abgeschaltet werden. Diese Eigenschaften werden über die Schlüssel &#039;&#039;&amp;quot;mode=can&amp;quot;&#039;&#039; und &#039;&#039;&amp;quot;interruptable=&amp;quot;1&amp;quot;&#039;&#039; festgelegt. Zuletzt soll grundsätzlich nur in der Zeit zwischen 08:00 Uhr bis 20:00 Uhr geheizt werden dürfen. Die Schlüssel &#039;&#039;&amp;quot;notbefore=8&amp;quot;&#039;&#039; und &#039;&#039;&amp;quot;notafter=20&amp;quot;&#039;&#039; legen diese Eigenschaften fest. Zur Anzeige des Schaltzustands der Heizung wurde der Schlüssel &#039;&#039;&amp;quot;swstate=heaterstate:1:0&amp;quot;&#039;&#039; hinzugefügt (Wert 1 = Heizung aktiv, Wert 0= Heizung aus). &lt;br /&gt;
&lt;br /&gt;
==== Priorisierung vor externen PV-Überschuss gesteuerten Verbrauchern: ====&lt;br /&gt;
Der Schlüssel-Wert &#039;&#039;&#039;&amp;quot;spignorecond=&amp;quot;&#039;&#039;&#039; bietet optional die Möglichkeit, ein Consumer auch ohne ausreichend PV-Überschuss einzuschalten. Bei erfüllter Bedingung wird der Verbraucher entsprechend der Planung eingeschaltet auch wenn zu dem Zeitpunkt kein PV Überschuß vorliegt. Im obigen Beispiel existiert in der Haus-Elektroinstallation eine Elektroauto-Ladestation mit eigener (externer) dynamischer PV-gesteuerter Fahrzeugladung ohne Integration in &#039;&#039;SolarForecast&#039;&#039;. In Abhängigkeit von PV-Generatorleistung und Sonneneinstrahlung besteht manchmal eine Möglichkeit, dass der gesamte PV-Überschuss zur Fahrzeugladung genutzt wird. Das Modul SolarForecast würde entsprechend keinen (oder zu wenig) PV-Überschuss erkennen und den Consumer &#039;&#039;MQTT2_layzspa&#039;&#039; nicht aktivieren. &lt;br /&gt;
&lt;br /&gt;
Durch Verwendung von &#039;&#039;spignorecond=EVCharger22:LadungMitPVUeberschussActive:1&#039;&#039; wird die Poolheizung gegenüber der Ladestation jedoch priorisiert mit PV-Überschuss versorgt. In diesem Beispiel wird Consumer1 aktiviert, wenn die Ladestation &amp;quot;&#039;&#039;EVCharger22&#039;&#039;&amp;quot; sich im PV-Überschuss-Modus befindet &#039;&#039;&#039;und&#039;&#039;&#039; momentan ein Fahrzeug lädt. In der Folge würde der Hausstromverbrauch um ca. 1950 Watt steigen, die externe Fahrzeugladestation diese Änderung registrieren und die Fahrzeugladeleistung entsprechend verringern oder ganz abbrechen.&lt;br /&gt;
&lt;br /&gt;
=== Luftentfeuchter PV-Überschuss gesteuert mit externer Zwangs-Einschaltbedingung ===&lt;br /&gt;
Im folgenden Beispiel wird ein Luftentfeuchter normalerweise nur bei ausreichend PV-Überschuss Energie eingeschaltet (Eigenverbrauchsoptimierung), soll jedoch bei hoher Luftfeuchtigkeit zusätzlich aktiviert werden.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr Forecast SolarForecast ShellyPlug1 type=other power=300 mode=can on=on off=off pcurr=power:W interruptable=1 swstate=state:on:off mintime=SunPath locktime=900 notbefore=07 notafter=22 spignorecond=ESPEasy_ESP_Easy1_am2302_sensor:humidity:high icon=Ventilator_fett&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Das in FHEM bereits angelegte Device namens &#039;&#039;ShellyPlug1&#039;&#039; dient als Zwischenstecker zur Steuerung des Luftentfeuchters. Der Schlüsselwert &amp;quot;&#039;&#039;mintime=SunPath&#039;&#039;&amp;quot; definiert die zeitliche Einplanung von Sonnenauf- bis untergang. Jedoch soll das Gerät unter keinen Umständen in der Nacht eingeschaltet werden, was über die Schlüssel &#039;&#039;&amp;quot;notbefore=07&amp;quot;&#039;&#039; bzw. &#039;&#039;&amp;quot;notafter=22&amp;quot;&#039;&#039; festgelegt ist. Weiterhin wurde im Schlüssel &#039;&#039;&amp;quot;locktime=900&amp;quot;&#039;&#039; festgelegt, dass zwischen (möglichen) Ein- und Ausschaltintervallen wenigstens 15 Minuten Wartezeit vergehen soll.&lt;br /&gt;
&lt;br /&gt;
Der Schlüssel-Wert &#039;&#039;&#039;&amp;quot;spignorecond=&amp;quot;&#039;&#039;&#039; bietet optional die Möglichkeit, ein Consumer bei erfüllter Bedingung auch ohne ausreichend PV-Überschuss einzuschalten. In diesem Beispiel wird ein Raumluftsensor abgefragt. Bei Vorhandensein der Einschaltschwelle &amp;quot;high&amp;quot; aktiviert sich der Consumer zur geplanten Laufzeit zwischen 07:00 bis 22:00 Uhr solange, bis der Raumluftsensor einen abweichenden Wert meldet. &lt;br /&gt;
&lt;br /&gt;
== weiterführende Links ==&lt;br /&gt;
* {{Link2Forum|Topic=117864|LinkText=Forenthema zum Modul}}&lt;br /&gt;
* Forenthema &amp;quot;{{Link2Forum|Topic=117864|LinkText=Leistungsprognose für Wechselrichter}}&amp;quot;&lt;br /&gt;
* Solcast API Toolkit: https://toolkit.solcast.com.au&lt;br /&gt;
* Kostal Plenticore 10 Plus mit SQL-Datenbank Integration ([[Kostal Plenticore 10 Plus]])&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>Dracolein</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung&amp;diff=38508</id>
		<title>SolarForecast - Solare Prognose (PV Erzeugung) und Verbrauchersteuerung</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung&amp;diff=38508"/>
		<updated>2023-07-21T07:46:01Z</updated>

		<summary type="html">&lt;p&gt;Dracolein: /* Praxisbeispiele und Lösungsansätze für Steuerungen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Hinweis|Das Modul 76_SolarForecast ist im Stadium &amp;quot;Testing&amp;quot; und ist zur Zeit noch nicht im offiziellen FHEM Repository verfügbar. Die vorliegende Wiki-Seite befindet sich im Aufbau.}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Solarprognose und Verbrauchersteuerung&lt;br /&gt;
|ModType=x&lt;br /&gt;
|ModCmdRef=76_SolarForecast&lt;br /&gt;
|ModFTopic=117864&lt;br /&gt;
|ModForumArea=Solaranlagen&lt;br /&gt;
|ModTechName=76_SolarForecast.pm&lt;br /&gt;
|ModOwner=DS_Starter ({{Link2FU|16933|Forum}}/[[Benutzer Diskussion:DS_Starter|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
[[SolarForecast - Solare Prognose (PV Erzeugung) und Verbrauchersteuerung|SolarForecast]] ist ein integratives Modul zur Gewinnung solarer Vorhersagedaten, deren Verarbeitung und grafischen Darstellung. Desweiteren bietet es die Möglichkeit, in FHEM definierte Verbraucher in einem SolarForecast-Device zu registrieren und eine PV Prognose basierte Steuerung der Verbraucher vom Modul übernehmen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Das Modul ist insbesondere durch folgende Eigenschaften gekennzeichnet:&lt;br /&gt;
[[Datei:sfc1.png|right|thumb|300px|grafische Ansicht SolarForecast]]&lt;br /&gt;
&lt;br /&gt;
::* zur Gewinnung solarer Strahlungswerte werden die SolCast API oder alternativ DWD Stahlungswerte-Stationen integriert&lt;br /&gt;
&lt;br /&gt;
::* es wird sowohl die Erzeugungsprognose als auch eine Verbrauchsprognose erstellt&lt;br /&gt;
&lt;br /&gt;
::* Wetterdaten werden über DWD Wetter-Stationen integriert&lt;br /&gt;
&lt;br /&gt;
::* Sprachensupport EN | DE&lt;br /&gt;
&lt;br /&gt;
::* die Prognosedaten, Wetterdaten, Verbraucherplanungen und die aktuellen Energieflüsse werden in umfangreich anpassbaren integrierten Grafiken dargestellt&lt;br /&gt;
&lt;br /&gt;
::* es wird keine externe SQL-Datenbank benötigt, die Datenhaltung erfolgt in einer Memory basierten Cachedatenbank inkl. einer Filesystempersistenz zur Datensicherung und Wiederherstellung beim Restart&lt;br /&gt;
&lt;br /&gt;
::* die Integration von Geräten wie Wechselrichter, Energy Meter, Batterien, Wetterstationen oder Verbrauchern ist offen und universell gestaltet und bietet dem Anwender maximale Freiheiten bei der Einrichtung seines individuellen Solardatensystems.&lt;br /&gt;
&lt;br /&gt;
::* eine integrierte und umfangreich anpassbare Verbrauchersteuerung vereint die PV Prognose basierte Einplanung der Verbraucher mit der Möglichkeit die Verbraucher durch das Modul schalten zu lassen und dadurch auf PV Erzeugungsschwankungen automatisch dynamisch zu reagieren&lt;br /&gt;
&lt;br /&gt;
::* trotz der hohen Komplexität wird dem Anwender durch eine &amp;quot;Guided Procedure&amp;quot; bei der Gerätedefinition der Einstieg erleichtert und damit ein optimales Benutzerlebnis geboten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Abgrenzung:&#039;&#039;&#039; Das Modul 76_SolarForecast ist nicht zu verwechseln mit der SQL-basierten (DbLog) Prognose-Lösung mit Kostal Plenticore Wechselrichtern, die auf der eigenen Seite &#039;&#039;&#039;[[Kostal_Plenticore_10_Plus]]&#039;&#039;&#039; behandelt wird. Diese Lösung beschreibt kein monolithisches Modul, sondern basiert auf einer orchestrierbaren Zusammenstellung individueller Perl Programmbausteine. &lt;br /&gt;
&lt;br /&gt;
Im vorliegenden Wiki-Beitrag wird ausschließlich das Modul 76_SolarForecast behandelt.&lt;br /&gt;
&lt;br /&gt;
== Rahmenbedingungen und Voraussetzungen ==&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Die Hilfe zu dem Modul ist über &amp;quot;help SolarForecast de&amp;quot; aufrufbar.&lt;br /&gt;
&lt;br /&gt;
== Konfigurationsbeispiele ==&lt;br /&gt;
=== Beispiel 1 ===&lt;br /&gt;
Dies ist eine Konfiguration mit &lt;br /&gt;
&lt;br /&gt;
SummenDummy für 2 BatterieWR (Namen : SBS25 / SBS25_2)&lt;br /&gt;
&lt;br /&gt;
SummenDummy für 3 PV-Wechselrichter (Namen : SB25 / SB30 / SB40)&lt;br /&gt;
&lt;br /&gt;
            mit verschiedenen InverterStrings / ModulDirection / ModulTiltAngle, ModulPeakString&lt;br /&gt;
&lt;br /&gt;
und auch mit den notwendigen zugehörigen anderen Modul-Konfigs.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ACHTUNG:&#039;&#039;&#039; Zusätzlich enthalten ist bei dem Beispiel-Notify eine Sonderkonstellation für eine Brennstoffzelle &amp;quot;FCU&amp;quot; als weitere bzw. zusätzliche Stromerzeugungsquelle. Diese &amp;quot;FCU&amp;quot; wird dadurch mit in der Grafik mit deren Erzeugungsleistung Tag und Nacht in der Erzeugersumme (am Symbol = Sonne) berücksichtigt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;(ReadingsVal(&amp;quot;FCU&amp;quot;,&amp;quot;FCU-Strom-aktuelle-Leistung&amp;quot;,0)/1000)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== DWD ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
define DWD DWD_OpenData&lt;br /&gt;
attr DWD DbLogExclude .*&lt;br /&gt;
attr DWD forecastDays 7&lt;br /&gt;
attr DWD forecastProperties SunUp, SunRise, SunSet, Rad1h, R101, TTT, Tx, Tn, Tg, DD, FX1, RR6c, R600, RRhc, Rh00, ww, wwd, Neff&lt;br /&gt;
attr DWD forecastResolution 1&lt;br /&gt;
attr DWD forecastStation H568&lt;br /&gt;
attr DWD forecastWW2Text 1&lt;br /&gt;
attr DWD group Umwelt&lt;br /&gt;
attr DWD icon rc_WEB&lt;br /&gt;
attr DWD room 021_DWD&lt;br /&gt;
attr DWD stateFormat Tomorrow Tmax fc1_Tx °C on fc1_date at Blintrop&lt;br /&gt;
attr DWD verbose 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== InverterDummy ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
define InverterDummy dummy&lt;br /&gt;
attr InverterDummy DbLogExclude .*&lt;br /&gt;
attr InverterDummy DbLogInclude Today_PVforecast,etoday&lt;br /&gt;
attr InverterDummy event-on-change-reading .*&lt;br /&gt;
attr InverterDummy group Energy Meter&lt;br /&gt;
attr InverterDummy icon measure_photovoltaic_inst@green&lt;br /&gt;
attr InverterDummy room 020_PV,Energie&lt;br /&gt;
attr InverterDummy stateFormat {sprintf(&amp;quot;current %9.3f kW    Today_PVforecast  %9.3f kWh      Today_PV %9.3f kWh      Total_PV %9.3f kWh&amp;quot;,\&lt;br /&gt;
ReadingsVal($name,&amp;quot;total_pac&amp;quot;,0)/1,\&lt;br /&gt;
ReadingsNum(&amp;quot;Forecast&amp;quot;,&amp;quot;Today_PVforecast&amp;quot;,0)/1000,\&lt;br /&gt;
ReadingsVal($name,&amp;quot;etoday&amp;quot;,0)/1,\&lt;br /&gt;
ReadingsVal($name,&amp;quot;etotal&amp;quot;,0)/1,)}&lt;br /&gt;
attr InverterDummy verbose 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== SMA_Energymeter ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
define SMA_Energymeter SMAEM&lt;br /&gt;
attr SMA_Energymeter DbLogExclude state&lt;br /&gt;
attr SMA_Energymeter diffAccept 50&lt;br /&gt;
attr SMA_Energymeter disable 0&lt;br /&gt;
attr SMA_Energymeter disableSernoInReading 1&lt;br /&gt;
attr SMA_Energymeter event-on-update-reading state,Saldo_Wirkleistung,Bezug_Wirkleistung,Einspeisung_Wirkleistung,Bezug_Wirkleistung_Zaehler,Einspeisung_Wirkleistung_Zaehler&lt;br /&gt;
attr SMA_Energymeter group Energy Meter&lt;br /&gt;
attr SMA_Energymeter icon measure_power@green&lt;br /&gt;
attr SMA_Energymeter interval 15&lt;br /&gt;
attr SMA_Energymeter room 020_PV,Energie&lt;br /&gt;
attr SMA_Energymeter serialNumber XXXXXXXXXX    &lt;br /&gt;
attr SMA_Energymeter stateFormat state W (IN -) P1: L1_Saldo_Wirkleistung P2: L2_Saldo_Wirkleistung P3:L3_Saldo_Wirkleistung&lt;br /&gt;
attr SMA_Energymeter verbose 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== BatteryDummy ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
define BatteryDummy dummy&lt;br /&gt;
attr BatteryDummy DbLogExclude .*&lt;br /&gt;
attr BatteryDummy event-on-change-reading .*&lt;br /&gt;
attr BatteryDummy group Energy Meter&lt;br /&gt;
attr BatteryDummy icon batterie@green&lt;br /&gt;
attr BatteryDummy room 020_PV,Energie&lt;br /&gt;
attr BatteryDummy stateFormat {ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;total_pac&amp;quot;, undef).&amp;quot; kW &amp;quot;.\&lt;br /&gt;
&amp;quot; - total &amp;quot;.ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;bat_loadtotal&amp;quot;, undef).&amp;quot; kWh (-in)&amp;quot;.\&lt;br /&gt;
&amp;quot; - &amp;quot;.ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;bat_unloadtotal&amp;quot;, undef).&amp;quot; kWh (out)&amp;quot;.\&lt;br /&gt;
&amp;quot; - charged &amp;quot;.ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;chargestatus&amp;quot;, undef).&amp;quot; %&amp;quot;}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;quot;Berechnungs&amp;quot;-Notify der Werte für Batterie- und InverterDummy ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
define N.PV.TotalConsumption.Dum.Energy notify SMA_Energymeter:Saldo_Wirkleistung:.* {\&lt;br /&gt;
 # Forecast Invertererzeugung InverterDummy \&lt;br /&gt;
fhem &amp;quot;setreading InverterDummy Today_PVforecast &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(ReadingsNum(&amp;quot;Forecast&amp;quot;,&amp;quot;Today_PVforecast&amp;quot;,0)));;\&lt;br /&gt;
 # Invertererzeugung InverterDummy \&lt;br /&gt;
fhem &amp;quot;setreading InverterDummy etotal &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(ReadingsNum(&amp;quot;SB25&amp;quot;,&amp;quot;etotal&amp;quot;,0))+(ReadingsNum(&amp;quot;SB30&amp;quot;,&amp;quot;etotal&amp;quot;,0))+(ReadingsNum(&amp;quot;SB40&amp;quot;,&amp;quot;etotal&amp;quot;,0)));;\&lt;br /&gt;
 # Invertererzeugung InverterDummy \&lt;br /&gt;
fhem &amp;quot;setreading InverterDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(ReadingsVal(&amp;quot;FCU&amp;quot;,&amp;quot;FCU-Strom-aktuelle-Leistung&amp;quot;,0)/1000)+(ReadingsNum(&amp;quot;SB25&amp;quot;,&amp;quot;total_pac&amp;quot;,0))+(ReadingsNum(&amp;quot;SB30&amp;quot;,&amp;quot;total_pac&amp;quot;,0))+(ReadingsNum(&amp;quot;SB40&amp;quot;,&amp;quot;total_pac&amp;quot;,0)));;\&lt;br /&gt;
 # Invertererzeugung InverterDummy \&lt;br /&gt;
my $wert1234 = &amp;quot;0&amp;quot; ;;\&lt;br /&gt;
$wert1234 = sprintf(&amp;quot;%.3f&amp;quot;,(ReadingsNum(&amp;quot;SB25&amp;quot;,&amp;quot;etoday&amp;quot;,0))+(ReadingsNum(&amp;quot;SB30&amp;quot;,&amp;quot;etoday&amp;quot;,0))+(ReadingsNum(&amp;quot;SB40&amp;quot;,&amp;quot;etoday&amp;quot;,0)));; \&lt;br /&gt;
fhem (&amp;quot;setreading InverterDummy etoday &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert1234));;\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme InverterDummy\&lt;br /&gt;
fhem &amp;quot;setreading BatteryDummy power_out &amp;quot;.sprintf(&amp;quot;%.0f&amp;quot;,(ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;power_out&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung InverterDummyBatterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading BatteryDummy power_in &amp;quot;.sprintf(&amp;quot;%.0f&amp;quot;,(ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;power_in&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Bezug -bat_loadtotal Batterieentnahme InverterDummy\&lt;br /&gt;
fhem &amp;quot;setreading BatteryDummy bat_unloadtotal &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_unloadtotal&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_unloadtotal&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung bat_loadtotal InverterDummyBatterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading BatteryDummy bat_loadtotal &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_loadtotal&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_loadtotal&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus InverterDummy\&lt;br /&gt;
my $wert5 = sprintf(&amp;quot;%.2f&amp;quot;,(((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0))/2) + ((ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0))/2)));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy chargestatus &amp;quot;.sprintf(&amp;quot;%.2f&amp;quot;,$wert5));;\&lt;br /&gt;
 # Batterie-total_pac  InverterDummy\&lt;br /&gt;
my $wert6 = sprintf(&amp;quot;%.3f&amp;quot;,((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;total_pac&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;total_pac&amp;quot;,0))));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert6));;\&lt;br /&gt;
}&lt;br /&gt;
attr N.PV.TotalConsumption.Dum.Energy DbLogExclude .*&lt;br /&gt;
attr N.PV.TotalConsumption.Dum.Energy room Energie&lt;br /&gt;
attr N.PV.TotalConsumption.Dum.Energy verbose 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== SolarForecast ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
define Forecast SolarForecast&lt;br /&gt;
attr Forecast DbLogExclude .*&lt;br /&gt;
attr Forecast affect70percentRule 0&lt;br /&gt;
attr Forecast comment update per &amp;quot;wget -qO /opt/fhem/FHEM/76_SolarForecast.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/76_SolarForecast.pm&amp;quot;&lt;br /&gt;
attr Forecast ctrlInterval 10&lt;br /&gt;
attr Forecast disable 0&lt;br /&gt;
attr Forecast event-on-change-reading .*&lt;br /&gt;
attr Forecast flowGraphicAnimate 1&lt;br /&gt;
attr Forecast flowGraphicShowConsumer 1&lt;br /&gt;
attr Forecast flowGraphicShowConsumerDummy 1&lt;br /&gt;
attr Forecast flowGraphicShowConsumerPower 1&lt;br /&gt;
attr Forecast flowGraphicShowConsumerRemainTime 1&lt;br /&gt;
attr Forecast flowGraphicSize 400&lt;br /&gt;
attr Forecast graphicBeam1Color 3C14FF&lt;br /&gt;
attr Forecast graphicBeam1Content pvForecast&lt;br /&gt;
attr Forecast graphicBeam2Color 19FF29&lt;br /&gt;
attr Forecast graphicBeam2Content pvReal&lt;br /&gt;
attr Forecast graphicHeaderDetail all&lt;br /&gt;
attr Forecast graphicHistoryHour 4&lt;br /&gt;
attr Forecast graphicLayoutType double&lt;br /&gt;
attr Forecast graphicShowDiff top&lt;br /&gt;
attr Forecast graphicShowNight 0&lt;br /&gt;
attr Forecast group Energy Meter&lt;br /&gt;
attr Forecast room 020_PV,Energie&lt;br /&gt;
attr Forecast stateFormat Current_PV&lt;br /&gt;
attr Forecast verbose 2&lt;br /&gt;
&lt;br /&gt;
setstate Forecast 2023-03-03 19:35:46 currentBatteryDev BatteryDummy pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus&lt;br /&gt;
setstate Forecast 2023-02-27 19:53:12 currentForecastDev DWD&lt;br /&gt;
setstate Forecast 2023-02-27 22:42:02 currentInverterDev InverterDummy pv=total_pac:kW etotal=etotal:kWh capacity=9500&lt;br /&gt;
setstate Forecast 2022-03-29 08:44:11 currentMeterDev SMA_Energymeter gcon=Bezug_Wirkleistung:W contotal=Bezug_Wirkleistung_Zaehler:kWh gfeedin=Einspeisung_Wirkleistung:W feedtotal=Einspeisung_Wirkleistung_Zaehler:kWh&lt;br /&gt;
setstate Forecast 2022-03-06 20:12:10 currentRadiationDev DWD&lt;br /&gt;
setstate Forecast 2023-04-05 16:44:50 inverterStrings Garage_SE,Garage_NW,Haus_NW,Haus_SW&lt;br /&gt;
setstate Forecast 2023-04-05 16:44:32 moduleDirection Garage_SE=SE Garage_NW=NW Haus_NW=NW Haus_SW=SW&lt;br /&gt;
setstate Forecast 2023-04-05 16:45:13 modulePeakString Garage_SE=2.75 Garage_NW=3.2 Haus_NW=2.230 Haus_SW=2.230&lt;br /&gt;
setstate Forecast 2023-04-05 16:45:39 moduleTiltAngle Garage_SE=35 Garage_NW=35 Haus_NW=45 Haus_SW=45&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So sollte es dann als Ergebnis aussehen:&lt;br /&gt;
[[Datei:Solarforecast Beispiel Screenshot.png|zentriert|mini|Ergebnis nach dieser Konfiguration]]&lt;br /&gt;
&lt;br /&gt;
== Einbinden / Registrieren von Verbrauchern ==&lt;br /&gt;
&lt;br /&gt;
Das Modul gestattet es beliebige Verbraucher (Devices) über die Attribute &#039;&#039;&#039;consumerXX&#039;&#039;&#039; zu registrieren. Durch die Registrierung wird dem Modul der Namen des Devices sowie dessen Eingenschaften durch die Angabe von Schlüssel-Wert Paaren bekannt gemacht.&lt;br /&gt;
&lt;br /&gt;
Nach der Registrierung können die Verbraucher durch das Modul genutzt werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* es erfolgt eine Planung der Ein- und Ausschaltzeiten abhängig von der solaren Prognose in Bezug zu den Leistungsdaten des Verbrauchers sowie der anderen registrierten Consumer&lt;br /&gt;
* das Modul kann die Ein- und Ausschaltsteuerung der Consumer übernehmen (optional)&lt;br /&gt;
* die aktuellen Status (Verbrauchsdaten) werden in der Energiefußgrafik dargestellt&lt;br /&gt;
* das Modul lernt mit der Zeit das Verbrauchsverhalten der registrierten Verbraucher&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um einen Verbaucher zu registrieren, wird ein freies &#039;&#039;&#039;consumerXX&#039;&#039;&#039; Attribut, zum Beispiel consumer01, gesetzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Beispiel Registrierung eines Shelly Devices ===&lt;br /&gt;
&lt;br /&gt;
Nachfolgendes Beispiel zeigt eine Registrierung eines Heizlüfters der an einem Shelly Zwischenstecker angeschlossen ist und durch das Modul gesteuert werden soll. Dabei soll die Steuerung nicht nur von der Solarprognose, sondern auch von der Raumtemperatur abhängig erfolgen. Im Beispiel wird das Attribut consumer03 verwendet.&lt;br /&gt;
&lt;br /&gt;
Zwingende Angaben sind&lt;br /&gt;
&lt;br /&gt;
 consumerXX &amp;lt;Device Name&amp;gt; type=&amp;lt;type&amp;gt; power=&amp;lt;power&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Alle Angaben können mehrzeilig eingegeben werden. Die Schlüssel-Werte Paare sind jeweils durch ein Leerzeichen getrennt.&lt;br /&gt;
&lt;br /&gt;
 consumerXX Shelly.shellyplug3 type=heater power=1700 &lt;br /&gt;
&lt;br /&gt;
In dem Beispiel ist Shelly.shellyplug3 der Devicename des Shellies in FHEM. Der Schlüssel &#039;&#039;&#039;type&#039;&#039;&#039; definiert die Art des Verbrauchers. In der Hilfe sind die möglichen Typen aufgeführt. Den richtigen Typ anzugeben hat Einfluß auf die spätere Einschätzung des Leistungsverhaltens über die Laufzeit. So wird von einem &#039;&#039;&#039;heater&#039;&#039;&#039; gleich nach dem Einschalten die angegebene Nominalleistung abgerufen und wird über die Zeit gleichbleiben. &lt;br /&gt;
Eine Waschmaschine oder ein Trockner rufen über ihre Laufzeit die Leistung nicht gleichbleibend ab und ändern die Leistungsaufnahme sich über die Einschaltdauer.&lt;br /&gt;
&lt;br /&gt;
Die Angabe von &#039;&#039;&#039;power&#039;&#039;&#039; definiert die Nominalleistung (Watt) die für den Verbraucher laut Typenschild vom Hersteller angegeben wird. Diese Angabe wird vom Modul bei der Planung der Einschaltzeiten verwendet indem die Nominalleistung in das Verhältnis zur Solarprognose bzw. Verbrauchsprognose des Netzes gesetzt wird. Weiterhin ist dieser Wert auch wichtig um später den tatsächlichen Einschaltzeitpunkt auszuführen wenn ein realer PV Überschuss festgestellt wird.&lt;br /&gt;
&lt;br /&gt;
Es ist möglich &#039;&#039;&#039;power=0&#039;&#039;&#039; zu setzen. Das führt dazu, dass die Planung und letztendlich auch der Schaltvorgang unabhängig von der Solarprognose bzw. einem realen PV Überschuss vorgenommen wird.  &lt;br /&gt;
&lt;br /&gt;
Es werden weitere Schlüsseleingaben vorgenommen:&lt;br /&gt;
:&amp;lt;code&amp;gt;Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit dem Schlüssel &#039;&#039;&#039;icon&#039;&#039;&#039; legt man ein Icon fest welches in der Grafik für den Verbraucher verwendet wird. Der &#039;&#039;&#039;mode&#039;&#039;&#039; definiert die Art und Weise der Einplanung:&lt;br /&gt;
&lt;br /&gt;
;can: Die Einplanung erfolgt zum Zeitpunkt mit wahrscheinlich genügend verfügbaren PV Überschuss. Der Start des Verbrauchers zum Planungszeitpunkt unterbleibt bei ungenügendem PV-Überschuss.&lt;br /&gt;
&lt;br /&gt;
;must: Der Verbaucher wird optimiert eingeplant auch wenn wahrscheinlich nicht genügend PV Überschuss vorhanden sein wird. Der Start des Verbrauchers erfolgt auch bei ungenügendem PV-Überschuss.  &lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;notbefore&#039;&#039;&#039; wird festgelegt, dass die Einplanung nicht vor neun Uhr morgens erfolgen soll auch falls schon genügend PV Überschuss vorhanden wäre. Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; definiert die Einplanungsdauer des Verbrauchers in Minuten im einfachsten Fall. Die hier verwendete Angabe &#039;&#039;&#039;SunPath&#039;&#039;&#039; ist ein Spezialfall. Der Verbraucher soll von Sonnenaufgang bis Sonnenuntergang eingeschaltet werden, wobei die Angabe von 60 bzw. -60 ein relative Verschiebung bewirken. Dadurch wird das Einschalten 60 Mintuen nach Sonnenaufgang bis 60 Minuten vor Sonnenuntergang geplant.&lt;br /&gt;
&lt;br /&gt;
Die Schlüssel &#039;&#039;&#039;on&#039;&#039;&#039; und &#039;&#039;&#039;off&#039;&#039;&#039; teilen dem Modul die jeweiligen gültigen Ein- und Aus-Kommandos mit, mit dem das (Shelly)Device geschaltet werden kann. Werden diese Schlüssel nicht oder &amp;quot;leer&amp;quot; (on= off=) angegeben, erfolgt kein Schalten durch das Modul, nur die Planungsdaten werden erzeugt.&lt;br /&gt;
&lt;br /&gt;
Die Verbraucherregistrierung wird mit weiteren Angaben ergänzt um das gewünschte Verhalten zu erreichen:&lt;br /&gt;
&lt;br /&gt;
 Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off etotal=relay_0_energy_Wh:Wh  &lt;br /&gt;
                    pcurr=relay_0_power:W auto=automatic interruptable=og.bad.wandthermostat:diff-temp:[0-9]\.[0-9]:0.2&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;etotal&#039;&#039;&#039; wird der Readingname des Shelly Devices angegeben welches die Summe der verbrauchten Energie (Wh/kWh) des Consumer Device liefert. D.h. es muß ein sich stetig erhöhender Wert sein. Durch die Auswertung dieses Readings ermittelt das Modul die in bestimmten Zeiteinheiten verbrauchte Energie zur weiteren Verwendung. &lt;br /&gt;
&lt;br /&gt;
In dem Shelly Device ist per default ein solches Reading nicht vorhanden. Über userReadings kann in dem Device Shelly.shellyplug3 ein Reading für etotal erzeugt werden:&lt;br /&gt;
&lt;br /&gt;
 userReadings relay_0_energy_Wh:relay_0_energy.* monotonic { sprintf &amp;quot;%.0f&amp;quot;, ReadingsVal ($name, &#039;relay_0_energy&#039;, 0) / 60 } &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;pcurr&#039;&#039;&#039; enthält das Reading in Shelly.shellyplug3 welches den aktuellen Energieverbrauch liefert. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;auto&#039;&#039;&#039; enthält das Reading in Shelly.shellyplug3 welches zur Freigabe/Sperrung der autmatischen Schaltung durch das Modul dienen soll. Ist das angegebene Reading (im Beispiel &amp;quot;automatic&amp;quot;) im Shelly.shellyplug3 nicht vorhanden, wird es vom Modul automatisch mit dem Wert &amp;quot;1&amp;quot; angelegt.&lt;br /&gt;
Dadurch ist per default das automatische Schalten von Shelly.shellyplug3 durch das Modul freigegeben. &lt;br /&gt;
Der User kann durch Setzen des Readings &#039;&#039;&#039;automatic=0&#039;&#039;&#039; das automatische Schalten durch das Modul sperren und mit &amp;quot;1&amp;quot; wieder freigeben. Dadurch kann man zu bestimmten Zeiten (Urlaub, Feiertage, etc.) die Schaltung temporär deaktivieren.&lt;br /&gt;
&lt;br /&gt;
Wie oben beschrieben, soll der Heizlüfter als weitere Schaltbedingung die Abhängigkeit von der Raumtemperatur beachten. Konkret soll der Heizlüfter mit einer Hysterese von 0.2 (Grad) bei Erreichen einer Soll-Raumtemperatur ausschalten und bei Unterschreiten einer bestimmten Temperatur einschalten.&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; übernimmt diese temporäre Schaltsequenzen.&lt;br /&gt;
&lt;br /&gt;
Zunächst wird in dem Sensordevice (In dem Beispiel ein Homatic Wandthermostat HM-TC-IT-WM-W-EU) ein Reading erstellt welches dann im Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; angegeben wird. Dieses Reading soll einen Wert enthalten auf den der angegebene Regex ([0-9]\.[0-9]) matchen soll um Shelly.shellyplug3 temporär auszuschalten.&lt;br /&gt;
Im Wandthermostat wird dazu ein userReading angelegt:&lt;br /&gt;
&lt;br /&gt;
 userReadings diff-temp:desired-temp.* { &lt;br /&gt;
     sprintf &amp;quot;%.1f&amp;quot;, ReadingsVal ($name, &#039;measured-temp&#039;, 0) - ReadingsVal ($name, &#039;desired-temp&#039;, 0) &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das bedeutet, wenn die Raumtemperatur die Solltemperatur erreicht oder höher ist, wird diff-temp &amp;gt;= 0.&lt;br /&gt;
In diesem Fall matcht der angebene Regex in:&lt;br /&gt;
&lt;br /&gt;
 interruptable=og.bad.wandthermostat:diff-temp:&#039;&#039;&#039;[0-9]\.[0-9]&#039;&#039;&#039;:0.2&lt;br /&gt;
&lt;br /&gt;
und Shelly.shellyplug3 wird ausgeschaltet. &lt;br /&gt;
Unterschreitet der Wert von diff-temp 0, matcht der Regex nicht mehr und der Verbraucher wird wieder eingeschaltet. Dabei wird die angegebene Hysterese berücksichtigt, d.h der Verbraucher wird erst ausgeschaltet wenn &amp;quot;diff-temp - 0.2 &amp;gt;= 0&amp;quot; wahr ist.&lt;br /&gt;
&lt;br /&gt;
Für das Wiedereinschalten des Heizlüfters ist außerdem Voraussetzung, dass ein entsprechender PV-Überschuss vorliegt. Diese Bedingung wird durch die Angabe von &#039;&#039;&#039;power=1700&#039;&#039;&#039; bewirkt. Soll der zwangsweise PV Überschuss ignoriert werden, kann &#039;&#039;&#039;power=0&#039;&#039;&#039; angegeben werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Praxisbeispiele und Lösungsansätze für Steuerungen ==&lt;br /&gt;
&lt;br /&gt;
=== dynamische Ladestromsteuerung eines Victron MultiPlus II Chargers mit Pylontech Batterie ===&lt;br /&gt;
&lt;br /&gt;
Die nachfolgend beschriebene Lösung soll als Anregung für eigene Optimierungen verstanden werden und ist weiter ausbaufähig bzw. erweiterbar um zum Beipiel jahreszeitliche Anpassungen des Verfahrens.&lt;br /&gt;
&lt;br /&gt;
Die MultiPlus II Batteriewechselrichter von Victron sollten die Batterien nicht mit dem maximal möglichen Ladestrom beladen, da sich die Effizienz deutlich verschlechtert wenn sich die Ströme den jeweiligen Grenzwerten nähern ([https://www.victronenergy.com/upload/documents/Output-rating-operating-temperature-and-efficiency.pdf Lesestoff]). &lt;br /&gt;
Andererseits sollen die Ladeleistungen so gewählt werden, dass die verfügbare Solarenergie eine volle Aufladung der Akkus ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Das Victron System ermöglicht das Auslesen und die Steuerung der Anlage via MQTT. Die Einbindung in FHEM über MQTT soll hier nicht beschrieben werden.&lt;br /&gt;
Aber wenn dies erfolgt ist, kann der Ladestrom z.B. mit dem Kommando:&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;Device&amp;gt; MaxChargeCurrent &amp;lt;Wert&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
eingestellt bzw. variiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Modul bietet dem Nutzer die Möglichkeit, im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltetene Code wird am Ende jedes Zyklus (siehe Attribut &#039;&#039;ctrlInterval&#039;&#039;) ausgeführt.&lt;br /&gt;
In dem Attribut wird dieser Code eingetragen dessen Funktion und Zusammenspiel nachfolgend erläutert wird:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  ## Vars&lt;br /&gt;
  ########&lt;br /&gt;
  my $batdev  = (split &amp;quot; &amp;quot;, ReadingsVal ($name, &#039;currentBatteryDev&#039;, &#039;&#039;))[0];  # Batteriedevice&lt;br /&gt;
  my $vebus   = &#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;;                            # Victron Vebus Device&lt;br /&gt;
  my $maxcspc = 35;                                                            # max. Ladesollstrom (A) nominal&lt;br /&gt;
  my $spcorr  = 0.7;                                       # Korrekturfaktor Überschuss 70%&lt;br /&gt;
  my $sch     = 3;                                         # Minuend des Sonnenuntergangs             &lt;br /&gt;
  my $cclvl1  = 10;                                        # Ladestrom Level 1 max. 10 A (500 W)&lt;br /&gt;
  my $cclvl2  = 20;                                        # Ladestrom Level 2 max. 20 A (1000 W)&lt;br /&gt;
  my $cclvl3  = 29;                                        # Ladestrom Level 3 max. 29 A (1400 W)&lt;br /&gt;
  &lt;br /&gt;
  ###############&lt;br /&gt;
  my $pvfc   = ReadingsNum ($name, &#039;RestOfDayPVforecast&#039;,            0);&lt;br /&gt;
  my $cofc   = ReadingsNum ($name, &#039;RestOfDayConsumptionForecast&#039;,   0);&lt;br /&gt;
  my $cpv    = ReadingsNum ($name, &#039;Current_PV&#039;,                     0);&lt;br /&gt;
  &lt;br /&gt;
  my $solh   = ReadingsNum ($name, &#039;statistic_SunHours_Remain&#039;,      0) - $sch; # verbleibende h bis SunSet-3&lt;br /&gt;
  $solh      = $solh &amp;lt; 0 ? 0 : $solh;&lt;br /&gt;
  &lt;br /&gt;
  my $ahrem  = ReadingsNum ($batdev, &#039;EnergyRemain&#039;,                 0) / 48;   # Ladung Batterie verbleibend&lt;br /&gt;
  $ahrem     = sprintf &amp;quot;%.0f&amp;quot;, $ahrem;&lt;br /&gt;
  &lt;br /&gt;
  my $fcdiff = ($pvfc - $cofc) * $spcorr;     # Korrektur der noch aktuell prognostizierten Überschussenergie &lt;br /&gt;
  $fcdiff    = $fcdiff &amp;lt; 0 ? 0 : $fcdiff;     # Wh&lt;br /&gt;
  &lt;br /&gt;
  my $splah  = $fcdiff / 48;                  # Wh -&amp;gt; Ah auf 48 V bezogen&lt;br /&gt;
  &lt;br /&gt;
  if ($cpv &amp;amp;&amp;amp; $solh &amp;amp;&amp;amp; $ahrem &amp;amp;&amp;amp; $ahrem &amp;lt; $fcdiff) {  # Ladeanforderung und Überschuss übersteigt Lademenge&lt;br /&gt;
      my $cspc = $ahrem / $solh;              # A = Ah / h&lt;br /&gt;
	  &lt;br /&gt;
      $maxcspc = $cspc &amp;lt;= $cclvl1 ? $cclvl1 : # Ladung mit Level 1 Leistung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl2 ? $cclvl2 : # Ladung mit Level 2 Leistung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl3 ? $cclvl3 : # Ladung mit Level 3 Leistung&lt;br /&gt;
                 $maxcspc;                    # max. Ladesollstrom         &lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($defs{$batdev}, &#039;SolCast_userFn_MaxChargeCurrent&#039;, $maxcspc, 1);&lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent&#039;, $maxcspc, 1);&lt;br /&gt;
  CommandSet           (undef, &amp;quot;$vebus MaxChargeCurrent $maxcspc&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2023-05-03 201457.png|right|thumb|300px|Vorhersage PV Erzeugung und Energieverbrauch des (restlichen) Tages]]&lt;br /&gt;
Zunächst wird der am aktuellen Tag zu erwartende Totalüberschuss solarer Energie ermittelt. Das erfolgt aus der Differenz von &#039;&#039;RestOfDayPVforecast&#039;&#039; und &#039;&#039;RestOfDayConsumptionForecast&#039;&#039; unter Berücksichtigung eines Sicherheitsabschlages (&#039;&#039;Korrekturfaktor Überschuss 70%&#039;&#039;). Das Ergebnis liegt in Wh vor und wird bezogen auf 48 V (die Spannung des Batteriesystems) in Ah umgerechnet. &lt;br /&gt;
&lt;br /&gt;
Die noch benötigte Ladung der Batterie zur Erreichung des Soll SOC-Wertes ermittelt das ReadingsNum &#039;&#039;statistic_SunHours_Remain&#039;&#039; aus dem Batteriedevice, welches vom Modulreading &#039;&#039;currentBatteryDev&#039;&#039; ausgelesen wird.&lt;br /&gt;
&lt;br /&gt;
Sofern der so ermittelte solare Überschuss des (Rest)Tages die benötigte Lademenge der Batterie übersteigt, wird der DC Ladestrom so verringert, dass er sich in einem effizienten Bereich des MultiPlus II bewegt und dennoch rechnerisch ausreicht auf den Soll SOC-Wert zu laden.  &lt;br /&gt;
&lt;br /&gt;
Zu diesem Zweck wird im Modul über die Auswahl von &#039;&#039;SunHours_Remain&#039;&#039; im Attribut &#039;&#039;ctrlStatisticReadings&#039;&#039; das zusätzliche Reading &#039;&#039;statistic_SunHours_Remain&#039;&#039; erzeugt. Aus dem (noch) erforderlichen Ladungswert &#039;&#039;&#039;EnergyRemain&#039;&#039;&#039; (Ah) und der um eine Sicherheitszeit (&#039;&#039;Minuend des Sonnenuntergangs&#039;&#039;) reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche Mindestladestromstärke ermittelt.&lt;br /&gt;
&lt;br /&gt;
Dieser Wert wird auf die zu Anfang des Codeblocks definierten Ladelevel (&#039;&#039;Ladestrom Level X&#039;&#039;) abstrahiert und ein passender &#039;&#039;&#039;effizienter&#039;&#039;&#039; Ladestrom-Bereich ausgewählt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2023-05-03 201719.png|right|thumb|300px|Vorhersage PV Erzeugung und Energieverbrauch des (restlichen) Tages]]&lt;br /&gt;
&lt;br /&gt;
In allen anderen Fällen, wenn z.B. rechnerisch nicht genügend oder keine Solarenergie erzeugt wird (nachts) oder der Speicher gefüllt ist, wird der maximale (Sollwert) des Ladestroms &#039;&#039;$maxcspc = 35&#039;&#039; eingestellt. Dieser Wert entspricht dem maximalen Ladestrom gemäß Herstellerunterlagen Pylontech.&lt;br /&gt;
&lt;br /&gt;
Die Einstellung erfolgt per Set-Kommando im Victron vebus MQTT Device &#039;&#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;&#039;. Dieses Device wurde ebenfalls während der MQTT Integration des Victron Systems angelegt und wird hier nicht näher diskutiert.&lt;br /&gt;
Zur Kontrolle des kalkulierten Wertes werden noch die Readings &#039;&#039;SolCast_userFn_MaxChargeCurrent&#039;&#039; im Batteriedevice und &#039;&#039;userFn_Bat_MaxChargeCurrent&#039;&#039; im SolarForecast Device generiert.&lt;br /&gt;
&lt;br /&gt;
Neben der Effizienzoptimierung hat dieses Verfahren auch den Vorteil einer möglichst schonenden Batterieaufladung was der Lebensdauer der Komponenten zugute kommen sollte.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Poolheizung in Abhängigkeit von vorhandenenm Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren)&#039;&#039;&#039; ===&lt;br /&gt;
Eine (Whirl-)Poolheizung soll bei ausreichend überschüssiger Energie aus einer Photovoltaikanlage dynamisch gesteuert werden (Eigenverbrauchsoptimierung). Im folgenden Beispiel ist ein Device mit der Bezeichnung &#039;&#039;Forecast&#039;&#039; des Typs &#039;&#039;SolarForecast bereits&#039;&#039; angelegt und konfiguriert. Ein freies Consumer-Attribut &#039;&#039;consumer1&#039;&#039; wird beispielhaft wie folgt definiert:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr Forecast consumer1 MQTT2_layzspa type=other power=1950 mode=can on=&amp;quot;heater on&amp;quot; off=&amp;quot;heater off&amp;quot; pcurr=WATT interruptable=1 swstate=heaterstate:1:0 auto=Automatiksteuerung mintime=SunPath spignorecond=EVCharger22:LadungMitPVUeberschussActive:1 icon=scene_pool notbefore=8 notafter=20&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Poolheizung ist innerhalb FHEM bereits im Device &#039;&#039;MQTT2_layzspa&#039;&#039; integriert und lässt sich normalerweise per FHEM-Befehl &amp;quot;set &#039;&#039;MQTT2_layzspa heater on&amp;quot;&#039;&#039; oder &#039;&#039;&amp;quot;set MQTT2_layzspa heater off&amp;quot;&#039;&#039; steuern. Entsprechend werden die Schlüssel-Wert-Paare &#039;&#039;&amp;quot;on=&amp;quot;&#039;&#039; und &#039;&#039;&amp;quot;off=&amp;quot;&#039;&#039; definiert. Der Stromverbrauch einer aktiven Poolheizung ist uns bekannt und wird im Schlüssel &#039;&#039;&amp;quot;power=1950&amp;quot;&#039;&#039; definiert. Die Heizfunktion soll nur bei ausreichend Überschuss aktiviert werden dürfen und muss bei Unterschreitung sofort abgeschaltet werden. Diese Eigenschaften werden über die Schlüssel &#039;&#039;&amp;quot;mode=can&amp;quot;&#039;&#039; und &#039;&#039;&amp;quot;interruptable=&amp;quot;1&amp;quot;&#039;&#039; festgelegt. Zuletzt soll grundsätzlich nur in der Zeit zwischen 08:00 Uhr bis 20:00 Uhr geheizt werden dürfen. Die Schlüssel &#039;&#039;&amp;quot;notbefore=8&amp;quot;&#039;&#039; und &#039;&#039;&amp;quot;notafter=20&amp;quot;&#039;&#039; legen diese Eigenschaften fest. Zur Anzeige des Schaltzustands der Heizung wurde der Schlüssel &#039;&#039;&amp;quot;swstate=heaterstate:1:0&amp;quot;&#039;&#039; hinzugefügt (Wert 1 = Heizung aktiv, Wert 0= Heizung aus). &lt;br /&gt;
&lt;br /&gt;
==== Priorisierung vor externen PV-Überschuss gesteuerten Verbrauchern: ====&lt;br /&gt;
Der Schlüssel-Wert &#039;&#039;&#039;&amp;quot;spignorecond=&amp;quot;&#039;&#039;&#039; bietet optional die Möglichkeit, ein Consumer auch ohne ausreichend PV-Überschuss einzuschalten. Bei erfüllter Bedingung wird der Verbraucher entsprechend der Planung eingeschaltet auch wenn zu dem Zeitpunkt kein PV Überschuß vorliegt. Im obigen Beispiel existiert in der Haus-Elektroinstallation eine Elektroauto-Ladestation mit eigener (externer) dynamischer PV-gesteuerter Fahrzeugladung ohne Integration in &#039;&#039;SolarForecast&#039;&#039;. In Abhängigkeit von PV-Generatorleistung und Sonneneinstrahlung besteht manchmal eine Möglichkeit, dass der gesamte PV-Überschuss zur Fahrzeugladung genutzt wird. Das Modul SolarForecast würde entsprechend keinen (oder zu wenig) PV-Überschuss erkennen und den Consumer &#039;&#039;MQTT2_layzspa&#039;&#039; nicht aktivieren. &lt;br /&gt;
&lt;br /&gt;
Durch Verwendung von &#039;&#039;spignorecond=EVCharger22:LadungMitPVUeberschussActive:1&#039;&#039; wird die Poolheizung gegenüber der Ladestation jedoch priorisiert mit PV-Überschuss versorgt. In diesem Beispiel wird Consumer1 aktiviert, wenn die Ladestation &amp;quot;&#039;&#039;EVCharger22&#039;&#039;&amp;quot; sich im PV-Überschuss-Modus befindet &#039;&#039;&#039;und&#039;&#039;&#039; momentan ein Fahrzeug lädt. In der Folge würde der Hausstromverbrauch um ca. 1950 Watt steigen, die externe Fahrzeugladestation diese Änderung registrieren und die Fahrzeugladeleistung entsprechend verringern oder ganz abbrechen.&lt;br /&gt;
&lt;br /&gt;
== weiterführende Links ==&lt;br /&gt;
* {{Link2Forum|Topic=117864|LinkText=Forenthema zum Modul}}&lt;br /&gt;
* Forenthema &amp;quot;{{Link2Forum|Topic=117864|LinkText=Leistungsprognose für Wechselrichter}}&amp;quot;&lt;br /&gt;
* Solcast API Toolkit: https://toolkit.solcast.com.au&lt;br /&gt;
* Kostal Plenticore 10 Plus mit SQL-Datenbank Integration ([[Kostal Plenticore 10 Plus]])&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>Dracolein</name></author>
	</entry>
</feed>