<?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=All-Ex</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=All-Ex"/>
	<link rel="alternate" type="text/html" href="http://wiki.fhem.de/wiki/Spezial:Beitr%C3%A4ge/All-Ex"/>
	<updated>2026-04-11T07:59:55Z</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=40492</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=40492"/>
		<updated>2025-11-10T16:45:33Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Hinweis|Die vorliegende Wiki-Seite befindet sich im Aufbau.}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Solarprognose und Verbrauchersteuerung&lt;br /&gt;
|ModType=d&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 Prognosewerte können die SolCast API, OpenMeteo API, Forecast.Solar API, Victron VRM Portal API oder alternativ DWD Stahlungswerte-Stationen verwendet werden&lt;br /&gt;
&lt;br /&gt;
::* optionale KI Unterstützung der PV-Prognose bei Verwendung von geeigneten Solar-API&#039;s&lt;br /&gt;
&lt;br /&gt;
::* es wird sowohl die Erzeugungsprognose als auch eine Verbrauchsprognose sowie SoC Prognose (bei Batterie-Integration) erstellt&lt;br /&gt;
&lt;br /&gt;
::* Wetterdaten werden über DWD Wetter-Stationen oder verschiedene API integriert. Es können verschiedene API zur Gewinnung von Solar- und Wetterdaten kombiniert werden. &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 FHEM-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 Integration von bis zu 4 Inverter und Smartloader (DC-DC Batterieladegeräte) ist möglich&lt;br /&gt;
&lt;br /&gt;
::* eine Integration von bis zu 3 nicht PV-Energieerzeugern wie BHKW, Windrädern oder Notstromaggregaten ist möglich&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;
::* Einbindung von bis zu drei Batteriespeichersystemen&lt;br /&gt;
&lt;br /&gt;
::* Bereitstellung von Leitwerten zur optimalen Einstellung/Steuerung von Batteriespeichersystemen&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 Benutzererlebnis 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;
Das Wiki gibt allgemeingültige und teilweise sehr spezifische bzw. tiefgehende Informationen und Handlungsempfehlungen zum SolarForecast Modul. Die dargestellten Informationen beziehen sich auf den zum Zeitpunkt der Wiki-Erstellung vorhandenen Entwicklungsstand des Moduls. Durch die stetige Weiterentwicklung können sich Abweichungen zum beschriebenen Inhalt ergeben oder zur Obsoleszenz dieser Inhalte führen. &lt;br /&gt;
&lt;br /&gt;
Vergleiche deshalb die Informationen immer mit der aktuellen Befehls-Referenz zum Modul!&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Ein SolarForecast Device wird mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 define &amp;lt;Name&amp;gt; SolarForecast &lt;br /&gt;
&lt;br /&gt;
angelegt. Nach der Definition wird der User durch einen Dialog geführt, der einige unerlässliche Einstellungen abfragt und in den entsprechenden Attributen und Readings persistiert. Alle Attribute und Readings die eine Einstellung der Anlage bewirken, sind mit dem Präfix &amp;quot;setup&amp;quot; versehen. &lt;br /&gt;
&lt;br /&gt;
Die Verwendung von setup-Readings gestattet es die Anlagenparameter dynamisch im Betrieb zu verändern. So kann mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringAzimuth   bzw.&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringDeclination &lt;br /&gt;
&lt;br /&gt;
die Ausrichtung und der Neigungswinkel der PV-Module ständig angepasst werden, was zum Beispiel bei einer dem Sonnenstand nachgeführten Anlage von Bedeutung ist.&lt;br /&gt;
&lt;br /&gt;
Die abgefragten Einstellungen während des Dialoges sind ausführlich in den entsprechenden Attributen bzw. Set-Kommandos erläutert. Die benötigten Informationen sind anhängig von der gewählten Prognose-API und können im Umfang variieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 213257.png|right|thumb|400px|Anlagenprüfung über Drucktaste in der Kopfgrafik]]&lt;br /&gt;
&lt;br /&gt;
Sobald alle verlangten Einstellungen vorgenommen sind, sollte eine Anlagenprüfung mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; plantConfiguration check&lt;br /&gt;
&lt;br /&gt;
oder über die angebotene Drucktaste in der Grafik durchgeführt werden. Es wird eine Plausibilitätsprüfung vorgenommen und das Ergebnis sowie eventuelle Hinweise bzw. Fehler ausgegeben.&lt;br /&gt;
Die Prüfung kann beliebig wiederholt werden und sollte sich bei jeder Einstellungsänderung der Anlage durchgeführt werden. Dadurch wird die Wahrscheinlichkeit von fehlerhaften Einstellungen minimiert.&lt;br /&gt;
&lt;br /&gt;
Neben den grundlegenden Einstellungen können im Device weitere sekundäre Anlagenkomponenten wie Batteriesystem(e) (Attribut setupBatteryDev1 - setupBatteryDev3), weitere Wetter-Devices (Attribut setupWeatherDev1 - setupWeatherDev3) oder sonstige Erzeuger (z.B. BHKW, Winderzeugung, Notstromaggregat) integriert werden (Attribut setupOtherProducer01 - setupOtherProducer03).&lt;br /&gt;
&lt;br /&gt;
Die verlangten Parameter der Anlage werden in der Online-Hilfe umfassend beschrieben und deren Funktion erschließt sich zum größten Teil selbst. Dennoch soll nachfolgend auf einige Punkte im Zusammenhang der Einrichtung eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Hinweise zur Struktur der Attribute ===&lt;br /&gt;
&lt;br /&gt;
Durch die umfangreichen Funktionen des Moduls würde bei Nutzung der im FHEM herkömmlich vorhandenen Attributstruktur die Anzahl der benötigten Attribute extrem stark steigen und nicht sinnvoll genutzt werden können. Deshalb gibt es neben den &#039;&#039;gewöhnlichen&#039;&#039; Attributen mit einfachen Werteauswahlmöglichkeiten oder Eingaben (z.B. ctrlDebug, ctrlSpecialReadings) sogenannte &#039;&#039;zusammengesetzte&#039;&#039; Attribute, deren Inhalt durch &#039;&#039;&#039;Schlüssel=Wert Paare&#039;&#039;&#039; gebildet wird und dadurch deutlich mehr Funktionen und Informationen transportieren als ein gewöhnliches Attribut.&lt;br /&gt;
&lt;br /&gt;
Für zusammengesetzte Attribute besteht die zusätzliche Möglichkeit, gewünschte Änderungen der Schlüssel=Wert Paare selektiv vornehmen zu können, ohne das gesamte Attribut aufrufen und ändern zu müssen. Die Vorgang, der vor allem für programmtechnische Manipulationen gedacht ist, kann durch eine Set-Funktion ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; attrKeyVal &amp;lt;Attribut&amp;gt; [&amp;lt;Gerät&amp;gt;] &amp;lt;Schlüssel=Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiele für zusammengesetzte Attribute sind:&lt;br /&gt;
&lt;br /&gt;
* aiControl&lt;br /&gt;
* plantControl&lt;br /&gt;
* setup* Attribute&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktionen der Attribute werden durch einen Präfix geclustert und so inhaltlich, aber vor allem auch in der Attribute Drop-Down Liste, strukturiert dargestellt.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der &#039;&#039;&#039;Präfixe&#039;&#039;&#039; sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ai&#039;&#039;&#039; - Steuerungsfunktionen für KI (z.B. aiControl)&lt;br /&gt;
* &#039;&#039;&#039;consumer&#039;&#039;&#039; - Registrierung und Einstellungen für Verbraucher (z.B. consumer02, consumerControl)&lt;br /&gt;
* &#039;&#039;&#039;ctrl&#039;&#039;&#039; - Steuerungsfunktion allgemeiner Art (z.B. ctrlDebug, ctrlSpecialReadings, ctrlUserExitFn)&lt;br /&gt;
* &#039;&#039;&#039;flowGraphic&#039;&#039;&#039; - Einstellungen für die Energieflußgrafik (z.B. flowGraphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphic&#039;&#039;&#039; - Einstellung für die Grafik allgemein (z.B. graphicSelect, graphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphicBeam&#039;&#039;&#039; -  Einstellungen bestimmte Balkeneigenschaften in der Balkengrafik (z.B. graphicBeamHeightLevel1)&lt;br /&gt;
* &#039;&#039;&#039;plant&#039;&#039;&#039; - übergreifende Einstellungen betreffend der gesamten PV-Anlage bzw. des SolarForecast-Devices (z.B. plantControl)&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039; - Registrierung von Geräten in der Gesamtanlage und Einstellung deren Eigenschaften (Inverter, Zähler, Batterien usw.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Einrichtung der Wechselrichter mit setupInverterDevXX ===&lt;br /&gt;
&lt;br /&gt;
Mit den Attributen setupInverterDev01 bis setupInverterDevXX werden die vorhandenen Wechselrichter der Anlage registriert.&lt;br /&gt;
Das Modul unterscheidet verschiedene Wechselrichter-Typen, die sich durch ihre Arbeitsweise innerhalb der Anlage unterscheiden. Die Schlüssel=Wert Paare in den Attributen können mehrzeilig organisiert werden. Das erleichtert die Übersicht wenn viele dieser Parameter eingegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;PV-Wechselrichter: Es ist der Standard Wechselrichter in einer PV-Anlage. An ihn sind die Solarzellen bzw. Strings angeschlossen. Die zugeordneten Strings können mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ohne diese Angabe werden diesem Gerät alle definierten Strings (siehe Attribut &#039;&#039;setupInverterStrings&#039;&#039;) zugeordnet. Der Wechselrichter liefert seine Energie in das Hausnetz. Alternativ kann mit der Angabe &#039;&#039;&#039;feed=grid&#039;&#039;&#039; die Funktion des Wechselrichters geändert werden. Diese Angabe sagt aus, dass dieser Wechselrichter ausschließlich in das öffentliche Netz einspeist.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel-Setup eines PV-Wechselrichters (SMA STP):&lt;br /&gt;
&lt;br /&gt;
 STP_5000 pvIn=string_1_pdc:kW pvOut=total_pac:kW etotal=etotal:kWh capacity=5000 strings=Süddach asynchron=1 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Solar-Ladegeräte: Solar-Ladegeräte sind DC-DC Wandler und liefern die Energie der angeschlossenen Solarzellen nicht in das Wechselstromnetz, sondern laden direkt eine Batterie bzw. versorgen einen Batteriewechselrichter auf der Gleichstromseite. Die Funktion als Solar-Ladegerät wird mit &#039;&#039;&#039;feed=bat&#039;&#039;&#039; aktiviert, die relevanten Strings können ebenfalls mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ein Beispiel eines Solar-Ladegerätes ist ein Victron SmartSolar MPPT. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel für das Setup eines Solar-Ladegeräts (SmartSolar Charger MPPT):&lt;br /&gt;
&lt;br /&gt;
 MQTT2_cerboGX_c0619ab34e08_solarcharger_Common pv=Yield_Power_value:W etotal=Yield_System_value:kWh capacity=2080 strings=Schleppdach feed=bat synchron=0 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Batterie-Wechselrichter: Dieses Gerät hat keine angeschlossenen Solarzellen und arbeitet als DC-AC bzw. AC-DC Wandler zwischen einer Batterie (=Gleichstromquelle) und dem Wechselstrom-Hausnetz. Die Funktion als Batterie-Wechselrichter wird mit der Angabe &#039;&#039;&#039;strings=none&#039;&#039;&#039; aktiviert. Die Schlüssel &#039;&#039;etotal&#039;&#039; und &#039;&#039;pv&#039;&#039; können bei einem Batterie-Wechselrichter ohne zugeordnete Solarzellen nicht gesetzt werden. Ein Beispiel eines Batterie-Wechselrichter ist der Victron MultiPlus II.&lt;br /&gt;
&lt;br /&gt;
Ein Setup-Beispiel für einen Batterie-Wechselrichter (Victron MultiPlus II):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dc2ac=DC_IN:W&lt;br /&gt;
ac2dc=DC_OUT:W&lt;br /&gt;
capacity=7200&lt;br /&gt;
strings=none&lt;br /&gt;
icon=inverter@darkorange:inverter@grey&lt;br /&gt;
asynchron=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Eigenschaften des Wechselrichters werden durch eine Reihe von &amp;lt;Schlüssel=Wert&amp;gt; Paaren festgelegt. Auf einige dieser Paramter soll hier eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Ausgewählte Schlüssel=Wert Paare ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;pvIn=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvIn&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell zugeführte PV-Leistung bereitstellt. Der Schlüssel ist optional und dient in erster Linie dazu den entsprechenden Input-Wert in der Flußgrafik anzuzeigen sofern man das Attribut flowGraphicControl-&amp;gt;showGenerators=1 setzt. Dadurch ist auch der Eigenverbrauch des Inverters bzw. dessen Wandlungsverlust visuell abschätzbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pvOut=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvOut&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell erzeugte Leistung als positiven Wert liefert. Für einen PV-Wechselrichter (DC-&amp;gt;AC) oder Solar-Ladegerät (DC-&amp;gt;DC) ist es die erzeugte PV-Leistung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ac2dc=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter vom Hausnetz in Richtung Batterie (AC-&amp;gt;DC) wandelt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;dc2ac=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter aus einer Gleichstromquelle, d.h. einer Batterie oder einem Solar-Ladegerät, in Richtung des Hausnetzes (AC) wandelt . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;capacity=&amp;lt;max. WR-Leistung&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In dem Schlüssel &#039;&#039;capacity&#039;&#039; wird die maximal mögliche Leistung in Watt (ohne Einheit) angegeben, die der Wechselrichter lt. seinem Datenblatt in der Lage ist zu leisten. &lt;br /&gt;
&lt;br /&gt;
Die Angabe &#039;&#039;capacity&#039;&#039; hat in erster Linie die Aufgabe, die max. mögliche PV-Leistung für die Prognose zu begrenzen. Oft sind die installierten Peak-Leistungen der PV-Module höher als die angeschlossene Wechselrichter-Leistung bzw. kommt es vor, dass die KI / (korrigierte) API-Prognose über der maximal möglichen Wechselrichter-Leistung liegt. In diesen Fällen wird die Prognose auf die angegebene &#039;&#039;capacity&#039;&#039; begrenzt.&lt;br /&gt;
&lt;br /&gt;
Der Wert in diesem Schlüssel kann, wie andere Schlüssel auch, dynamisch zur Laufzeit mit dem Set-Befehl &amp;quot;[[#Hinweise zur Struktur der Attribute|set &amp;lt;Name&amp;gt; attrKeyVal ...]]&amp;quot; geändert werden. Ein Beispiel zur Anwendung ergibt sich aus folgendem Szenario.&lt;br /&gt;
&lt;br /&gt;
Gegeben sei eine Anlage die aus Solarzellen (1300 W Peak) mit einem Solar-Ladegerät mit max. 1800 W Leistung, einer Batterie und einem Batterie-Wechselrichter besteht. Die Anlage versorgt nur das Hausnetz. Eine Netzeinspeisung ist nicht vorgesehen oder nicht erlaubt.  &lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, es ist ein Tag voller Sonnenschein prognostiziert und die Batterie ist zunächst entladen. Der Haushalt verbraucht 300 W. Dann würden die PV-Module Module ihre volle Leistung von 1300 W Peak leisten können, die sich auch in der Balken-Vorhersage niederschlägt. Die Leistung wird nicht begrenzt, weil:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* sie niedriger ist als die nominale und angegebene Wechselrichter Kapazität von &#039;&#039;capacity=1800&#039;&#039;&lt;br /&gt;
* die erzeugte Energie anteilig für die Verorgung des Hauses und die Aufladung der Batterie verwendet wird&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders verhält es sich wenn nach einer gewissen Zeit die Batterie voll ist und weiterhin volle PV Leistung zur Verfügung steht. In diesem Fall würde der Haushalt seine benötigte Leistung von 300 W abnehmen, aber das Solar-Ladegerät kann keine weitere Leistung mehr abgeben, da die Batterie bereits voll geladen ist, d.h. die Anlagensteuerung würde die PV-Anlage abregeln. In diesem Fall, wenn es einen längeren Zeitraum betrifft, muß auch die Prognose PV-Energie auf 300 Wh (bzw. den durchschnittlichen Energieverbrauch des Hauses pro Stunde) begrenzt werden, damit die PV-Prognose nach unten angepasst wird und so eine realitätsnahere Prognose ermöglicht wird. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;icon=&amp;lt;aktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;][:&amp;lt;inaktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Jeder Wechselrichter wird im Standard durch ein Icon getrennt nach Tag und Nacht, d.h. je nach Aktiv-Status und Inaktiv-Status, symbolisiert.&lt;br /&gt;
&lt;br /&gt;
;Tag bzw. Aktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Sonnensymbol im Standard verwendet. Batterie-Wechselrichter verwenden ein gefärbtes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
;Nacht bzw. Inaktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Symbol der aktuellen Mondphasen im Standard verwendet. Batterie-Wechselrichter verwenden ein ausgegrautes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie angegeben, kann man für Tag und Nacht jeweils ein Wunsch-Icon, wenn gewünscht mit einer alternativen Färbung, auswählen.&lt;br /&gt;
&lt;br /&gt;
 icon=inverter@darkorange:inverter@gray&lt;br /&gt;
&lt;br /&gt;
Soll nur das Icon für die Nacht bzw. Inaktivät geändert werden, kann dies in dieser Form angegeben werden:&lt;br /&gt;
&lt;br /&gt;
 icon=:inverter@gray  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(beachte den führenden &#039;:&#039;)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Definition von Hybrid-Wechselrichtern  ====&lt;br /&gt;
&lt;br /&gt;
Zur Zeit der Erstellung dieses Abschnittes ist es in der SolarForecast Version 1.58.x nicht möglich, einen Hybridwechselrichter nativ zu definieren. Als Workaround wird eine passende Kombination aus PV-Wechselrichter und Batterie-Device oder einer Kombination aus PV-Wechselrichter + Batterie-Wechselrichter und Batterie-Device erstellt.&lt;br /&gt;
&lt;br /&gt;
Bei allen benutzten Methoden ist es sehr wichtig!, dass die geforderten Inhalte der jeweilige Attributschlüssel beachtet und eingehalten werden. So ist zum Beispiel die Angabe von:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pvOut&#039;&#039;&#039; - Ein Reading, welches die aktuelle Leistung aus PV-Erzeugung, die an das Hausnetz oder öffentliche Netz geliefert wird, bereitstellt. Es wird ein positiver numerischer Wert erwartet.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
bei einem PV-Wechselrichter ein Reading welches ausschließlich die Leistung liefert, die von den Solarzellen-Generatoren erzeugt wird. Elemente von Batterieleistungen oder Gridbestandteile dürfen hier nicht enthalten sein. Sind in den Gerätemodulen diese Readings in dieser Form nicht enthalten, bietet es sich an, userReadings zur Erstellung von zusätzlichen Readings in den Quellendevices zu nutzen um den nötigen Input für SolarForecast bereitzustellen. &lt;br /&gt;
&lt;br /&gt;
So wird zum Beispiel bei einem 	Batterie-Wechselrichter gefordert, dass die Readings &#039;&#039;&#039;ac2dc&#039;&#039;&#039; (AC-&amp;gt;DC-Leistung Hausnetz zur Batterie) und &#039;&#039;&#039;dc2ac&#039;&#039;&#039; (DC-&amp;gt;AC-Leistung (Batterie zum Hausnetz) &#039;&#039;&#039;jeweils als als positiver Wert&#039;&#039;&#039; anzugeben ist. Manche Batterie-Devices stellen allerdings nur ein Reading zur Verfügung, welches vorzeichenbehaftet die Leistungen in die Batterie bzw. aus der Batterie heraus liefert. Mit einem userReadings Attribut kann aus diesem Reading zwei neue Readings erzeugt werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; userReadings  BatIn:DC_Power_value.* {&lt;br /&gt;
                          my $pwr = ReadingsVal ($name, &#039;DC_Power_value&#039;, 0);&lt;br /&gt;
                          $pwr    = $pwr &amp;gt; 0 ? $pwr : 0;&lt;br /&gt;
                          $pwr&lt;br /&gt;
                          },&lt;br /&gt;
                          BatOut:DC_Power_value.* {&lt;br /&gt;
                          my $pwr = ReadingsVal ($name, &#039;DC_Power_value&#039;, 0);&lt;br /&gt;
                          $pwr    = $pwr &amp;lt; 0 ? - $pwr : 0;&lt;br /&gt;
                          $pwr&lt;br /&gt;
                          },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist das Quellenreading &#039;&#039;DC_Power_value&#039;&#039; positiv, stellt der Wert AC-&amp;gt;DC-Leistung dar und wird als neues Reading BatIn bereitgestellt. Mit einem negativen Vorzeichen ist es eine DC-&amp;gt;AC-Leistung und wird in dem neuen Reading BatOut &#039;&#039;&#039;ebenfalls als positiver Wert&#039;&#039;&#039; bereitgestellt. Auch hier gilt der Grundsatz, dass zum Beispiel BatOut nur die von der Batterie gelieferte Energie und keinen Mix aus Batterie- und PV-Energie enthalten darf.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
===== Integration eines DEYE SUN-12K-SG04LP3-EU =====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-09-23 203955.png|right|thumb|400px|DEYE SUN-12K-SG04LP3-EU Grundlegende Systemarchitektur]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der DEYE vereint wie wohl alle bzw. die meisten Hybrid-Wechselrichter die Anschlüsse:&lt;br /&gt;
&lt;br /&gt;
* Eingang Solar-Strings&lt;br /&gt;
* Anschluß Batteriespeicher&lt;br /&gt;
* AC-Anschluß öffnetliches Netz&lt;br /&gt;
* AC-Anschluß Ersatzlast (wird bei Netzausfall weiter versorgt)&lt;br /&gt;
* AC-Anschluß Notstromgenerator bzw. netzgekoppelter anderer Wechselrichter (hier ist ein Growatt Micro-Wechselrichter angeschlossen)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Integration werden die setup-Attribute durch das FHEM Device &#039;&#039;Deye_Inverter&#039;&#039; besetzt:&lt;br /&gt;
&lt;br /&gt;
* setupInverterStrings zur Definition der vorhandenen Solarstrings&lt;br /&gt;
* setupInverterDev01 zur Definition der Inverteranschlüsse und Eigenschaften&lt;br /&gt;
* setupBatteryDev01 integriert die Batterie&lt;br /&gt;
* setupMeterDev liefert die Daten für Netzbezug und Netzeinspeisung&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das nachfolgend verwendete Device &#039;&#039;Deye_Inverter&#039;&#039; ist ein MQTT-Device. Es bekommt Daten vom Deye-Hybridwechselrichter per MQTT und sendet Einstellungen zum Deye, bspw. maximaler Lade/Entladestrom des Akkus, Laden des Akkus aus dem Netz, Ein- und Ausschalten des Micro-Inverter-Ports.&lt;br /&gt;
Das Reading &#039;&#039;Deye_Growatt_power&#039;&#039; im Schlüssel &#039;&#039;pvOut&#039;&#039; ist eine Addition aus den Daten des Deye WR und des angeschlossenen Growatt Micro-Wechselrichters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupInverterStrings Sueddach,Garagendach&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupInverterDev01 Deye_Inverter pvOut=Deye_Growatt_power:W capacity=15200 etotal=total_pv_production:kWh&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupBatteryDev01 Deye_Inverter pin=-pout pout=battery_output_power:W intotal=total_charge_of_the_battery:kWh outtotal=total_discharge_of_the_battery:kWh cap=15200 charge=SOC_jkbms&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupMeterDev Deye_Inverter gcon=total_grid_power:W contotal=total_energy_bought:kWh gfeedin=-gcon feedtotal=total_energy_sold:kWh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;setupInverterStrings&#039;&#039; benennt alle vorhandenen Solarstrings. Werden mehrere Inverter definiert, kann mit dem hier nicht verwendeten Schlüssel &#039;&#039;strings&#039;&#039; eine Zuordnung der Strings zum angeschlossenen Inverter vorgenommen werden.&lt;br /&gt;
&lt;br /&gt;
Im Attribut &#039;&#039;setupInverterDev01&#039;&#039; ist der allgemeine Schlüssel &#039;&#039;capacity&#039;&#039; zur Festlegung der Inverterleistung von 15200 Watt gesetzt. Die spezifischen Schlüssel &#039;&#039;pvOut&#039;&#039; und &#039;&#039;etotal&#039;&#039; teilen dem Modul die aktuell erzeugte PV-Leistung sowie die gesamte erzeugte PV-Energie mit. Letzteres dient unter anderem dazu die stündlich real erzeugte PV-Energie festzuhalten und mit der Prognose zu vergleichen. Die in den schlüsseln hinterlegten dürfen keine Battrie- oder Netzanteile enthalten.&lt;br /&gt;
&lt;br /&gt;
Das Attr &#039;&#039;setupBatteryDev01&#039;&#039; implementiert alle relevanten Batteriewerte. Das Reading &#039;&#039;battery_output_power&#039;&#039; im Schlüssel &#039;&#039;pout&#039;&#039; liefert den Batterie-Output als positiven Wert. Als Besonderheit kann der Wert &#039;&#039;pin&#039;&#039;, die Batterie-Ladeleistung, den Wert des Readings in &#039;&#039;pout&#039;&#039; übernehmen wenn dieser Wert ein negatives Vorzeichen hat. Die Schlüssel &#039;&#039;intotal&#039;&#039; und &#039;&#039;outtotal&#039;&#039; liefern die summierten Totalwerte für Batterie Ladung bzw. Entladung. Die Kapazität &#039;&#039;cap&#039;&#039; wird für verschiedene Aspekte der SoC- und Ladesteuerung verwendet. &lt;br /&gt;
&lt;br /&gt;
Abschließend liefern die angebenen Readings in den Schlüsseln des Attributes &#039;&#039;setupMeterDev&#039;&#039; alle notwendigen Werte des Netzbezugs und der Netzeinspeisung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nachfolgende Links liefern &#039;&#039;&#039;weitere Infos&#039;&#039;&#039; wie man Daten aus dem Deye WR ausliest und Einstellungen des Deye WR verändert:&lt;br /&gt;
&lt;br /&gt;
* https://github.com/klatremis/esphome-for-deye&lt;br /&gt;
* https://github.com/philipphenkel/esphome-config&lt;br /&gt;
* https://github.com/bagges/deye-esp32-bridge&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für eine weiterführende Automation soll der Akku netzdienlich in der Mittagszeit geladen werden. Dazu wurde durch den Anwender folgendes userReadings &#039;&#039;MaxBattCharge_Request&#039;&#039; im Device &#039;&#039;Deye_Inverter&#039;&#039; für den maximalen Ladestrom definiert (bei 90% SOC und bei 100% SOC):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MaxBattCharge_Request:SOC_jkbms.* {&lt;br /&gt;
                                    if ((ReadingsNum(&#039;mySolarForecast&#039;,&#039;RestOfDayPVforecast&#039;,&#039;&#039;)&lt;br /&gt;
                                         - ReadingsNum(&#039;mySolarForecast&#039;,&#039;special_todayConForecastTillSunset&#039;,&#039;&#039;)&lt;br /&gt;
                                         - (90-ReadingsNum(&#039;JK_BMS&#039;,&#039;capacity_remaining&#039;,&#039;&#039;))/100*310*51.2) &amp;lt; 400&lt;br /&gt;
                                         and ReadingsAge(&#039;JK_BMS&#039;,&#039;capacity_full_timestamp&#039;,&#039;&#039;) &amp;lt; 561600)&lt;br /&gt;
                                    {100}&lt;br /&gt;
                                    elsif ((ReadingsNum(&#039;mySolarForecast&#039;,&#039;RestOfDayPVforecast&#039;,&#039;&#039;)&lt;br /&gt;
                                            - ReadingsNum(&#039;mySolarForecast&#039;,&#039;special_todayConForecastTillSunset&#039;,&#039;&#039;)&lt;br /&gt;
                                            - (100-ReadingsNum(&#039;JK_BMS&#039;,&#039;capacity_remaining&#039;,&#039;&#039;))/100*310*51.2) &amp;lt; 400&lt;br /&gt;
                                            and ReadingsAge(&#039;JK_BMS&#039;,&#039;capacity_full_timestamp&#039;,&#039;&#039;) &amp;gt;= 561600)&lt;br /&gt;
                                    {100}&lt;br /&gt;
                                    elsif ((ReadingsNum(&#039;mySolarForecast&#039;,&#039;RestOfDayPVforecast&#039;,&#039;&#039;)&lt;br /&gt;
                                            - ReadingsNum(&#039;mySolarForecast&#039;,&#039;special_todayConForecastTillSunset&#039;,&#039;&#039;)&lt;br /&gt;
                                            - (90-ReadingsNum(&#039;JK_BMS&#039;,&#039;capacity_remaining&#039;,&#039;&#039;))/100*310*51.2) &amp;gt;= 400&lt;br /&gt;
                                            and ReadingsAge(&#039;JK_BMS&#039;,&#039;capacity_full_timestamp&#039;,&#039;&#039;) &amp;lt; 561600)&lt;br /&gt;
                                    {ceil ((90-ReadingsNum(&#039;JK_BMS&#039;,&#039;capacity_remaining&#039;,&#039;&#039;))/100*310/3.5)}&lt;br /&gt;
                                    elsif ((ReadingsNum(&#039;mySolarForecast&#039;,&#039;RestOfDayPVforecast&#039;,&#039;&#039;)&lt;br /&gt;
                                            - ReadingsNum(&#039;mySolarForecast&#039;,&#039;special_todayConForecastTillSunset&#039;,&#039;&#039;)&lt;br /&gt;
                                            - (100-ReadingsNum(&#039;JK_BMS&#039;,&#039;capacity_remaining&#039;,&#039;&#039;))/100*310*51.2) &amp;gt;= 400&lt;br /&gt;
                                            and ReadingsAge(&#039;JK_BMS&#039;,&#039;capacity_full_timestamp&#039;,&#039;&#039;) &amp;gt;= 561600)&lt;br /&gt;
                                    {ceil ((100-ReadingsNum(&#039;JK_BMS&#039;,&#039;capacity_remaining&#039;,&#039;&#039;))/100*310/3.0)}&lt;br /&gt;
                                  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das userReading wird in einer Automation benutzt, um den maximalen Ladestrom einzustellen; Ladebeginn bei ausreichend Sonne ist ab 11:30 eingestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Integration eines Fronius Symo GEN24 10.0 Plus mit (virtuellen) Batterie-Wechselrichter =====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-10-04 162422.png|right|thumb|400px|Flußgrafik mit eingebauten Hybrid-Wechselrichter]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Integration des Wechselrichters Fronius Symo GEN24 10.0 Plus benötigt zunächst eine Anbindung in FHEM, was mit dem Modul 98_fronius.pm vorgenommen wurde.&lt;br /&gt;
&lt;br /&gt;
Das Ziel der Kurzdokumentation ist neben der Darstellung eines Hybridwechselrichters aufzuzeigen, wie man den Wandlungsverlust eines PV-Wechselrichters (pvIn – pvOut) in Näherung visualisieren kann.  &lt;br /&gt;
&#039;&#039;&#039;pvIn&#039;&#039;&#039; ist dabei die Summe der Produkte aus den DC Strom- und Spannungswerten der einzelnen Strings (hier 2109 W), &#039;&#039;&#039;pvOut&#039;&#039;&#039; (hier 2065 W) ist die an den Inverterknoten (hier 1105 W) plus die an die Batterie abgegebene Leistung (hier 960 W). Bei dieser Implementierung wird mit einem zusätzlichen (virtuellen) Batterie-Wechselrichter gearbeitet. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In Vorbereitung werden die beiden anzugebenden Readings &#039;&#039;&amp;lt;pvIn&amp;gt;&#039;&#039; und &#039;&#039;&amp;lt;pvOut&amp;gt;&#039;&#039; zum Beispiel als userReadings erstellt, wobei &#039;&amp;lt;pvIn&amp;gt;&#039;&#039; und &#039;&#039;&amp;lt;pvOut&amp;gt;&#039;&#039; natürlich durch Readingnamen ersetzt werden müssen. Diese beiden Readings werden wie folgt berechnet / erstellt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;pvOut&amp;gt; = Inverter_Common_PAC_Value - PowerFlow_Site_P_Akku&lt;br /&gt;
&amp;lt;pvIn&amp;gt; = Inverter_Common_IDC_Value * Inverter_Common_UDC_Value + Inverter_Common_IDC_2_Value * Inverter_Common_UDC_2_Value&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der &#039;&#039;&#039;PV-Wechselrichter&#039;&#039;&#039; wird mit dem Attribut setupInverterDev01 definiert, wobei die angelegten Readingnamen in den Schlüsseln &#039;&#039;pvIn&#039;&#039; bzw. &#039;&#039;pvOut&#039;&#039; verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SymGen24 icon=inverter@#ff8c00:inverter@grey capacity=10000 strings=suedwest,nordost etotal=User_Produced_PV:kWh pvOut=&amp;lt;pvOut&amp;gt;:W pvIn=&amp;lt;pvIn&amp;gt;:W&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dem PV-Wechselrichter sind die Strings &#039;&#039;suedwest&#039;&#039; und &#039;&#039;nordost&#039;&#039; zugewiesen.&lt;br /&gt;
&lt;br /&gt;
Der zusätzliche &#039;&#039;&#039;Batterie-Wechselrichter&#039;&#039;&#039; wird mit dem Attribut setupInverterDev02 hinzugefügt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SymGen24 icon=inverter@#ff8c00:inverter@grey strings=none ac2dc=-PowerFlow_Site_P_Akku:W  dc2ac=PowerFlow_Site_P_Akku:W capacity=7680&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bemerkungen:&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
- strings=none sowie die Schlüssel ac2cd und dc2ac sind typisch für einen Batterie-WR bzw. kennzeichnen einen WR als Batterie-Wechselrichter &amp;lt;br&amp;gt;&lt;br /&gt;
- die an die Batterie abgegebene Leistung ist negativ&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Einbindung eines Fronius Symo GEN24 10.0 Plus mit BYD Batterie ohne (virtuellen) Batterie-Wechselrichter =====&lt;br /&gt;
Diee Implementierung ist komplett in diesem verlinkten [https://wiki.fhem.de/wiki/Solaranlage_Komplettbeispiel_Fronius_BYD Wiki Beitrag] beschrieben.&lt;br /&gt;
&lt;br /&gt;
Zur Integration des &#039;&#039;Fronius Symo&#039;&#039; in FHEM wird das Modul &#039;&#039;fronius.pm&#039;&#039; verwendet und in dem definierten Device &#039;&#039;Fronius_Symo_Gen24&#039;&#039; diverse userReadings erzeugt. Diese Readings werden in den korrespondierenden Schlüsseln des Attributes &#039;&#039;setupInverterDev01&#039;&#039; angegeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setupInverterDev01 Fronius_Symo_Gen24 etotal=User_Produced_PV_Energie:kWh pvOut=PowerFlow_Site_P_PV:W capacity=6000 strings=Dach_Ost,Dach_West&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Am Wechselrichter Fronius Symo Gen24 ist eine BYD Batterie angeschlossen. Das Device &#039;&#039;[https://wiki.fhem.de/wiki/Solaranlage_Komplettbeispiel_Fronius_BYD#PV_Batterie PV-Batterie]&#039;&#039; wird per [https://wiki.fhem.de/wiki/ModbusAttr ModbusAttr] angelegt und gemanaged. Die entsprechenden Readings werden im Attribut &#039;&#039;SetupBatteryDev01&#039;&#039; hinterlegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PV_Batterie&lt;br /&gt;
cap=10240&lt;br /&gt;
charge=BatteryChargePercent&lt;br /&gt;
icon=@dyn:@dyn:@dyn:@dyn&lt;br /&gt;
intotal=Summe_Ladung:Wh&lt;br /&gt;
outtotal=Summe_Entladung:Wh&lt;br /&gt;
pin=BatteryChargeWatt:W&lt;br /&gt;
pout=BatteryDischargeWatt:W&lt;br /&gt;
pinmax=10000&lt;br /&gt;
show=2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Einbindung eines SMA - Hybrid Sunny Tripower Smart Energy  =====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-10-05 083530.png|right|thumb|400px|SMAInverter.pm]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der genannte Wechselrichter wird über das Modul SMAInverter.pm in FHEM integriert. Die nebenstehende Abbildung zeigt und benennt die einzelnen Readings des Moduls welche in den entsprechenden Schlüsseln der SolarForecast Attribute &#039;&#039;setupInverterDevXX&#039;&#039; und &#039;&#039;setupBatteryDevXX&#039;&#039; zugeordnet werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Readings des SMAInverter Moduls können vor der Verwendung über geeignete Methoden (userReadings) in Readings mit sprechenden Namen überführt werden um sie mit diesen Namen in die genannten Attributschlüssel einzufügen. In der vorliegenden Lösung befinden sich die  Anwendungen SolarForecast und und die Inverter-Steuerung jeweils auf unterschiedlicher Hardware. Als Verbindungslayer wird MQTT genutzt, wobei dadurch bereits die dargestellten Readingnamen entstehen. &lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Der integrierte SolarForecast Grafikbereich ==&lt;br /&gt;
Das SolarForecast Modul beinhaltet eine Grafikdarstellung die sich in mehrere Bereiche gliedert. Diese Bereiche können über Attribute ein- bzw. ausgeblendet sowie die Inhalte festgelegt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 223545.png|right|thumb|400px|Bereiche der integrierten Grafik]]&lt;br /&gt;
&lt;br /&gt;
Der nebenstehende Screenshot gibt die Gliederung der Grafikbereiche wieder:&lt;br /&gt;
&lt;br /&gt;
 1 - der Kopfbereich (Graphic Header)&lt;br /&gt;
 2 - durch den Nutzer selbst definierbarer Inhalt (Graphic Header Own Specification) als Teil des Kopfbereiches&lt;br /&gt;
 3 - Bereich Verbraucherdarstellung (Consumer Legend)&lt;br /&gt;
 4 - Bereich Balkengrafik (Beam Graphic)&lt;br /&gt;
 5 - Energieflußgrafik (Flow Graphic)&lt;br /&gt;
&lt;br /&gt;
Jeder dieser Bereiche hat spezifische Steuerungsattribute zur Anpassung des Verhaltens und ggf. des Inhalts.&lt;br /&gt;
&lt;br /&gt;
=== 1 - Der Grafik Kopfbereich ===&lt;br /&gt;
Im Kopfbereich befinden sich fest verankerte Informationen zur verwendeten Vorhersage-API sowie deren Status, Informationen zum Sonnenaufgang und Sonnenuntergang, dem aktuellen Gesamtstatus des SolarForecast Devices, Abweichungskennzahlen der PV Vorhersage sowie weitere Kennzeichen zur Verfügung.&lt;br /&gt;
Über zwei Drucktasten kann eine Anlagenprüfung durchgeführt und in den Spportthread des Moduls im FHEM Forum abgesprungen werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;graphicHeaderShow&#039;&#039;&#039; kann der gesamte Kopfbereich 1 und 2 (nutzereigener Teilbereich) ausgeblendet werden. Wird der Kopbereich ausgeblendet, ist es hilfreich mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;showLink&#039;&#039;&#039; einen Link zur Detailgrafik einzufügen da der in der Kopfgrafik integrierte Link in diesem Fall nicht mehr zur Verfügung steht. &lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;graphicHeaderDetail&#039;&#039;&#039; definiert welche Bereiche des Grafikkopfes angezeigt werden sollen. Es kann die Anzeige des Energieverbrauches, der PV-Erzeugung und der vom Nutzer selbst definierte Inhalt miteinander frei kombiniert werden.&lt;br /&gt;
&lt;br /&gt;
=== 2 - Der Bereich mit selbst definierbarem Inhalt (Graphic Header Own Specification) ===&lt;br /&gt;
In diesem Bereich kann der User beliebige Readings, Set-Kommandos und Attribute des SolarForecast Devices oder anderer Devices, die sich im gleichen FHEM-System wie das SolarForecast Device befinden, anzeigen lassen.&lt;br /&gt;
&lt;br /&gt;
Dieser Bereich ist als Tabelle mit einer beliebigen Anzahl von Zeilen organisiert. Jede Zeile beinhaltet ein Kommentarfeld und vier Nutzfelder zur Darstellung ausgewähler Werte + Label. Der Bereich bzw. der Inhalt des Bereiches wird mit dem Attribut &#039;&#039;&#039;graphicHeaderOwnspec&#039;&#039;&#039; definiert.  &lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt ein real gesetztes graphicHeaderOwnspec Attribut. Die Leerzeilen sind nicht notwendig, erhöhen aber die Lesbarkeit der Struktur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
Autarkierate:Current_AutarkyRate&lt;br /&gt;
PV&amp;amp;nbsp;übermorgen:special_dayAfterTomorrowPVforecast&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;Sunset:special_todayConForecastTillSunset&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;nächsten&amp;amp;nbsp;Sunrise:special_conForecastTillNextSunrise&lt;br /&gt;
&lt;br /&gt;
#Batterie&lt;br /&gt;
BatteryLive&amp;amp;nbsp;Status:userFn_BatLive_State&lt;br /&gt;
SoC&amp;amp;nbsp;Limit:Settings_CGwacs_BatteryLife_MinimumSocLimit_value@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SoC&amp;amp;nbsp;Ist:SOC_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
SOC&amp;amp;nbsp;Optimum:Battery_OptimumTargetSoC&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
aktuelle&amp;amp;nbsp;Ladung:userFn_Bat_EnergyState&lt;br /&gt;
Verfügbar:userFn_BatLive_UsableEnergy&lt;br /&gt;
benötigte&amp;amp;nbsp;Ladeenergie:userFn_Bat_EnergyRemain&lt;br /&gt;
Ladefreigabe:Battery_ChargeRecommended&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
akt.&amp;amp;nbsp;DC&amp;amp;nbsp;Strom:DC_Current_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
Restladezeit&amp;amp;nbsp;Ziel:userFn_Bat_HoursUntilChargeFinish&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Soll:userFn_Bat_MaxChargeCurrent_set&lt;br /&gt;
:&lt;br /&gt;
&lt;br /&gt;
#Settings&lt;br /&gt;
Batterie&amp;amp;nbsp;Lademanagement:userFn_BatteryChargeManagement&lt;br /&gt;
SoC&amp;amp;nbsp;Management:userFn_BatterySoCManagement&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Ist:MaxChargeCurrent@MQTT2_cerboGX_c0619ab34e08_vebus&lt;br /&gt;
SmartSolar&amp;lt;br&amp;gt;Einspeisung:OvervoltageFeedIn@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
MPII&amp;amp;nbsp;Limit&amp;lt;br&amp;gt;Einspeisung&amp;amp;nbsp;(W):MaxFeedInPower@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SOC&amp;amp;nbsp;Limit&amp;amp;nbsp;Soll:MinimumSocLimit@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Verbr.&amp;amp;nbsp;Neuplanung:consumerNewPlanning&lt;br /&gt;
Wetteranzeige:graphicShowWeather &lt;br /&gt;
&lt;br /&gt;
Anzeige&amp;amp;nbsp;Nachtstunden:graphicShowNight&lt;br /&gt;
hist.&amp;amp;nbsp;Stunden:graphicHistoryHour&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto&lt;br /&gt;
Victron&amp;amp;nbsp;BatteryLife&amp;lt;br&amp;gt;(1=an,10=aus):BatteryLife@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Debug:ctrlDebu&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Kommentarfeld am Beginn einer Zeile wird durch ein &#039;&#039;&#039;#&#039;&#039;&#039; gekennzeichnet. Folgt dem # ein String, wird dieser String als Kommentarangabe gewertet und in der Grafik ausgegeben. Ein leeres Kommentarfeld wird lediglich durch ein # gefolgt von einem Leerzeichen oder NL beschrieben:&lt;br /&gt;
&lt;br /&gt;
 #:&amp;lt;Text&amp;gt;  (bzw nur # für einen &#039;leeren&#039; Titel)&lt;br /&gt;
&lt;br /&gt;
Ein Netzfeld bzw. ein Datensatz wird durch die Angabe von einem Label und dem darzustellenden Wert getrennt durch &#039;:&#039; definiert:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Label&amp;gt;:&amp;lt;Reading, Attribut oder Set-Kommando&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das System erkennt selbständig, ob es sich bei der Angabe um ein Reading, Attribut oder ein Set-Kommando handelt. Sollen Readings, Set-Kommandos und Attribute anderer Devices als dem SolarForecast-Device angezeigt werden, kann dies einfach durch Zusatz von&lt;br /&gt;
&lt;br /&gt;
 ....@&amp;lt;Device-Name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
an den Parameter erreicht werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-12-05 203916.png|right|thumb|400px|Darstellung eigener Grafikbereich]]&lt;br /&gt;
Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten &amp;quot;Wh&amp;quot; bzw. &amp;quot;kWh&amp;quot; werden entsprechend der Einstellung des Attributs &#039;&#039;&#039;graphicEnergyUnit&#039;&#039;&#039; umgerechnet. Im Label sind Leerzeichen durch &amp;quot;&amp;amp;amp;nbsp;&amp;quot; einzufügen, ein Zeilenumbruch durch &amp;quot;&amp;amp;lt;br&amp;amp;gt;&amp;quot;. Ein leeres Feld in einer Zeile wird durch &amp;quot;:&amp;quot; ohne eine weitere Angabe erzeugt.&lt;br /&gt;
&lt;br /&gt;
Die nebenstehende Abbildung zeigt die reale Darstellung der oben angegebenen Struktur im Attribut graphicHeaderOwnspec.&lt;br /&gt;
&lt;br /&gt;
==== Formatierung der Inhalte im Bereich &amp;quot;Graphic Header Own Specification&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
Die angezeigten Inhalte, wie z.B. Readingwerte, des User eigenen Bereiches (Attribut graphicHeaderOwnspec) können durch Spezifikationen im Attribut &#039;&#039;&#039;graphicHeaderOwnspecValForm&#039;&#039;&#039; manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
Die Online-Hilfe zum Attribut graphicHeaderOwnspecValForm erläutert die verfügbaren Möglichkeiten und Optionen.&lt;br /&gt;
Als Beispiel hier einige mögliche Notationen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &#039;userFn_Bat_HoursUntilChargeFinish&#039;                        =&amp;gt; &amp;quot;($VALUE).&#039; Stunden&#039;&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_battery.SOC_value&#039;             =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Settings_CGwacs_BatteryLife_MinimumSocLimit_value&#039;        =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Info_MaxChargeCurrent_value&#039;                              =&amp;gt; &amp;quot;($VALUE).&#039; A&#039;&amp;quot;,&lt;br /&gt;
  &#039;DC_Current_value&#039;                                         =&amp;gt; &amp;quot;%.0f A&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common.Regulated&#039; =&amp;gt; &amp;quot;($VALUE eq &#039;1&#039; ? &#039;Ja&#039; : &#039;Nein&#039;)&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine Besonderheit besteht bei darzustellenden Werten die die Einheiten &#039;Wh&#039; bzw. &#039;kWh&#039; besitzen. Diese Werte und Einheiten werden automatisch entsprechend des gesetzten Attributes graphicEnergyUnit umgerechnet und angezeigt.&lt;br /&gt;
&lt;br /&gt;
Soll in diesen Fällen eine automatische Formatierung umgangen werden, kann eine solche Notation verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &#039;Today_PVforecast&#039; =&amp;gt; &amp;quot;(sprintf &#039;%.1f &amp;amp;amp;nbsp;kWh&#039;, ($VALUE / 1000))&amp;quot;,&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Die Angabe von &amp;amp;amp;nbsp; vor &#039;kWh&#039; verhindert die Erkennung der Einheit und so auch die automatische Umsetzung durch das Modul. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 3 - Bereich Verbraucherdarstellung (Consumer Legend) ===&lt;br /&gt;
Dieser Grafikbereich zeigt die im Modul registrierten Verbraucher sowie deren Status und weitere Informationen an. Sind die Voraussetzungen gegeben, d.h. entsprechende Schlüssel in der ConsumerXX-Attributen gesetzt, können die Verbraucher über das Paneel manuell geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Zur Anpassung der Darstellung sind verschiedene Attribute verfügbar:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;consumerControl-&amp;gt;showLegend: Definiert die Lage bzw. Darstellungsweise der Verbraucherlegende sofern Verbraucher im SolarForecast Device registriert sind.&lt;br /&gt;
;consumerControl-&amp;gt;adviceIcon: Definiert die Art der Information über die geplanten Schaltzeiten eines Verbrauchers in der Verbraucherlegende. &lt;br /&gt;
;consumerControl-&amp;gt;detailLink: Wenn gesetzt, ist der jeweilige Verbraucher klickbar um direkt zur Detailansicht des jeweiligen Geräts auf einer neuen Browserseite zu gelangen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Standard wird das Verbraucherpaneel zwischen dem Kopfbereich und der ersten Balkengrafik Ebene dargestellt. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;showLegend&#039;&#039;&#039; und Argument &#039;&#039;&#039;icon_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_bottom&#039;&#039;&#039; kann das Verbraucherpaneel an das Ende des Grafikbereiches verschoben werden.&lt;br /&gt;
Die Verwendung von &#039;&#039;&#039;text_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_top&#039;&#039;&#039; blendet die Icon-Spalte im Verbraucherpaneel aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Screenshot 2025-02-08 093239.png|Darstellung mit consumerControl showLegend=icon_top (default)&lt;br /&gt;
File:Screenshot 2025-02-08 093646.png|Darstellung mit consumerControl showLegend=icon_bottom&lt;br /&gt;
File:Screenshot 2025-02-08 152018.png|Darstellung mit consumerControl showLegend=text_top bzw. text_bottom&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 213634.png|right|thumb|400px|]]&lt;br /&gt;
Ein Mouse-Over über das Uhrensymbol zeigt nähere Informationen zum Status, den Planungsdaten, Modus und weitere Daten des Verbrauchers. Der Schalter &amp;quot;Aus/Ein&amp;quot; visualisiert den Schaltzustand des Verbrauchers und können auch zum manuellen Schalten des Verbrauchers dienen. Voraussetzung ist, dass im consumer-Attribut die Schlüssel &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; mit den Set-Kommandos zum Schalten des Verbrauchers defininiert sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 222210.png|right|thumb|300px|]]&lt;br /&gt;
Der Auto-Schieberegler zeigt einerseits den Freigabestatus zum Schalten des Verbrauchers durch das SolarForecast Modul und kann andererseits manuell betätigt werden. Der Status des Reglers korrespondiert mit dem im zugehörigen Consumer Attribut vorhandenen Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; angegebenen Reading-Wert.&lt;br /&gt;
&lt;br /&gt;
Die Verbraucherbezeichnungen in dem Paneel können in der Standardkonfiguration angeklickt werden um direkt zur Detailansicht des Devices zu gelangen. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;detailLink&#039;&#039;&#039; kann der Link zur Detailansicht deaktiviert werden.&lt;br /&gt;
&lt;br /&gt;
Das Uhrensymbol kann mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;adviceIcon&#039;&#039;&#039; geändert und/oder dessen Farbe angepasst, sowie einen Informationstext statt eines Icons angezeigt werden. &lt;br /&gt;
&lt;br /&gt;
=== 4 - Bereich Balkengrafik (Beam Graphic) ===&lt;br /&gt;
&lt;br /&gt;
Die Balkengrafik des Moduls ist ein wesentliches Visualisierungshilfsmittel. Im Auslieferungszustand existiert eine Balkengrafikebene, die &#039;&#039;&#039;Ebene 1&#039;&#039;&#039;.&lt;br /&gt;
Jede Ebene kann zwei Balkendiagramme mit auswählbaren Inhalten, Farben und einstellbarem LayoutTyp darstellen. In Ebene 1 kann die Wettervorhersage eingebettet oder, bei Vorhandensein von Batteriegeräten, die zukünftigen Zeiten mit empfohlener Ladefreigabe und SoC-Prognose eingeblendet werden. &lt;br /&gt;
&lt;br /&gt;
Welche Daten in welchen Zeiträumen dargestellt werden sollen, die Bestimmung des Layouts, die Gestaltung der Balken und einiges mehr wird durch Attribute gesteuert. Ein Teil dieser Einstellungen wird über das zusammengesetzete Attribut &#039;&#039;&#039;graphicControl-&amp;gt;&#039;Schlüssel&#039;=&#039;Wert&#039;&#039;&#039;&#039; eingestellt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;grundsätzliche Layout Definitionen&#039;&#039;&#039;&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204342.png|right|thumb|400px|Standardanzeige mit Wetter-Icons, gesetzen Attributen graphicBeam1Color=D4C177, graphicHistoryHour=11]]&lt;br /&gt;
&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingTop:Legt den Platz in px im Balkendiagramm fest, der zwischen dem oberen Rand der jeweiligen Balkengrafik Ebene und der ersten Text- oder Iconreihe dieser Ebene eingefügt wird.&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingBottom:Legt den Platz in px im Balkendiagramm fest, der zwischen der letzten Text- oder Iconreihe der jeweiligen Balkengrafik Ebene und dem unteren Rand dieser Ebene eingefügt wird. &lt;br /&gt;
;graphicControl-&amp;gt;layoutType:Layout-Optionen zur grundlegenden Gestaltung der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourStyle:Format der Zeitangabe in der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourCount:Anzahl der darzustellenden Balken/Stunden in der Balkengrafk&lt;br /&gt;
[[Datei:Screenshot Screenshot 2025-05-21 153613.png|right|thumb|400px|Erweiterung des oberen und unteren Abstandes mit den Attributen graphicControl-&amp;gt;beamPaddingTop und graphicControl-&amp;gt;beamPaddingBottom]]&lt;br /&gt;
;graphicControl-&amp;gt;energyUnit:definiert die Einheit zur Anzeige der elektrischen Leistung in der Grafik&lt;br /&gt;
;graphicHistoryHour:Anzahl der vorangegangenen Stunden die in der Balkengrafik dargestellt werden&lt;br /&gt;
;graphicControl-&amp;gt;beamWidth:Vorgabe Breite der Balken der Balkengrafik in px (sonst automatische Bestimmung) &lt;br /&gt;
;graphicBeamHeightLevel1:Multiplikator zur Festlegung der maximalen Balkenhöhe der jeweiligen Ebene (hier Ebene 1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;Definition der Inhalte und Balkeneigenschaften&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204756.png|right|thumb|400px|Wie oben aber mit gesetzem Attribut graphicShowNight=1]]&lt;br /&gt;
;graphicBeam1Color:Farbauswahl des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2Color:Farbauswahl des sekundären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam1Content:Legt den darzustellenden Inhalt des primären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam2Content:Legt den darzustellenden Inhalt des sekundären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam1FontColor:Auswahl der Schriftfarbe des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2FontColor:Auswahl der Schriftfarbe des sekundären Balkens (Ebene 1)&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 205024.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=0 (ohne Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;zusätzliche Optionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;graphicShowNight:Anzeigen oder Verbergen der Nachtstunden in der Balkengrafik&lt;br /&gt;
;graphicShowWeather:Wettericons in der Balkengrafik anzeigen/verbergen (nur Ebene 1)&lt;br /&gt;
;graphicWeatherColor:Farbe der Wetter-Icons für die Tagesstunden&lt;br /&gt;
;graphicWeatherColorNight:Farbe der Wetter-Icons für die Nachtstunden&lt;br /&gt;
;graphicShowDiff:Zusätzliche Anzeige der Differenz &amp;quot;&amp;lt;primärer Balkeninhalt&amp;gt; - &amp;lt;sekundärer Balkeninhalt&amp;gt;&amp;quot; im Kopf- oder Fußbereich der Balkengrafik&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die genaue Beschreibung und deren Optionen sind der aktuellen Online-Hilfe zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Für alle Ebenen gilt:&#039;&#039;&#039; Ein Attribut mit einer ungeraden Balkennummer (z.B. graphicBeam1Content) bezieht sich immer auf den primären Balken, ein Attribut mit einer geraden Balkennummer (z.B. graphicBeam2Content) bezieht sich immer auf den sekundären Balken.&lt;br /&gt;
&lt;br /&gt;
Die Balken haben, wie die meisten Elemente in der Balkengrafik, eine Mouse-Over Eigenschaft welche relevante Informationen zu den dargestellten Werten anzeigt. &lt;br /&gt;
&lt;br /&gt;
Sind die Nachtunden mit &#039;&#039;&#039;graphicShowNight&#039;&#039;&#039; ausgeblendet, werden keine Balken angezeigt sofern es keine Werte anzuzeigen gibt. Sollten dennoch Werte ungleich 0 anzuzeigen sein, werden diese Werte auch trotz ausgeblendeter Nachstunden angezeigt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 2 ====&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 211741.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=01 (mit Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 2&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam3Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam4Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 4 für Balken 4) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wetter-Icons können nur in Ebene 1 integriert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 2 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 2 gibt, eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgende Ebene.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 3 ====&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 3&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam5Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam6Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 5 für Balken 5) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 3 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 3 gibt, ist eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgenden Ebenen, d.h. auch auf die Ebene 3.&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 5 - Die Energieflußgrafik (Flow Graphic) ===&lt;br /&gt;
[[Datei:Screenshot 2025-02-13 213424.png|right|thumb|400px|Energieflußgrafik mit Verbrauchern in der Nachtdarstellung (Mondphasen) nach Sonnenuntergang]]&lt;br /&gt;
&lt;br /&gt;
Die Energieflußgrafik stellt die registrierten Erzeuger, Batterien, Netzzugänge und Verbraucher strukturiert in mehreren Ebenen dar:&lt;br /&gt;
&lt;br /&gt;
;Ebene 1: In der oberen Ebene befinden sich die PV-Generatoren, Smart-Loader sowie sonstigen Erzeuger &lt;br /&gt;
;Ebene 2: Die mittlere Ebene organisiert den Zugang zum öffentlichen Netz, dem Hausknoten, dem Batterieknoten sowie einem Dummy-Verbraucher (Lampensymbol) für den Energieverbrauch des Hauses der keinem der registrierten Verbraucher zugeordnet werden kann.&lt;br /&gt;
;Ebene 3: In der unteren Ebene werden die registrierten Verbraucher dargestellt. Unterhalb der Verbrauchersymbole werden der aktuelle Verbrauch (bzw. der On/Off-Zustand) sowie darunter die Restlaufzeit (Minuten) des Verbrauchers, sofern er durch das Modul geplant und gestartet wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Position und Gestaltung der Grafikelemente ist umfangreich über das Attribut &#039;&#039;&#039;flowGraphicControl&#039;&#039;&#039; und den darin verfügbaren Schlüsseln einstellbar.&lt;br /&gt;
Die Bedeutung der Schlüssel ist in der Online-Hilfe zum Attribut mit einem Beispiel beschrieben. &lt;br /&gt;
&lt;br /&gt;
Darüber hinaus enthalten die Setup-Attribute &#039;&#039;&#039;setupInverterDevXX&#039;&#039;&#039;, &#039;&#039;&#039;setupOtherProducerXX&#039;&#039;&#039; und &#039;&#039;&#039;consumerXX&#039;&#039;&#039; weitere Einstellungsmöglichkeiten um deren Icons und Färbungen in der Flußgrafik individuell einstellen zu können. So sind zum Beispiel die Icons der PV-Inverter und deren Färbung mit dem Schlüssel &#039;&#039;&#039;icon&#039;&#039;&#039; der setupInverterDevXX-Attribute in Abhängigkeit von Tag und Nacht separat definierbar.&lt;br /&gt;
&lt;br /&gt;
In den Verbraucher-Attributen ist mit dem Schlüssel &#039;&#039;&#039;noshow&#039;&#039;&#039; die Sichtbarkeit in der Flußgrafik definierbar.&lt;br /&gt;
&lt;br /&gt;
Generell steuert das Attribut &#039;&#039;&#039;graphicSelect&#039;&#039;&#039; die Ein- bzw. Ausblendung der gesamten Flußgrafik.&lt;br /&gt;
&lt;br /&gt;
== Die Verbrauchsprognose ==&lt;br /&gt;
Im Gegensatz zu der PV Prognose gibt es keine API oder andere externen Datenquellen die für die Verbrauchsprognose herangezogen werden könnten.&lt;br /&gt;
&lt;br /&gt;
Zum Zweck der Verbrauchsermittlung verwendet das Modul die Meterdaten aus dem Attribut &#039;&#039;setupMeterDev&#039;&#039; sowie den weiteren setup-Attributen &#039;&#039;setupInverterDevXX&#039;&#039;. &lt;br /&gt;
Sind auch andere Erzeuger (BHKW, Windanlagen, etc.) bzw. eine Batterie vorhanden, sind ebenfalls die Attribute &#039;&#039;setupOtherProducerXX&#039;&#039; bzw. &#039;&#039;setupBatteryDev&#039;&#039; für die Berechnung des Hausverbrauchs relevant. In diesen Attributen gibt es die Schlüssel &#039;&#039;*total&#039;&#039; die teilweise optional sind. Für die Verbrauchsprognose bilden sie jedoch die Berechnungsgrundlage und sind deswegen für diese Funktionalität wichtig anzugeben.&lt;br /&gt;
&lt;br /&gt;
Die Verbrauchswerte werden stundengenau erfasst und im Datenspeicher &#039;&#039;pvHistory&#039;&#039; für 31 Tage, sowie im Datenspeicher &#039;&#039;pvCircular&#039;&#039; 210 Tage gespeichert. Die beiden Datenspeicher übernehmen unterschiedliche Aufgaben im Rahmen der Prognoseerstellung. Auf Grundlage der gespeicherten und somit historischen Verbrauchswerte erstellt das Modul eine Prognose für die kommende Zeit.&lt;br /&gt;
&lt;br /&gt;
Mit dem Kommando &lt;br /&gt;
&lt;br /&gt;
   &amp;quot;get ... pvHistory [Tag]&amp;quot; &lt;br /&gt;
&lt;br /&gt;
wird der Inhalt aufgelistet. Die Schlüssel &#039;&#039;confc&#039;&#039;, &#039;&#039;con&#039;&#039; und &#039;&#039;gcon&#039;&#039; zeigen die Verbrauchsprognose, den Verbrauch und den Netzbezug der jeweiligen Stunde des gewählten Tages.&lt;br /&gt;
Die Stunde &amp;quot;99&amp;quot; zeigt die Summen dieser Schlüsssel für den Tag:&lt;br /&gt;
&lt;br /&gt;
      99 =&amp;gt; etotal: , pvfc: 782, pvrl: 0, rad1h: -&lt;br /&gt;
            confc: 14540, con: 13873, gcon: 13873, gfeedin: 0&lt;br /&gt;
            batintotal: , batin: 0, batouttotal: , batout: 0&lt;br /&gt;
            batmaxsoc: -, batsetsoc: -&lt;br /&gt;
            wid: , wcc: , wrp: , pvcorrf: , dayname: So&lt;br /&gt;
            cyclescsm01: 0&lt;br /&gt;
            cyclescsm02: 0&lt;br /&gt;
            cyclescsm03: 0&lt;br /&gt;
            cyclescsm04: 1, hourscsme04: 0.00&lt;br /&gt;
            cyclescsm05: 0&lt;br /&gt;
            cyclescsm06: 0&lt;br /&gt;
            cyclescsm07: 1, hourscsme07: 0.00&lt;br /&gt;
            cyclescsm08: 1, hourscsme08: 0.00&lt;br /&gt;
            cyclescsm09: 1, hourscsme09: 0.03 &lt;br /&gt;
&lt;br /&gt;
In dem Beispiel wurden für den Tag 14540 Wh Verbrauch prognostiziert, 13873 Wh tatsächlich verbraucht und davon 13873 Wh aus dem Netz bezogen. Leider war an diesem Tag keinerlei PV Ertrag vorhanden, was man auch an dem Schlüssel &#039;&#039;pvrl&#039;&#039; erkennen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Inhalt des pvCircular-Speichers kann mit dem Befehl  &lt;br /&gt;
&lt;br /&gt;
     &amp;quot;get ... pvCircular [Tag]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Das nachfolgende Beispiel zeigt die Ausgabe für die Tagesstunde 23:&lt;br /&gt;
&lt;br /&gt;
 23 =&amp;gt; pvapifc: 0, pvaifc: -, pvfc: 0, aihit: 0, pvrl: 0&lt;br /&gt;
       batin01: 0, batin02: -, batin03: -&lt;br /&gt;
       batout01: 619, batout02: -, batout03: -&lt;br /&gt;
       confc: 650, gcon: 23, gfeedin: 0, wcc: 40, rr1c: 0.00&lt;br /&gt;
       temp: -6.00, wid: 100, wtxt: Bewölkungsentwicklung nicht beobachtet&lt;br /&gt;
       pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
       ... &lt;br /&gt;
       con_all =&amp;gt; Sa  @ 617 762&lt;br /&gt;
                  Di  @ 693 645&lt;br /&gt;
                  Mo  @ 620 679&lt;br /&gt;
                  So  @ 669 666 636&lt;br /&gt;
                  Mi  @ 701 626&lt;br /&gt;
                  Do  @ 612 642&lt;br /&gt;
                  Fr  @ 615 606&lt;br /&gt;
&lt;br /&gt;
Der Schüssel &#039;&#039;con_all&#039;&#039; enthält einen Hash aus Arrays die für jeden Wochentag (Mo..So) bis zu 30 Verbrauchswerte (in Wh) für die angezeigte Stunde speichern. Wie hier erkennbar ist, wurden an den drei vergangenen Sonntagen jweils 669 Wh, 666 Wh bzw. 636 Wh in der Stunde 23 (22:00-22:59) verbraucht.&lt;br /&gt;
Der Median aus diesen Werten geht in die Verbrauchsprognose ein. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wochentagsnamen Mo..So sind von den installierten Locales auf Betriebsystemebene abhängig. Ist keine deutsche locale installiert, werden die englischen Wochentagsnamen Mon..Sun verwendet. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Wie wird der Verbrauch des Hauses ermittelt und gespeichert? ===&lt;br /&gt;
Die Verbrauchsdaten des Hauses werden auf Stundenbasis ermittelt und gespeichert. Das &amp;quot;Haus&amp;quot; steht als Synonym aller im Kontext des Solarforecast Devices zusammengeführten Inverter (setupInverterDevXX), sonstigen Erzeuger (setupOtherProducerXX), Netzanschlüsse (setupMeterDev), Verbraucher (consumerXX) und Batterien (setupBatteryDev).&lt;br /&gt;
&lt;br /&gt;
Alle diese Daten werden durch das Modul mit jedem ausgeführten Zyklus (Attribut plantControl-&amp;gt;cycleInterval) und, wenn ein Event eines als &#039;asynchron&#039; definierten Devices auftritt, gesammelt und daraus permanent ein aktualisierter Verbrauch berechnet. Die Berechnung beschreibt folgende Formel:&lt;br /&gt;
&lt;br /&gt;
 PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung - Verbrauch = 0&lt;br /&gt;
&lt;br /&gt;
bzw.&lt;br /&gt;
 &lt;br /&gt;
 Verbrauch (Wh) = PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung&lt;br /&gt;
            con = PV           + PP                 - GridIn          + GridCon   - BatIn          + BatOut&lt;br /&gt;
&lt;br /&gt;
Die PV-Erzeugung beinhaltet die Summe aller durch die angegebnen Inverter (setupInverterDev01 .. setupInverterDevXX) erzeugten Energien. Die &amp;quot;sonstige Erzeugung&amp;quot; summiert sich aus den Werten aller angegebenen Producer (setupOtherProducer01 .. setupOtherProducerXX). Der Verbrauch wird durch die registrierten Geräte consumerXX teilweise direkt erfasst, ist aber grundsätzlich unvollständig da nicht alle Verbrauchswerte im &amp;quot;Haus&amp;quot; gemessen und durch das Modul erfasst werden können.&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel zeigt das Ergebnis bei 300 Wh PV-Erzeugung und gleichzeitige 500 Wh Netzbezug:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 300 + 0 - 0 + 500 - 0 + 0 = 800 Wh&lt;br /&gt;
&lt;br /&gt;
Bei 1300Wh PV-Erzeugung, 100 Wh Netzeinspeisung sowie 200 Wh Batterieladung ergibt sich der Verbrauch zu:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 1300 + 0 - 100 + 0 - 200 + 0 = 1000 Wh&lt;br /&gt;
&lt;br /&gt;
Ohne Erzeugung, aber mit der Energielieferung von 500 Wh aus der Batterie, 800 Wh Netzbezug (mit einem Anteil Batterienachladung aus dem Netz von 200 Wh) sieht die Verbrauchsrechnung wie folgt aus: &lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 0 + 0 - 0 + 800 - 200 + 500 = 1100 Wh&lt;br /&gt;
&lt;br /&gt;
Der so ermittelte Verbrauchsert wird mit jedem Zyklus in der pvHistory im Schlüssel &amp;quot;con&amp;quot; gespeichert. Man kann sich die gespeicherten Werte mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;name&amp;gt; pvHistory [&amp;lt;Tag&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Nachfolgendes Beispiel zeigt einen Datensatz für die Stunde 8 eines Tages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      08 =&amp;gt; pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotali01: 62940734, etotali02: 2928860, etotali03: -&lt;br /&gt;
            pvrl01: 0, pvrl02: 0, pvrl03: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 630, con: 962, gcons: 962, conprice: 0.2958&lt;br /&gt;
            gfeedin: 0, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 120, sunalt: -3&lt;br /&gt;
            batintotal: 3713815.07742543, batouttotal: 3604468.26993988, batin: 0, batout: 0&lt;br /&gt;
            wid: 161, wcc: 89, rr1c: 0.00, pvcorrf: 0.27/0.00 temp: 7.40, &lt;br /&gt;
            csmt01: 110996.12, csme01: 32.1399999999994, minutescsm01: 30&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 2513.67, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1581293.6, csme04: 136.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 1662.17, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 90.53, csme06: 0, minutescsm06: 0&lt;br /&gt;
            csmt07: 39.75, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 38050, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 131627, csme09: 33.2000000000116, minutescsm09: 39&lt;br /&gt;
            minutescsm10: 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Schlüssel &amp;quot;con&amp;quot; ist der gespeicherte Verbrauch von 962 Wh ersichtlich.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit bekommt man mit dem Attribut &#039;&#039;ctrlDebug=collectData&#039;&#039; einen Einblick in die Verbrauchsermittlung bei jedem Zyklus und kann so die Eingangswerte und das daraus resultierende Ergebnis im FHEM Log nachverfolgen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
2024.11.28 11:38:20.080 1: SolCast DEBUG&amp;gt; EnergyConsumption input -&amp;gt; PV: 96, PP: 0, GridIn: 0, GridCon: 582, BatIn: 5, BatOut: 0&lt;br /&gt;
2024.11.28 11:38:20.081 1: SolCast DEBUG&amp;gt; EnergyConsumption result -&amp;gt; 673 Wh&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie wird die Verbrauchsprognose erstellt? ===&lt;br /&gt;
&lt;br /&gt;
Aus den gespeicherten con-Werten (Verbrauchsdaten) der pvCircular (Schlüssel con_all) sowie Einträgen der pvHistory wird der Median der historischen Tage ermittelt und für den kommenden Tag bzw. die kommen Stunden zur Prognose angewendet. Dabei geht per default jeder verfügbare historische Tag gleichberechtigt in die Prognose ein. Mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039; kann festgelegt werden, dass nur gleiche Wochentage (Mo..So) für die Prognose verwendet werden. Hierbei spielt die Vermutung, dass das Verbrauchsverhalten eine gewisse Korrelation zum Wochentag hat, eine Rolle. &lt;br /&gt;
&lt;br /&gt;
Verwendet man die Einstellung consForecastIdentWeekdays=1, hat es sich als vorteilhaft erwiesen, das Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays&#039;&#039;&#039; auf einen niedrigeren Wert als den Default zu setzen. Eine Einstellung auf &#039;8&#039; zum Beispiel verwendet den Median der gleichen Wochentage der vergangenenen 8 Wochen. Dadurch wird nicht zu weit in die Vergangenheit verzweigt und so eine langsame Veränderung des Verbrauchsmedian, zum Beispiel hervorgerufen durch den Übergang vom Winter in das Frühjahr hinein, abgebildet.&lt;br /&gt;
&lt;br /&gt;
Weiteren Einfluß auf die Verbrauchsprognose kann mit dem Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; im Consumerattribut genommen werden. Insbesondere bei der unregelmäßigen Nutzung von Verbrauchern mit hoher Leistung kann die Projektion der aufgezeichneten historischen Werte in die Prognose zu unverhältnismäßig hohen Verbrauchswerwartunden führen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Möglicherweise führt in Fällen die Verwendung eine der nachfolgenden Optionen zu einem besseren Ergebnis:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;1 -&#039;&#039;&#039; die allgemeine Verbrauchsprognose wird um die gespeicherten Energieverbrauchsanteile reduziert.&lt;br /&gt;
* &#039;&#039;&#039;2 -&#039;&#039;&#039; wie bei &#039;1&#039;, jedoch gehen die Planungsdaten des Verbrauchers bei der Prognose der kommenden Stunden wieder mit ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;&#039;exconfc&#039;&#039;&#039; in einem der Consumer verwendet, sollte&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays=4&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
eingestellt werden. Hintergrund ist, dass die Verbrauchsanteile der jeweiligen Verbraucher nur maximal 31 Tage in der pvHistory verfügbar sind. Für längere Zeiträume stehen nur Gesamtsummen des Verbrauchs in der pvCircular zu Verfügung.  &lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=1&#039;&#039;&#039; werden die in der Historie aufgezeichneten Verbrauchsbestandteile aus einer Prognose herausgerechnet. Konkret werden die in der pvHistory aufgezeichneten Verbrauchsbestandteile für die relevante Stunde ermittelt und daraus ein Durchschnitt gebildet der vom Prognosewert subtrahiert wird. Mit dem Attributwert plantControl-&amp;gt;consForecastIdentWeekdays=1 werden wiederum nur identische Wochentage (Mo .. So) zusammengefasst.&lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=2&#039;&#039;&#039; erfolgt ebenso die Eliminierung des Verbrauchsanteils, es wird jedoch auf die Planungsdaten für diesen Verbraucher zugegriffen und die geplanten Energieanteile wiederum der Verbrauchsprognose für die kommenden Stunden hinzugerechnet.&lt;br /&gt;
&lt;br /&gt;
In beiden Anwendungsfällen ist es notwendig, dass dem Modul durch die Angabe entsprechender Readings der Energieverbrauch im Setup des Consumers bekannt gemacht wird damit diese Energieanteile registriert werden können. Allgemein funktioniert die Verbrauchsprognose gut wenn Verbrauchsprozesse regelmäßig in einem wiederkehrenden Zeitraster ablaufen, der Verbrauch durch persönliche Rituale bestimmt ist. So zum Beispiel könnte am Dienstag und Samstag gewöhnlich die Waschmaschine laufen, das E-Auto täglich aufgeladen werden und gebügelt wird oft am Sonntag Nachmittag.&lt;br /&gt;
&lt;br /&gt;
Unregelmäßige Nutzung, vor allem vom Großverbrauchern, lässt sich nur sehr schwer und ungenügend auf zukünftige Verbrauchsprognosen projizieren.&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis der Prognose wird im Kopf der Grafik in der Zeile &#039;&#039;Verbrauch&#039;&#039; sowie in diversen Readings wie &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RestOfDayConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den Rest des Tages)&lt;br /&gt;
* &#039;&#039;&#039;NextHours_Sum04_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für die nächsten 4 Stunden)&lt;br /&gt;
* &#039;&#039;&#039;Tomorrow_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den kommenden Tag)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
angezeigt.&lt;br /&gt;
&lt;br /&gt;
Weitere Aggregationen kann man sich über das Attribut &#039;&#039;&#039;ctrlStatisticReadings&#039;&#039;&#039; bei Bedarf zuschalten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;conForecastTillNextSunrise&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
* &#039;&#039;&#039;todayConForecastTillSunset&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
* &#039;&#039;&#039;todayConsumptionForecast&#039;&#039;&#039; - Verbrauchsprognose aufgesplittet pro Stunde des aktuellen Tages (01-24) &lt;br /&gt;
 &lt;br /&gt;
==== Debugging der Verbrauchsprognose ====&lt;br /&gt;
Um sich einen Einblick über die Erstellung der Verbrauchsprognose zu verschaffen, bietet sich die Einschaltung von:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
an. Mit diesem gesetzten Attribut wird die Erstellung der Prognose im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; ################### Start Consumption forecast ###################&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; Basics - installed locale: de_DE.UTF-8, used scheme: DE&lt;br /&gt;
2025.02.27 19:52:00.064 1: SolCast DEBUG&amp;gt; process Today dayname: Do, Tomorrow dayname: Fr&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 01 - 74.43 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 10 - 290.77 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 24 - 660.70 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 20, hod: 07 - 459.93 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;07&#039; register for exclude day 20, hod: 02 - 0.33 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 30, hod: 08 - 264.78 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next Hours (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; excl. hist 74 Wh for Hour 01, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; estimated cons of Hour 01: 436 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; excl. hist 0 Wh for Hour 02, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 02: 428 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 03: 458 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 04: 503 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 05: 489 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 06: 482 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; excl. hist 460 Wh for Hour 07, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 07: 274 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 265 Wh for Hour 08, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 08: 441 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 09: 558 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 291 Wh for Hour 10, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 10: 443 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 11: 881 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 12: 794 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 13: 840 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 14: 660 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 15: 812 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 16: 752 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 17: 597 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 18: 652 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 19: 634 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 20: 628 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 21: 713 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 22: 596 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 23: 629 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; excl. hist 661 Wh for Hour 24, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons of Hour 24: 660 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons Tomorrow: 16848 Wh, Individual hourly values considered: 72, exclude: 0 Wh (avg of 0 entities)&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Store Consumption forecast values (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour00&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;20&#039; confc: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour01&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;21&#039; confc: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour02&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;22&#039; confc: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour03&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;23&#039; confc: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store &#039;NextHour04&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;24&#039; confc: 660&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour05&#039; hod &#039;01&#039; confc: 436, confcEx: 436&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour06&#039; hod &#039;02&#039; confc: 428, confcEx: 428&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour07&#039; hod &#039;03&#039; confc: 458, confcEx: 458&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour08&#039; hod &#039;04&#039; confc: 503, confcEx: 503&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour09&#039; hod &#039;05&#039; confc: 489, confcEx: 489&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour10&#039; hod &#039;06&#039; confc: 482, confcEx: 482&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour11&#039; hod &#039;07&#039; confc: 274, confcEx: 274&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour12&#039; hod &#039;08&#039; confc: 441, confcEx: 441&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour13&#039; hod &#039;09&#039; confc: 558, confcEx: 558&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour14&#039; hod &#039;10&#039; confc: 443, confcEx: 443&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour15&#039; hod &#039;11&#039; confc: 881, confcEx: 881&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour16&#039; hod &#039;12&#039; confc: 794, confcEx: 794&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour17&#039; hod &#039;13&#039; confc: 840, confcEx: 840&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour18&#039; hod &#039;14&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour19&#039; hod &#039;15&#039; confc: 812, confcEx: 812&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour20&#039; hod &#039;16&#039; confc: 752, confcEx: 752&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour21&#039; hod &#039;17&#039; confc: 597, confcEx: 597&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour22&#039; hod &#039;18&#039; confc: 652, confcEx: 652&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour23&#039; hod &#039;19&#039; confc: 634, confcEx: 634&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour24&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour25&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour26&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour27&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour28&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; consumption calculated - day: 27, hod: 20, con: 574 Wh&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; write pvCircular consumption - hod: 99, todayConsumption: 11210 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe startet mit &#039;&#039;&amp;quot;Start Consumption forecast&#039;&#039;&amp;quot;, es werden die zu exkludierenden historischen Daten für jeden Consumer bzgl. jedem Tag (day) und Stunde des Tages (hod) getrennt registriert. Diese Werte werden durch die gespeicherte Einträge in der pvHistory (max. 31 historische Tage) geliefert. &lt;br /&gt;
&lt;br /&gt;
Im nächsten Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next Hours (new median)&amp;quot;&#039;&#039; werden die Prognosen für die nächsten Stunden kalkuliert und die zuvor registrierten Excludes angewendet. Die Prognose für den kommenden Tag ist im Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next day (new median)&amp;quot;&#039;&#039; protokolliert. Die Prognose für den kommenden Tag ist nicht einfach die Summe der Prognose der nächsten Stunden, denn in den kommenden Stunden werden auch die verfügbaren Planungen der Consumer einbezogen. Für den kommenden Tag können diese Werte unter Umständen nicht einbezogen werden da sie zum Zeitpunkt X noch nicht verfügbar sind.&lt;br /&gt;
&lt;br /&gt;
Im Abschnitt &#039;&#039;&amp;quot;Store Consumption forecast values (new median)&amp;quot;&#039;&#039; erscheinen die effektiv gespeicherten Werte. Diese sind die Grandlage für die grafische Darstellung sowie weiteren Kalkulationen.&lt;br /&gt;
&lt;br /&gt;
=== Wie kann eine fehlerhafte Verbrauchsprognose korrigiert werden? ===&lt;br /&gt;
Wie im vorherigen Abschnitt beschrieben, wird die Prognose aus den gespeicherten &amp;quot;con&amp;quot;-Werten der vergangenen Tage (bzw. Stunden) abgeleitet. &lt;br /&gt;
Grundsätzlich muß zunächst sichergestellt werden, dass die auszulesenden Readings der angegebenen Energiezähler sowie deren Einheiten! korrekt eingestellt sind. Das gilt ebenfalls für die registrierten Verbraucher im Modul.&lt;br /&gt;
&lt;br /&gt;
Für einen ersten Überblick bietet sich das Debug Attribut an zu setzen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
Beispielausgabe des Debug:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2024.09.21 13:28:27.041 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day ###################&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;01&amp;lt; considering possible exclusions: 14082&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;08&amp;lt; considering possible exclusions: 16446&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;15&amp;lt; considering possible exclusions: 14568&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;25&amp;lt; considering possible exclusions: 15522&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; estimated Consumption for tomorrow: 15154, days for avg: 4&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next hours ###################&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 14 -&amp;gt; 850 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 14 -&amp;gt; 643 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 14 -&amp;gt; 590 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 14 -&amp;gt; 522 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 13:00:00, confc: 651, days for avg: 4, hist. consumption registered consumers: 560.97&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 15 -&amp;gt; 720 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 15 -&amp;gt; 743 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 15 -&amp;gt; 897 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 15 -&amp;gt; 557 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 14:00:00, confc: 729, days for avg: 4, hist. consumption registered consumers: 620.97&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 16 -&amp;gt; 676 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 16 -&amp;gt; 790 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 16 -&amp;gt; 785 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 16 -&amp;gt; 581 Wh&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 15:00:00, confc: 708, days for avg: 4, hist. consumption registered consumers: 647.29&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 17 -&amp;gt; 622 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 17 -&amp;gt; 639 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 17 -&amp;gt; 646 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 17 -&amp;gt; 572 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 16:00:00, confc: 619, days for avg: 4, hist. consumption registered consumers: 618.30&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 18 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 18 -&amp;gt; 614 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 18 -&amp;gt; 580 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 18 -&amp;gt; 480 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 17:00:00, confc: 567, days for avg: 4, hist. consumption registered consumers: 583.41&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 19 -&amp;gt; 615 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 19 -&amp;gt; 1659 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 19 -&amp;gt; 597 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 19 -&amp;gt; 618 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 18:00:00, confc: 872, days for avg: 4, hist. consumption registered consumers: 636.97&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 20 -&amp;gt; 611 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 20 -&amp;gt; 1124 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 20 -&amp;gt; 546 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 20 -&amp;gt; 479 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 19:00:00, confc: 690, days for avg: 4, hist. consumption registered consumers: 578.87&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 21 -&amp;gt; 1474 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 21 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 21 -&amp;gt; 619 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 21 -&amp;gt; 433 Wh&lt;br /&gt;
2024.09.21 13:28:27.058 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Im ersten Teil wird die erwartete Consumption für den nächsten Tag unter Berücksichtigung möglicher Ausschlüsse von Verbrauchern ausgegeben. Ausschlüsse von Verbrauchern ergeben sich wenn in dem Verbraucherattribut der Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; gesetzt ist. Er besagt, dass die Verbrauchswerte des Verbrauchers in eine zukünftige Prognose nicht eingehen sollen. Zum Beispiel wenn ein Verbraucher mit sehr hohen Verbrauchswerten nur sporadisch eingesetzt wird und dadurch die Prognose stark verfälschen würde. Es ist auch zu sehen, dass bedingt durch das Attribut &#039;&#039;&#039;affectConsForecastIdentWeekdays = 1&#039;&#039;&#039; nur die historischen Tage 01, 08, 15 und 25 berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Teil wird die berechnete Erwartung für die nächsten Stunden ausgegeben. &lt;br /&gt;
Zur Beschreibung der Fehlersuche gehen wir davon aus, dass die Prognose von 780 Wh am 2024-09-21 20:00:00 zu hoch erscheint weil am Tag &amp;quot;07&amp;quot; ein Wert von 1474 Wh gespeichert ist:&lt;br /&gt;
&lt;br /&gt;
 SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt geben wir die historischen Werte für den Tag 07 aus:&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;Name&amp;gt; pvHistory 07&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz interessiert die Stunde 21. Sie resultiert aus der obigen Angabe &amp;quot;starttime: xxxx-xx-xx 20:00:00&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      21 =&amp;gt; etotal: 64354660, pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 496, con: 1474, gcons: 23, conprice: 0.2958&lt;br /&gt;
            gfeedin: 5, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 289, sunalt: -8&lt;br /&gt;
            batintotal: 3064096.92456668, batouttotal: 2958021.37946804, batin: 0, batout: 1460&lt;br /&gt;
            wid: 101, wcc: 20, rr1c: 0.00, pvcorrf: 1.00/-temp: 26.00, &lt;br /&gt;
            csmt01: 64262.43, csme01: 28.8099999999977, minutescsm01: 25&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 0, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1389417.4, csme04: 94.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 0, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 290.15, csme06: 6.66999999999996, minutescsm06: 54&lt;br /&gt;
            csmt07: 0, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 32800, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 103987.8, csme09: 38, minutescsm09: 43&lt;br /&gt;
            csmt10: 9151.24999999783, csme10: 3.99999999997999, minutescsm10: 60&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz sind die Energieverbrauchsanteile der im Device registrierten Verbraucher mit dem Schlüssel &amp;quot;csmeXX&amp;quot; gespeichert. Dabei ist &amp;quot;XX&amp;quot; die Verbrauchernummer. In dem Beispiel existieren die Anteile csme01 und csme03 - csme10. Keiner dieser Verbraucher hat einen auffälligen Verbrauchswert gespeichert, d.h. die Messung der Verbraucher scheidet als Problemquelle aus. Wäre ein unverhältmismäßig hoher Verbrauch bei einem der Verbraucher feststellbar, müssten die Schlüssel &#039;&#039;&#039;pcurr&#039;&#039;&#039; und &#039;&#039;&#039;etotal&#039;&#039;&#039; im consumerXX-Attribut geprüft, sowie die Datenlieferung des Consumerdevices selbst geprüft werden.  &lt;br /&gt;
&lt;br /&gt;
Es wurde offensichtlich ein hoher Verbrauch von einem nicht registrierten Verbraucher verursacht oder durch die Übertragung eines Meßfehlers des Devices, angegeben im Attribut &#039;&#039;&#039;setupMeterDev&#039;&#039;&#039;, in das SolarForecast Device übertragen. Eine weitere Analyse ist an dieser Stelle nicht möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Behebung des falschen Wertes kann ein Reset der gespeicherten Consumption der relevanten Stunde durchgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; reset consumptionHistory 07 21&lt;br /&gt;
&lt;br /&gt;
== Modulinterne Datenstrukturen ==&lt;br /&gt;
Das Modul speichert die verschiedenen historischen und aktuellen Daten wie PV-Prognose, Witterungsdaten (Regen, Bewölkung), Strahlungsdaten, Einspeisung, Bezug, reale Erzeugungsdaten und vieles mehr zur Laufzeit im Arbeitsspeicher. Dadurch ist die Verarbeitung dieser Daten im Vergleich zu Lesevorgängen aus dem Filesystem bzw. einer Datenbank sehr performant. Allerdings würden diese Daten bei einem FHEM Absturz bzw. bei einem regulären Shutdown verlorengehen.&lt;br /&gt;
&lt;br /&gt;
Deswegen werden die relevanten Daten regelmäßig in Dateien gesichert und bei Bedarf wiederhergestellt. Diese Dateien befinden sich im Verzeichnis &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; und heißen &#039;&#039;&#039;.*_SolarForecast_.*&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Die Daten werden in jedem Zyklus der Zentralschleife (CentralTask) gesammelt bzw. berechnet. Der Zyklus wird mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;cycleInterval&#039;&#039;&#039; eingestellt.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit können diese Daten über get-Kommandos abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvHistory [Tag]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der pvHistory Datenspeicher enthält die vergangenen Kennwerte der letzten 31 Tage mit einer Genauigkeit von einer Stunde. Es werden die Prognosewerte für Erzeugung und Verbrauch, die realen Werte für Erzeugung und Verbrauch sowie ebenso die Laufzeiten jedes einzelnen Verbrauchers (Consumer) festgehalten. Für jeden Tag gibt es die Stunde &amp;quot;99&amp;quot; die eine Summierung der Stundenwerte des Tages bzw. Sonderschlüssel enthält.&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf lässt sich mit dem Befehl &amp;quot;set ... reset pvHistory&amp;quot; der gesamte Inhalt des Speichers löschen (nicht empfohlen). Selektiver funktioniert die Datenlöschung mit &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt;&amp;quot; (Daten eines bestimmten Tages löschen) bzw. &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt; &amp;lt;Stunde&amp;gt;&amp;quot; (Daten der Stunde  eines bestimmten Tages löschen). Die letzten beiden Kommandos müssen über die Kommandozeile im Browser ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvCircular &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Ringspeicher enthält Daten der letzten 24 Stunden sowie fortwährend berechnete Werte wie Korrekturfaktoren der PV-Erzeugung und Prognosequalität.&lt;br /&gt;
Neue Stundenwerte des Tages überschreiben die gespeicherten Schüssel des vorangegangenen Tages sofern es sich nicht um fortwährend berechnete Werte handelt. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... nextHours&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Speicher enthält sämtliche Prognosewerte der kommenden Stunden beginnend mit der aktuellen Stunde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... radiationApiData&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Abhängig von der ausgewählten Strahlungsdaten API enthält dieser Speicher die von der API gelieferten Rohdaten sowie evtl. weitere für die Funktion benötigte Daten wie API-Keys, Response Messages, Anzahl der API Abruf und weitere.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valCurrent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Struktur wird nicht regelmäßig im Filesystem gespeichert und enthält immer aktuell gesammelte oder berechnete/gelieferte Daten wie z.B. die Autarkierate, letze Laufzeit der Zentralschleife (CentralTask), Zeit des Sonnenauf- und untergangs sowie weitere Betriebsdaten. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valConsumerMaster [XX]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zeigt die Daten der aktuell im SolarForecast Device registrierten Verbraucher. Mit der Nummer &#039;&#039;&#039;XX&#039;&#039;&#039; kann ein bestimmter Verbraucher angesprungen werden. Die Nummer korrespondiert mit dem entsprechenden &#039;&#039;&#039;consumerXX&#039;&#039;&#039; Attribut.&lt;br /&gt;
Neben anderen Betriebs- und Energiedaten werden insbesondere folgende Daten ermittelt, die für die zukünftige Planung der Verbraucherschaltzeiten relevant sind:&lt;br /&gt;
&lt;br /&gt;
* epieces - prognostizierte Energiescheiben pro Betriebsstunde &lt;br /&gt;
&lt;br /&gt;
Ausgehend von gespeicherten historischen Verbrauchsdaten des Verbrauchers wird der Energieverbrauch des Verbrauchers in seiner ersten Betriebsstunde prognostiziert, was insbesondere für die Planung der optimalen Startzeit des Verbrauchers in Bezug zu der prognostizierten PV Energie und den Verbrauchswerten weiterer vorhandener bzw. zu planender Verbraucher Berücksichtigung findet. Weitere Informationen zur Verbrauchersteuerung in diesem  [[#Verbrauchersteuerung_-_Registrieren_und_visualisieren_von_Verbrauchern|Abschnitt]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Schnittstelle für Modulautoren bzw. eigenen Code ===&lt;br /&gt;
&lt;br /&gt;
Die im vorherigen Artikel beschriebenen internen Datenstrukturen können durch externen Code abgefragt und ausgewertet werden.&lt;br /&gt;
Dazu stehen die folgenden Funktionen zur Verfügung. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]BatteryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Bn&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valBattery&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CurrentVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valCurrent&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]InverterVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valInverter&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ProducerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valProducer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]HistoryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Day&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvHistory&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CircularVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvCircular&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]NexthoursVal (&#039;&amp;lt;Name&amp;gt;&#039;, &amp;lt;nhr&amp;gt;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... nextHours&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ConsumerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valConsumerMaster&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]RadiationAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;DateTime&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... radiationApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]WeatherAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;TimeCode&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... weatherApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StatusAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;QTag&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... statusApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StringVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valStrings&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Angabe des Packages (FHEM::SolarForecast::) ist nur notwendig wenn die Funktionen von außerhalb des SolarForecast-Devices aufgerufen werden. Innerhalb des Devices (Code-Ausführung im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039;) kann darauf verzichtet werden.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der Platzhalter sind:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     &amp;lt;Name&amp;gt;     - Name des SolarForecast Devices&lt;br /&gt;
     &amp;lt;Day&amp;gt;      - abzufragender Tag (01 - 31)&lt;br /&gt;
     &amp;lt;Bn&amp;gt;       - Batterie Nummer (01, 02, ...)&lt;br /&gt;
     &amp;lt;DateTime&amp;gt; - Startzeit der Form YYYY-MM-DD hh:00:00&lt;br /&gt;
     &amp;lt;TimeCode&amp;gt; - Zeitwert der Form fcX_XX (z.B. fc1_19)&lt;br /&gt;
     &amp;lt;APIname&amp;gt;  - Hauptname der API gemäß setupWeatherDev1 (z.B. OpenMeteo)&lt;br /&gt;
     &amp;lt;String&amp;gt;   - Name des PV-Modulstrings wie im Attribut &#039;setupInverterStrings&#039;&lt;br /&gt;
     &amp;lt;QTag&amp;gt;     - Question Tag, z.B. &#039;?All&#039;&lt;br /&gt;
     &amp;lt;Nr&amp;gt;       - laufende Nummer des Verbrauchers / Gerätes (01, 02, 03, 04,...)&lt;br /&gt;
     &amp;lt;HoD&amp;gt;      - abzufragende Stunde (01 - 24, 99)&lt;br /&gt;
     &amp;lt;nhr&amp;gt;      - nächste Stunde (NextHour00, NextHour01,...)&lt;br /&gt;
     &amp;lt;Key&amp;gt;      - der abzufragende Schlüssel &lt;br /&gt;
     &amp;lt;default&amp;gt;  - def default-Rückgabewert&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Beispiel Auslesen der Batterieladestrategie und Anlegen eines Readings ====&lt;br /&gt;
&lt;br /&gt;
Als Praxisbeispiel soll die aktuelle gesetzte Ladestrategie für Batterie &amp;quot;01&amp;quot; ausgelesen und mit dem Wert ein Reading im SolarForecast Device angelegt werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Dazu wird der folgende Code im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; hinterlegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  my $wert = NexthoursVal ($name, &#039;NextHour00&#039;, &#039;strategybat01&#039;, &#039;loadRelease&#039;);&lt;br /&gt;
  storeReading (&#039;Ladestrategie&#039;, $wert);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei jedem Zyklus des SF-Devices wird der aktuelle Wert von &#039;&#039;strategybat01&#039;&#039; gelesen und im Reading &#039;&#039;Ladestrategie&#039;&#039; gespeichert. Die Paket-Definition &#039;&#039;FHEM::SolarForecast::&#039;&#039; braucht nicht verwendet werden, da der Aufruf im Attribut ctrlUserExitFn innerhalb des SolarForecast-Paketes erfolgt.&lt;br /&gt;
&lt;br /&gt;
Für andere Batterienummern ist der NexthoursVal-Schlüssel &#039;&#039;strategybat01&#039;&#039; entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Auswerten von internen Arrays ===&lt;br /&gt;
&lt;br /&gt;
Die meisten der internen Datenstrukturen liefern bei der Abfrage einen einfachen String oder numerischen Wert der ausgewertet werden kann. Es gibt allerdings auch intern gespeicherte Wertelisten. Werden die Listenstrukturen mit den oben beschriebenen Befehlen abgefragt, wird eine Referenz auf die Liste geliefert sofern sie vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
Um auf die Werte einer solchen Liste zuzugreifen, ist am Beispiel des Arrays &#039;&#039;surplusslidereg&#039;&#039; aus dem Current-Speicher (get ... valCurrent) dargestellt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
my $splref = CurrentVal ($name, &#039;surplusslidereg&#039;, &#039;.&#039;);&lt;br /&gt;
my $spser  = ref $splref eq &#039;ARRAY&#039; ? join &#039; &#039;, @{$splref} : undef;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Variable $spser enthält bei Vorhandensein der Liste einen String, der die Listenelemente von &#039;surplusslidereg&#039; durch Leerzeichen getrennt enthält.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backup und Wiederherstellung der Moduldaten ==&lt;br /&gt;
Neben der Datenhaltung in den Attributen und Readings des SolarForecast Devices, erzeugt jedes SolarForecast Device Dateien im Verzeichnis  &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; mit folgenden Inhalten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PVH_SolarForecast_&amp;lt;name&amp;gt;        - PV History&lt;br /&gt;
PVC_SolarForecast_&amp;lt;name&amp;gt;        - PV Circular&lt;br /&gt;
PVCfg_SolarForecast_&amp;lt;name&amp;gt;      - PV Anlagenkonfiguration&lt;br /&gt;
PVCsm_SolarForecast_&amp;lt;name&amp;gt;      - Consumer Status&lt;br /&gt;
ScApi_SolarForecast_&amp;lt;name&amp;gt;      - Strahlungswerte aus verwendeter API&lt;br /&gt;
StatApi_SolarForecast_&amp;lt;name&amp;gt;    - Statusdaten der verwendeten API&#039;s&lt;br /&gt;
WeatherApi_SolarForecast_&amp;lt;name&amp;gt; - Wetterdaten der gewählten Wetter-API (außer DWD-Device)&lt;br /&gt;
AItra_SolarForecast_&amp;lt;name&amp;gt;      - KI Entscheidungsquelle (trainierte Daten)&lt;br /&gt;
AIraw_SolarForecast_&amp;lt;name&amp;gt;      - KI Input Daten = Raw Trainigsdaten&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nach Ausprägung und eingesetzten Features des SolarForecast Devices sind alle oder nur ein Teil dieser Dateien vorhanden. Dabei ist &#039;&#039;&#039;&amp;lt;name&amp;gt;&#039;&#039;&#039; der Name des SolarForecast Devices.&lt;br /&gt;
&lt;br /&gt;
Bei einem Filebackup des FHEM-Servers ist darauf zu achten, dass diese Dateien in dem Backup enthalten sind. Der Inhalt der Dateien ist nicht statisch, sondern kann sich dynamisch aktualisieren. Um im Bedarfsfall einen aktuellen Datenstand zu haben, ist mindestens ein tägliches Backup dieser Dateien empfehlenswert. Eventuell auch öfter mit Hilfe einer Versionierung welche z.B. immer die letzten 3 Versionen aufbewahrt.&lt;br /&gt;
&lt;br /&gt;
Beim Start von FHEM werden bestimmte Dateien automatisch gelesen und in das SolarForecast Device importiert. &lt;br /&gt;
Der Vorgang ist mit verbose=3 im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2023.10.02 09:57:07.967 3: SolCast6 - cached data &amp;quot;pvHistory&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.969 3: SolCast6 - cached data &amp;quot;pvCircular&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;consumerMaster&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;radiationApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;statusApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;weatherApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.974 3: SolCast6 - cached data &amp;quot;aiTrainedData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.976 3: SolCast6 - cached data &amp;quot;aiRawData&amp;quot; restored&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bestimmte Betriebsdaten, wie z.B. die witterungsabhängigen Korrekturfaktoren (circular) oder die KI-Daten (aitrained/airaw), bauen sich über die Zeit immer granularer auf und stellen einen wertvollen Datenbestand dar.&lt;br /&gt;
&lt;br /&gt;
Wird das SolarForecast Device gelöscht und anschließend wieder neu mit dem gleichen Namen definiert, können die bisher verfügbaren Daten sehr einfach wiederhergestellt werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices, d.h. ein einfaches &amp;quot;define &amp;lt;Name&amp;gt; SolarForecast&amp;quot;, und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. Anpassen der Dateieigentümer und Berechtigungen: chown fhem:dialout /opt/fhem/FHEM/FhemUtils/*,  chmod 774 /opt/fhem/FHEM/FhemUtils/*&lt;br /&gt;
* 5. starten von FHEM (bestimmte Daten werden automatisch importiert)&lt;br /&gt;
* 6. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
* 7. FHEM Konfiguration sichern und restarten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
Das zuvor beschriebene Verfahren kann auch angewendet werden um das SolarForcast Device von einer FHEM Installation in eine andere Installation umzuziehen. In diesem Fall ist aber besonders darauf zu achten, vorab alle in den SF-Attributen referenzierten Devices wie Inverter, Meter oder DWD-Devices mit den zutreffenden Namen in der neuen Installation anzulegen.&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Soll das neue SolarForecast Device mit einem anderen Namen oder weitere SolarForecast Devices erstellt werden, welche die Betriebsdaten des primären Devices verwenden sollen, ist wie folgt vorzugehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices, d.h. ein einfaches &amp;quot;define &amp;lt;Name&amp;gt; SolarForecast&amp;quot;, und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. umbenenen der Dateien, wobei &amp;lt;name&amp;gt; durch den Namen des neuen SolarForecast Devices ersetzt wird&lt;br /&gt;
* 5. Anpassen der Dateieigentümer und Berechtigungen: chown fhem:dialout /opt/fhem/FHEM/FhemUtils/*,  chmod 774 /opt/fhem/FHEM/FhemUtils/*&lt;br /&gt;
* 6. starten von FHEM (bestimmte Daten werden automatisch importiert)&lt;br /&gt;
* 7. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
* 8. FHEM Konfiguration sichern und restarten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn sich die SolarForecast Devices hinsichtlich ihres Models oder der integrierten Consumer unterscheiden, sind die Dateien &amp;quot;PVCsm_SolarForecast_&amp;lt;name&amp;gt; &amp;quot; , &amp;quot;ScApi_SolarForecast_&amp;lt;name&amp;gt;&amp;quot; von dem Verfahren auszuschließen.&lt;br /&gt;
&lt;br /&gt;
== Batterieintegration und -steuerung ==&lt;br /&gt;
&lt;br /&gt;
=== Wie eine Batterie eingebunden wird ===&lt;br /&gt;
Wie immer muß die Batterieanlage zunächst mit einem für die Batterie spezifischen FHEM-Device in FHEM definiert sein.&lt;br /&gt;
In diesem Device werden Readings erwartet die folgende Werte bereitstellen:&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieentladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die installierte Batteriekapazität liefert (&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; dieser Schlüssel ist für die Aktivierung des Batterie SOC-Managements und die grafische Anzeige des SOC wesentlich!)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Lade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Entlade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* Reading welches den aktuellen Ladezustand (SOC in Prozent) liefert (optional)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Batterie, bzw. das Batteriedevice wird mit dem Attribut &#039;&#039;&#039;setupBatteryDev&#039;&#039;&#039; im SolarForecast Device registriert. Die Syntax des Attributes ist in  der Online-Hilfe zum Attribut umfassend erläutert. &lt;br /&gt;
Auch wenn manche Readings optional sind, wird empfohlen alle Werte bereitzustellen um alle Batterie-Funktionen im Modul nutzen zu können. Durch die Weiterentwicklung des Moduls können optionale Readings später auch obligatorisch werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Visualisierung der Batterie in der Balkengrafik ====&lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;setupBatteryDevXX&#039;&#039;&#039; verfügt über den Schlüssel &#039;&#039;&#039;show&#039;&#039;&#039;, mit dem die Einblendung des bzw. der Batteriesymbole in den Ebenen der Balkengrafik gesteuert werden kann:&lt;br /&gt;
[[Datei:Screenshot 2025-02-23 192002.png|right|thumb|400px|Einblendung der Batterieleiste und Darstellung des Batterie-SoC als Balkencontent in der zweiten Ebene]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 0 - keine Anzeige des Gerätes (default)&lt;br /&gt;
* 1 - Anzeige des Gerätes in der Balkengrafik Ebene 1&lt;br /&gt;
* 2 - Anzeige des Gerätes in der Balkengrafik Ebene 2 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Symbole und die Farbgebung der Batterie(n) können mittels des Schlüssels &#039;&#039;&#039;icon&#039;&#039;&#039; verändert werden. Die Online-Hilfe gibt weitere Informationen zur Ausgestaltung. &lt;br /&gt;
&lt;br /&gt;
In der Batteriedarstellung wird das Symbol der aktuellen Stunde hervorgehoben. Ein Mouse-Over zeigt wesentliche Betriebszustände der Batterie. Die Batteriesymbole vergangener Stunden zeigen mit einem Mouse-Over die erreichten SoC (State of Charge) Stände. Die kommenden Stunden visualisieren die folgenden Prognosen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der prognostizierte SoC unter Berücksichtigung der PV-Prognose und der [[#Aktivierung_des_Batterie_SOC-Managements|Batteriesteuerung]] sofern sie im Modul aktiviert ist.&lt;br /&gt;
* eine Freigabe bzw. Empfehlung der Batterieladung zur [[#Unterstützung_eines_netzdienlichen_Verhaltens|Unterstützung eines netzdienlichen Verhaltens]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Neben der Einblendung der Batterieleiste über der Balkengrafik selbst können bestimmte Batteriekennwerte als Balkeninhalt dargestellt werden. Die Auswahl erfolgt über das Attribut &#039;&#039;&#039;graphicBeamXContent&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Aktivierung des Batterie SOC- und Lade-Managements ===&lt;br /&gt;
Das integrierte SOC- und Lade-Management verfolgt insbesondere diese Ziele: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* den Ladezustand der Batterie(n) zu optmimieren, was besonders in den Monaten mit geringerer PV-Erzeugung einen wertvollen Beitrag zur Erhöhung der Autarkierate und Batteriepflege leisten kann&lt;br /&gt;
 &lt;br /&gt;
* eine PV-Prognose und Verbrauch optimierte Beladungssteuerung, die in den Monaten mit hoher PV-Erzeugung hilft eine evtl. Abregelung der Anlage zu verhindern, die Batterie ausgewogen über den Tag zu laden und ein netzdienliches Verhalten zu unterstützen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese Aspekte der Batteriesteuerung werden in den folgenden Abschnitten beschrieben. Sind mehrere Batterien installiert, kann die Steuerung getrennt für jede einzelne Batterie aktiviert und eingestellt werden. Dabei ist zu beachten, dass vom Modul nur Signale und Readings bereitgestellt werden, die durch eine entsprechende Routine ausgewertet werden können um spezifische Befehle zur Umsetzung der Steuerung an das Batteriesystem zu senden. &lt;br /&gt;
 &lt;br /&gt;
Für eine Aktivierung des Managements muß zunächst das Batterie-Device wie im vorigen Abschnitt im SolarForecast Device registriert werden.&lt;br /&gt;
Das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; aktiviert die im Modul integrierte SOC- und Lade-Management Routine: &lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; ctrlBatSocManagementXX lowSoc=&amp;lt;Wert&amp;gt; upSoC=&amp;lt;Wert&amp;gt; [maxSoC=&amp;lt;Wert&amp;gt;] [careCycle=&amp;lt;Wert&amp;gt;] [loadAbort=&amp;lt;SoC1&amp;gt;:&amp;lt;MinPwr&amp;gt;:&amp;lt;SoC2&amp;gt;] [safetyMargin=&amp;lt;Wert&amp;gt;[:&amp;lt;Wert&amp;gt;]] ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die einzelnen Schlüssel werden der Kalkulationsroutine als Steuerungsparameter übergeben und bedeuten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;lowSoc:unterer Mindest-SoC, die Batterie wird nicht tiefer als dieser Wert entladen (muß &amp;gt; 0 sein). Dieser Wert kann zum Beispiel dazu dienen, stets eine Mindestenergiemenge für den Fall eines Stromausfalls im öffentlichen Netz in den Batterien vorzuhalten.&lt;br /&gt;
&lt;br /&gt;
;upSoC:oberer Mindest-SoC, Der übliche Wert des optimalen SoC bewegt sich in Perioden mit hohen PV-Überschuß tendenziell zwischen &#039;lowSoC&#039; und &#039;upSoC&#039;, in Perioden mit geringer PV-Ausbeute bzw. geringem PV Energieüberschuß bewegt sich der optimale SoC tendenziell zwischen &#039;upSoC&#039; und &#039;maxSoC&#039;. Die Einstellung von upSoC=50 für ein ausgewogenes Verhalten kann als guter Startwert dienen.&lt;br /&gt;
&lt;br /&gt;
;maxSoC:maximaler Mindest-SoC, d.h. der SoC Wert der mindestens im Abstand von &#039;careCycle&#039; Tagen erreicht werden muß um den Ladungsausgleich im Speicherverbund auszuführen. Die Angabe ist optional (muß &amp;lt;= 100 sein, default: 95)&lt;br /&gt;
&lt;br /&gt;
;stepSoC: Optionale Schrittweite zur optimalen SoC-Berechnung (Battery_OptimumTargetSoC_XX) in %. Mit der Angabe &#039;stepSoC=0&#039; wird das SoC-Management deaktiviert und Battery_OptimumTargetSoC_XX auf den Wert &#039;lowSoC&#039; gesetzt. &#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Beziehung &#039;careCycle * stepSoC = 100&#039; sollte eingehalten werden! Wert: 0..5, default: 5 &lt;br /&gt;
&lt;br /&gt;
;careCycle:maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens &#039;maxSoC&#039; auftreten darf. Die Angabe ist optional. (default: 20)&lt;br /&gt;
&lt;br /&gt;
;lcSlot: Es wird ein tägliches Zeitfenster festgelegt, in dem die Ladesteuerung des Moduls für diese Batterie aktiv sein soll. Außerhalb des Zeitfensters wird die Batterieladung mit voller Leistung freigegeben. Das SoC-Management der Batterie ist davon nicht betroffen. Wert: &amp;lt;hh:mm&amp;gt;-&amp;lt;hh:mm&amp;gt;, default: ganztägig&lt;br /&gt;
&lt;br /&gt;
;loadAbort: definiert eine vom Anwender gewünnschte Bedingung für einen generellen Ladeabbruch und Wiederfreigabe der Lademöglichkeit. Die Abbruchbedingung ist erfüllt, wenn der angegebene SoC1 (%) erreicht bzw. überschritten ist &#039;&#039;&#039;UND&#039;&#039;&#039; die angegebene Ladeleistung &amp;lt;MinPwr&amp;gt; (W) unterschritten wurde -&amp;gt; Reading Battery_ChargeAbort_XX=1. Fällt der aktuelle SoC wieder unter den SoC2, wird Battery_ChargeAbort_XX=0 gesetzt. Ist SoC2 nicht angegeben, gilt SoC2=SoC1.  &lt;br /&gt;
&lt;br /&gt;
;loadStrategy: Abhängig von der gewählten Ladestrategie wird die Prognose der Batterieladung und ggf. die Generierung der Steuerreadings beeinflusst. Die Angabe ist optional. Wert: loadRelease | optPower | smartPower, default: loadRelease&lt;br /&gt;
	&lt;br /&gt;
;loadTarget: Optionaler Ziel-SoC in % für die Berechnung der Ladefreigabe bzw. der optimalen Ladeleistung. Der Zielwert ist eine kalkulatorische Rechengröße. Der reale SoC kann situativ in Grenzen über- oder unterschritten werden. Der höhere Wert aus Reading Battery_OptimumTargetSoC_XX und &#039;loadTarget&#039; hat für die Berechnung Vorrang. Wert: 0..100, default: 100 &lt;br /&gt;
&lt;br /&gt;
;safetyMargin: Bei der Berechnung der Ladefreigabe und optimierten Ladeleistung werden Sicherheitszuschläge auf den prognostizierten Ladungsbedarf berücksichtigt. Abweichend vom Default können mit diesem Parameter individuelle Sicherheitszuschläge getrennt für die Berechnung der Ladefreigabe und optimierten Ladeleistung angegeben werden. Der erste Wert ist der Zuschlag bei der Berechnung der Ladefreigabe, der zweite Wert der Zuschlag bei der Berechnung der optimierten Ladeleistung. Beide Angaben sind Prozentwerte von 0..100.&lt;br /&gt;
&lt;br /&gt;
;weightOwnUse: Optionale Gewichtung der stündlichen Verbrauchsprognose als zusätzlich verwendbaren Anteil zur Batterieladung in %. Technisch wird der verfügbare PV-Überschuß zur Berechnung der optimierten Ladeleistung erhöht indem der kalkulierte Verbrauch um den angegebenen Prozentsatz gesenkt wird. Wert: 0..100 default: 0 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle SoC-Werte sind ganze Zahlen in %. Dabei gilt: &lt;br /&gt;
&lt;br /&gt;
 lowSoc &amp;lt; upSoC &amp;lt; maxSoC&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====  Erläuterung der Batterie-Steuerungsreadings ==== &lt;br /&gt;
&lt;br /&gt;
Für die Steuerung des Batteriesystems gibt es im SolarForecast einen Satz an Readings, die unterschiedliche Zustände signalisieren und für entsprechende Steuerungsaufgaben bezüglich der Batteriesysteme eingesetzt werden können. In den nachfolgenden Abschnitten werden diese Zusammenhänge noch dataillierter beschrieben.&lt;br /&gt;
&lt;br /&gt;
;Hinweis: SolarForecast stellt lediglich Steuerungsinformationen zur Verfügung. Die Umsetzung des Eingriffs in das Batteriesystem erfolgt durch den Anwender selbst über entsprechende Skripte. In den thematischen Abschnitten werden Beispiele für solche Steuerungsskripte vorgestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle erstellten Readings gelten für ein Batteriesystem, es können mehrere Batteriesysteme in SolarForecast integriert sein. Die Endung &#039;&#039;XX&#039;&#039; der Readings beschreibt die Nummer des Batteriesystems und korrespondiert mit der Endung des entsprechenden Attributes &#039;&#039;ctrlBatSocManagementXX&#039;&#039; bzw. &#039;&#039;setupBatteryDevXX&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Battery_OptimumTargetSoC_XX: Mit den im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; hinterlegten Parametern unter Berücksichtigung von PV- und Verbrauchsprognosen wird ein optimaler SOC-Wert errechnet. Dieser Wert dient zur Einstellung des unteren SOC des Batteriesystems.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeRequest_XX: Dieses Reading signalisiert mit 1 eine Anforderung zur Zwangsladung der Batterie um die Batterie vor Schäden zu schützen (wenn der SOC unter ctrlBatSocManagementXX-&amp;gt;lowSoc gefallen ist) oder wenn der aktuelle SOC unter den berechneten Mindest-SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeUnrestricted_XX: Dieses Reading kann den Wert &#039;&#039;&#039;0&#039;&#039;&#039; oder &#039;&#039;&#039;1&#039;&#039;&#039; einnehmen. Ist der Wert 0, sollte die Batterie nur geladen werden, wenn der im Attribut &#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039; definierte Wert überschritten wird. Ist der Wert 1, sollte die Batterie mit der vollen zur Verfügung stehenden Ladeleistung angesteuert werden, um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten. Der Fokus der Steuerung mit diesem Reading ist es, die Speicherkapazität der Batterie optimal zur Verhinderung der Überschreitung von Einspeiselimits einzusetzen und dennoch einen maximal möglichen SoC am Tagesende zu erreichen. (siehe das beschriebene [[SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#PV-Prognose_und_Verbrauch_optimierte_Beladungssteuerung_unter_Berücksichtigung_einer_Wirkleistungsbegrenzung|Nutzungsbeispiel]])&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeOptTargetPower_XX: Dieses Reading enthält einen Richtwert für die optimierte Ladeleistung für jede Batterie. Die Aufladung wird prognosegeführt über den gesamten Tag verteilt, wobei der Fokus auf eine kontinuierliche, aber möglichst niederige Ladeleistung gelegt wird. (siehe diesen [[SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#leistungsoptimierte_Beladungssteuerung_mit_dem_Fokus_geringe_Verlustleistung_und_Verschleiß|Abschnitt]])  &lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeAbort_XX: Im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; kann mit dem Schlüssel &#039;&#039;loadAbort&#039;&#039; eine Bedingung definiert werden, bei deren Eintritt die Ladung der Batterie abgebrochen werden soll. In diesem Fall wird &#039;&#039;Battery_ChargeAbort_XX=1&#039;&#039; gesetzt. Mit einem entsprechenden Befehl kann der Anwender das Batteriesystem anweisen den Ladevorgang abzubrechen. &lt;br /&gt;
&lt;br /&gt;
;Battery_TargetAchievable_XX: Diese Reading enthält einen Boolean Wert 0|1 und signalisiert ob der im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX-&amp;gt;loadTarget&#039;&#039;&#039; gesetzte Ziel-SoC lt. Prognose am aktuellen Tag tatsächlich erreicht werden kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Nutzung des Batterie SOC-Management ====&lt;br /&gt;
&lt;br /&gt;
Oftmals wird durch die Anlagenhersteller ein hoher statischer SOC eingestellt bzw. empfohlen, der eine längere Verharrungszeit auf einem tiefen SOC-Wert verhindern soll. Allerdings wechseln sich in auch in den Herbst-, Frühlings- und Wintermonaten Zeiten mit wenig PV-Erzeugung mit Phasen stärkerer Solarstrahlung bei klarem Himmel und Sonnenschein ab.&lt;br /&gt;
&lt;br /&gt;
Ein statischer SOC würde dazu führen, dass in den erwähnten Phasen zuviel Energie in das öffentliche Netz eingespeist wird. Dies soll verhindert werden da die wertvolle Energie besser im eigenen Netz gespeichert und in Dunkelphasen verwendet werden kann. Andererseits soll die Batterie nicht zu lange auf einem tiefen SOC verbleiben und außerdem in gewissen Abständen auf einen so hohen SOC geladen werden der den internen Zellausgleich ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Die SOC Kalkulationsroutine des Moduls errechnet unter Berücksichtigung des prognostizierten PV-Ertrages der kommenden Tage, des aktuellen SOC und der im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; (nachfolgend beschrieben) angegebenen Steuerparameter den Vorschlag für eine optimale SOC-Einstellung. Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert.&lt;br /&gt;
&lt;br /&gt;
Durch das Modul selbst findet keine Steuerung der Batterie statt. Es stellt entsprechende Readings zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen SoC.&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SoC unter den optimalen SoC gefallen ist. In diesem Fall sollte die Batterie, unter Umständen mit Netzstrom, zwangsgeladen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Readings können zur Steuerung des SoC (State of Charge) sowie zur Steuerung des verwendeten Ladestroms der Batterie verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ermittlung des optimalen SOC erfolgt nach folgender Logik:&lt;br /&gt;
&lt;br /&gt;
# 	Ausgehend von &#039;lowSoc&#039; wird der Mindest-SoC kurz vor Sonnenuntergang um 5% inkrementiert sofern am laufenden Tag &#039;maxSoC&#039; nicht erreicht wurde und die PV-Prognose keinen hinreichenden Ertrag des kommenden Tages vorhersagt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Wird &#039;maxSoC&#039; (wieder) erreicht, wird Mindest-SoC um 5%, aber nicht tiefer als &#039;lowSoc&#039;, verringert. Ist der berechnete Mindest-SoC größer als &#039;upSoc&#039;, wird der Mindest-SoC auf &#039;upSoc&#039; gesetzt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#   Mindest-SoC wird soweit verringert, dass die prognostizierte PV Energie des aktuellen bzw. des folgenden Tages von der Batterie aufgenommen werden kann. Mindest-SoC wird typisch auf &#039;upSoc&#039; und nicht tiefer als &#039;lowSoc&#039; verringert.  &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Das Modul erfasst den letzten Zeitpunkt am &#039;maxSoC&#039;-Level, um eine Ladung auf &#039;maxSoC&#039; mindestens alle &#039;careCycle&#039; Tage zu realisieren. Zu diesem Zweck wird der optimierte SoC in Abhängigkeit der Resttage bis zum nächsten &#039;careCycle&#039; Zeitpunkt derart verändert, dass durch eine tägliche 5% SoC-Steigerung &#039;maxSoC&#039; am &#039;careCycle&#039; Zeitpunkt rechnerisch erreicht wird. Wird zwischenzeitlich &#039;maxSoC&#039; erreicht, beginnt der &#039;careCycle&#039; Zeitraum erneut. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im fünften Schritt werden die Grenzen &#039;lowSoc&#039; und &#039;upSoc&#039; berücksichtigt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im letzten Schritt erfolgt Generierung des Readings &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; zur Signalisierung einer eventuell empfohlenen Zwangsladung auf den berechneten Min-SoC. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei sehr wenig Erzeugungungsprognose, d.h. wenn sich der berechnete Min-SoC oberhalb von &#039;upSoC&#039; bewegt, wird &#039;upSoC&#039; eingestellt. Liegt der berechnete Min-SoC unterhalb von &#039;upSoC&#039;, ist jedoch größer als &#039;lowSoC&#039;, wird der berechnete SOC im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; eingestellt. Somit eignet sich die Angabe im Schlüssel &#039;upSoC&#039; um in Zeiten geringer Solarenergieerzeugung die Batterie für eine Notstromerzeugung auf mindestens diesem Wert zu halten. Sollte die PV-Prognose kurzfristig einen größeren Ertrag vorhersagen als die Batterie durch die Einhaltung von &#039;upSoC&#039; aufnehmen kann, wird der Min-SoC unter &#039;upSoC&#039; abgesenkt um möglichst allen PV-Überschuß in der Batterie zu speichern und somit dem Eigenverbrauch zuzuführen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der berechnete Mindest-SoC ist immer nur ein unterer Grenzwert. Die Batterie kann durch Ladevorgänge natürlich jederzeit einen höheren als den im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; dargestellten optimalen SoC haben. Der optimale SoC sollte nicht unterschritten werden um die oben genannten Zusammenhänge abbilden zu können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Die dynamische SOC Steuerung mit Umsetzungsbeispiel =====&lt;br /&gt;
Das Modul bietet eine Unterstützung zur automatisierten Einstellung eines optimalen SoC Wertes.&lt;br /&gt;
&lt;br /&gt;
Ziel ist es, den Minimum SoC in Abhängigkeit der zu erwartenden Solarerträge des aktuellen und des folgenden Tages so einzustellen, dass der prognostizierte Solarertrag von der Batterie aufgenommen werden kann. Die Einspeisung in das öffentliche Netz soll minimiert werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin soll ein unterer SoC nicht unterschritten, sowie ein oberer Minimum SoC im Normalfall nicht überschritten werden. Der obere Grenzwert stellt sicher, dass die Batterie mindestens bis zu diesem Wert wieder entladen werden kann. Dadurch bleibt innerhalb der Batterie immer genügend Kapazität verfügbar um unvorhergesehene PV Energie aufnehmen zu können.&lt;br /&gt;
&lt;br /&gt;
Aktiviert wird die Unterstützung der Batteriesteuerung durch das Setzen des Attributes &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; z.B. mit diesen Angaben:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagementXX lowSoc=x upSoC=x maxSoC=x careCycle=x &lt;br /&gt;
&lt;br /&gt;
so zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=98 careCycle=20&lt;br /&gt;
&lt;br /&gt;
Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert. &lt;br /&gt;
Ist dieses Attribut gesetzt, werden Steuerungs-Readings erstellt, die der Nutzer auswerten und seine Batterieanlage z.B. via notify oder DOIF steuern kann. &amp;lt;bR&amp;gt;&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen Mindest-SoC.&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SOC unter den optimalen SOC bzw. minimalen SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
Die Schlüssel &#039;&#039;&#039;lowSoc&#039;&#039;&#039; und &#039;&#039;&#039;upSoC&#039;&#039;&#039; sind die unteren und oberen Grenzen, zwischen denen sich der Minimum SoC im normalen Betrieb bewegen soll.&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;maxSoC&#039;&#039;&#039; stellt eine Ladungsgrenze dar, die mindestens alle X (careCycle) Tage erreicht werden soll. Zu diesem Zweck errechnet das Modul die Anzahl der nötigen Erhöhungen der Minimum Batterieladung von 5% pro Tag um ausgehend vom aktuellen SoC-Level. Der resultierende Minimum SoC Wert wird entsprechend angepasst. Wurde der einstellte maxSoC Level erreicht, startet der Wartungszyklus (careCycle) erneut. &amp;lt;br&amp;gt;&lt;br /&gt;
Der maxSoC in Verbindung mit dem durch &#039;&#039;&#039;careCycle&#039;&#039;&#039; definierten Zyklus soll sicherstellen, dass der Batterieverbund in regelmäßigen Abständen einen Ladungsausgleich vollziehen kann. &lt;br /&gt;
&lt;br /&gt;
Durch die Modullogik erfolgt eine 5 protentige Anhebung des Minimum SoC wenn am Vortag maxSoC nicht erreicht wurde. Die Anhebung erfolgt aber nicht über upSoC. upSoC ist die obere Grenze des Minimum SoC. Wird am Vortag mindestens die maxSoC Ladung erreicht, verringert sich der Minimum SoC wieder schrittweise um 5%, aber nicht tiefer als lowSoc.&lt;br /&gt;
&lt;br /&gt;
Ergänzt wird die Logik noch um die PV Vorhersage. Dabei wird die obige Minimum SoC Berechnung um die Erwartung der PV Erwartung am aktuellen und folgenden Tag korrigiert. Das bedeutet, dass der Minimum SoC z.B. von heute 50% auf 10% abgesenkt und dadurch die gespeicherte Energie dem Haushalt zugeführt wird, wenn am heutigen oder kommenden Tag eine entsprechende PV Energie zu erwarten ist um die Batterie wieder vollständig zu zuladen.&lt;br /&gt;
Dadurch ist immer genügend &amp;quot;Freiplatz&amp;quot; in der Batterie und andererseits hat die Batterie in langen Dunkelphasen eine Reserve für einen eventuellen Stromausfall (falls der abgesichert werden soll) und wird vor einem dauerhaften tiefen SoC geschützt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Umsetzungsbeispiel =====&lt;br /&gt;
&lt;br /&gt;
Wie das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; genutzt werden kann, wird am Beispiel einer Victron Batterieanlage gezeigt. Die Anlage wird durch Cerbo GX Gerät gesteuert. Der Cerbo GX ist per MQTT2 in FHEM eingebunden. Umgesetzt ist die Steuerung der Batterie &#039;01&#039;, d.h. die Angabe &#039;XX&#039; ist durch &#039;01&#039; ersetzt.&lt;br /&gt;
&lt;br /&gt;
Die folgende kleine Logik ist in einem &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; File eingebaut und wird regelmäßig mit&lt;br /&gt;
&lt;br /&gt;
 batSocChargeMgmnt (&#039;&amp;lt;Name SolarForecast Device&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
aufgerufen. Der Aufruf erfolgt durch Angabe der Routine im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; des SolarForecast Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
  # Hinweis: die Zeichen &#039;::&#039; vor der Routine sind durch das SolarForecast Package bedingt&lt;br /&gt;
  ::batSocChargeMgmnt ($name);&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Routine wird dadurch automatisch am Ende jedes Zyklus (siehe Attribut plantControl-&amp;gt;cycleInterval) ausgeführt.&lt;br /&gt;
Um die SOC Managementfunktion nach Bedarf ein- bzw. ausschalten zu können wird zunächst im SolarForecast Device ein userattr zur Steuerung der SOC-Logik angelegt:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; userattr userFn_BatterySoCManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
Die Perl Routine &#039;&#039;&#039;batSocChargeMgmnt&#039;&#039;&#039; ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#      Batterie SOC und Max. Ladestrom Management&lt;br /&gt;
############################################################################&lt;br /&gt;
sub batSocChargeMgmnt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $bn   = &#039;01&#039;;                                                                      # Batterienummer (evtl. im Aufruf mitgeben)&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vebus   = &#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;;                                     # Victron Vebus Device&lt;br /&gt;
  my $vicsets = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                                  # Victron Einstellungen&lt;br /&gt;
&lt;br /&gt;
  my $maxcspc = 105;                                                                    # max. Ladestrom (A) für Victron MPII Verbund&lt;br /&gt;
  my $preduce = FHEM::SolarForecast::BatteryVal ($name, $bn, &#039;bpinreduced&#039;, $maxcspc);  # reduzierte Ladeleistung aus Bat-Konfig (W)&lt;br /&gt;
  my $actmcc  = ReadingsNum ($vicsets, &#039;MaxChargeCurrent&#039;, undef);                      # akt. Ladestromeinstellung&lt;br /&gt;
  my $load    = $actmcc // $maxcspc;                                                    # Soll-Ladestrom (A)  &lt;br /&gt;
&lt;br /&gt;
  ## Battery SoC Management&lt;br /&gt;
  ###########################&lt;br /&gt;
  my $ubsm = AttrVal ($name, &#039;userFn_BatterySoCManagement&#039;, &#039;aus&#039;); &lt;br /&gt;
  &lt;br /&gt;
  if ($ubsm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name,    &#039;Battery_ChargeRequest_&#039;.$bn,     0);&lt;br /&gt;
    my $csoc = ReadingsNum ($vicsets, &#039;MinimumSocLimit&#039;,               10);             # akt. SoC&lt;br /&gt;
    my $osoc = ReadingsNum ($name,    &#039;Battery_OptimumTargetSoC_&#039;.$bn, 10);             # Soll-SoC&lt;br /&gt;
	my $surp = ReadingsNum ($name,    &#039;Current_Surplus&#039;,                0);             # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if ($csoc != $osoc) {&lt;br /&gt;
      CommandSet (undef, &amp;quot;$vicsets MinimumSocLimit $osoc&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn SoCMgmnt -&amp;gt; MinimumSocLimit in $vicsets set to $osoc %});&lt;br /&gt;
    }&lt;br /&gt;
	                                           &lt;br /&gt;
    if ($bcrq &amp;amp;&amp;amp; $surp &amp;lt; 1000) {                                                       # max. Ladestrom (A) b. Battery_ChargeRequest&lt;br /&gt;
      $load = $preduce / 48;                                                           # bei 48V Batteriesystem&lt;br /&gt;
    }&lt;br /&gt;
	else {&lt;br /&gt;
	  $load = $maxcspc;&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Einstellung MPII Verbund MaxChargeCurrent&lt;br /&gt;
  ##############################################&lt;br /&gt;
  if ($actmcc &amp;amp;&amp;amp; $load != $actmcc) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$vicsets MaxChargeCurrent $load&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
    Log3 ($name, 3, qq{$name - userFn ChargeMgmnt -&amp;gt; MaxChargeCurrent in $vicsets set }.&lt;br /&gt;
                    qq{from old $actmcc A to $load A});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_MPII_MaxChargeCurrent_set&#039;, $load, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist im SolarForecast Device das Reading  &#039;&#039;&#039;Battery_ChargeRequest_01&#039;&#039;&#039; gesetzt, ist der aktuelle SOC kleiner als der optimale SOC und die Batterie wird (eventuell aus dem öffentlichen Netz) geladen. Das kann automatisch durch den Cerbo GX bzw. in anderen Anlagen durch einen entsprechenden Befehl erfolgen.&lt;br /&gt;
Damit die Netzbeladung nicht mit der vollen Ladestromstärke geschieht, wird der Ladestrom auf den gewünschten Wert (hier 21 A -&amp;gt; ca. 1000 W bei einem 48V System) reduziert sofern kein oder zu wenig PV-Überschuß vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== weitere mögliche Aspekte der SOC- und Batterieladesteuerung ====&lt;br /&gt;
&lt;br /&gt;
SolarForecast liefert durch seine internen Logiken bereits sehr hilfreiche Signale zur Steuerung von Batteriesystemen in Form von Readings an. Abhängig von den individuellen Möglichkeiten der vorhandenen Anlage käme zum Beispiel zusätzlich zu einer Steurung des optimalen SOC oder der Zeitfenster für die Batterieaufladung auch eine Steuerung des Ladestroms bzw. der verwendeten Ladeleistung in Betracht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hintergründe:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Das Laden eines Akkus mit möglichst gleichbleibender und geringer Leistung wirkt sich positiv auf dessen Langlebigkeit aus, was u.a. auch daran liegt, dass der Temperaturstreß im Akku bei langsamer Energiezuführung nur gering ist.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom führt zu einem geringen Absacken der Akkuspannung beim (ggf, temporären) Abschalten des Ladestroms, was sich positiv auf die SOC-Schätzung auswirkt.&lt;br /&gt;
    &lt;br /&gt;
* Ein geringer Ladestrom führt, insb. bei Nutzung passiver Balancer (sind in den Akku-Systemen üblicherweise verbaut), zu einer geringen Differenz zwischen den einzelnen Zellspannungen und damit zu einer besseren Kapazitätsausnutzung eins Akkus.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom kann zu einem zeitlich punktgenauen Zielfüllstand (im Winter 100%, ansonsten natürlich weniger) am Ende des Tages führen.&lt;br /&gt;
    &lt;br /&gt;
* Eine geringer Ladestrom führt auch zu geringen Leitungsverlusten, da der Strom quadratisch zu den Leitungsverlusten beiträgt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann auch die Verweildauer oder die Begrenzung des SOC, auf den die Batterie maximal geladen werden soll, Gegenstand von Optimierungen sein.&lt;br /&gt;
&lt;br /&gt;
Die häufig zu findende Empfehlung, Akkus nicht zu lange bei einem SOC von 100% verweilen zu lassen, liegt weniger an dem SOC als solchem, sondern daran, dass &#039;&#039;SOC=100%&#039;&#039; üblicherweise dadurch ermittelt wird, dass eine Zelle im Akku einen Spannungsschwellenwert überschreitet, der – würde dieser Schwellenwert zeitlich länger überschritten sein – zu einer Schädigung des Akkus führen könnte. Schädlich sind insbesondere häufige Nachladevorgänge bei Werten um die 100% SOC, da Zellen dann ja häufiger und damit - integral gesehen - auch länger den o.g. Schwellenwert überschreiten.&lt;br /&gt;
&lt;br /&gt;
Einige Akku-Hersteller, z.B. BYD, haben auf o.g, Grund in der (neueren) Firmware Ihrer Systeme einen SOC-Threshold (bei BYD liegt dieser bei 95%) eingebaut. Dieser Wert muss nach einem erreichten SOC von 100% unterschritten  werden, bevor überhaupt eine weitere Ladung erfolgt. Insbesondere in der dunklen Jahreszeit kann es daher sinnvoll sein, den Akku unter Verwendung von PV-Leistung so zu füllen, dass dieser möglichst nur einmal vor Einbruch der Dunkelheit auf &#039;&#039;SOC=100%&#039;&#039; geladen wird. Hierbei sollte darauf geachtet werden, dass der Ladeschlussstrom des jeweiligen Systems nicht unterschritten wird. &lt;br /&gt;
&lt;br /&gt;
SolarForecast unterstützt die oben betrachtete Batteriesteuerung durch die optionale Angabe von &#039;&#039;&#039;loadAbort&#039;&#039;&#039; im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039;. Das in diesem Kontext erstellte Reading &#039;&#039;&#039;Battery_ChargeAbort_XX&#039;&#039;&#039; stellt die auswertbaren Steuerungsinformationen zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== PV-Prognose und Verbrauch optimierte Beladungssteuerung unter Berücksichtigung einer Wirkleistungsbegrenzung ====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-04-25 143910.png|right|thumb|400px|Batterie Popup &amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Die in diesem Abschnitt beschriebene Ladestrategie &#039;&#039;&#039;loadRelease&#039;&#039;&#039; wird im Modul als &#039;&#039;&#039;Ladefreigabe&#039;&#039;&#039; bezeichnet.&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Batterie geladen. sobald PV-Überschuß vorhanden ist ohne eine Prognose zu berücksichtigen. Dadurch sind die Batterien im Sommer unter Umständen schon um 10-12 Uhr voll geladen und die Anlage liefert ihre mehr oder weniger volle Energie (je nach Ausrichtung) in das öffentliche Netz. Dann könnte es zu einer Begrenzung der PV-Leistung durch einen Schwellenwert (z.B. 70%-Regelung) oder eventuell Zwangsabregelung durch den Netzbetreiber kommen.&lt;br /&gt;
&lt;br /&gt;
Hintergrund dieser Erweiterung ist das Bestreben, eine optimale Unterstützung bei der Maximierung des Eigenverbrauchs zu geben und einen Beitrag zur Netzstabilität zu leisten.&lt;br /&gt;
Das Ziel der Beladungssteuerung der Batterie ist es, die Ladung der Batterie über den Tag verteilt so zu steuern, dass die Batterie erst dann geladen wird, wenn durch den PV-Überschuß eine Netzeinspeisung erfolgen würde bzw. ein Grenzwert erreicht werden würde, der zu einer Abregelung der PV-Anlage führen könnte.&lt;br /&gt;
Es kann auch zu einer Zwangsabregelung durch den Netzbetreiber führen, was vermieden werden soll.&lt;br /&gt;
 &lt;br /&gt;
Die interne Kalkulationslogik erstellt zu diesem Zweck ein Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039;.&lt;br /&gt;
Dieses Reading gibt dem User ein Signal, ob zu der aktuellen Stunde der Ladevorgang der Batterie freigegeben (1) oder nicht freigegeben werden sollte (0). Die Freigabe zur Ladung bedeutet dass:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; die Batterie mit ihrer vollen, oder der im Reading [[SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#leistungsoptimierte_Beladungssteuerung_mit_dem_Fokus_geringe_Verlustleistung_und_Verschleiß|Battery_ChargeOptTargetPower_XX]] angegebenen Ladeleistung angesteuert werden sollte um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten..&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=0&#039;&#039;&#039; die Batterie nur geladen werden sollte wenn der im Attribut plantControl-&amp;gt;feedinPowerLimit definierte Wert überschritten wird&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ist keine Freigabe zur Ladung vorhanden, kann bzw. sollte dennoch eine Ladung der Batterie vorgenommen werden, sofern eine über dem im &amp;lt;br&amp;gt;&lt;br /&gt;
Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limit liegende Einspeiseleistung vorhanden ist. In diesem Status sollte die Batterie nur mit der Differenzleistung von vorhandener Einspeiseleistung und dem gesetzen Einspeiselimit geladen werden und damit das gesetzte Einspeiselimit einhalten ohne die Anlage abzuregeln. Ist die Batterie in einer Balkengrafikebene dargestellt, wird im Mouse-Over Popup die Battrie mit &#039;&#039;&amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;&#039;&#039; gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Möglichkeiten der Batteriesteuerung sind stark von der individuellen Anlage abhängig und können hier nicht beschrieben werden. Ein Umsetzungsbeispiel mit einer Victron-Anlage mit Pylontech Batterie ist weiter unten dargestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Aktivierung und Arbeitsweise =====&lt;br /&gt;
&lt;br /&gt;
Die implementierte Logik zur optimierten Batterie Beladungssteuerung wird aktiviert, wenn folgende Kriterien erfüllt sind: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;capacity&#039;&#039;&#039; in den setupInverterDevXX Atributen ist gesetzt&lt;br /&gt;
* das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; für die jeweilige Batterie ist gesetzt&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;cap&#039;&#039;&#039; im Attribut setupBatteryDevXX der jeweiligen Batterie ist gesetzt&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Die Logik arbeitet wie folgt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Der resultierende Schwellenwert der Wirkleistungsbegrenzung: der Gesamtanlage wird durch die Auswertung der in den Inverter-Attributen setupInverterDevXX  gesetzen Schlüssel limit (optional) und capacity ermittelt. Inverter mit gesetztem Schlüssel feed = grid (deren Energie wird ausschließlich in das öffentlich Netz eingespeist) werden von der Betrachtung in diesem Kontext ausgeschlossen.&lt;br /&gt;
&lt;br /&gt;
;Die benötigte Beladung bis zu maxSoC (im Attribut setupBatteryDevXX) : wird ermittelt und mit der zu erwartenden PV Tagesprognose in Beziehung gesetzt. Sofern die PV-Erzeugung abzgl. Verbrauch noch nicht das Wirkleistungbegrenzungs-Limit erreicht UND noch genügend PV-Überschuß für eine Ladung auf &#039;&#039;maxSoC&#039;&#039; im Laufe der kommenden Stunden des Tages zu erwarten ist, bleibt das Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 0&#039;&#039;&#039;. Die erreichte Qualität der Steuerungslogik ist stark von der Prognosequaliät abhängig. Um die Steuerung resilienter zu gestalten, wird per default ein Sicherheitsaufschlag von 50% auf die prognostizierte benötigte Ladeenenergie auf Stundenbasis einkalkuliert. Dieser Wert kann mit dem Attribut &#039;&#039;&#039;ctrlBatSocManagementXX-&amp;gt;safetyMargin&#039;&#039;&#039; individuell angepasst werden.&lt;br /&gt;
&lt;br /&gt;
;Wird das Wirkleistungbegrenzungs-Limit erreicht/überschritten und/oder die PV-Überschußprognose: zzgl. eines Sicherheitspuffers unterschritten, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 1&#039;&#039;&#039; gesetzt. Der User kann darauf reagieren und den Batterie Ladevorgang aktivieren. Die Möglichkeiten der Aktivierung sind natürlich von der installierten Anlage abhängig. Das SolarForecast Device greift nicht in die Batteriesteuerung direkt ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders ausgedrückt erfolgt immer dann eine Ladefreigabe, wenn einer der nachfolgenden Sachverhalte &#039;&#039;wahr&#039;&#039; ist:&lt;br /&gt;
&lt;br /&gt;
- die benötigte Ladeenergie (aller installierten Batterien) &amp;gt;= PV-Restüberschuß des Tages (Reading RestOfDayPVforecast) zzgl. Sicherheitsaufschlag&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- der Zeitpunkt des PV-Erzeugungszenit des laufenden Tages überschritten ist (Reading Today_MaxPVforecastTime)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn die aktuelle PV Leistung &amp;gt;= einer eventuellen Wechselrichter-Leistungsbegrenzung ist (Summe aller WR-Begrenzungen)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn das BatSoc-Management _nicht_ aktiviert ist (nicht alle oben genannten Aktivierungskriterien erfüllt sind)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind mehrere Batterien installiert und durch das Management einer Batterie die Einhaltung der genannten Kriterien bzw. Sachverhalte erwirkt wird, bleiben die weiteren Batterien im Modus Ladefreigabe (Battery_ChargeUnrestricted_XX=1).  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Umsetzungsbeispiel Batterie Ladesteuerung mit Victron GX Venus über den Grid Setpoint =====&lt;br /&gt;
&lt;br /&gt;
Ziel der Steuerung ist es abhängig vom Wert des Readings Battery_ChargeUnrestricted_XX (z.B. Battery_ChargeUnrestricted_01) die Ladung des angeschlossenen Batteriesystems zu aktivieren bzw. zu deaktivieren.&lt;br /&gt;
Das vorliegende Beispiel soll umzusetzen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 0 -&amp;gt; Batterie nicht aufladen bzw. nur laden wenn Einspeiselimit überschritten (Attribut plantControl-&amp;gt;feedinPowerLimit)&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 1 -&amp;gt; Batterie aufladen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Grid Setpoint ist ein Parameter in den Victron Systemeinstellungen. Das Victron System wird den eingestellten Grid Setpoint versuchen einzuhalten und bei einem positiven Wert Energie aus dem Netz beziehen bzw. bei einem negativen Grid Setpoint Energie in das Netz einspeisen.&lt;br /&gt;
&lt;br /&gt;
Normalerweise wird das Victron System die erzeugte PV Energie zunächst zur Deckung des Hausverbrauchs verwenden, ist dann noch ein PV Überschuß vorhanden, die Batterien aufladen und bei weiter vohandenen PV Überschuß diese Energie in das öffentliche Netz einspeisen sofern dem System eine Einspeisung erlaubt ist. Anderenfalls werden die Wechselrichter oder MPPT Smartloader heruntergeregelt bzw. limitiert. &lt;br /&gt;
&lt;br /&gt;
In der Standardeinstellung ist beim Victron System ein Grid Setpoint von ca. 20 bis 50 Watt, d.h. das System strebt danach diese Vorgabe zu erfüllen zieht ständig Energie in diesem Bereich aus dem öffentlich Netz von einem gelegentlichen Überschwingen der Regelung abgesehen. Damit ein eventueller PV Überschuß nicht zum Laden der Batterie verwendet, sondern statt dessen in das öffentliche Netz eingespeist wird, muß der Grid Setpoint um diesen Betrag abgesenkt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-24 114403.png|right|thumb|400px|Integration des Grid Setpoint-Managements in den Own_Spec-Bereich]]&lt;br /&gt;
&lt;br /&gt;
Damit man später per Attribut bzw. über den [[#Formatierung_der_Inhalte_im_Bereich_&amp;quot;Graphic_Header_Own_Specification&amp;quot;|Own_Spec-Bereich]] die automatische Ladesteuerung über den Grid Setpoint ein- bzw. ausschalten kann, legen wir ein userattr an:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 userattr &amp;lt;Name&amp;gt; userFn_GridSetpointManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin sind einige Vorbereitungen im Device MQTT2_cerboGX_c0619ab34e08_settings vorzunehmen. Dieses Device ist im vorliegenden Beispiel ein in FHEM vorhandenes MQTT2_DEVICE, über das die Victron CerboGX Einstellungen zugreifbar sowie einstellbar sind. Die Vorgehensweise zur Erstellung des MQTT2_DEVICE ist hier nicht beschrieben und wird vorausgesetzt.&lt;br /&gt;
&lt;br /&gt;
Damit ein entsprechender Set-Befehl zur Einstellung des Grid Setpoints vorhanden ist, werden folgende Attribute gesetzt:&lt;br /&gt;
&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings jsonMap Settings_CGwacs_AcPowerSetPoint_value:GridSetpoint&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings setList GridSetpoint W/c0619ab34e08/settings/0/Settings/CGwacs/AcPowerSetPoint {&amp;quot;value&amp;quot;:$EVTPART1}&lt;br /&gt;
&lt;br /&gt;
Nach dieser Attributierung kann mit einem &amp;quot;&#039;&#039;set MQTT2_cerboGX_c0619ab34e08_settings GridSetpoint &amp;lt;Wert&amp;gt;&#039;&#039;&amp;quot; der Grid Setpoint eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Das Attribut userFn_GridSetpointManagement kann nun im Perl Code ausgewertet werden um das Grid Setpoint-Management ein- bzw. auszuschalten.&lt;br /&gt;
Der nachfolgende Code wird in die Datei &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; eingefügt. Ist diese Datei nicht vorhanden, legen wir sie vorab als Kopie der ausgelieferten 99_myUtils.pm an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible mw-collapsed&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Code Management Batterieladung über Victron Grid Setpoint -&amp;gt;&#039;&#039;&#039; &amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Steuerung Start/Stop der Batterieladung über den Victron Grid Setpoint&lt;br /&gt;
############################################################################&lt;br /&gt;
sub gridSetpointMgmt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vicsets   = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                               # Device Victron Einstellungen&lt;br /&gt;
  my $gspdef    = 20;                                                                  # Default Einstellung des Grid Setpoint&lt;br /&gt;
  my $targetgsp = $gspdef;                                                             # Voreinstellung Grid Setpoint&lt;br /&gt;
  my $neggspmax = FHEM::SolarForecast::CurrentVal ($name, &#039;feedinPowerLimit&#039;, 5000);   # max. gewünschte Einspeiseleistung in Watt&lt;br /&gt;
  $neggspmax    = $neggspmax * -1;&lt;br /&gt;
  my $gspm      = AttrVal ($name, &#039;userFn_GridSetpointManagement&#039;, &#039;aus&#039;);             # Freischaltung des Grid Setpoint-Managements&lt;br /&gt;
  my $curgsp    = ReadingsNum ($vicsets, &#039;GridSetpoint&#039;,         $gspdef);             # aktuelle Einstellung Grid Setpoint&lt;br /&gt;
  &lt;br /&gt;
  if ($gspm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name, &#039;Battery_ChargeUnrestricted_01&#039;, 0);         # Ladefreigabe (1 -&amp;gt; Bat Ladefreigabe)&lt;br /&gt;
    my $surp = ReadingsNum ($name, &#039;Current_Surplus&#039;,               0);         # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if (!$bcrq) {                                                               # Grid Setpoint absenken wenn keine .. &lt;br /&gt;
        $targetgsp = $gspdef - $surp;                                           # ..Batterie Ladefreigabe&lt;br /&gt;
        $targetgsp = $neggspmax if($targetgsp &amp;lt; $neggspmax);                    # Begrenzung der Einspeiseleistung&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($curgsp != $targetgsp) {&lt;br /&gt;
	  fhem (&amp;quot;set $vicsets GridSetpoint $targetgsp&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn gridSetpointMgmt -&amp;gt; GridSetpoint in $vicsets set to $targetgsp});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Victron_GridSetpoint_set&#039;, $targetgsp, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Vergleich des Setpoints mit der Vorgabe von &#039;&#039;$neggspmax&#039;&#039; dient dazu die maximale Einspeiseleistung in das öffentliche Netz zu begrenzen. Ist diese Grenze erreicht, wird der noch verbleibende Überschuß in die Batterie geladen. Dadurch wird eine Abregelung der Anlage vermieden wenn der Schwellenwert &#039;&#039;$neggspmax&#039;&#039;erreicht ist sofern die Batterie aufnahmefähig ist und nicht voll geladen ist. &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::gridSetpointMgmt  ($name);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zum Management des automatischen Grid Setpoint und der Anzeige des eingestellten Wertes wird das Attribut und die Readinganzeige in den Own_Spec-Bereich eingebunden, z.B.:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; graphicHeaderOwnspec  #Settings&lt;br /&gt;
                                   SetPoint&amp;amp;nbsp;Management:userFn_GridSetpointManagement&lt;br /&gt;
                                   Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== leistungsoptimierte Beladungssteuerung mit dem Fokus geringe Verlustleistung und Verschleiß ====&lt;br /&gt;
&lt;br /&gt;
Über das Attribut ctrlBatSocManagementXX kann mit dem Schlüssel loadStrategy die Ladestrategie &#039;&#039;&#039;optPower&#039;&#039;&#039; oder &#039;&#039;&#039;smartPower&#039;&#039;&#039; eingestellt werden.&lt;br /&gt;
Das SF-Modul bietet ein weiteres Reading &#039;&#039;&#039;Battery_ChargeOptTargetPower_XX&#039;&#039;&#039; zur Batteriesteuerung an. Dieses Reading liefert eine kalkulierte optimale Ladeleistung in Watt.&lt;br /&gt;
&lt;br /&gt;
Die in diesem Abschnitt beschriebene Ladestrategie &#039;&#039;&#039;optPower&#039;&#039;&#039; wird im Modul als &#039;&#039;&#039;optimierte Ladeleistung&#039;&#039;&#039;, die Ladestrategie &#039;&#039;&#039;smartPower&#039;&#039;&#039; als &#039;&#039;&#039;zieloptimierte Ladeleistung&#039;&#039;&#039; bezeichnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beide Strategien kalkulieren die Ladeleistung kontinuierlich neu und berücksichtigen dabei:&lt;br /&gt;
&lt;br /&gt;
* die Prognose der PV-Erzeugung der nächsten Stunden und des (Rest-)Tages&lt;br /&gt;
* den prognostizierten Verbrauch auf Stunden- bzw. Tagesbasis&lt;br /&gt;
* eine eventuell mögliche Überschreitung des gesetzten Einspeiselimits (plantControl-&amp;gt;feedinPowerLimit)&lt;br /&gt;
* die gesetzten Leistungsparameter der Batterie &lt;br /&gt;
* das Ziel, am Tagesende einen möglichst maximalen SoC der Batterie erreicht zu haben bzw. den eingestellten Ziel-SoC &#039;&#039;&#039;loadTarget&#039;&#039;&#039;&lt;br /&gt;
* die Effizienz der Batterieanlage (Einstellung &#039;&#039;&#039;setupBatteryDevXX-&amp;gt;efficiency&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Fokus der implementierten Logik liegt dabei auf einer kontinuierlichen Ladeleistung, die aber unter den oben genannten Gesichtspunkten möglichst (relativ) gering sein soll um den Batterieverschleiß und die Verlustleistung zu minimieren. Die im Reading angezeigte Ladeleistung kann mit geeigneten Mitteln direkt in die Leistungssteuerung der Batterie eingebracht werden. Natürlich kann die Leistung auch vorab in einen optimalen Ladestrom umgerechnet werden.&lt;br /&gt;
&lt;br /&gt;
Da das Ergebnis der Kalkulation stark von den Prognosen abhängt, ist zur Erhöhung der Resilienz per Default ein Sicherheitszuschlag von 20% eingebaut. Dieser Wert kann mit dem Attribut &#039;&#039;&#039;ctrlBatSocManagementXX-&amp;gt;safetyMargin&#039;&#039;&#039; individuell angepasst werden. &lt;br /&gt;
&lt;br /&gt;
Ist kein PV-Überschuß (mehr) vorhanden / prognostiziert oder das Ladeziel erreicht, erfolgt ein Rückfall der Ladeleistung im Reading Battery_ChargeOptTargetPower_XX auf den  im Attribut &#039;&#039;&#039;setupBatteryDevXX-&amp;gt;pinmax&#039;&#039;&#039; angegebenen Wert. Ist dieser Wert nicht gesetzt, erfolgt der Rückfall auf &amp;quot;Unendlich&amp;quot; (9223372036854775807). &lt;br /&gt;
 &lt;br /&gt;
Im Reading Battery_ChargeOptTargetPower_XX wird der Wert des Parameters &#039;&#039;&#039;setupBatteryDevXX-&amp;gt;pinreduced&#039;&#039;&#039; gesetzt, wenn weniger Ladeleistung als pinreduced berechnet wurde (Einhaltung einer Mindestladeleistung) oder wenn der SoC der Batterie &amp;lt;= [[#Aktivierung_des_Batterie_SOC-_und_Lade-Managements|lowSoC]] beträgt.&lt;br /&gt;
Somit wird die Batterie bei einer Anforderungsladung bei Unterschreitung von lowSoC mit nur wenig Leistung aus dem Grid geladen falls es nötig sein sollte.&lt;br /&gt;
Es ist demzufolge ratsam den optionalen Parameter &#039;&#039;&#039;setupBatteryDevXX-&amp;gt;pinreduced&#039;&#039;&#039; zu setzen, da ansonsten ebenfalls ein Rückfall auf &#039;&#039;&#039;setupBatteryDevXX-&amp;gt;pinmax&#039;&#039;&#039; bzw. &amp;quot;Unendlich&amp;quot; erfolgt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beide Strategien, optPower und smartPower, setzen die zuvor beschriebene Arbeitsweise um.&lt;br /&gt;
Ergänzend wird bei der Ladestrategie &#039;&#039;&#039;smartPower&#039;&#039;&#039; die generelle Erreichbarkeit des Ladeziels bei der Festlegung der Ladeleistung berücksichtigt. Es führt dazu dass:&lt;br /&gt;
&lt;br /&gt;
* die Ladeleistung im Reading Battery_ChargeOptTargetPower_XX auf einen tendenziell höheren Wert als bei der optPower-Strategie gesetzt wird, wenn/solange das eingestellte Ladeziel als unerreichbar kalkuliert wird&lt;br /&gt;
* bei kalkulierter Erreichbarkeit des Ladeziels der Sicherheitsaufschlag linear absenkend proportional zum Kehrwert des verfügbaren PV-Überschusses auf die Ladeleistung angewendet wird&lt;br /&gt;
&lt;br /&gt;
Der nächste Abschnitt erläutert die smartPower Funktionen etwas eingehender.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== smartPower - die zieloptimierte Ladeleistung  =====&lt;br /&gt;
Die hinter smartPower liegende Anpassungslogik wird nachfolgend etwas näher beschrieben.&lt;br /&gt;
Ausgangspunkt ist das Ergbnis einer Ratio-Funktion aus dem (Rest)Tages-PV-Überschuß und benötigter Energie zur Erlangung des Batterie Ladeziels.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lineare Interpolation zwischen pinmax und abgesicherter minpower&#039;&#039;&#039;  &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Variablen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;P&#039;&#039;&#039;: resultierende Leistung.&lt;br /&gt;
* &#039;&#039;&#039;pinmax&#039;&#039;&#039;: maximale Ladeleistung.&lt;br /&gt;
* &#039;&#039;&#039;limpower&#039;&#039;&#039;: Leistungslimit, d.h. Ladeleistungssollwert.&lt;br /&gt;
* &#039;&#039;&#039;r&#039;&#039;&#039;: Verhältnis in Prozent (r = spday·100 / whneed).&lt;br /&gt;
* &#039;&#039;&#039;otpMargin&#039;&#039;&#039;: Prozentwert der Bandbreite, über die die Absenkung linear verläuft (die Steilheit kann mit dem Attributwert ctrlBatSocManagementXX-&amp;gt;safetyMargin im Device eingestellt werden).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Kennlinie der für smartPower eingesetzten Funktion ist stückweise definiert über das Verhältnis Ratio &#039;&#039;𝑟 = spday x 100 / &amp;lt;benötigte Ladeenergie bis Ziel&amp;gt;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* Für 𝑟 ≤ 100: &#039;&#039;𝑃 = pinmax&#039;&#039;, Interpretation: Es ist viel Bedarf vorhanden bzw. Überschuss ≤ 100 % des Bedarfs → maximal laden.&lt;br /&gt;
* Für 𝑟 ≥ 100 + otpMargin: &#039;&#039;𝑃 = limpower ⋅ (1 + otpMargin / 100 )&#039;&#039;&lt;br /&gt;
* Für 100 &amp;lt; 𝑟 &amp;lt; 100 + otpMargin: lineare Absenkung von &#039;&#039;&#039;P&#039;&#039;&#039; mit zunehmendem &#039;&#039;&#039;r&#039;&#039;&#039; für den Bereich 100 &amp;lt; 𝑟 &amp;lt; 100 + otpMargin. &#039;&#039;&#039;P&#039;&#039;&#039; wird bei 𝑟 = 100 gleich &#039;&#039;&#039;pinmax&#039;&#039;&#039; und bei 𝑟 = 100 + otpMargin gleich &#039;&#039;limpower ⋅ ( 1 + otpMargin/100 )&#039;&#039;, Interpretation: Sobald der Überschuss über den Bedarf hinausgeht (ratio &amp;gt; 100), wird das Ladeleistungslimit schrittweise von pinmax Richtung limpower reduziert; die Reduktion erfolgt gleichmäßig über die Margin-Spanne.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lineare Interpolation und Steigung&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Die Differenz &#039;&#039;(pinmax − limpower)&#039;&#039; wird gleichmäßig auf die otpMargin-Prozentpunkte verteilt. Die Steigung der Geraden ist&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slope = − (pinmax − limpower) / otpMargin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
das heißt die Leistung sinkt um diesen Betrag pro Prozentpunkt von &#039;&#039;&#039;r&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nach Umformung ist der Zusammenhang wie folgt darstellbar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
𝑃 = pinmax − ( pinmax − limpower) ⋅ ((𝑟 − 100) / otpMargin)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und ist äquivalent zu&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
𝑃 = pinmax + ( 𝑟 − 100 ) ⋅ slope&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Numerisches Beispiel&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;limpower&#039;&#039;&#039; = 1000 W, &#039;&#039;&#039;pinmax&#039;&#039;&#039; = 3000 W, &#039;&#039;&#039;otpMargin&#039;&#039;&#039; = 20&lt;br /&gt;
* Unterschied = 2000 W, Steigung = −2000/20 = −100 W/%&lt;br /&gt;
* Für &#039;&#039;&#039;r = 105&#039;&#039;&#039;: 𝑃 = 3000 − 2000 ⋅ ( 5 / 20 ) = 3000 − 500 = 2500 W&lt;br /&gt;
* Für &#039;&#039;&#039;r = 120&#039;&#039;&#039; ergibt die Formel den abgesicherten Endwert 1200 W&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Formel sorgt dafür, dass die Zielleistung stufenlos und vorhersehbar reduziert wird, wenn der relative Rest-Überschuss des Tages über 100% steigt, und erreicht bei Ende der otpMargin den geplanten abgesicherten Wert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Ratio Kennlinie.png|right|thumb|200px|abfallend proportionale Anpassungsfunktion]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In einem grafischen Diagramm stellt sich die abfallend proportionale Anpassungsfunktion der resultierenden Soll-Ladeleistung wie nebenstehend abgebildet dar. Dabei entspricht pow=100 dem jeweiligen pinmax Wert (hier 3000 W). So ist auch pow=0 mit dem abgesicherten Endwert (hier 1200 W) gleichzusetzen. Die Linie verläuft waagerecht bei pinmax solange das das Ratio  r ≤ 100 % und knickt an r == 100 mit steigenden r nach unten. Es verringert sich pow linear von pinmax zu limpower zzgl. otpMargin.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Durch diese Maßnahmen wird eine flexible Lademöglichkeit bis pinmax erreicht, die sich bei unvorhergesehenen Aufklarungen mit starker Sonneneintrahlung bei ansonsten sehr bedeckten Himmel positiv auswirkt. Andererseits wird die Erhöhung der Ladeleistung weiter begrenzt, wenn viel PV-Überschuß in Verbindung mit einer generellen Erreichbarkeit des Ladeziels zum Ende des Tages prognostiziert ist. Man könnte die Ladestrategie &#039;&#039;&#039;smartPower&#039;&#039;&#039; in ihrer Wirkung als einen Mix aus &#039;&#039;&#039;optPower&#039;&#039;&#039; und &#039;&#039;&#039;loadRelease&#039;&#039;&#039; ansehen.&lt;br /&gt;
&lt;br /&gt;
Zusammenfassend ist optPower vorwiegend für die Nutzergruppe geeignet, die eine tendenziell sparsamere Ladeleistung bevorzugen und dafür bereit sind eventuelle &amp;quot;Verluste&amp;quot; in Form von Einspeisung zu akzeptieren. &amp;lt;br&amp;gt;&lt;br /&gt;
Demgegenüber eignet sich das aggressivere smartPower für Anwender, die bei niedrigen PV-Erträgen bewusst das Maximum an Batterieladung anstreben und dafür in Kauf nehmen, dass Ladeleistungen weniger knapp kalkuliert sind. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Unterstützung des Modus &amp;quot;Eigennutzung&amp;quot; bei Hybrid-Wechselrichtern =====&lt;br /&gt;
Viele Hybrid-Wechselrichter verteilen die zur Verfügung stehende PV-Leistung nach folgendem Prioritäten, wenn der (übliche) Modus &amp;quot;Eigennutzung&amp;quot; aktiviert ist:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Nutzung der Leistung zur Deckung des Hausverbrauchs,&lt;br /&gt;
# Nutzung der Leistung zur Ladung des bzw. der angeschlossenen Speicher.&lt;br /&gt;
# Einspeisung der Leistung in das öffentliche Netz.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Da in aller Regel die Leistung, mit der ein angeschlossener Speicher geladen wird, limitiert werden kann, lassen sich die o.g. Priorität bzgl. des Speichers zugunsten einer Überschusseinspeisung aufweichen. Ein entstehender &amp;quot;Überschuss&amp;quot; steht also ggf. nur deshalb zur Verfügung, weil die Ladeleistung des Speichers begrenzt wurde.&lt;br /&gt;
&lt;br /&gt;
Ab Version 1.58.6 bietet SolarForecat die Möglichkeit, prognostizierte Verbräuche nicht mehr komplett bei der Bestimmung der &#039;&#039;optimalen Ladeleistung&#039;&#039; zu berücksichtigen, sondern nur noch zu einem prozentualen Anteil von 0..100 %. Hierzu muss der Attribut-Schlüssel &#039;&#039;&#039;ctrlBatSocManagementXX-&amp;gt;weightOwnUse=&amp;lt;Percentage&amp;gt;&#039;&#039;&#039; entsprechend gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
So führt beispielsweise weightOwnUse=100 dazu, dass bei der Berechnung der optimalen Ladeleistung prognostizierte Verbräuche nicht mehr berücksichtigt werden indem sie bei der Bestimmung des stündlichen PV-Überschusses unberücksichtigt bleiben. Eine derartige Einstellung kann z.B. sinnvoll sein, wenn alle ansonsten täglich laufende Verbraucher zugunsten einer Batterieladung ausgeschaltet werden können.&lt;br /&gt;
&lt;br /&gt;
Ein Wert von zum Beispiel weightOwnUse=30 lässt 30% der stündlichen Verbrauchslast unberücksichtigt, sodass sich der kalkulierte PV-Überschuß pro Stunde um 30% des prognostizierten Verbrauchs erhöht. Da die Berechnung der optimierten Ladeleistung mit dem zur Verfügung stehenden PV-Überschuß gewichtet erfolgt, würde sich die kalkulierte Ladeleistung in den meisten Fällen ebenfalls um einen gewissen Betrag erhöhen sofern andere Faktoren dies nicht verhindern. Das kann beispielweise der Fall sein, wenn die kalkulierte Ladeleistung zu gering ist und automatisch aif mindestens &#039;&#039;&#039;setupBatteryDevXX-&amp;gt;pinreduced&#039;&#039;&#039; angehoben wurde.&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Welche Ladestrategie soll ich wählen? - eine Möglichkeit zur Best-Practice Findung mit Codebeispiel ====&lt;br /&gt;
&lt;br /&gt;
In den vorangegangenen Abschnitten wurden die verschiedenen Möglichkeiten zur Steuerung der Batterieladung und dem SoC vorgestellt. Diese Steuerungsvarianten optimieren die Arbeitweise der Batterie, haben aber jeweils einen eigenen Fokus auch wenn es gewisse Überschneidungen gibt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Steuerungsvarianten lassen sich folgendermaßen klassifizieren:&lt;br /&gt;
&lt;br /&gt;
# Steuerung der Batterieladung über eine Ladefreigabe, die durch bestimmte Indikatoren festgelegt wird. Diese Variante ist in [[SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#PV-Prognose_und_Verbrauch_optimierte_Beladungssteuerung_unter_Berücksichtigung_einer_Wirkleistungsbegrenzung|diesem]] Abschnitt beschrieben.&lt;br /&gt;
# Steuerung der Batterieladung durch eine optimierte maximale Ladeleistung. Diese Variante ist in [[SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#leistungsoptimierte_Beladungssteuerung_mit_dem_Fokus_geringe_Verlustleistung_und_Verschleiß|diesem]] Abschnitt dargelegt. Zu dieser Variante gehören die Strategien &#039;&#039;optPower&#039;&#039; sowie &#039;&#039;smartPower&#039;&#039;. Die Unterschiede beider Strategien sind ebenfalls in dem verlinkten Abschnitt beschrieben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die &#039;&#039;&#039;Variante 1.)&#039;&#039;&#039; gibt die Ladung der Batterie frei wenn der (verbleibende) PV-Überschuß des Tages kleiner oder gleich dem Ladungsbedarf der Batterie ist um einen SoC von 100% bzw. den maximal möglichen SoC am Ende des Tages zu erreichen. Dadurch wird die in der Batterie vorhandene freie Kapazität so lange wie möglich der Einhaltung von besonderen Grenzwerten, z.B. des Einspeiselimits (plantControl-&amp;gt;feedinPowerLimit), vorbehalten. Nebeneffekt ist, dass plötzlich und unerwartet auftretende hohe Erzeugungsleistungen in die Batterie geladen werden können und nicht unerwünscht in das öffentliche Netz eingespeist werden. &lt;br /&gt;
&lt;br /&gt;
Die &#039;&#039;&#039;Variante 2.)&#039;&#039;&#039; lässt die Batterie kontinuierlich laden, wobei die Ladeleistung auf ein optimiertes Minimum reduziert wird ohne das Ziel, einen maximalen SoC am Tagesende zu erreichen, zu ignorieren. Dadurch wird die Batterie schonend, mit möglichst wenig Verlustleistung und verschleißarm geladen. Die Vorhaltung der freien Kapaziäten der Batterie sind in dieser Variante nicht die Prämisse. Die Einhaltung des gesetzten Enispeiselimits wird auch in dieser Variante beachtet sofern es der Ladezustand der Batterie zulässt. Technisch bedingt kann diese Variante nur ungenügend auf unerwartete PV-Überschüsse reagieren, was zu einer Einspeisung in das öffentliche Netz oder im ungünstigsten Fall zur Abregelung der Anlage führen kann. Mit dem Attribut &#039;&#039;&#039;ctrlBatSocManagementXX-&amp;gt;safetyMargin&#039;&#039;&#039; kann man diesem negativen Aspekt in gewissem Maße entgegenwirken.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ausgehend von diesen unterschiedlichen Optimierungszielen bietet sich die Variante 1.) vorwiegend in den Übergangs- und Wintermonaten an. Durch die beschriebenen Eigenschaften dieser Variante ist bei tendeziell weniger PV-Überschuß über den Tag die Ladung der Batterie komplett freigegeben, wodurch bei plötzlich auftretenden sonnige Abschnitten und Aufklarungen die Batterie sofort mit dem verfügbaren PV-Überschuß geladen wird. Auch eine Einspeisung über das Einspeiselimit hinaus kann verhindert werden. In der übrigen Zeit wird die Ladeleistung durch den verfügbaren PV-Überschuß begrenzt. &lt;br /&gt;
Weiterhin soll der SoC nicht dauerhaft tief absinken und ebenfalls nicht auf einem zu hohen Level verharren was auch einer maximal möglichen Energiespeicherung an sonnigen Tagen entgegenwirken würde.&lt;br /&gt;
In dieser Zeit ist die Nutzung der Kombination von [[SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#Nutzung_des_Batterie_SOC-Management|SoC-Management]] und Variante 1.) wohl am Besten geeignet um die Ziele zu verwirklichen sowie Notreserven in den Batterien vorzuhalten. &lt;br /&gt;
&lt;br /&gt;
In den Sommermonaten hingegen ist üblicherweise sehr viel PV-Energie und Überschuß vorhanden. In dieser Periode würden die Batterien mit sehr hoher Leistung sehr zeitig am Tag vollgeladen. Die Variante 1.) ist im Prinzip ebenfalls gut geeignet den Zeitpunkt der Vollladung hinauszuzögern, jedoch erscheint die Varinte 2.) in dieser Zeit besser geeignet mit einer über den gesamten Tag verteilten moderaten Ladeleistung den Ziel-SoC zu erreichen. Auch diese Variante versucht eine Überschreitung des Einspeiselimits zu verhindern sofern der Ladezustand der Batterie dies ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Codebeispiel bietet die Möglichkeit über ein Attribut die Ladevariante auszuwählen, über ein weiteres Attribut die SoC-Steuerung zu aktivieren/deaktivieren und integriert auch die Ladesteuerung für eine Batterie-Anforderungsladung bei Unterschreitung von ctrlBatSocManagementXX-&amp;gt;lowSoc. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gesteuerte Batterieanlage besteht aus:&lt;br /&gt;
&lt;br /&gt;
* 3 x Victron MultiPlusII 3000/48&lt;br /&gt;
* Steuergerät CerboGX (in FHEM über MQTT eingebunden)&lt;br /&gt;
* einem Batteriestack bestehend aus Pylontech US3000C (wird durch CerboxGX gesteuert)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zur Umschaltung bzw. Auswahl der Ladestrategie und des SoC-Managements werden zwei User-Attribute im SolarForecast Device angelegt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr ... userattr userFn_BatterySoCManagement:Ein,Aus userFn_BatteryLoadManagement:Aus,loadRelease,optPower,smartPower&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Code werden diese Attribute ausgewertet. Das nachfolgende Script vereint folgende Funktionalitäten:&lt;br /&gt;
&lt;br /&gt;
* die Aktivierung/Deaktivierung des SoC-Managements via Attribut userFn_BatterySoCManagement&lt;br /&gt;
* die Auswahl der Ladestrategie oder Deaktivierung der Ladesteuerung via attribut userFn_BatteryLoadManagement&lt;br /&gt;
* Integration einer Anforderungsladung bei Signalisierung durch Reading Battery_ChargeRequest_XX&lt;br /&gt;
* Generierung von Readings userFn_Victron_GridSetpoint_set und userFn_MPII_MaxChargeCurrent_set zur Dokumentation der eingestellten Soll-Werte&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
Bei der Nachnutzung des Scripts sind zunächst die &#039;&#039;&#039;Konstanten&#039;&#039;&#039; und das Device &#039;&#039;&#039;MQTT2_cerboGX_c0619ab34e08_setting&#039;&#039;&#039;s sowie dessen Readings im Block &#039;&#039;&#039;aktuelle Indikatoren&#039;&#039;&#039; anzupassen.&lt;br /&gt;
&lt;br /&gt;
Das Script wird in die Datei &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; eingetragen und im SolarForecast Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; hinterlegt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr ... ctrlUserExitFn {&lt;br /&gt;
                          ::batLoadMgmnt ($name, &#039;01&#039;);&lt;br /&gt;
                          # ::batLoadMgmnt ($name, &#039;02&#039;);   # optional für eine weitere Batterie &#039;02&#039;&lt;br /&gt;
                          # ::batLoadMgmnt ($name, &#039;0X&#039;);   # optional für weitere Batterien&lt;br /&gt;
                        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit diesem Script ist der Nutzer in der Lage, das Batterie Lademanagement entsprechend seiner Motivation und gegebenenfalls abhängig von der Jahreszeit umzustellen und das Ergebnis bzw. die Zielerreichung zu testen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;userFn_BatteryLoadManagement&#039;&#039;&#039; selektiert die gewünschte Ladestrategie:&lt;br /&gt;
&lt;br /&gt;
;Aus: das Lademangement ist ausgeschaltet &lt;br /&gt;
&lt;br /&gt;
;loadRelease: das Lademangement Variante 1.) Ladestrategie Ladefreigabe ist aktiviert &lt;br /&gt;
&lt;br /&gt;
;optPower: das Lademangement Variante 2.) Ladestrategie optimierte Ladeleistung ist aktiviert &lt;br /&gt;
&lt;br /&gt;
;smartPower: das Lademangement Variante 2.) Ladestrategie zieloptimierte Ladeleistung ist aktiviert&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die selektierte Ladestrategie wird im Script in das SolarForecast Device repliziert, d.h. der Attributschlüssel ctrlBatSocManagement01-&amp;gt;loadStrategy wird identisch zum Wert des Attributes userFn_BatteryLoadManagement gesetzt. Dazu wird das Set-Kommando &#039;&#039;attrKeyVal&#039;&#039; verwendet. Das globale Attribut &#039;&#039;autosave&#039;&#039; sollte aus diesem Grund NICHT explizit auf &amp;quot;0&amp;quot; gesetzt sein um eine reibungslose Funktion zu ermöglichen. &lt;br /&gt;
&lt;br /&gt;
Hat man die individuell passende Management-Strategie gefunden, bietet sich auch eine automatische (zum Beispiel durch einen Kalender oder Sonnenstand (Elevation) zur Mittagszeit) Umschaltung der Ladestrategie an. Die Unterschreitung der Elevation unter einen bestimmten Wert würde den Beginn des Winterhalbjahres und reverse Überschreitung den Beginn des Sommerhalbjahres kennzeichnen. Entsprechend würde dann die gewünschte Ladestrategie selektiert. Alternativ könnte auch die PV-Überschußprognose für den aktuellen Tag über das Reading &#039;&#039;Today_PVforecast&#039;&#039; für eine Entscheidung bzgl. der Ladestrategie herangezogen werden.&lt;br /&gt;
&lt;br /&gt;
Das SoC-Management kann über das gesamte Jahr aktiviert bleiben, hat jedoch nach bisherigen Erfahrungen nur im Winterhalbjahr eine starke Relevanz.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible mw-collapsed&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Code Lademanagement -&amp;gt;&#039;&#039;&#039; &amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#      Komplettes Batterie Lademanagement&lt;br /&gt;
############################################################################&lt;br /&gt;
sub batLoadMgmnt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $bn   = shift // &#039;01&#039;;                                                             # Batterienummer&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  ## Konstanten&lt;br /&gt;
  ###############  &lt;br /&gt;
  use constant {&lt;br /&gt;
    GSPDEF    =&amp;gt; 20,                                                                    # Einstellung des Grid Setpoint&lt;br /&gt;
    FINDEF    =&amp;gt; 5000,                                                                  # Default Einspeiselimit&lt;br /&gt;
    MINSOCDEF =&amp;gt; 10,                                                                    # Default Minimum SoC&lt;br /&gt;
    MAXPLDEF  =&amp;gt; 105,                                                                   # max. Ladestrom (A) Victron MPII &lt;br /&gt;
    SYSVOLTAG =&amp;gt; 48,                                                                    # Batterie Systemspannung&lt;br /&gt;
  };&lt;br /&gt;
  &lt;br /&gt;
  my $batsocmgmt  = AttrVal ($name, &#039;userFn_BatterySoCManagement&#039;,  &#039;Aus&#039;);             # SoC-Management Vorgabe&lt;br /&gt;
  my $batloadmgmt = AttrVal ($name, &#039;userFn_BatteryLoadManagement&#039;, &#039;Aus&#039;);             # Lademanagement Vorgabe&lt;br /&gt;
  my $vicsets     = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                              # Victron CerboGX Einstellungen&lt;br /&gt;
&lt;br /&gt;
  ## Ladestrategie Ist-Einstellung und Soll-Abgleich&lt;br /&gt;
  ####################################################&lt;br /&gt;
  my $cgbt     = AttrVal ($name, &#039;ctrlBatSocManagement&#039;.$bn, undef);&lt;br /&gt;
  my $strategy = &#039;loadRelease&#039;; &lt;br /&gt;
&lt;br /&gt;
  if ($cgbt) {&lt;br /&gt;
    my $parsed = FHEM::SolarForecast::__parseAttrBatSoc ($name, $cgbt);                 # aktuell gesetzte Strategie ermitteln&lt;br /&gt;
    $strategy  = $parsed-&amp;gt;{loadStrategy} // $strategy;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($batloadmgmt ne &#039;Aus&#039; &amp;amp;&amp;amp; $strategy ne $batloadmgmt) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$name attrKeyVal ctrlBatSocManagement${bn} loadStrategy=$batloadmgmt&amp;quot;);              &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  ## aktuelle Indikatoren&lt;br /&gt;
  ##########################&lt;br /&gt;
  my $surp    = ReadingsNum ($name, &#039;Current_Surplus&#039;,            0);                   # aktueller PV-Überschuß&lt;br /&gt;
  my $bcrq    = ReadingsNum ($name, &#039;Battery_ChargeRequest_&#039;.$bn, 0);                   # Notfallladung&lt;br /&gt;
  my $curgsp  = ReadingsNum ($vicsets, &#039;GridSetpoint&#039;, GSPDEF);                         # aktuelle Einstellung Grid Setpoint&lt;br /&gt;
  my $finplim = FHEM::SolarForecast::CurrentVal ($name, &#039;feedinPowerLimit&#039;,   FINDEF);  # Limit plantControl-&amp;gt;feedinPowerLimit&lt;br /&gt;
  my $preduce = FHEM::SolarForecast::BatteryVal ($name, $bn, &#039;bpinreduced&#039;, MAXPLDEF);  # reduzierte Ladeleistung Bat-Konfig&lt;br /&gt;
  my $actmcc  = ReadingsNum ($vicsets, &#039;MaxChargeCurrent&#039;,     0);                      # akt. maximale Ladestromeinstellung&lt;br /&gt;
  my $actmcp  = ReadingsNum ($vicsets, &#039;MaxChargePower&#039;,   undef);                      # akt. Ladeleistungseinstellung&lt;br /&gt;
  my $load    = MAXPLDEF;                                                               # initialer Soll-Ladestrom (A)&lt;br /&gt;
  &lt;br /&gt;
  my $targetgsp = GSPDEF;                                                               # Voreinstellung Grid Setpoint&lt;br /&gt;
  my $ctype     = &#039;default&#039;;                                                            # Voreinstellung Steuerungstyp  &lt;br /&gt;
&lt;br /&gt;
  ## Battery SoC Management&lt;br /&gt;
  ###########################  &lt;br /&gt;
  if ($batsocmgmt eq &#039;Ein&#039;) { &lt;br /&gt;
    my $csoc = ReadingsNum ($vicsets, &#039;MinimumSocLimit&#039;,               MINSOCDEF);     # akt. SoC&lt;br /&gt;
    my $osoc = ReadingsNum ($name,    &#039;Battery_OptimumTargetSoC_&#039;.$bn, MINSOCDEF);     # optimierter Mindest-SoC&lt;br /&gt;
	&lt;br /&gt;
    if ($csoc != $osoc) {&lt;br /&gt;
      CommandSet (undef, &amp;quot;$vicsets MinimumSocLimit $osoc&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn SoCMgmnt -&amp;gt; MinimumSocLimit in $vicsets set to $osoc %});&lt;br /&gt;
    }                                       &lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Steuerung nach Ladungsfreigabe&lt;br /&gt;
  ###################################    &lt;br /&gt;
  if ($batloadmgmt eq &#039;loadRelease&#039;) {&lt;br /&gt;
    $ctype         = &#039;loadRelease&#039;;    &lt;br /&gt;
    my $unrestrict = ReadingsNum ($name, &#039;Battery_ChargeUnrestricted_&#039;.$bn, 0);         # Ladefreigabe (1 -&amp;gt; Ladefreigabe)&lt;br /&gt;
	&lt;br /&gt;
    if (!$unrestrict) {                                                                 # Grid Setpoint absenken wenn keine .. &lt;br /&gt;
        $targetgsp    = GSPDEF - $surp;                                                 # ..Batterie Ladefreigabe&lt;br /&gt;
        my $neggspmax = -1 * $finplim;&lt;br /&gt;
		$targetgsp    = $neggspmax if($targetgsp &amp;lt; $neggspmax);                         # Begrenzung der Einspeiseleistung&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($curgsp != $targetgsp) {                                                          # GridSetpoint setzen&lt;br /&gt;
	  fhem (&amp;quot;set $vicsets GridSetpoint $targetgsp&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn ChargeMgmnt &#039;loadRelease&#039; -&amp;gt; GridSetpoint in $vicsets set to $targetgsp});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Victron_GridSetpoint_set&#039;, $targetgsp, 0); &lt;br /&gt;
  &lt;br /&gt;
  ## Steuerung nach optimaler Ladeleistung&lt;br /&gt;
  ##########################################&lt;br /&gt;
  if ($batloadmgmt =~ /(?:opt|smart)Power/xs) {&lt;br /&gt;
    $ctype  = &#039;optPower&#039;; &lt;br /&gt;
    my $otp = ReadingsNum ($name, &#039;Battery_ChargeOptTargetPower_&#039;.$bn, $preduce);      # optimale Ladeleistung (W)&lt;br /&gt;
    $load   = sprintf &amp;quot;%.0f&amp;quot;, ($otp / SYSVOLTAG);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Anforderungsladung&lt;br /&gt;
  ####################### &lt;br /&gt;
  if ($bcrq) {                                                                         # max. Ladeleistung...&lt;br /&gt;
    $ctype = &#039;requestCharging&#039;;                                                        # bei Battery_ChargeRequest&lt;br /&gt;
    my $p;&lt;br /&gt;
    &lt;br /&gt;
	if ($surp &amp;lt; $preduce) {&lt;br /&gt;
	  $p = $preduce;&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
      $p = ReadingsNum ($name, &#039;Battery_ChargeOptTargetPower_&#039;.$bn, $preduce);         # optimale Ladeleistung (W) &lt;br /&gt;
    }&lt;br /&gt;
	&lt;br /&gt;
    $load = sprintf &amp;quot;%.0f&amp;quot;, ($p / SYSVOLTAG);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Stromeinstellung umsetzen&lt;br /&gt;
  #############################  &lt;br /&gt;
  if ($load != $actmcc) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$vicsets MaxChargeCurrent $load&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
    Log3 ($name, 3, qq{$name - userFn ChargeMgmnt &#039;$ctype&#039; -&amp;gt; MaxChargeCurrent in $vicsets set }.&lt;br /&gt;
                    qq{from old $actmcc A to $load A});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_MPII_MaxChargeCurrent_set&#039;, $load, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== sequentielle Batterie-Ladung mehrerer Batterien mit lcSlot ====&lt;br /&gt;
&lt;br /&gt;
Der Parameter &#039;&#039;&#039;ctrlBatSocManagementXX-&amp;gt;lcSlot&#039;&#039;&#039; (&amp;quot;load control Slot&amp;quot;) definiert eine Zeitperiode am aktuellen Tag in der die Steuerungslogik für die Batteriesteuerung aktiviert ist. Ist dieser Parameter nicht gesetzt, ist das eingestellte Lademanagement über den gesamten Tag aktiert und wäre identisch mit der Einstellung:&lt;br /&gt;
&lt;br /&gt;
 lcSlot=00:00-23:59&lt;br /&gt;
&lt;br /&gt;
Somit ist die Ladesteuerung per default über den gesamten Tag aktiv.&lt;br /&gt;
&lt;br /&gt;
Durch das Setzen von lcSlot auf einen täglichen Slot wird die Ladesteuerung auf diese Periode eingegrenzt. In der übrigen Zeit ist die Ladung der Batterie freigegeben (Reading Battery_ChargeUnrestricted_XX) bzw. auf die maximal konfigurierte Ladeleistung eingestellt (Reading Battery_ChargeOptTargetPower_XX). Diese Readings können je nach verwendeter Ladestrategie ausgewertet und zur Steuerung der Batterie(n) verwendet werden.  &lt;br /&gt;
Die SoC-Steuerung wird durch die lcSlot-Angabe nicht beeinflusst.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit lcSlot kann zum Beispiel ein sequentielles Laden von mehreren Batterien umgesetzt werden. Nachfolgend wird ein solches Szenario mit drei Batterien  skizziert:&lt;br /&gt;
&lt;br /&gt;
1. die Batterie 1 soll mit voller Leistung geladen werden, die anderen Batterien nur bei weiterem Überschuß. Man würde die jeweiligen &lt;br /&gt;
ctrlBatSocManagementXX-&amp;gt;lcSlot Schlüssel definieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement01 lcSlot=23:00-23:10&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement02 lcSlot=00:00-23:59&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement03 lcSlot=00:00-23:59&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Wie ist der Ablauf: Die Batterie 1 unterliegt keiner Steuerung (nur von 23:00 bis 23:10 als Dummy-Periode). Das Reading Battery_ChargeUnrestricted_01 wird &amp;quot;1&amp;quot; gesetzt, d.h. die Batterie 1 wird zur Ladung uneingeschränkt freigegeben. Die anderen Batterien unterliegen der Steuerung -&amp;gt; Battery_ChargeUnrestricted_02 / 03 sind &amp;quot;0&amp;quot; und sollen nur geladen werden falls ein gesetztes Einspeiselimit überschritten wird.&lt;br /&gt;
&lt;br /&gt;
Ist das Ladeziel der Batterie 1 erreicht, setzt man um die Batterie 2 vollzuladen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement01 lcSlot=00:00-23:59&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement02 lcSlot=23:00-23:10&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement03 lcSlot=00:00-23:59&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Batterien 1 und 3 unterliegen der Steuerung, d.h. Battery_ChargeUnrestricted_01 / 03 haben den Wert &amp;quot;0&amp;quot;. Demgegenüber ist Battery_ChargeUnrestricted_02=1 und soll uneingeschränkt geladen werden.&lt;br /&gt;
&lt;br /&gt;
Ist auch die Batterie 2 voll geladen, würde man das Laden der Batterie 3 aktivieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement01 lcSlot=00:00-23:59&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement02 lcSlot=00:00-23:59&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement03 lcSlot=23:00-23:10&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Setzens via &#039;&#039;&#039;attrKeyVal&#039;&#039;&#039; hat den Vorteil, dass die Zeitfenster-Syntax (Anfangszeit kleiner Endezeit usw.) im Hintergrund peprüft und ggf. ein Fehler zurückgegeben wird, den der Nutzer in seinem Script auswerten kann. Weiterhin werden die Attribute implizit gespeichert sofern global-&amp;gt;autosave nicht explizit auf &amp;quot;0&amp;quot; gesetzt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Unterstützung eines netzdienlichen Verhaltens ====&lt;br /&gt;
&lt;br /&gt;
Der Steuerungsprozess der Batterieanlage leistet insgesamt einen kleinen Beitrag zur Netzstabilität, indem die Speicherladung in den Zeitraum der meisten prognostizierten Überschußeinspeisung gelegt wird. Im Sommer kann sich dieser Zeitraum in die Zeit nach dem Maxmimum des prognostizierten PV-Überschusses verlagern, wenn auch danach noch genügend Überschußenergie zu Volladung der Batterie prognostiziert wird. In dem Zusammenhang sollte im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; ein Einspeiselimit gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zur Verdeutlichung soll das Beispiel dienen:&lt;br /&gt;
&lt;br /&gt;
* die Batterie ist zu 60% geladen &lt;br /&gt;
* der User hat upSoC=40 eingestellt&lt;br /&gt;
* der User hat maxSoC=90 eingestellt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Am Vormittag ist genügend Sonne vohanden, das Maximumum der Energie über die Zeit wird aber noch erwartet. &lt;br /&gt;
Zu diesem Zeitpunkt wird das Reading  &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039; auf den Wert &amp;quot;0&amp;quot; gesetzt. Durch den Nutzer erfolgt daraufhin, zum Beipiel über ein Notify, ein anlagenspezifischer Befehl &amp;quot;Ladestop&amp;quot; an die Batterieanlage. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ab diesem Moment wird:&lt;br /&gt;
&lt;br /&gt;
# die Batterie nicht geladen&lt;br /&gt;
# die erzeugte PV-Energie dem Haushalt zur Verfügung gestellt bzw. der verbleibende Überschuß eingespeist, sofern der Überschuß unterhalb des im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limits liegt.&lt;br /&gt;
# ein eventuell über dem Limit &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; vorhandener Überschuß in die Batterie geladen und so die Netzlast verringert sowie die Batterie schonend geladen. (dieser Punkt trifft in den Monaten mit wenig PV-Erzeugung eher nicht zu)  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig liefert die Batterie Energie an das Hausnetz und wird von 60% bis maximal einem SoC-Wert entladen, der durch die [[#Die_dynamische_SOC_Steuerung_mit_Umsetzungsbeispiel|dynamische SOC Steuerung]] bestimmt wird. Dazu muß diese Steuerung natürlich implementiert sein. Sofern der berechnete SoC größer als upSoC ist, wird der maximale Entladungs-SoC auf upSoC gesetzt. &lt;br /&gt;
&lt;br /&gt;
Zusätzlich überprüft das Modul permanent bei jedem Zyklus die Differenz des aktuell vorhandenen SoC zum eingestellten maxSoC.&lt;br /&gt;
Sie soll nicht größer sein um mit dem (noch) zu erwartenden PV-überschuß des Tages der eingestellte maxSoC bzw. dessen Nähe wahrscheinlich erreicht werden kann. &lt;br /&gt;
Sollte der Differenz-Grenzwert erreicht sein, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; gesetzt und der Nutzer sollte dann über einen geeigneten Befehl seine Anlage in den Modus &amp;quot;Laden&amp;quot; umschalten.&lt;br /&gt;
Dieser Vorgang kann beliebig oft während des Tages alternieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Nutzung von batteryTrigger ===&lt;br /&gt;
Ergänzt werden die Möglichkeiten durch das set-Kommando: &lt;br /&gt;
&lt;br /&gt;
 batteryTrigger &amp;lt;1on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;1off&amp;gt;=&amp;lt;Wert&amp;gt; [&amp;lt;2on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;2off&amp;gt;=&amp;lt;Wert&amp;gt; ...] &lt;br /&gt;
&lt;br /&gt;
Das Kommando setzt Triggerpunkte bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %).&lt;br /&gt;
&lt;br /&gt;
Der verwendete SoC wird als resultierender SoC als Summe der aktuellen Ladung aller registrierten Batterie-Geräte im Verhältnis zur installierten Gesamtkapazität gebildet. Das bedeutet, dass alle einzelnen Batterie-Geräte als ein gemeinsamer Cluster betrachtet werden. &lt;br /&gt;
&lt;br /&gt;
Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise definiert werden.&lt;br /&gt;
Überschreiten die letzten drei SoC-Messungen eine definierte Xon-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = on&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
Unterschreiten die letzten drei SoC-Messungen eine definierte Xoff-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = off&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
&lt;br /&gt;
Der Inhalt der Readings kann durch ein User-Programm oder, bei Erzeugung von entsprechenden Events, mittels notify-Device ausgewertet werden um bei Eintreten eines definierten Ereignisses entsprechende Reaktionen auszulösen. Das kann zum Beispiel die Freigabe eines Heizstabes oberhalb eines bestimmten SOC sein oder ein Entladeverbot der Batterie unterhalb eines SOC-Wertes um Reserven für einen eventuellen Stromausfall zu behalten.&lt;br /&gt;
&lt;br /&gt;
Damit die Batterietrigger dynamisch geändert werden können, ist die Einstellung als Set-Kommando und nicht als Attribut ausgeführt.   &lt;br /&gt;
&lt;br /&gt;
Alle Triggerpunkte können mit dem set-Befehl:&lt;br /&gt;
&lt;br /&gt;
 reset batteryTriggerSet&lt;br /&gt;
&lt;br /&gt;
wieder gelöscht werden.&lt;br /&gt;
&lt;br /&gt;
== Verbrauchersteuerung - Registrieren und visualisieren 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;
Die Eigenschaften und das Schaltverhalten wird durch die Angabe der verfügbaren Schlüssel gesteuert. Die Möglichkeiten sind sehr umfangreich. Die nachfolgenden Abschnitte beschreiben die Verwendung am Beispiel oft vorkommender bzw. nachgefragter Sachverhalte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die Phasen der Verbrauchersteuerung ===&lt;br /&gt;
&lt;br /&gt;
Jeder Zyklus eines Verbrauchers durchläuft im Modul die folgenden Phasen:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Planung&#039;&#039;&#039; der Aktivzeiten des Verbrauchers, d.h. wann der Verbraucher geplant eingeschaltet sowie geplant ausgeschaltet wird und damit der Zyklus beendet wird.&lt;br /&gt;
# &#039;&#039;&#039;Start&#039;&#039;&#039; des Zyklus, d.h. Einschalten des Verbrauchers entsprechend der Planungsdaten sofern weitere, in den Consumer-Schlüsseln definierbare Rahmenbedingungen das Einschalten nicht verhindern (z.B. kein oder zu wenig PV-Energieerzeugung / PV-Überschuss)&lt;br /&gt;
# &#039;&#039;&#039;Permanente Überprüfung von&#039;&#039;&#039; eventuell vorhandenen &#039;&#039;&#039;Interruptbedingungen&#039;&#039;&#039; die den Verbraucher temporär ausschalten und, sofern die Interruptbedingung nicht mehr vorliegt, den Verbraucher wieder einschalten und so den gestarteten Zyklus fortsetzen.&lt;br /&gt;
#  &#039;&#039;&#039;Beendigung&#039;&#039;&#039; der Zyklus. Die Beendigung erfolgt entweder (normalerweise) wenn die geplante Endezeit der Zyklus erreicht ist oder eine optionale Endebedingung erfüllt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Steuerung der Phasen ====&lt;br /&gt;
Der Ablauf der Phasen kann durch verschiedene Schlüssel-Wert Paare beeinflusst und gesteuert werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; kann eine &#039;&#039;&#039;zusätzliche externe Bedingung&#039;&#039;&#039; definiert werden um den Einschaltvorgang des Consumers freizugeben. Ist die Bedingung (Regex) nicht erfüllt, erfolgt kein Einschalten des Verbrauchers auch wenn die sonstigen Voraussetzungen wie Zeitplanung, on-Schlüssel, auto-Mode und aktuelle PV-Leistung gegeben sind. Es erfolgt somit eine &#039;&#039;&#039;UND-Verknüpfung&#039;&#039;&#039; des Schlüssels swoncond mit den Planungsdaten und weiteren Einschaltbedingungen.&lt;br /&gt;
&lt;br /&gt;
Der optionale Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; definiert eine &#039;&#039;&#039;vorrangige Ausschaltbedingung&#039;&#039;&#039; (Regex). Sobald diese Bedingung erfüllt ist, wird der Consumer ausgeschaltet auch wenn die geplante Endezeit (consumerXX_planned_stop) noch nicht erreicht ist (&#039;&#039;&#039;ODER-Verknüpfung&#039;&#039;&#039;). Weitere Bedingungen wie off-Schlüssel und auto-Mode müssen zum automatischen Ausschalten erfüllt sein.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; kann während der geplanten Einschaltzeit eine automatische Unterbrechung sowie Wiedereinschaltung des Verbrauchers vorgenommen werden. Der Verbraucher wird temporär ausgeschaltet (interrupted) und wieder eingeschaltet (continued) wenn die Interrupt-Bedingung nicht mehr vorliegt. Die verbleibende Laufzeit wird durch einen Interrupt nicht beeinflusst! &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;power&#039;&#039;&#039; gibt die nominale Leistungsaufnahme des Verbrauchers gemäß seines Datenblattes an. Dieser Wert wird verwendet um die Schaltzeiten des Verbrauchers zu planen und das Schalten in Abhängigkeit des tatsächlichen PV-Überschusses zum Einplanungszeitpunkt zu steuern. Ist &#039;&#039;&#039;power=0&#039;&#039;&#039; gesetzt, wird der Verbraucher unabhängig von einem zum Zeitpunkt des Zyklus-Start eventuell nicht ausreichend vorhandenem PV-Überschuss wie geplant eingeschaltet und somit der Zyklus gestartet.&lt;br /&gt;
&lt;br /&gt;
Durch die Schlüssel &#039;&#039;&#039;notbefore&#039;&#039;&#039; und &#039;&#039;&#039;notafter&#039;&#039;&#039; kann der Startzeitpunkt des Verbrauchers so gesteuert werden, dass der Start des Zyklus nicht vor bzw. nach der angegebenen Zeit eingeplant wird. Diese Steuerung bezieht sich auf die &#039;&#039;Planung&#039;&#039;, d.h. der eigentliche Start des Verbrauchers kann sich unter Umständen durch vorhandene Rahmenbedingungen verzögern. &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; legt die geplanten Einschaltzeit, d.h. die Laufzeit des Zyklus fest. Der Name &#039;&#039;&#039;mintime&#039;&#039;&#039; ist nicht als MInimum-Zeit zu deuten, sondern beschreibt die angegebene Zeit in Minuten die der Zyklus dauern soll.&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist optional, da sich die Standard-Laufzeit des Verbrauchers von dessen Typ abgeleitet wird. Diese Standard Laufzeiten sind:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|dryer&lt;br /&gt;
|90 Minten&lt;br /&gt;
|-&lt;br /&gt;
|dishwasher&lt;br /&gt;
|180 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|washingmachine&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|heater&lt;br /&gt;
|240 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|charger&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|other&lt;br /&gt;
|60 Minuten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Der Verbraucher wurde nicht gestartet obwohl die Startzeit der Einplanung erreicht wurde ===&lt;br /&gt;
&lt;br /&gt;
Wenn die Startzeit des Consumers entsprechend der Einplanung erreicht oder überschritten ist, wird der Consumer eingeschaltet wenn die weiteren Voraussetzungen wahr sind:&lt;br /&gt;
&lt;br /&gt;
* es ist aktuell ein PV-Überschuss vorhanden und der PV-Überschuss deckt die kalkulierten Leistungsaufnahme des Verbrauchers ab. Mit den Schlüsseln &#039;&#039;&#039;power&#039;&#039;&#039; und &#039;&#039;&#039;spignorecond&#039;&#039;&#039; kann die Einschaltung trotz fehlendem PV-Überschuss ermöglicht werden. &lt;br /&gt;
&lt;br /&gt;
* die Angabe im Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; ist wahr (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* das Schalten ist über den Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; freigegeben (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* im Schlüssel &#039;&#039;&#039;on&#039;&#039;&#039; ist ein valides Einschaltkommando hinterlegt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind diese zusätzlichen Bedingungen nicht erfüllt, erfolgt kein Start des eingeplanten Zyklus. Der Verbraucher verbleibt in diesem Fall weiterhin im Status &#039;&#039;planned&#039;&#039; oder &#039;&#039;suspended&#039;&#039;. Die Startbedingungen werden regelmäßig reviewed und der Consumer gestartet sobald alle Startbedingungen wahr sind bzw. Start verhindernde Bedingungen entfallen sind. &lt;br /&gt;
&lt;br /&gt;
Dieser Vorgang erfolgt bis das geplante Ende des Verbaucherzyklus erreicht ist oder die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; zutrifft. Sobald die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; wahr ist, wird der gesamte Planungszyklus des Consumers beendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Kann manuell / automatisiert in den Planungszyklus eines Verbrauchers eingegriffen werden? ===&lt;br /&gt;
&lt;br /&gt;
Die Einplanung und die darauf aufbauenden Schaltprozesse laufen gemäß den hinterlegten Schlüsseloptionen im Modul automatatisch ab ohne dass ein Eingriff durch den Anwender erfolgen muß.&lt;br /&gt;
&lt;br /&gt;
Dennoch kann es gewünscht sein eine Neuplanung oder eine Sofortplanung eines Consumers vorzunehmen weil der Bedarf dazu besteht. Zu diesem Zweck stehen die Set-Kommandos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* consumerNewPlanning &lt;br /&gt;
&lt;br /&gt;
* consumerImmediatePlanning &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
zur Verfügung. &lt;br /&gt;
Beide Befehle initiieren die Consumer-Neuplanung, wobei mit dem Befehl &#039;&#039;consumerImmediatePlanning&#039;&#039; die eventuell im consumerXX Attribut gesetzten Schlüssel notbefore, notafter bzw. mode werden nicht beachtet werden. Dagenen beachtet der Befehl &#039;&#039;consumerNewPlanning&#039;&#039; alle definierten Schlüsseloptionen und dient gewöhnlich dazu einen abgeschlossenen Verbraucherzyklus wiederholt ausführen zu lassen weil die aktuelle Witterungslage dazu geeignet ist. &lt;br /&gt;
&lt;br /&gt;
Ein Anwendungsbeispiel dafür ist zum Beispiel die Ausführung von mehreren Waschmaschinen-Zyklen an einem langen, sonnigen Sommertag.&lt;br /&gt;
Diese beiden Set-Befehle können zum Beispiel über ein auf einen Schalter/Taster reagierendes Notify oder DOIF Device ausgeführt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung eines Verbrauchers mit getrennten Geräten für Messung und Schalten ===&lt;br /&gt;
&lt;br /&gt;
Es existieren in FHEM Geräte, die über verschiedene Kanäle für unterschiedliche Aufgaben verfügen. Diese Kanäle werden jeweils in einem gesonderten Device abgebildet. HomeMatic oder readingsProxy sind Beispiele für solche Varianten.&lt;br /&gt;
&lt;br /&gt;
Um solche Verbraucher einzubinden gibt es im consumerXX Attribut den Schlüssel &#039;&#039;&#039;switchdev&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Bei der Registrierung gibt man als Consumerdevice das Gerät für die Messung an und im Schüssel switchdev das entsprechende FHEM-Device, welches für die Schaltvorgänge benutzt wird. &lt;br /&gt;
Ist switchdev angegeben, beziehen sich die weiteren Schlüssel on, off, swstate, auto und asynchron auf dieses Gerät.&lt;br /&gt;
&lt;br /&gt;
In dem nachfolgenden Beispiel (Homematic) ist &#039;&#039;eg.az.fridge_Pwr&#039;&#039; FHEM Device für die Energiemessung. Die Schlüssel &#039;&#039;pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; geben Readings in diesem Device an damit SolarForecast den Verbrauch und die Energiemengen auslesen kann. Demgegenüber ist im Schlüssel &#039;&#039;switchdev&#039;&#039; das zugehörige Schalter-Device der Kombination angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eg.az.fridge_Pwr&lt;br /&gt;
type=noSchedule switchdev=eg.az.fridge_Sw power=0 icon=fridge pcurr=power:W:5 etotal=energyCalc:Wh &lt;br /&gt;
swstate=state:on:off auto=automatic&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung von Verbrauchern ohne Zeitplanung und aktivem Schalten ===&lt;br /&gt;
Manchmal besteht der Wunsch, Verbraucher in SolarForecast zu integrieren um lediglich folgende Sachverhalte abzubilden:&lt;br /&gt;
&lt;br /&gt;
* Visualisierung des Schaltstatus in der Consumer Legende und/oder der Energieflußgrafik&lt;br /&gt;
* Darstellung des aktuellen Energieverbrauchs in der Energieflußgrafik&lt;br /&gt;
* Erfassung der (externen) Schaltzeiten, d.h. der Zeiten der Gerätenutzung sowie der Verbrauchsdaten um deren Einfluß bei den Planungszeiten anderer Geräte durch SolarForecast berücksichtigen zu lassen&lt;br /&gt;
&lt;br /&gt;
In solchen Fällen werden bei der Registrierung die Schlüssel &#039;&#039;swstate, pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; zur Erfassung der Schaltzustände und der Energieverbrauchs angegeben, jedoch zur Verhinderung der Zeitplanung durch SolarForecast der Schlüssel &#039;&#039;&#039;type=noSchedule&#039;&#039;&#039; gesetzt sowie die Schlüssel &#039;&#039;on&#039;&#039; und &#039;&#039;off&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt eine mögliche Registrierung eines Zwischensteckers (Shelly) zur Erfassung der Daten eines Gefrierschrankes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Shelly.shellyplug4&lt;br /&gt;
type=noSchedule power=65 asynchron=1&lt;br /&gt;
icon=gefrierschrank &lt;br /&gt;
swstate=state:.*on.*:.*off.* &lt;br /&gt;
pcurr=relay_0_power:W:5 etotal=relay_0_energy_Wh:Wh&lt;br /&gt;
&amp;lt;/pre&amp;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;
&lt;br /&gt;
 Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off&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;
&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;
&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. Alternativ kann die Berücksichtigung des zwangsweisen PV Überschuss mit dem Schlüssel &amp;quot;spignorecond&amp;quot; im Consumer-Attribut ausgesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== zusätzliche Readings bzw. Erzeugung von statistischen Readings ==&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den zahlreichen im Modul per Standard erzeugten Readings kann der Anwender weitere Readings generieren lassen.&lt;br /&gt;
Diese zusätzlichen Readings geben entweder einen bestimmten Sachverhalt (Laufzeit, Status der API-Abfragen, etc.) oder einen statistischen Wert, z.B. die Batterieentladung des aktuellen Tages, wieder.&lt;br /&gt;
&lt;br /&gt;
Die zusätzlich erstellten Readings sind durch den Präfix &#039;&#039;&#039;special_&#039;&#039;&#039; im Device gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Diese zusätzlichen Informationen können durch das Setzen einer oder mehrerer Kennzeichen im Attribut &#039;&#039;&#039;ctrlSpecialReadings&#039;&#039;&#039; erzeugt werden. Die mögliche Auswahl wird je nach Bedarf ausgebaut und umfasst zum aktuellen Zeitpunkt (07.02.2025) diese Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;BatPowerIn_Sum: 	die Summe der momentanen Batterieladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;BatPowerOut_Sum: 	die Summe der momentanen Batterieentladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;allStringsFullfilled: 	Erfüllungsstatus der fehlerfreien Generierung aller Strings&lt;br /&gt;
;conForecastTillNextSunrise: 	Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
;currentAPIinterval: 	das aktuelle Abrufintervall der gewählten Strahlungsdaten-API in Sekunden&lt;br /&gt;
;currentRunMtsConsumer_XX: 	die Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; seit dem letzten Einschalten. (letzter Laufzyklus)&lt;br /&gt;
;dayAfterTomorrowPVforecast: 	liefert die Vorhersage der PV Erzeugung für Übermorgen (sofern verfügbar) ohne Autokorrektur (Rohdaten).&lt;br /&gt;
;daysUntilBatteryCare_XX: 	Tage bis zur nächsten Batterie XX Pflege (Erreichen der Ladung &#039;maxSoC&#039; aus Attribut ctrlBatSocManagementXX)&lt;br /&gt;
;lastretrieval_time: 	der letzte Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;lastretrieval_timestamp: 	der Timestamp der letzen Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;response_message: 	die letzte Statusmeldung der gewählten Strahlungsdaten-API&lt;br /&gt;
;runTimeAvgDayConsumer_XX: 	die durchschnittliche Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; an einem Tag&lt;br /&gt;
;runTimeCentralTask: 	die Laufzeit des letzten SolarForecast Intervalls (Gesamtprozess) in Sekunden&lt;br /&gt;
;runTimeTrainAI: 	die Laufzeit des letzten KI Trainingszyklus in Sekunden&lt;br /&gt;
;runTimeLastAPIAnswer: 	die letzte Antwortzeit des Strahlungsdaten-API Abrufs auf einen Request in Sekunden&lt;br /&gt;
;runTimeLastAPIProc: 	die letzte Prozesszeit zur Verarbeitung der empfangenen Strahlungsdaten-API Daten&lt;br /&gt;
;SunMinutes_Remain: 	die verbleibenden Minuten bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;SunHours_Remain: 	die verbleibenden Stunden bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;todayConsumptionForecast: 	Verbrauchsprognose pro Stunde des aktuellen Tages (01-24)&lt;br /&gt;
;todayConForecastTillSunset: 	Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
;todayDoneAPIcalls: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Calls&lt;br /&gt;
;todayDoneAPIrequests: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Requests&lt;br /&gt;
;todayConsumption: 	der gesamte Energieverbrauch (Wh) des Hauses am aktuellen Tag&lt;br /&gt;
;todayGridConsumption: 	die aus dem öffentlichen Netz bezogene Energie am aktuellen Tag&lt;br /&gt;
;todayGridFeedIn: 	die in das öffentliche Netz eingespeiste PV Energie am aktuellen Tag&lt;br /&gt;
;todayMaxAPIcalls: 	die maximal mögliche Anzahl Strahlungsdaten-API Calls. Ein Call kann mehrere API Requests enthalten.&lt;br /&gt;
;todayRemainingAPIcalls: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Calls&lt;br /&gt;
;todayRemainingAPIrequests: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Requests&lt;br /&gt;
;todayBatIn_XX: 	die am aktuellen Tag in die Batterie XX geladene Energie&lt;br /&gt;
;todayBatInSum: 	Summe der am aktuellen Tag in alle Batterien geladene Energie&lt;br /&gt;
;todayBatOut_XX: 	die am aktuellen Tag aus der Batterie XX entnommene Energie&lt;br /&gt;
;todayBatOutSum: 	Summe der am aktuellen Tag aus allen Batterien entnommene Energie&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Manche Angaben sind im Setup des Moduls optional, d.h. sie müssen nicht zwingend beim Setup angegeben werden. Allerdings sind diese Angaben für die Erstellung eines zusätzlichen Readings unter Umständen Voraussetzung. Es empfiehlt sich deshalb bei Setup so viele Informationen wie möglich zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
So ist zum Beispiel für die sinnvolle Erstellung der Informationen &#039;&#039;&#039;todayBatInSum&#039;&#039;&#039; und &#039;&#039;&#039;todayBatOutSum&#039;&#039;&#039; (Readings special_todayBatInSum und special_todayBatOutSum) das Vorhandensein der Schlüssel &#039;&#039;intotal&#039;&#039; und &#039;&#039;outtotal&#039;&#039; im Attribut setupBatteryDevXX notwendig (Beispiel):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupBatteryDev01 MQTT2_cerboGX_c0619ab34e08_battery &lt;br /&gt;
                              pin=BatIn:W pout=BatOut:W charge=SOC_value intotal=BatInTotal:Wh outtotal=BatOutTotal:Wh &lt;br /&gt;
                              cap=InstalledCapacity_Wh:Wh asynchron=1 show=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Fehlersuche ==&lt;br /&gt;
Das Modul SolarForecast ist sehr komplex und es die verschiedensten Datenquellen ausgewertet, zusammengeführt und daraus Ergebnisse berechnet und/oder visualisiert. Wird etwas nicht wie erwartet durch das Modul geliefert, können die Ursachen vielfältig sein. Natürlich kann ein Fehler im Modulcode vorliegen, oftmals gibt es aber andere Ursachen.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgenden Hinweise sollen Hilfe zur Selbsthilfe geben und sind eine Zusammenfassung von realen Fällen die mit dem beschriebenen Wegen und Verfahren gelöst wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die erwartete erzeugte PV-Energie ist im Modul zu gering und wird im Balkendiagramm nicht angezeigt === &lt;br /&gt;
&lt;br /&gt;
Die erzeugte PV-Energie wird nicht richtig angezeigt: Am Vormittag sind keine Werte vorhanden und, wenn dann etwas kommt, ist die Anzeige zu gering. Für 13 und 14 Uhr wurden ca. 5.000Wh erwartet (im Vergleich mit den Daten aus einer anderen Auswertungsquelle). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lösungsweg:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Aus dem List des Devices wurden die für den Fall wesentlichen Readings herausgezogen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVforecast 152 Wh&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVforecast 1400 Wh&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVforecast 2500 Wh&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVforecast 4392 Wh&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVforecast 4000 Wh&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVreal 300 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVforecast 6415 Wh&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVreal 3200 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVforecast 5629 Wh&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVreal 2700 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVforecast 3958 Wh&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVreal 900 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVforecast 945 Wh&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVreal 500 Wh&lt;br /&gt;
   &lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour18_PVforecast 59 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man sieht dass bis 12:00 keine erzeugte Energie vom WR gemeldet wird. Deswegen wird in der Balkengrafik nichts dargestellt. Auch danach bleibt die registrierte PV-Energie hinter den Erwartungen zurück. Zuständig für die Lieferung der PV-Energie an das Modul ist das Reading im Schlüssel:&lt;br /&gt;
&lt;br /&gt;
 setupInverterDev01 SH10rt pv=Total_DC_Power:W &amp;lt;mark&amp;gt;etotal=Total_Export_Energy_from_PV:kWh&amp;lt;/mark&amp;gt; capacity=10000 strings=Hauptdach,Flachdach&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Welche Änderungen es zwischen den Stunden gab, sieht man mit einem &amp;quot;get ... pvHistory XX&amp;quot; (&amp;quot;XX&amp;quot; steht für das Datum, d.h. den Tag, z.B. 02). &amp;lt;br&amp;gt;&lt;br /&gt;
Hier ein Beispiel für die Stunden 10 (9:00 - 9:59) und 11 (10:00 - 10:59). &amp;lt;br&amp;gt;&lt;br /&gt;
Wichtig ist hier der Key etotali01 für den ersten Inverter. Die Differenz zwischen den Werten beider Stunden ist die in der Stunde erzeugte Energie (hier 380 Wh). Diese 380 Wh findest du auch im Key pvrl01 als PVReal für diese Stunde. Das Modul rechnet intern immer mit Wh, kWh werden vorher in Wh umgerechnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
10 =&amp;gt; pvfc: 365, pvrl: 530, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63364714&amp;lt;/mark&amp;gt;, etotali02: 3044110, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;pvrl01: 380&amp;lt;/mark&amp;gt;, pvrl02: 150, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 574, con: 518, gcons: 22, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 1, feedprice: 0.1269&lt;br /&gt;
&lt;br /&gt;
            DoN: 1, sunaz: 137, sunalt: 12&lt;br /&gt;
&lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
      11 =&amp;gt; pvfc: 2966, pvrl: 1862, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63365094&amp;lt;/mark&amp;gt;, etotali02: 3044260, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            pvrl01: 1392, pvrl02: 470, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 774, con: 609, gcons: 25, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 4, feedprice: 0.1269&lt;br /&gt;
           &lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
D.h. wenn zwischen den beiden Stunden keine Differenzen zu finden sind, liegt es sehr wahrscheinlich am Input des Readings:&lt;br /&gt;
&lt;br /&gt;
 etotal=Total_Export_Energy_from_PV:kWh&lt;br /&gt;
&lt;br /&gt;
welches sich in den ersten Stunden nicht ändert und danach auch nur wenig.&lt;br /&gt;
&lt;br /&gt;
Man kann mit dem Attribut:&lt;br /&gt;
&lt;br /&gt;
 ctrlDebug=collectData&lt;br /&gt;
&lt;br /&gt;
die Datensammlung verfolgen (leider entstehen viele Daten im Log). Man sieht welche Werte von dem Inverter/Reading geliefert werden:&lt;br /&gt;
 &lt;br /&gt;
 ....&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; collect Inverter 01 data - device: STP_5000, delivery: default =&amp;gt;&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; pv: 0 W, &amp;lt;mark&amp;gt;etotal: 63378810 Wh&amp;lt;/mark&amp;gt;&lt;br /&gt;
 ....&lt;br /&gt;
&lt;br /&gt;
Dieser Wert muß bei PV Erzeugung kontinuierlich hochzählen. Wenn nicht, muss das angegebene Reading, d.h. die Quelle überprüft werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ergebnis der Prüfung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tatsächlich wurde ein Reading benutzt, das ungeeignet war: Statt &amp;quot;Total_PV_Generation&amp;quot; wurde &amp;quot;Total_export_energy_from_PV&amp;quot; genutzt. In diesem Reading wurde immer die in die Batterie gespeicherte Energie von der gesamten erzeugten Energie abgezogen. Daher war auch vormittags alles 0, da in dieser Periode alle PV-Energie in die Batterie geladen wurde bzw. in weiteren Stunden ein Anteil der dann bei dem PV-Erzeugungswert fehlte.&lt;br /&gt;
&lt;br /&gt;
Nachdem die Ursache beseitigt war, zeigt SolarForecast wieder die erwarteten PV-Erzeugungswerte an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Konfigurationsbeispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Visualisierung solare Vorhersage und reale Erzeugung ===&lt;br /&gt;
&lt;br /&gt;
Zu Beginn jedes neuen Tages gegen 00:00 Uhr werden durch das SolarForecast Device Events für die initiale PV Prognose des kommenden Tages erstellt.&lt;br /&gt;
Der Readingteil dieser Events heißt&lt;br /&gt;
&lt;br /&gt;
 AllPVforecastsToEvent&lt;br /&gt;
&lt;br /&gt;
Die Uhrzeiten der Events sind so aufbereitet und können direkt geloggt werden um sie in einen SVG Plot zu integrieren.&lt;br /&gt;
Im SolarForecast Device ist dieses Reading nicht sichtbar, nur die Events werden erstellt.&lt;br /&gt;
&lt;br /&gt;
Die meteorologischen Bedingungen verändern sich über den Tag permanent. Je nach gewählter Strahlungsdatenquelle (eine API oder DWD Device) erfolgt eine mehr oder weniger dynamische Anpassung der Prognose an die sich verändernde Umwelt.&lt;br /&gt;
&lt;br /&gt;
Aktuelle Prognosedaten sowie die reale PV Erzeugung der vergangenen Stunde können über die Readings&lt;br /&gt;
&lt;br /&gt;
 LastHourPVforecast&lt;br /&gt;
 LastHourPVreal&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-10-20 134050.png|right|thumb|400px|Übersicht solare Vorhersage]]&lt;br /&gt;
geloggt werden. &lt;br /&gt;
&lt;br /&gt;
Werden alle drei Werte in einem SVG kombiniert, kann die Entwicklung der Prognose über den Tag und die Beziehung von Prognose zu realer PV Erzeugnung pro Stunde visualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Für das rechts abgebildete Beispiel des Plots aus einer Datenbank &amp;quot;LogDBShort&amp;quot; sieht das gplot-File wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Created by FHEM/98_SVG.pm, 2024-03-08 15:05:31&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;TL&amp;gt;&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid&lt;br /&gt;
set ylabel &amp;quot;Wh&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Wh&amp;quot;&lt;br /&gt;
set yrange [0:7500]&lt;br /&gt;
set y2range [0:7500]&lt;br /&gt;
&lt;br /&gt;
#LogDBShort SolCast:LastHourPVforecast:::&lt;br /&gt;
#LogDBShort SolCast:LastHourPVreal:::&lt;br /&gt;
#LogDBShort SolCast:AllPVforecastsToEvent:::&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;aktuelle PV Vorhersage&#039; ls l6fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;reale PV Erzeugung&#039; ls l2fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;initiale PV Vorhersage&#039; ls l4 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; In manchen Fällen werden die Vorhersagewerte im SVG-Plot nicht angezeigt wenn FileLog verwendet wird. Ein Setzen des Attribute &amp;quot;fixedrange=3days +1&amp;quot; im SVG löst das Problem. Die Definition des SVG-Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_LogDBShort_SolCast SVG LogDBShort:SVG_LogDBShort_SolCast:HISTORY&lt;br /&gt;
attr SVG_LogDBShort_SolCast fixedrange 3days +1&lt;br /&gt;
attr SVG_LogDBShort_SolCast room Energie-&amp;gt;SolarPrognose&lt;br /&gt;
attr SVG_LogDBShort_SolCast sortby 2&lt;br /&gt;
attr SVG_LogDBShort_SolCast title &amp;quot;Übersicht solare Vorhersage&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Technisch bedingt werden an einem Tag X kurz nach 00:00 Uhr die am Vortag für den Tag X erzeugten Events aktualisiert. Diese Daten erzeugen in der Datenbank einen zweiten Satz an Daten mit dem gleichen Timestamp was für die Anzeige unvorteilhaft ist. &lt;br /&gt;
Um nur die aktualisierten Events von &#039;&#039;&#039;AllPVforecastsToEvent&#039;&#039;&#039; in der Datenbank zu erhalten, bietet sich ein DbRep-Device an. Die nachfolgende Vorschlagsdefinition kann per at-Device jeden Tag kurz vor Mitternacht (z.B. 23:57:10) ausgeführt werden. Es werden immer die in der Vergangenheit geschriebenen (veralteten) Daten aus der Datenbank gelöscht, doppelte Datesätze vermieden und immer die aktuellste initiale Prognose gespeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.Del.AllPVforecastsToEvent DbRep LogDBShort&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent alias Löschen Readings AllPVforecastsToEvent des Folgetages&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent comment ermöglicht dass die Readings AllPVforecastsToEvent am Folgetag wieder neu und aktuell geschrieben werden können&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent devStateIcon initialized:control_3dot_hor_s connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent disable 0&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent event-on-update-reading state&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent icon edit_delete&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent showproctime 1&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent device TYPE=SolarForecast&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_begin next_day_begin&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_end next_day_end&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das angegebene DbLog-Device &#039;&#039;&#039;LogDBShort&#039;&#039;&#039; ist natürlich anzupassen.&lt;br /&gt;
&lt;br /&gt;
Das at-Device zum Starten der Datenbankbereinigung sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define At.Del.AllPVforecastsToEvent at *23:58:10 set Rep.Del.AllPVforecastsToEvent delEntries&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent alias Start Löschen Readings AllPVforecastsToEventn LogDBShort&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent icon clock&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich sind auch hier die eigenen Devicenamen entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
Ab SolarForecast Version 1.51.7 kann die Eventerzeugung für bestimmte SVG Plot-Typen optimiert werden. &amp;lt;br&amp;gt; &lt;br /&gt;
Die Aktivierung dieser Optimierungen ist in der Online Hilfe zum Attribut &#039;&#039;&#039;plantControl-&amp;gt;genPVforecastsToEvent&#039;&#039;&#039; beschrieben. Bei Nutzung des Attributes plantControl-&amp;gt;genPVforecastsToEvent ist ebenfalls das Attribut &#039;&#039;&#039;event-on-update-reading=AllPVforecastsToEvent&#039;&#039;&#039; zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispielkonfiguration 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;
Bitte dabei diese DWD-Version aus dem [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter Contrib] von DS_Starter dazu nutzen&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|55_DWD_OpenData.pm&lt;br /&gt;
|136.2 KB ​&lt;br /&gt;
|29260  &lt;br /&gt;
|DS_Starter&lt;br /&gt;
|55_DWD_OpenData: contrib 1.17.7&lt;br /&gt;
|}&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 downloadTimeout 120&lt;br /&gt;
attr DWD comment Im DWD Wetterdevice verwendet Solarforecast : \&lt;br /&gt;
TTT,Neff,RR1c,ww,SunUp,SunRise,SunSet \&lt;br /&gt;
zusätzlich ist jedoch auch noch Rad1h notwendig \&lt;br /&gt;
wenn dieses DWD-Device als Strahlungsdevice genutzt wird.\&lt;br /&gt;
Die Station 10418 (Lüdenscheid) überträgt aktuell am 09.03.2025 (noch) Rad1h.\&lt;br /&gt;
attr DWD downloadTimeout 120&lt;br /&gt;
attr DWD forecastDays 7&lt;br /&gt;
attr DWD forecastProperties SunUp, SunRise, SunSet, Rad1h, R101, RR1c, TTT, Tx, Tn, Tg, DD, FX1, RR6c, R600, RRhc, Rh00, ww, wwd, Neff&lt;br /&gt;
attr DWD forecastRefresh 1&lt;br /&gt;
attr DWD forecastResolution 1&lt;br /&gt;
attr DWD forecastStation 10418&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 fc_description  -(state fc_time)&lt;br /&gt;
attr DWD verbose 2&lt;br /&gt;
&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;
defmod InverterDummy dummy&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;
defmod 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 feedinPrice 0.08&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 powerCost 0.25&lt;br /&gt;
attr SMA_Energymeter room 015_Zaehler,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;
defmod 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;
attr BatteryDummy userReadings total_pac, power_out, power_in, chargestatus, bat_rated_capacity, bat_loadtotal, bat_unloadtotal&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;
defmod N.PV.TotalConsumption.Dum.Energy notify SMA_Energymeter:Saldo_Wirkleistung:.* {\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung_2 Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&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;MB_USRW610_004&amp;quot;,&amp;quot;Power_Sum__W&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;
fhem &amp;quot;setreading InverterDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(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;
#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;
 # Batterie-total_pac  InverterDummy\&lt;br /&gt;
my $wert7 = sprintf(&amp;quot;%.3f&amp;quot;,((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy bat_rated_capacity &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert7));;\&lt;br /&gt;
 # möglicher Aufruf einer Batterie-Bebladung-Routine....SMABatteryChargewithTibber();;\&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;
defmod Forecast SolarForecast&lt;br /&gt;
attr Forecast DbLogExclude .*&lt;br /&gt;
attr Forecast DbLogInclude Current_BatCharge999&lt;br /&gt;
attr Forecast affectBatteryPreferredCharge 30&lt;br /&gt;
attr Forecast affectConsForecastLastDays 31&lt;br /&gt;
attr Forecast affect70percentRule 0&lt;br /&gt;
attr Forecast comment &amp;quot;wget -qO ./FHEM/76_SolarForecast.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/76_SolarForecast.pm&amp;quot;\&lt;br /&gt;
&amp;quot;wget -qO ./FHEM/55_DWD_OpenData.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/55_DWD_OpenData.pm&amp;quot;\&lt;br /&gt;
&amp;quot;13.01.2025 mit der Version 76_SolarForecast.pm:v1.43.2-s29518/2025-01-12&amp;quot;&lt;br /&gt;
attr Forecast graphicHeaderOwnspec PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal Verbrauch&amp;amp;nbsp;;bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast  Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest FCU-Erzeugung&amp;amp;nbsp;;:Current_PP01\&lt;br /&gt;
attr Forecast consumer01 FBDECT_fbahahttp_11657_0127183 icon=scene_washing_machine@orange type=washingmachine power=10 swstate:state notbefore=09 notafter=20 pcurr=power:W:3 etotal=energy:Wh interruptable=1 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer02 FBDECT_fbahahttp_E8_DF_70_07_3E_57 icon=light_floor_lamp@orange type=other power=15 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer03 FBDECT_fbahahttp_E8_DF_70_07_42_0B icon=raspberrypi@orange type=other power=8 swstate:state pcurr=power:W:1 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer04 FBDECT_fbahahttp_11657_0067275 icon=springbrunnen_icon@orange type=other power=50 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer05 FBDECT_fbahahttp_34_31_C4_D4_31_37 icon=sani_domestic_waterworks@orange type=other power=10 swstate:state pcurr=power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer06 tuya_local_bf5037060f450bdbd4rl0q icon=scene_clothes_dryer@orange type=dryer power=10 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer07 tuya_local_bfac44fb487476efd1vhdu icon=weather_sunset@orange type=noSchedule power=5 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumerControl adviceIcon=light_light_dim_100@gold&lt;br /&gt;
attr Forecast consumerControl showLegend=icon_top&lt;br /&gt;
attr Forecast consumerControl detailLink=1&lt;br /&gt;
attr Forecast ctrlAIdataStorageDuration 1825&lt;br /&gt;
attr Forecast ctrlAIshiftTrainStart 2&lt;br /&gt;
attr Forecast ctrlBatSocManagement01 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlBatSocManagement02 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlDebug none&lt;br /&gt;
attr Forecast plantControl genPVdeviation=continuously&lt;br /&gt;
attr Forecast plantControl cycleInterval=15&lt;br /&gt;
attr Forecast ctrlNextDayForecastReadings 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24&lt;br /&gt;
attr Forecast ctrlNextHoursSoCForecastReadings 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23&lt;br /&gt;
attr Forecast ctrlSpecialReadings BatPowerIn_Sum,BatPowerOut_Sum,SunHours_Remain,SunMinutes_Remain,allStringsFullfilled,conForecastTillNextSunrise,currentAPIinterval,currentRunMtsConsumer_01,currentRunMtsConsumer_02,currentRunMtsConsumer_03,currentRunMtsConsumer_04,currentRunMtsConsumer_05,currentRunMtsConsumer_06,currentRunMtsConsumer_07,dayAfterTomorrowPVforecast,daysUntilBatteryCare_01,daysUntilBatteryCare_02,lastretrieval_time,lastretrieval_timestamp,response_message,runTimeAvgDayConsumer_01,runTimeAvgDayConsumer_02,runTimeAvgDayConsumer_03,runTimeAvgDayConsumer_04,runTimeAvgDayConsumer_05,runTimeAvgDayConsumer_06,runTimeAvgDayConsumer_07,runTimeCentralTask,runTimeLastAPIAnswer,runTimeLastAPIProc,runTimeTrainAI,todayBatIn_01,todayBatIn_02,todayBatOut_01,todayBatOut_02,todayConForecastTillSunset,todayConsumptionForecast,todayDoneAPIcalls,todayDoneAPIrequests,todayGridConsumption,todayGridFeedIn,todayMaxAPIcalls,todayRemainingAPIcalls,todayRemainingAPIrequests&lt;br /&gt;
attr Forecast disable 0&lt;br /&gt;
attr Forecast event-min-interval .*:1800&lt;br /&gt;
attr Forecast event-on-change-reading .*&lt;br /&gt;
attr Forecast flowGraphicControl animate=1 consumerdist=80 h2consumerdist=50 shiftx=0  shifty=0 showconsumer=1 showconsumerdummy=1 showconsumerpower=1 showconsumerremaintime=0 size=400 strokewidth=12&lt;br /&gt;
attr Forecast graphicBeam1Color 3C14FF&lt;br /&gt;
attr Forecast graphicBeam1Content pvReal&lt;br /&gt;
attr Forecast graphicBeam2Color 19FF29&lt;br /&gt;
attr Forecast graphicBeam2Content pvForecast&lt;br /&gt;
attr Forecast graphicBeam3Color D60924&lt;br /&gt;
attr Forecast graphicBeam3Content batsocforecast_02&lt;br /&gt;
attr Forecast graphicBeam3FontColor FFFF0D&lt;br /&gt;
attr Forecast graphicBeam4Color FFFF1F&lt;br /&gt;
attr Forecast graphicBeam4Content batsocforecast_01&lt;br /&gt;
attr Forecast graphicBeam4FontColor 000000&lt;br /&gt;
attr Forecast graphicBeamHeightLevel1 200&lt;br /&gt;
attr Forecast graphicBeamHeightLevel2 200&lt;br /&gt;
attr Forecast graphicHeaderDetail all&lt;br /&gt;
attr Forecast graphicHeaderOwnspec #PV\&lt;br /&gt;
PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal\&lt;br /&gt;
PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast\&lt;br /&gt;
PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast\&lt;br /&gt;
:\&lt;br /&gt;
#\&lt;br /&gt;
AutarkyRate:Current_AutarkyRate\&lt;br /&gt;
Überschuss:Current_Surplus\&lt;br /&gt;
aktueller&amp;amp;nbsp;;Netzbezug:Current_GridConsumption\&lt;br /&gt;
:\&lt;br /&gt;
#Verbrauch\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenuntergang:special_todayConForecastTillSunset\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie01\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_01\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_01\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_01\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_01\&lt;br /&gt;
#Batterie01_tmp\&lt;br /&gt;
Current_PowerBatIn_01:Current_PowerBatIn_01\&lt;br /&gt;
Current_PowerBatOut_01:Current_PowerBatOut_01\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie02\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_02\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_02\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_02\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_02\&lt;br /&gt;
#Batterie02_tmp\&lt;br /&gt;
Current_PowerBatIn_02:Current_PowerBatIn_02\&lt;br /&gt;
Current_PowerBatOut_02:Current_PowerBatOut_02\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Settings\&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto \&lt;br /&gt;
Wetter:graphicShowWeather\&lt;br /&gt;
History:graphicHistoryHour\&lt;br /&gt;
ShowNight:graphicShowNight\&lt;br /&gt;
Debug:ctrlDebug\&lt;br /&gt;
FCU-Modus:FCU-Betriebsmodus@FCU&lt;br /&gt;
attr Forecast graphicHistoryHour 4&lt;br /&gt;
attr Forecast graphicHourCount 24&lt;br /&gt;
attr Forecast graphicLayoutType double&lt;br /&gt;
attr Forecast graphicShowDiff top&lt;br /&gt;
attr Forecast graphicShowNight 1&lt;br /&gt;
attr Forecast graphicShowWeather 1&lt;br /&gt;
attr Forecast group Energy Meter&lt;br /&gt;
attr Forecast room 020_PV,Energie&lt;br /&gt;
attr Forecast setupBatteryDev01 SBS25 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupBatteryDev02 SBS25_2 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupInverterDev01 SB25 pv=total_pac:kW etotal=etotal:kWh capacity=2500 strings=GarageSE limit=70&lt;br /&gt;
attr Forecast setupInverterDev02 SB30 pv=total_pac:kW etotal=etotal:kWh capacity=3000 strings=GarageNW,HausNW limit=70&lt;br /&gt;
attr Forecast setupInverterDev03 SB40 pv=total_pac:kW etotal=etotal:kWh capacity=4000 strings=HausSE1,HausSE2,HausSW limit=70&lt;br /&gt;
attr Forecast setupInverterStrings GarageSE,GarageNW,HausNW,HausSW,HausSE1,HausSE2&lt;br /&gt;
attr Forecast setupMeterDev SMA_Energymeter gcon=Bezug_Wirkleistung:W contotal=Bezug_Wirkleistung_Zaehler:kWh gfeedin=Einspeisung_Wirkleistung:W feedtotal=Einspeisung_Wirkleistung_Zaehler:kWh conprice=0.25:€ feedprice=0.08123:€&lt;br /&gt;
attr Forecast setupOtherProducer01 icon=Heizung_FCU_green@red MB_USRW610_004 pcurr=Power_L1__W:W etotal=Energy_L1_import__kWh:kWh&lt;br /&gt;
attr Forecast setupRadiationAPI DWD&lt;br /&gt;
attr Forecast setupStringPeak GarageSE=2.75 GarageNW=3.200 HausNW=2.230 HausSW=2.230 HausSE1=2.200 HausSE2=2.200&lt;br /&gt;
attr Forecast setupWeatherDev1 DWD&lt;br /&gt;
attr Forecast stateFormat Current_PV&lt;br /&gt;
attr Forecast userReadings Current_BatCharge999 {((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))) / ( (ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0) * 1000)  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0)*1000))*100}&lt;br /&gt;
attr Forecast verbose 2&lt;br /&gt;
&lt;br /&gt;
setstate Forecast 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .FCU_FCU-Betriebsmodus 2&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_ctrlDebug none&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicHistoryHour 4&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowNight 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowWeather 1&lt;br /&gt;
setstate Forecast 2025-01-13 08:24:25 .associatedWith SMA_Energymeter FBDECT_fbahahttp_11657_0127183 FBDECT_fbahahttp_E8_DF_70_07_3E_57 FBDECT_fbahahttp_E8_DF_70_07_42_0B FBDECT_fbahahttp_11657_0067275 FBDECT_fbahahttp_34_31_C4_D4_31_37 tuya_local_bf5037060f450bdbd4rl0q tuya_local_bfac44fb487476efd1vhdu SBS25 SBS25_2 SB25 SB30 SB40 DWD MB_USRW610_004&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .lastupdateForecastValues 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .pvCorrectionFactor_Auto_Soll on_complex_ai&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .signaldone_01 done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .signaldone_02 done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .signaldone_03 done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .signaldone_04 done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .signaldone_05 done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .signaldone_06 done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .signaldone_07 done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .signaldone_08 done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .signaldone_09 done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .signaldone_10 done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .signaldone_11 done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .signaldone_12 done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .signaldone_13 done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .signaldone_14 done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .signaldone_15 done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .signaldone_16 done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .signaldone_17 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .signaldone_18 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_01 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_02 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_01 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_02 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_AutarkyRate 83 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 Current_BatCharge999 10&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_01 12 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_02 8 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Consumption 626 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridConsumption 2 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridFeedIn 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PP_01 746.0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PV 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_01 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_02 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_01 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_02 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumption 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumptionRate 0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Surplus 120 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourGridconsumptionReal 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_ConsumptionForecast 2944 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayConsumptionForecast 3609 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_01 272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PPreal_01 748 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PPreal_01 787 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_01 271 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PPreal_01 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PPreal_01 745 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_01 267 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PPreal_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_01 255 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PPreal_01 752 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_01 226 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_01 50 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PPreal_01 681 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_02 233 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_01 845 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridConsumption 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_01 37 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_02 90 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_01 351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_02 188 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridConsumption 447 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVforecast 127 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridConsumption 1650 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVforecast 478 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVreal 26 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridConsumption 513 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVforecast 868 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVreal 97 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridConsumption 576 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVforecast 1157 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVreal 320 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_01 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_02 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridConsumption 1272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridFeedIn 7 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVforecast 1238 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVreal 945 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_01 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_02 53 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridConsumption 955 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridFeedIn 31 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PPreal_01 562 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVforecast 1168 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVreal 1410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_01 703 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_02 500 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_01 22 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_02 18 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridConsumption 32 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridFeedIn 71 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PPreal_01 777 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVreal 1416 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_01 296 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_02 70 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_01 74 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_02 258 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridConsumption 13 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridFeedIn 17 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PPreal_01 732 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVforecast 880 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVreal 1051 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_01 47 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_02 126 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_01 102 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_02 75 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridConsumption 15 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridFeedIn 23 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PPreal_01 771 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVforecast 117 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVreal 86 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_02 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_02 67 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridConsumption 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridFeedIn 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PPreal_01 723 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_01 349 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_02 124 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_01 73 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_02 450 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridConsumption 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridFeedIn 6 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PPreal_01 671 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecastTime 2025-01-13 14:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVdeviation 30.17 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVforecast 7663 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVreal 5351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunRise 08:28&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunSet 16:46&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_ConsumptionForecast 17043 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour05_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour06_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour07_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour08_PVforecast 10 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour09_PVforecast 161 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour10_PVforecast 275 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour11_PVforecast 532 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour12_PVforecast 730 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour13_PVforecast 1252 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour14_PVforecast 818 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour15_PVforecast 1465 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour16_PVforecast 303 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour17_PVforecast 20 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour18_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour19_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour20_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour21_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour22_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour23_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour24_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_PVforecast 5566 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunRise 08:27&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunSet 16:47&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01 name=&#039;_Waschmaschine&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_start 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_stop 14.01.2025 11:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02 name=&#039;_Esszimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_currentPower 15.3 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03 name=&#039;_FCU&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_currentPower 7.15 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04 name=&#039;_Brunnen&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05 name=&#039;_Zisterne&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06 name=&#039;SW Trockner&#039; state=&#039;unknown&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_stop 14.01.2025 08:30:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07 name=&#039;SW Urlaubslicht-Wohnzimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;noSchedule&#039; info=&#039;von extern umgeschaltet&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 nextCycletime 18:54:09&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 pvCorrectionFactor_10 0.53 (automatic - old factor: 1.00, Sun Alt range: 5, Cloud range: 75, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 pvCorrectionFactor_11 0.56 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 70, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 pvCorrectionFactor_12 0.64 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 pvCorrectionFactor_13 0.88 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 pvCorrectionFactor_14 1.10 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 50, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 pvCorrectionFactor_15 1.01 (automatic - old factor: 1.06, Sun Alt range: 15, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 pvCorrectionFactor_16 1.09 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 45, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 pvCorrectionFactor_17 0.28 (automatic - old factor: 0.52, Sun Alt range: 0, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 pvCorrectionFactor_Auto on_complex_ai&lt;br /&gt;
setstate Forecast 2024-10-30 19:42:19 setupStringAzimuth GarageSE=-55 GarageNW=125 HausNW=125 HausSW=35 HausSE1=-55 HausSE2=-55&lt;br /&gt;
setstate Forecast 2024-10-30 19:37:38 setupStringDeclination GarageSE=40 GarageNW=40 HausNW=50 HausSW=50 HausSE1=50 HausSE2=50&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerIn_Sum 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerOut_Sum 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunHours_Remain 0.00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunMinutes_Remain 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_allStringsFullfilled 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_conForecastTillNextSunrise 9467 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentAPIinterval 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_01 132 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_02 184 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_03 329512 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_04 200 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_05 27 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_06 193 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_07 106 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_dayAfterTomorrowPVforecast 7344 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_01 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_02 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_time 2025-01-13 18:53:54&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_timestamp 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_response_message success&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_01 545.94 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_02 382.10 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_03 1430.13 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_04 262.05 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_05 28.80 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_06 622.63 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_07 276.51 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeCentralTask 0.3744&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIAnswer -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIProc -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeTrainAI 1.2529&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_01 3683.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_02 1617.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_01 2287.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_02 1057.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConForecastTillSunset 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 special_todayConsumptionForecast_01 509 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 special_todayConsumptionForecast_02 499 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 special_todayConsumptionForecast_03 501 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 special_todayConsumptionForecast_04 511 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 special_todayConsumptionForecast_05 503 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 special_todayConsumptionForecast_06 495 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 special_todayConsumptionForecast_07 504 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 special_todayConsumptionForecast_08 561 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 special_todayConsumptionForecast_09 768 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 special_todayConsumptionForecast_10 783 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 special_todayConsumptionForecast_11 692 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 special_todayConsumptionForecast_12 791 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 special_todayConsumptionForecast_13 910 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 special_todayConsumptionForecast_14 1022 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 special_todayConsumptionForecast_15 965 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 special_todayConsumptionForecast_16 812 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 special_todayConsumptionForecast_17 884 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 special_todayConsumptionForecast_18 928 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_19 874 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_20 763 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_21 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_22 765 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_23 643 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_24 601 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIcalls 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIrequests 4532&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridConsumption 5500.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridFeedIn 178.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayMaxAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIrequests n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 state updated&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So sollte es dann als Ergebnis aussehen:&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13.png|zentriert|mini|Ergebnis nach kompletter Einrichtung]]&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13 Teil II.png|alternativtext=Unterer Teil der Anzeige|zentriert|mini]]&lt;br /&gt;
&lt;br /&gt;
== Praxisbeispiele und Lösungsansätze für Steuerungen ==&lt;br /&gt;
=== Fallstudie: Trockner darf pausiert werden, wenn nicht genug PV-Überschuss vorhanden ist, soll aber nach spätestens X Stunden fertig sein ===&lt;br /&gt;
Für diese Aufgabenstellung sind mehrere Schlüssel essentiell wichtig, &#039;&#039;&#039;power&#039;&#039;&#039;, &#039;&#039;&#039;mintime&#039;&#039;&#039;, &#039;&#039;&#039;mode&#039;&#039;&#039; und &#039;&#039;&#039;interruptable&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Die Bedingung, dass der Trockner nach spätestens X Stunden fertig sein soll, steht in einem Widerspruch zu der Möglichkeit den Trockner bei zu wenig PV-Überschuss unterbrechen zu können. Im Extremfall könnte nach dem Start die gesamte Planungszeit ungenügender Überschuss vorliegen und der Trockner nicht arbeiten. Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; (in Minuten) wird nun wie folgt angesetzt:&lt;br /&gt;
&lt;br /&gt;
 mintime = 2,5 x &amp;lt;gewöhnliche Betriebszeit für einen Trockengang (mneed, z.B. 120)&amp;gt; = 300 Minuten&lt;br /&gt;
&lt;br /&gt;
Das bedeutet, der Trockner wird nach 300 Minuten Laufzeit abgeschaltet werden bzw. vom Netz getrennt. Der Trockenvorgang wird natürlich bereits nach 120 Minuten beendet sein, sofern nach Start keine Unterbrechnung des Vorganges erfolgte. Wurde der Vorgang unterbrochen, soll der Trockner innerhalb &lt;br /&gt;
&lt;br /&gt;
 X+120 bis X+300 &lt;br /&gt;
&lt;br /&gt;
fertig sein. &lt;br /&gt;
&lt;br /&gt;
Demnach ist die ausgeführte Laufzeit des Trockners permanent zu überwachen, zu summieren (rtsum) und die notwendige Restzeit (mneed - rtsum) mit der noch verbleibenden Restzeit (mrest) bis zur geplanten Abschaltung des Consumers zu vergleichen. Ist der Consumer gestartet, wird die Laufzeit in der pvHistory für jede Stunde des Tages im Schlüssel &#039;&#039;minutescsmXX&#039;&#039; (XX = Consumernummer) aufgezeichnet und kann darüber ausgewertet werden. Somit ist:&lt;br /&gt;
&lt;br /&gt;
 msum = for (01 .. 24) {Summe von minutescsmXX} des aktuellen Tages&lt;br /&gt;
&lt;br /&gt;
Solange die Bedingung &lt;br /&gt;
&lt;br /&gt;
 mrest &amp;gt;= (mneed - msum)&lt;br /&gt;
&lt;br /&gt;
zutrifft, darf der Trockner unterbrochen werden, anderenfalls darf er nicht mehr unterbrochen werden da die Restzeit evtl. nicht ausreichen könnte um den Vorgang abzuschließen. Für die Planung des Trockners wird der Consumer wie gewöhnlich nach dem Bedarf im Modul registriert. Für die Steuerung der Unterbrechbarkeit wird noch ein Code erstellt, welcher im Trockner-Device &#039;&#039;Dryerdev&#039;&#039; das Reading &#039;&#039;SF_Int&#039;&#039; zur Unterbrechnungssteuerung verwaltet. Dieses Reading wird dem Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; übergeben. Für das Beispiel wird der Consumer &#039;07&#039; verwendet, es kann natürlich jede andere freie Nummer verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Dryerdev:Trockner&lt;br /&gt;
                        icon=scene_cloves_dryer type=dryer power=2000 mode=must mintime=300 &lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic asynchron=1&lt;br /&gt;
                        interruptable=Dryerdev:SF_Int:1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Kombination &#039;&#039;&#039;auto=automatic&#039;&#039;&#039; eröffnet die Möglickeit, in der Consumer-Legende den Trockner-Start zusätzlich manuell freizugeben oder zu verbieten. &lt;br /&gt;
&lt;br /&gt;
Im nachfolgenden Code werden modulinterne Subroutinen verwendet. Diese sind inklusive dem Paket &#039;&#039;FHEM::SolarForecast::&#039;&#039; anzugeben. Die erstellte Subroutine wird in die 99_mySolarForecastUtils.pm eingefügt. Die Datei 99_mySolarForecastUtils.pm wird vorher von 99_myUtils.pm kopiert und enthält für die Übersichtlichkeit nur Routinen für SolarForecast.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Trocknersteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub dryControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # gewöhlich benötigte Zeit für &lt;br /&gt;
                                                                                  # einen Trockengang, z.B. 120 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $dryer     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename des Trockners&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Trockner-Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit des Trockners&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      my $dhash = $defs{$dryer};&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 1, 0);                        # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 0, 0);                        # keine Interrupt-Freigabe&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die gewöhnliche Laufzeit des Trockners für einen Trockenvorgang (120 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::dryControl ($name, &#039;07&#039;, 120);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Fallstudie: Umwälzpumpe Pool soll X Stunden am Tag laufen. Ist kein PV-Überschuß vorhanden, müssen die X Stunden/Tag trotzdem erreicht werden ===&lt;br /&gt;
&lt;br /&gt;
Die Vorgehensweise ähnelt der Fallstudie zuvor. Verändernd kommt hinzu, dass der Planungszeitraum bewusst sehr lang angesetzt wird mit der Option, den Zyklus des Consumers vorfristig zu beenden sobald die Laufzeit von X Stunden am Tag erreicht ist. &lt;br /&gt;
Im folgenden Beispiel soll die Pumpe 5 Stunden am Tag (300 Minuten) laufen und dabei mögliche PV-Überschüsse ausnutzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Pump:Zirkulationspumpe&lt;br /&gt;
                        icon=sani_pump type=other power=50 mode=must mintime=780 notafter=09&lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic &lt;br /&gt;
                        interruptable=1 swoffcond=Pump:SF_Abort:1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit dieser Registrierung wird die Pumpe ca. 09 Uhr täglich starten. Wenn kein bzw. ungenügender PV-Überschuß vorhanden ist, erfolgt eine Unterbrechung nach dem Start. Ist genügender PV-Überschuß (wieder) vorhanden, erfolgt keine Unterbrechnung (mehr). Zusätzlich wird über den Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; eine vorfristige Beendigung veranlasst, sobald die gewünschte Tageslaufzeit erreicht ist.&lt;br /&gt;
&lt;br /&gt;
Zur Verwaltung des Schlüssels &#039;&#039;interruptable&#039;&#039; und des Readings &#039;&#039;SF_Abort&#039;&#039; verwenden wir eine leicht veränderte Subroutine aus dem vorhergehenden Fallbeispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Pumpensteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub pumpControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # Soll-Pumpenzeit, z.B. 300 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $pump      = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename der Pumpe&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;);&lt;br /&gt;
  my $intbl     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;interruptable&#039;, 1); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
  my $dhash     = $defs{$pump};&lt;br /&gt;
&lt;br /&gt;
  readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 0, 0);                                # default keine Zyklusbeendigung&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Pumpen Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit der Pumpe&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
     &lt;br /&gt;
      if ($msum &amp;gt;= $mneed) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 1, 0);                       # vorfristige Zyklusbeendigung&lt;br /&gt;
          return;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=1&amp;quot;) if(!$intbl);  # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=0&amp;quot;) if($intbl);   # keine Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Befehl &#039;&#039;attrKeyVal&#039;&#039; setzt den Schlüssel &#039;&#039;interruptable&#039;&#039; im Attribut &#039;&#039;consumer07&#039;&#039; dynamisch. Diese Strukturänderung wird automatisch im System gespeichert, sofern &#039;&#039;global-&amp;gt;autosave=1&#039;&#039; gesetzt ist. Diese Einstellung ist der FHEM default.  &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die Mindestlaufzeit der Umwälzpumpe (300 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::pumpControl ($name, &#039;07&#039;, 300);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamische Ladestromsteuerung eines Victron MultiPlus II Chargers mit Pylontech Batterie ===&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;
&lt;br /&gt;
 set &amp;lt;Device&amp;gt; MaxChargeCurrent &amp;lt;Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
eingestellt bzw. variiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Modul bietet dem Nutzer die Möglichkeit in dem Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltene Code wird am Ende jedes Zyklus (siehe Attribut &#039;&#039;plantControl-&amp;gt;cycleInterval&#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;
&lt;br /&gt;
&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 $mppt1   = &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common&#039;;              # SmartLoader Device&lt;br /&gt;
  my $maxcspc = 105;                        # max. Ladesollstrom (A) nominal&lt;br /&gt;
  my $spcorr  = 0.9;                        # Korrekturfaktor Überschuss 90%&lt;br /&gt;
  my $sch     = 0.25;                       # Verkürzungsfaktor Zeit bis Vollladung vor Sunset             &lt;br /&gt;
  &lt;br /&gt;
  my $cclvl0  = 15;                         # Ladestrom Level 0 max. 5  A (240 W) pro WR  (720  W)&lt;br /&gt;
  my $cclvl1  = 27;                         # Ladestrom Level 1 max. 9  A (432 W) pro WR  (1296 W)&lt;br /&gt;
  my $cclvl2  = 54;                         # Ladestrom Level 2 max. 18 A (864 W) pro WR  (2592 W)&lt;br /&gt;
  my $cclvl3  = 81;                         # Ladestrom Level 3 max. 27 A (1296 W) pro WR (3888 W)&lt;br /&gt;
  ###############&lt;br /&gt;
  &lt;br /&gt;
  my $cofc   = ReadingsNum ($name,  &#039;special_todayConForecastTillSunset&#039;, 0);&lt;br /&gt;
  my $pvfc   = ReadingsNum ($name,  &#039;RestOfDayPVforecast&#039;, 0);&lt;br /&gt;
  my $cpv    = ReadingsNum ($name,  &#039;Current_PV&#039;,          0);&lt;br /&gt;
  my $mppt1c = ReadingsNum ($mppt1, &#039;DC_0_Current_value&#039;,  0);             # Load I MPPT1 (max. 44 A)&lt;br /&gt;
  my $ssts   = CurrentVal  ($hash,  &#039;sunsetTodayTs&#039;,        0);&lt;br /&gt;
  my $srts   = CurrentVal  ($hash,  &#039;sunriseTodayTs&#039;,       0);&lt;br /&gt;
  my $sdiff  = ($ssts - $srts) / 3600;                                     # Sonnengang heute in h &lt;br /&gt;
  &lt;br /&gt;
  my $solh   = ReadingsNum ($name, &#039;special_SunHours_Remain&#039;, 0);          # h bis SunSet&lt;br /&gt;
  $solh      = $solh - ($sdiff * $sch);                                    # h bis SunSet - X&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;              # Ah Bat bis SOC&lt;br /&gt;
  $ahrem     = sprintf &amp;quot;%.0f&amp;quot;, $ahrem;&lt;br /&gt;
  &lt;br /&gt;
  my $fcdiff = ($pvfc - $cofc) * $spcorr;     # Korrektur d. noch prognostizierten Überschussenergie &lt;br /&gt;
  $fcdiff    = $fcdiff &amp;lt; 0 ? 0 : $fcdiff;     # Wh&lt;br /&gt;
  &lt;br /&gt;
  my $loadcur = $maxcspc;&lt;br /&gt;
  &lt;br /&gt;
  if ($cpv &amp;amp;&amp;amp; $solh &amp;amp;&amp;amp; $ahrem &amp;amp;&amp;amp; $fcdiff &amp;gt; $ahrem) {  # Ladeanforderung und Überschuss übersteigt &lt;br /&gt;
                                                      # Lademenge&lt;br /&gt;
      my $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($ahrem / $solh);    # A = Ah / h -&amp;gt; A Soll Schätzung&lt;br /&gt;
&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Battery charging process should be completed }.&lt;br /&gt;
                      qq{in &amp;gt;$solh&amp;lt; hours});&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; raw Target charging current: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($cspc - $mppt1c);      # SmartLoader IST berücksichtigen&lt;br /&gt;
	  &lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Charge Current minus MPPT load Current &amp;gt;$mppt1c&amp;lt;: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $loadcur = $cspc &amp;lt;= 0       ? 0       :     # nur MPPT Ladung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl0 ? $cclvl0 :     # Übergangsbereich&lt;br /&gt;
                 $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;
	  Log3 ($name, 3, qq{$name - userFn -&amp;gt; MaxChargeCurrent calculated: $loadcur});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent&#039;,       $loadcur.&#039; A&#039;,          1);&lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_HoursUntilChargeFinish&#039;, sprintf (&amp;quot;%.2f&amp;quot;,$solh), 1);&lt;br /&gt;
  CommandSet           (undef, &amp;quot;$vebus MaxChargeCurrent $loadcur&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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. 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;special_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;special_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;Verkürzungsfaktor Zeit bis Vollladung vor Sunset&#039;&#039;) reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche mindest Ladestromstärke ermittelt.&lt;br /&gt;
&lt;br /&gt;
&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 auch während der MQTT Intergration 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;
=== Poolheizung in Abhängigkeit von vorhandenem Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren) ===&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;consumer01&#039;&#039; wird beispielhaft wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr Forecast consumer01 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;&lt;br /&gt;
&lt;br /&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. &lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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, einen 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 Überschuss 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;. &lt;br /&gt;
&lt;br /&gt;
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;
=== PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) ===&lt;br /&gt;
[https://evcc.io evcc] ist ein Energie-Management-System, mit dem u.a. Überschussladen von Elektroautos möglich ist. Hier ist beschreiben, wie die SolarForecast-Vorhersagedaten per API von evcc abgerufen werden.&lt;br /&gt;
Lege im SolarForecast-Device ein User-Reading mit dem Namen forecast_json an. Es wandelt die Forecast-Werte in JSON und ins UTC-Zeitformat um, so dass evcc die Daten einlesen kann. Der Code wird nur ausgeführt, wenn das Reading nextCycletime ein Event erzeugt.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
forecast_json:nextCycletime.* {&lt;br /&gt;
&lt;br /&gt;
    use strict;&lt;br /&gt;
    use warnings;&lt;br /&gt;
    use JSON;&lt;br /&gt;
    use DateTime;&lt;br /&gt;
    use DateTime::Format::Strptime;&lt;br /&gt;
&lt;br /&gt;
    my $hour = 0;&lt;br /&gt;
    my $last_start_ts;    &lt;br /&gt;
    my @output;&lt;br /&gt;
    &lt;br /&gt;
    # Parser für Datum mit CET/CEST&lt;br /&gt;
    my $parser = DateTime::Format::Strptime-&amp;gt;new(&lt;br /&gt;
        pattern   =&amp;gt; &amp;quot;%Y-%m-%d %H:%M:%S&amp;quot;,&lt;br /&gt;
        time_zone =&amp;gt; &amp;quot;Europe/Berlin&amp;quot;,&lt;br /&gt;
    );&lt;br /&gt;
    my $start_ts;&lt;br /&gt;
    &lt;br /&gt;
    # Alle NextHour-Daten durchsuchen (als Fallback zur Vermeidung einer Endlosschleife auf max. 100 Std. begrenzen)&lt;br /&gt;
    while ($hour &amp;lt; 100) {&lt;br /&gt;
        my $hour_str = sprintf(&amp;quot;NextHour%02d&amp;quot;, $hour);&lt;br /&gt;
        my $start_str = FHEM::SolarForecast::NexthoursVal(&amp;quot;$NAME&amp;quot;, $hour_str, &amp;quot;starttime&amp;quot;, &amp;quot;na&amp;quot;);&lt;br /&gt;
        my $pvfc = FHEM::SolarForecast::NexthoursVal(&amp;quot;$NAME&amp;quot;, $hour_str, &amp;quot;pvfc&amp;quot;, &amp;quot;na&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        # Schleife beenden, wenn keine Vorhersage-Werte mehr vorhanden sind&lt;br /&gt;
        last if $start_str eq &amp;quot;na&amp;quot; or $pvfc eq &amp;quot;na&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        $start_ts = $parser-&amp;gt;parse_datetime($start_str);  # Zeitzone und Sommer/Winterzeit berücksichtigen&lt;br /&gt;
&lt;br /&gt;
        # Zeit nach UTC und ISO 8601 konvertieren und Vorhersagewert ergänzen&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $start_ts-&amp;gt;set_time_zone(&amp;quot;UTC&amp;quot;)-&amp;gt;iso8601() . &amp;quot;Z&amp;quot;,&lt;br /&gt;
            end   =&amp;gt; $start_ts-&amp;gt;add(hours =&amp;gt; 1)-&amp;gt;set_time_zone(&amp;quot;UTC&amp;quot;)-&amp;gt;iso8601() . &amp;quot;Z&amp;quot;,&lt;br /&gt;
            value =&amp;gt; 0 + $pvfc,&lt;br /&gt;
        };&lt;br /&gt;
        $hour++;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # Prüfen, ob der letzte Wert 23 Uhr war -&amp;gt; zusätzliche Stunde anhängen, damit der Tag&lt;br /&gt;
    # bei evcc als vollständig angezeigt wird (siehe https://github.com/evcc-io/evcc/issues/22979)&lt;br /&gt;
    if ($start_ts-&amp;gt;hour == 23) {&lt;br /&gt;
&lt;br /&gt;
        # Zeit nach UTC und ISO 8601 konvertieren und Vorhersagewert ergänzen&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $start_ts-&amp;gt;set_time_zone(&amp;quot;UTC&amp;quot;)-&amp;gt;iso8601() . &amp;quot;Z&amp;quot;,&lt;br /&gt;
            end   =&amp;gt; $start_ts-&amp;gt;add(hours =&amp;gt; 1)-&amp;gt;set_time_zone(&amp;quot;UTC&amp;quot;)-&amp;gt;iso8601() . &amp;quot;Z&amp;quot;,&lt;br /&gt;
            value =&amp;gt; 0,&lt;br /&gt;
        };      &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # Ausgabe als JSON&lt;br /&gt;
    my $json = JSON-&amp;gt;new-&amp;gt;utf8-&amp;gt;pretty-&amp;gt;encode(\@output);&lt;br /&gt;
    return $json;&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Datei:Screenshot 2025-08-04 104835.png|right|thumb|300px|Darstellung der PV-Vorhersage in evcc auf Basis der SolarForecast-Daten]]&lt;br /&gt;
Die Kommunikation läuft über den integrierten FHEM-Webserver, der die JSON-Daten aus dem Reading forecast_json veröffentlicht. Dazu wird in FHEM eine separate Webinstanz auf einem neuen Port erstellt, die ohne [[CsrfToken-HowTo|CSFR-Token]] (Achtung, Auswirkungen auf die Sicherheit beachten!) und nur von localhost aufrufbar ist (Voraussetzung: evcc läuft auf derselben Maschine wie FHEM):&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
define WEBapi FHEMWEB 8089&lt;br /&gt;
attr WEBapi csrfToken none&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;In der [https://docs.evcc.io/docs/tariffs#pv-vorhersage evcc-Konfig unter tariffs] steht die Quelle für die Solar-Vorhersage. Der FHEM-Befehl {ReadingsVal(&#039;solarforecast_dev&#039;,&#039;forecast_json&#039;,&#039;[]&#039;)} wird encoded und in die uri eingetragen. Trage statt solarforecast_dev den passenden Namen deines SolarForecast-Device ein. evcc holt die Daten aus dem Reading forecast_json dann regelmäßig ab.&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
solar:&lt;br /&gt;
  type: custom&lt;br /&gt;
  interval: 20m    &lt;br /&gt;
  forecast:&lt;br /&gt;
    source: http&lt;br /&gt;
    uri: http://localhost:8089/fhem?cmd=%7BReadingsVal%28%27solarforecast_dev%27%2C%27forecast_json%27%2C%27%5B%5D%27%29%7D&amp;amp;XHR=1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Zur Verbesserung der Sicherheit kann das neue WEBapi Device auch ein [[CsrfToken-HowTo#csrfToken festlegen|festes CSFR-Token]] verwenden. Dieses Token muss dann in der evcc-Konfiguration an die uri mittels &amp;amp;fwcsrf=&amp;lt;festes token&amp;gt; angehängt werden.&lt;br /&gt;
&lt;br /&gt;
=== Poolsteuerung inkl. Eigenverbrauchsoptimierung und zusätzlichem Verbraucher, um Einspeiselimit zu vermeiden + manuelle Steuerung durch Sonderprogramme ===&lt;br /&gt;
&#039;&#039;&#039;Vorhandene Hardware:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Poolpumpe, die über mehrere Stufen verfügt. Hier werden zwei verwendet.&lt;br /&gt;
** Pump Low: Energiesparprogramm um den Pool umzuwälzen, auch wenn nicht genug PV Leistung zur Verfügung steht. -&amp;gt; ca. 250W&lt;br /&gt;
** Pump High: Normalbetrieb wenn genug PV Überschuss zur Verfügung steht. -&amp;gt; ca. 800W zusätzlich&lt;br /&gt;
* Poolheizung: Wärmepumpe -&amp;gt; ca. 1,5kW elektrisch&lt;br /&gt;
* Nachbars Pool: Pumpe + Salzanlage +pH-Regler -&amp;gt; ca. 650W&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Anforderungen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Pool muss täglich mindestens 1x umgewälzt werden.&lt;br /&gt;
* Im Idealfall wird der Pool &amp;gt; 2x umgewälzt.&lt;br /&gt;
* Bei genügend Überschuss soll der Pool geheizt werden. Es soll nur Sonnenstrom für die Poolheizung verwendet werden.&lt;br /&gt;
* Um das Einspeiselimit zu vermeiden, soll auch geheizt werden, wenn der Pool schon warm genug ist. (&amp;gt;28,5 °C)&lt;br /&gt;
* Sollte trotzdem noch das Einspeiselimit erreicht werden, soll auch der Pool des Nachbarn versorgt werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Herausforderungen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Verbraucher dürfen nur in einer gewissen Reihenfolge geschaltet werden, auch wenn der Überschuss eine andere Reihenfolge ergeben würde.&lt;br /&gt;
* Pumpe mit mehreren Stufen muss als zwei Consumer abgebildet werden, um die Schaltlogik in SolarForecast abzubilden. Würde die Trennung außerhalb von Solarforecast realisiert, könnte Solarforecast den Verbraucher schlechter &amp;quot;lernen&amp;quot;, denn dann wäre es ein Consumer mit ständig wechselndem Verbrauch.&lt;br /&gt;
* Pool des Nachbarn darf nicht laut der benötigten Leistung geschaltet werden, sondern in Abhängigkeit der Einspeisebegrenzung.&lt;br /&gt;
&lt;br /&gt;
In diesem Solarforcast-Device sind 16 Verbraucher definiert. Im Weiteren werden jedoch nur die verwendeten betrachtet. Da diese Reglung mittlerweile recht komplex ist, werden auch viele Dinge, die nicht SolarForcast betreffen, aber trotzdem dazu gehören, gezeigt. Es trägt zum Verständnis bei und man kann sich hier sicher Ideen holen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ergebnis:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In den folgenden beiden Bildern sieht man das Regelverhalten recht gut.&lt;br /&gt;
[[Datei:Mustertag ohne Wolken.jpg|zentriert|mini|823x823px|Wolkenloser Tag]]&lt;br /&gt;
Hier erkennt man gut das Einschalten der jeweiligen Verbraucher (Pump Low, Pump High, Wärmepumpe und Nachbar Pool). Die Wärempumpe schaltet erst bei 5kW Überschuss ein, da der Pool eigentlich schon warm genug ist. Sie dient &amp;quot;nur&amp;quot; dazu, das EInspeiselimit zu verhindern.Auch das Auschalten ist wieder deutlich zu erkennen. Die Regleung folgt dem Überschuss recht gut. (Die Leistungsspitzen auf dem Plateau sind normale Großverbraucher im Haus.)&lt;br /&gt;
[[Datei:Wechselhaft.jpg|zentriert|mini|818x818px|Wechselhafter Tag.]]&lt;br /&gt;
In diesem Bild sieht man das &amp;quot;verzweifelte&amp;quot; Regeln um das wechselhafte Wetter auszugleichen. Hier gibt es keine korrekte Reaktion und es wird durch die Sperrzeiten und andere Delays versucht, ein zu häufiges hin- und herschalten möglichst zu vermeiden. In Summe aber auch bei so einem Wetter ein akzeptables Verhalten.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Definition der Consumer:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemeine Erklärungen zu den Definitionen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;asynchron=0&#039;&#039;&#039;: Da hier die Werte des Überschusses für das Timing der Schaltvorgänge verwendet werden, darf hier keine Eventsteuerung verwendet werden. Sonst kann man nicht mehr sagen, über welchen Zeitraum der Mittelwert oder der Median gebildet wurde. Dafür wurde die Zykluszeit des SolarForecast-Device auf 60 Sekunden geändert, um die Überlegungen zu vereinfachen. Bei Event-Steuerung könnte man nicht sagen ob die letzten 10 Events in den letzten 5 Sekunden oder in den letzten 10 Minuten aufgetreten sind.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;power=xxx&#039;&#039;&#039;: Wurde teilweise etwas höher als der tatsächliche Wert gewählt, um nach dem Einschalten sicherzustellen, dass nicht sofort der gesamte Überschuss &amp;quot;verbraucht&amp;quot; wird und somit gleich wieder abgeschaltet wird.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;auto=xxx&#039;&#039;&#039;: Jeder Verbraucher benötigt sein eigenes auto-Reading, da die Automatik für die Regelung in verschiedenen Stufen ein- und ausgeschaltet werden muss.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dum_valve&#039;&#039;&#039;: Dummy-Device in dem die Zustände der Regelung abgebildet werden. Notifys lesen bzw. befüllen diesen Dummy und steuern dann die Hardware bzw. wird der Dummy durch Werte aus der Hardware passend befüllt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;surpmeth=median_xx:&#039;&#039;&#039; Durch das asynchron=0 in allen Consumern und beim Generator wird von Solarforcast genau alle 60 Sekunden ein Zyklus ausgeführt. Das führt dazu, dass der Median genau über xx Minuten gebildet wird.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;locktime=xx:xx&#039;&#039;&#039;: Sicherheitsvorkehrung, dass nicht zu oft geschaltet werden kann. Schont die Hardware und verhindert ein Schwingen. Abhänging vom geschalteten Gerät. z.B. soll die Wärmepumpe möglichst wenig takten, um die Lebensdauer zu verlängern.&lt;br /&gt;
&lt;br /&gt;
Es gibt dann auch noch einige weitere Sicherheitsvorkehrungen, um diese Regelung möglichst stabil und hardwareschonend zu gestalten. Die Schwierigkeit sind nicht die Bilderbuchtage mit einem glatten Verlauf der PV-Leistung, sondern Tage mit ständig wechselndem Überschuss in der Nähe der Schaltgrenzen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;swoncond= dum_valve:sf_true:{main::xxx_On}:&#039;&#039;&#039; Hier werden verschiedene Zustände geprüft, um ein Gerät nur dann einzuschalten, wenn es sinnvoll und sicher ist.&lt;br /&gt;
&lt;br /&gt;
Details unter &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;swoffcond= dum_valve:sf_true:{main::xxx_Off}&#039;&#039;&#039;: Hier werden verschiedene Zustände geprüft, um ein Gerät nur dann auszuschalten, wenn es sinnvoll und sicher ist.&lt;br /&gt;
&lt;br /&gt;
Details unter &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pump Low: (consumer01)&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:Pool+Low&lt;br /&gt;
aliasshort=Low&lt;br /&gt;
asynchron=0&lt;br /&gt;
auto=pump_low_auto&lt;br /&gt;
icon=scene_pool&lt;br /&gt;
interruptable=0&lt;br /&gt;
mintime=SunPath:0:180&lt;br /&gt;
mode=must&lt;br /&gt;
noshow=0&lt;br /&gt;
notafter=08:00&lt;br /&gt;
off=&amp;quot;pump_low off&amp;quot;&lt;br /&gt;
on=&amp;quot;pump_low on&amp;quot;&lt;br /&gt;
pcurr=pump_low_power&lt;br /&gt;
power=250&lt;br /&gt;
surpmeth=median_13&lt;br /&gt;
switchdev=dum_valve&lt;br /&gt;
swoffcond=dum_valve:sf_true:{main::Check_Pump_Low_Off}&lt;br /&gt;
swoncond=dum_valve:sf_true:{main::Check_Pump_Low_On}&lt;br /&gt;
swstate=pump_low:on:off&lt;br /&gt;
type=other&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Die Pumpe soll ab Sonnenaufgang, bis 180 Minuten nach Sonnenuntergang (mintime=SunPath:0:180), bei mindestens 250W Überschuss (power=250) gestartet werden.&lt;br /&gt;
* Die Pumpe muss spätestens um 8:00 eingeplant werden (notafter=08:00), um das Umwälzen auch bei Schlechtwetter zu garantieren.&lt;br /&gt;
* Die Pumpe muss gestartet werden (mode=must) sobald sie eingeplant ist.&lt;br /&gt;
* swoncond sorgt dafür, dass sie vor 8:00 nur bei genügend Überschuss gestartet wird, oder es 8:00 ist. swondcond ist mit der eigentlichen Einschaltbedingung (eingeplant und mode=must) UND verknüpft. -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
* Überschuss wird auch in swoncond mit der gewählten Methode geprüft.&lt;br /&gt;
* Die Pumpe darf, wenn sie gestartet wurde, auch bei fehlendem Überschuss nicht mehr unterbrochen werden. (interruptable=0)&lt;br /&gt;
* Die Pumpe wird am Ende der Einplanung ausgeschaltet oder wenn swoffcond erfüllt ist. swoffcond wird true, wenn eine gewisse Wassermenge umgewälzt wurde oder die Sicherheitsbedingungen nicht (mehr) erfüllt sind. swoffcond ist mit der eigentlichen Ausschaltbedingung (Planung endet) ODER verknüpft. -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
* {&#039;&#039;&#039;main::&#039;&#039;&#039;xxx} dient dazu, um die Funktion xxx in der 99_mySolarForecastUtils.pm aus Solarforecast erreichbar zu machen.&lt;br /&gt;
* dum_valve:sf_true ist ein Reading, das fix 1 ist und als Vergleichswert für den in Klammern folgenden Perlcode dient. Wenn dieses Reading und der Perlcode gleich sind (1==1), ist die swoncond bzw swoffcond erfüllt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pump High: (consumer03)&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:Pool+High&lt;br /&gt;
aliasshort=High&lt;br /&gt;
type=other power=1000 asynchron=0&lt;br /&gt;
auto=pump_high_auto&lt;br /&gt;
icon=scene_pool&lt;br /&gt;
pcurr=pump_high_power&lt;br /&gt;
switchdev=dum_valve&lt;br /&gt;
swstate=pump_high:on:off&lt;br /&gt;
mode=can&lt;br /&gt;
mintime=SunPath&lt;br /&gt;
on=&amp;quot;pump_high on&amp;quot;&lt;br /&gt;
off=&amp;quot;pump_high off&amp;quot;&lt;br /&gt;
surpmeth=median_5&lt;br /&gt;
noshow=0&lt;br /&gt;
locktime=180:300&lt;br /&gt;
interruptable=1&lt;br /&gt;
swoncond=dum_valve:sf_true:{main::Check_Pump_High_On}&lt;br /&gt;
swoffcond=dum_valve:sf_true:{main::Check_Pump_High_Off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Pump HIgh ist die selbe Pumpe, aber eine höhere Durchflussmenge&lt;br /&gt;
* Der Mehrverbrauch beträgt eigentlich 800W wird hier aber mit 1000W angegeben, um eine Hysterese von ca. 200W zu erreichen und damit ein schnelles Abschalten nach dem Einschalten zu verhindern.&lt;br /&gt;
* Diese Stufe wird nur bei genügend Überschuss aktiviert. (mode=can)&lt;br /&gt;
* Diese Stufe wird bei fehlendem Überschuss unterbrochen. (interruptable=1)&lt;br /&gt;
* Diese Stufe wird nur während Sonnenschein eingeplant. (mintime=SunPath)&lt;br /&gt;
* locktime sorgt dafür, dass bei schnell wechselnden Bedingungen, nicht ständig umgeschaltet wird. -&amp;gt; Schonung der Pumpe.&lt;br /&gt;
* swoncond und swoffcond -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Heatpump: (consumer05)&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Pool_Strom_Heizung:Poolheizung&lt;br /&gt;
aliasshort=WP&lt;br /&gt;
type=other power=1800 asynchron=0&lt;br /&gt;
icon=sani_heating_heatpump&lt;br /&gt;
auto=heatpump_auto&lt;br /&gt;
pcurr=Pool_Pin32_monotonic_count_PowerCurrent:W&lt;br /&gt;
etotal=Pool_Pin32_monotonic_count_EnergyMeter:kWh&lt;br /&gt;
switchdev=dum_valve&lt;br /&gt;
swstate=heatpump:on:off&lt;br /&gt;
mode=can&lt;br /&gt;
locktime=600:600&lt;br /&gt;
mintime=SunPath&lt;br /&gt;
on=&amp;quot;heatpump on&amp;quot;&lt;br /&gt;
off=&amp;quot;heatpump off&amp;quot;&lt;br /&gt;
surpmeth=median_13&lt;br /&gt;
noshow=0&lt;br /&gt;
swoncond=dum_valve:sf_true:{main::CheckWPOn}&lt;br /&gt;
interruptable=1&lt;br /&gt;
swoffcond=dum_valve:sf_true:{main::CheckWPOff}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Der Verbrauch ist hier wieder etwas zu hoch angegeben (1800W statt realen 1500W), um eine Hysterese zu erreichen.&lt;br /&gt;
* Da es sich hier um eine Wärmepumpe handelt, die nicht getaktet werden sollte, ist die locktime in beide Schaltrichtungen mit 10 Minuten relativ hoch.&lt;br /&gt;
* Die Ermittlung des Medians ist mit 13 Minuten recht lang, um den Überschuss über lange Zeit zu glätten, damit möglichst selten geschaltet wird. Diese 13 Minuten in Kombination mit der Locktime und der Hysterese führten bei dieser Anlage bisher dazu, dass höchstens 5 Zyklen am Tag geschaltet wurden. -&amp;gt; Hier kann das individuelle Schaltverhalten optimiert werden. Besseres Verfolgen des Überschusses vs. weniger Taktungen der Wärmepumpe.&lt;br /&gt;
* swoncond und swoffcond -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nachbars Pool: (consumer07)&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Shelly_Plug_S_1:Kurz+Pool&lt;br /&gt;
aliasshort=Kurz&lt;br /&gt;
type=other power=650 asynchron=0&lt;br /&gt;
icon=scene_pool&lt;br /&gt;
auto=pool_kurz_auto&lt;br /&gt;
pcurr=power:W&lt;br /&gt;
switchdev=dum_valve&lt;br /&gt;
swstate=pool_kurz:on:off&lt;br /&gt;
mode=can&lt;br /&gt;
mintime=SunPath&lt;br /&gt;
on=&amp;quot;pool_kurz on&amp;quot;&lt;br /&gt;
off=&amp;quot;pool_kurz off&amp;quot;&lt;br /&gt;
surpmeth=median_13&lt;br /&gt;
noshow=0&lt;br /&gt;
interruptable=1&lt;br /&gt;
locktime=600:300&lt;br /&gt;
swoncond=dum_valve:sf_true:{main::Check_Pool_Kurz_On}&lt;br /&gt;
swoffcond=dum_valve:sf_true:{main::Check_Pool_Kurz_Off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Dieser Consumer dient als Einspeisebegrenzungsschutz und wird aktiviert, sobald sich der Überschuss der Einspeisegrenze nähert.  -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
* Verbraucher kann recht träge geschaltet werden. (surpmeth=median_13 und locktime=600:300)&lt;br /&gt;
* Consumer wird ausgeschaltet wenn ein gewisser Überschuss unterschritten wird und somit die Einspeisegrenze wieder weit genug weg ist. -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; &lt;br /&gt;
&#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hier sind die Funktionen, die für diese Regelung verwendet werden, der Übersichtlichkeit halber in einzelnen Blöcken mit Erklärungen dargestellt.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
package main;&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
&lt;br /&gt;
my $pool_dummy = &#039;dum_valve&#039;;&lt;br /&gt;
my $pool_temperature = &#039;Pool_Temp&#039;;&lt;br /&gt;
my $flow_sensor = &#039;Pool_Pin_A0&#039;;&lt;br /&gt;
my $water_counter_l1 = &#039;pump_l1_hc&#039;;&lt;br /&gt;
my $water_counter_l2 = &#039;pump_l2_hc&#039;;&lt;br /&gt;
my $target_temp = 28.4; # maximum temperature for heating, without infeed limit&lt;br /&gt;
my $pool_kurz_sw_hofb = &#039;PwSw_Schalter&#039;; # Homematic switch at pool neighbour&lt;br /&gt;
my $pool_kurz_sw_kurz = &#039;Shelly_Plug_S_1&#039;; # Shelly switch for pool Kurz at home&lt;br /&gt;
&lt;br /&gt;
my $pump_low_id			= sprintf &amp;quot;%02d&amp;quot;, 1;&lt;br /&gt;
my $pump_high_id		= sprintf &amp;quot;%02d&amp;quot;, 3;&lt;br /&gt;
my $heatpump_id			= sprintf &amp;quot;%02d&amp;quot;, 5;&lt;br /&gt;
my $pool_kurz_id		= sprintf &amp;quot;%02d&amp;quot;, 7;&lt;br /&gt;
&lt;br /&gt;
my $switch_delay = 160; # just under three minutes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
SolarForecastUtils_Initialize($$)&lt;br /&gt;
{&lt;br /&gt;
  my ($hash) = @_;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Hier werden die IDs der Geräte definiert, um über sprechende Namen darauf zugreifen zu können.&lt;br /&gt;
* Einige Devices und Parameter, die immer wieder gebraucht werden sind hier angegeben.&lt;br /&gt;
* sprintf wird verwendet um sicherzustellen, dass die IDs zweistellig sind. z.B. 3 -&amp;gt; 03&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pump Low&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
###################&lt;br /&gt;
### Pumpe - LOW ###&lt;br /&gt;
###################&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
Check_Pump_Low_On{&lt;br /&gt;
my $name = &#039;energy_mgmt&#039;;&lt;br /&gt;
my $surplus	= FHEM::SolarForecast::ConsumerVal ($name,$pump_low_id,&#039;surpmethResult&#039;,&#039;&#039;);&lt;br /&gt;
my $nom_power	= FHEM::SolarForecast::ConsumerVal ($name,$pump_low_id,&#039;power&#039;,&#039;&#039;);&lt;br /&gt;
my ($min, $hour) = (localtime())[1,2];&lt;br /&gt;
my $timer = 0;&lt;br /&gt;
if($hour &amp;gt; 8 || ($hour == 8 &amp;amp;&amp;amp; $min &amp;gt;= 0)){$timer=1;}&lt;br /&gt;
&lt;br /&gt;
if(ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;normal&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ($surplus &amp;gt; $nom_power&lt;br /&gt;
		|| $timer&lt;br /&gt;
	)&lt;br /&gt;
)&lt;br /&gt;
	{&lt;br /&gt;
	return 1;}&lt;br /&gt;
else&lt;br /&gt;
	{&lt;br /&gt;
	return 0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
Check_Pump_Low_Off{&lt;br /&gt;
my $bath_mode = ReadingsVal($pool_dummy,&amp;quot;bath_mode&amp;quot;,0);&lt;br /&gt;
my $m3_l1 = ReadingsVal($water_counter_l1,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $m3_l2 = ReadingsVal($water_counter_l2,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $water_volume = AttrVal($pool_dummy,&amp;quot;water_volume&amp;quot;,42); #42m³&lt;br /&gt;
my $desired_cf_l1 = AttrVal($pool_dummy,&amp;quot;desired_cf_l1&amp;quot;,0); #circulation_factor_level1&lt;br /&gt;
my $desired_cf_l2 = AttrVal($pool_dummy,&amp;quot;desired_cf_l2&amp;quot;,0); #circulation_factor_level2&lt;br /&gt;
my $bathmode_factor = AttrVal($pool_dummy,&amp;quot;bathmode_factor&amp;quot;,1);&lt;br /&gt;
my $desired_amount_l1;&lt;br /&gt;
my $desired_amount_l2;&lt;br /&gt;
my $amount = $m3_l1 + $m3_l2;&lt;br /&gt;
if($bath_mode == 1){&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume;&lt;br /&gt;
}else{&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume/$bathmode_factor;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume/$bathmode_factor;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if(($amount &amp;gt; $desired_amount_l1)&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;pump_high&amp;quot;,&amp;quot;on&amp;quot;) eq &amp;quot;off&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;pump_high&amp;quot;,0) &amp;gt;160)&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;normal&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
	{&lt;br /&gt;
		return 1;&lt;br /&gt;
	}else{&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Einschalten:&lt;br /&gt;
&lt;br /&gt;
* Es wird der errechnete Wert für den Überschuss von SolarForecast verwendet und auch der benötigte Überschuss aus dem Consumer ausgelesen.&lt;br /&gt;
* Das Einschalten wird erst durch erfolgreiche Prüfung der Hardwarevoraussetzungen erlaubt. -&amp;gt; Das Motorventil steht richtig und es ist kein Sonderbetrieb (Reinigung, Massage, Winter, o.ä.) aktiv.&lt;br /&gt;
* Es muss entweder genügend Überschuss vorhanden sein oder es ist 8:00.&lt;br /&gt;
&lt;br /&gt;
Ausschalten:&lt;br /&gt;
&lt;br /&gt;
* Wenn der Badebetrieb aktiv ist (bath_mode==1, [bei Außentemperatur &amp;gt; 24°C]) wird nach 90m³ Gesamtumwälzung ausgeschaltet.&lt;br /&gt;
* Wenn der Badebetrieb nicht aktiv ist (bath_mode==0, [bei Außentemperatur &amp;lt; 20°C]) wird bereits nach 42m³ Gesamtumwälzung ausgeschaltet.&lt;br /&gt;
* Prüfung, ob Pump High schon aus ist. Sollte durch die Logik gar nicht möglich sein, aber es könnte manuell oder durch einen (Logik-)Fehler trotzdem eingeschaltet sein.&lt;br /&gt;
* Prüfung, ob alle Hardware-Funktionen in einem für die Automatik geeigneten Zustand sind.&lt;br /&gt;
* Es wird auch geprüft, ob Pump High seit mindestens 3 Minuten aus ist, um zu verhindern, dass wegen fehlendem Überschuss gleich mehrere Geräte ausgeschaltet werden.&lt;br /&gt;
* Da die Zykluszeit 60 Sekunden ist, führen die 160 Sekunden dazu, dass nach drei Minuten(180 Sekunden) ein definierter Wert gilt. Mit 180 Sekunden könnte es manchaml eine Minute mehr sein.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pump High&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
####################&lt;br /&gt;
### Pumpe - HIGH ###&lt;br /&gt;
####################&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
Check_Pump_High_On{&lt;br /&gt;
my $bath_mode = ReadingsVal($pool_dummy,&amp;quot;bath_mode&amp;quot;,0);&lt;br /&gt;
my $m3_l1 = ReadingsVal($water_counter_l1,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $m3_l2 = ReadingsVal($water_counter_l2,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $water_volume = AttrVal($pool_dummy,&amp;quot;water_volume&amp;quot;,42); #42m³&lt;br /&gt;
my $desired_cf_l1 = AttrVal($pool_dummy,&amp;quot;desired_cf_l1&amp;quot;,0); #circulation_factor_level1&lt;br /&gt;
my $desired_cf_l2 = AttrVal($pool_dummy,&amp;quot;desired_cf_l2&amp;quot;,0); #circulation_factor_level2&lt;br /&gt;
my $bathmode_factor = AttrVal($pool_dummy,&amp;quot;bathmode_factor&amp;quot;,1);&lt;br /&gt;
my $desired_amount_l1;&lt;br /&gt;
my $desired_amount_l2;&lt;br /&gt;
my $amount = $m3_l1 + $m3_l2;&lt;br /&gt;
if($bath_mode == 1){&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume;&lt;br /&gt;
}else{&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume/$bathmode_factor;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume/$bathmode_factor;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if(($amount &amp;lt; $desired_amount_l2)&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;normal&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;pump_low&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;pump_low&amp;quot;,0) &amp;gt; $switch_delay)&lt;br /&gt;
)&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
Check_Pump_High_Off{&lt;br /&gt;
my $bath_mode = ReadingsVal($pool_dummy,&amp;quot;bath_mode&amp;quot;,0);&lt;br /&gt;
my $m3_l1 = ReadingsVal($water_counter_l1,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $m3_l2 = ReadingsVal($water_counter_l2,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $water_volume = AttrVal($pool_dummy,&amp;quot;water_volume&amp;quot;,42); #42m³&lt;br /&gt;
my $desired_cf_l1 = AttrVal($pool_dummy,&amp;quot;desired_cf_l1&amp;quot;,0); #circulation_factor_level1&lt;br /&gt;
my $desired_cf_l2 = AttrVal($pool_dummy,&amp;quot;desired_cf_l2&amp;quot;,0); #circulation_factor_level2&lt;br /&gt;
my $bathmode_factor = AttrVal($pool_dummy,&amp;quot;bathmode_factor&amp;quot;,1);&lt;br /&gt;
my $desired_amount_l1;&lt;br /&gt;
my $desired_amount_l2;&lt;br /&gt;
my $amount = $m3_l1 + $m3_l2;&lt;br /&gt;
&lt;br /&gt;
if($bath_mode == 1){&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume;&lt;br /&gt;
}else{&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume/$bathmode_factor;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume/$bathmode_factor;&lt;br /&gt;
}&lt;br /&gt;
if(($amount &amp;gt; $desired_amount_l2)&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;heatpump&amp;quot;,&amp;quot;on&amp;quot;) eq &amp;quot;off&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;heatpump&amp;quot;,0) &amp;gt;160)&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;normal&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Einschalten:&lt;br /&gt;
&lt;br /&gt;
* Prüfung, ob die gewünschte Umwälzung bezüglich des Badebetriebs noch nicht erreicht wurde.&lt;br /&gt;
* Prüfung der Hardwarevoraussetzungen.&lt;br /&gt;
* Prüfung, ob Pump Low schon seit mindestens 3 Minuten aktiv ist. (sollte eigentlich immer der Fall sein, wenn die Automatik für Pump High aktiv ist)&lt;br /&gt;
&lt;br /&gt;
Ausschalten:&lt;br /&gt;
&lt;br /&gt;
* Prüfung, ob die gewünschte Umwälzung bezüglich des Badebetriebs bereits erreicht wurde.&lt;br /&gt;
* Prüfung der Hardwarevoraussetzungen.&lt;br /&gt;
* Prüfung, ob die Wärmepumpe schon seit mindestens 3 Minuten aus ist. Ermöglicht drei Minuten lang, den Median für den Überschuss zu aktualisieren.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wärmepumpe&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
##################&lt;br /&gt;
### Wärempumpe ###&lt;br /&gt;
##################&lt;br /&gt;
sub&lt;br /&gt;
CheckWPOn(){&lt;br /&gt;
my $name = &#039;energy_mgmt&#039;;&lt;br /&gt;
my $surplus_on = 5000; # minimum surplus to avoid infeed limit with heatpump&lt;br /&gt;
my $surplus_restart = 3000; # minimum surplus to re-enable heatpump, when avoidung infeed limit and a big consumer turned the hp off&lt;br /&gt;
&lt;br /&gt;
my $planstate = FHEM::SolarForecast::ConsumerVal ($name,$heatpump_id,&#039;planstate&#039;,&#039;&#039;);&lt;br /&gt;
my $surplus	= FHEM::SolarForecast::ConsumerVal ($name,$heatpump_id,&#039;surpmethResult&#039;,&#039;&#039;);&lt;br /&gt;
if ($planstate =~ /^([^:]+)/) {&lt;br /&gt;
	$planstate = $1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if(ReadingsVal($flow_sensor,&amp;quot;reading&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;&lt;br /&gt;
		|| ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;party&amp;quot;&lt;br /&gt;
	)&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&#039;heat_protection&#039;,&#039;on&#039;) eq &amp;quot;off&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;normal&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;pump_high&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;pump_high&amp;quot;,0) &amp;gt; $switch_delay)&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_temperature,&amp;quot;temperature&amp;quot;,30) &amp;lt; $target_temp &lt;br /&gt;
		|| (ReadingsVal($pool_temperature,&amp;quot;temperature&amp;quot;,15) &amp;gt;= $target_temp&lt;br /&gt;
			&amp;amp;&amp;amp; ( $surplus &amp;gt; $surplus_on&lt;br /&gt;
				|| (($planstate eq &amp;quot;replanned&amp;quot;) &amp;amp;&amp;amp; ($surplus &amp;gt; $surplus_restart))&lt;br /&gt;
			)&lt;br /&gt;
		)&lt;br /&gt;
	)&lt;br /&gt;
)&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
CheckWPOff{&lt;br /&gt;
my $name = &#039;energy_mgmt&#039;;&lt;br /&gt;
my $surplus_off = 1000; #minimum surplus to keep heatpump on, when avoiding infeed limit&lt;br /&gt;
&lt;br /&gt;
my $surplus	= FHEM::SolarForecast::ConsumerVal ($name,$heatpump_id,&#039;surpmethResult&#039;,&#039;&#039;);&lt;br /&gt;
if((ReadingsVal($flow_sensor,&amp;quot;reading&amp;quot;,&amp;quot;on&amp;quot;) eq &amp;quot;off&amp;quot;&lt;br /&gt;
	|| !((ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;) &lt;br /&gt;
		|| (ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;party&amp;quot;)&lt;br /&gt;
	)&lt;br /&gt;
	|| ReadingsVal($pool_dummy,&#039;heat_protection&#039;,&#039;off&#039;) eq &amp;quot;on&amp;quot;&lt;br /&gt;
	|| ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) ne &amp;quot;normal&amp;quot;&lt;br /&gt;
	|| ((ReadingsVal($pool_temperature,&amp;quot;temperature&amp;quot;,15) &amp;gt; $target_temp)&lt;br /&gt;
		&amp;amp;&amp;amp; ($surplus &amp;lt; $surplus_off)&lt;br /&gt;
		)&lt;br /&gt;
	)&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;heatpump&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;heatpump&amp;quot;,0) &amp;gt; $switch_delay)&lt;br /&gt;
)&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Einschalten:&lt;br /&gt;
&lt;br /&gt;
* Prüfung, ob Flussensor ein. (Pool_pin_A0) -&amp;gt; Wasser fließt durch die Wärmepumpe.&lt;br /&gt;
* Prüfung, ob Pool in Normal- oder Partybetrieb ist und das Ventil in Normalposition ist. In beiden Fällen läuft Pump High.&lt;br /&gt;
* Einschalten wenn genug Überschuss da ist und die Temperatur &amp;lt;28.4°C ist oder wenn über 5000W Überschuss (Einspeisebegrenzung bei 5900W) da ist, egal wie warm der Pool ist.&lt;br /&gt;
* Sonderfall: Wenn die Wärmepumpe durch einen/mehrere Großverbrucher &amp;quot;kurz&amp;quot; ausgeschaltet wurde (swoffcond) wird sie ausgeplant. Ein Notify plant sie wieder ein. Wenn das passiert, soll die Wärmepumpe aber wieder bei 3000W Überschuss gestartet werden, um die Energie noch weiter zu nutzen bis der Überschuss unter 1000W fällt. (Hysterese von 500W, da die WP nur 1500W braucht)&lt;br /&gt;
&lt;br /&gt;
Ausschalten:&lt;br /&gt;
&lt;br /&gt;
* Ausschalten sobald hardwaremäßig irgendetwas faul ist. (Betriebsart, Ventilstellung, Durchfluss)&lt;br /&gt;
* Ausschalten wenn kein Überschuss. (interruptable=1)&lt;br /&gt;
* Wenn Wassertemperatur über 28,5°C und der Überschuss kleiner als 1000W ist.&lt;br /&gt;
* Nur schalten, wenn Wärmepumpe läuft und seit mindestens 3 Minuten läuft (Sicherheit). Das verhindert das erneute Triggern des Notifys, wenn die Pumpe schon aus ist. Sollte nicht passieren, aber sicher ist sicher.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nachbar Pool&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
###################&lt;br /&gt;
### Pool - KURZ ###&lt;br /&gt;
###################&lt;br /&gt;
sub&lt;br /&gt;
Check_Pool_Kurz_On{&lt;br /&gt;
my $name = &#039;energy_mgmt&#039;;&lt;br /&gt;
my $surplus	= FHEM::SolarForecast::ConsumerVal ($name,$pool_kurz_id,&#039;surpmethResult&#039;,&#039;&#039;);&lt;br /&gt;
if(($surplus &amp;gt; 3000)&lt;br /&gt;
	&amp;amp;&amp;amp; ((ReadingsVal($pool_dummy,&amp;quot;heatpump&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;heatpump&amp;quot;,0) &amp;gt;160) || ReadingsVal($pool_dummy,&#039;heat_protection&#039;,&#039;off&#039;) eq &#039;on&#039; ))&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
Check_Pool_Kurz_Off{&lt;br /&gt;
my $name = &#039;energy_mgmt&#039;;&lt;br /&gt;
my $surplus	= FHEM::SolarForecast::ConsumerVal ($name,$pool_kurz_id,&#039;surpmethResult&#039;,&#039;&#039;);&lt;br /&gt;
if(($surplus &amp;lt; 1000 )&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;pool_kurz&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;pool_kurz&amp;quot;,0) &amp;gt;160))&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Einschalten:&lt;br /&gt;
&lt;br /&gt;
* Überschuss ist nahe der Einspeisegrenze (5900W) und Wärmepumpe läuft seit mindestens 3 Minuten. Es wird schon bei 3000W eingeschaltet, um dem Nachbarn etwas Gutes zu tun ;-)&lt;br /&gt;
&lt;br /&gt;
Ausschalten:&lt;br /&gt;
&lt;br /&gt;
* Überschuss ist unter 1000W. -&amp;gt; Um noch Reserven für den eigenen Verbrauch zu haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hilfsfunktionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hier erfolgt nach jedem Zyklus die Festlegung der verschiedenen Automatikmodi.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#############################################################&lt;br /&gt;
##################### Exit Function #########################&lt;br /&gt;
#############################################################&lt;br /&gt;
my $ctrl_dummy	= &amp;quot;dum_valve&amp;quot;; # dummy device for pool-control&lt;br /&gt;
my $automatic	= ReadingsNum($ctrl_dummy,&amp;quot;sf_automatic&amp;quot;,1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if($automatic){&lt;br /&gt;
&lt;br /&gt;
	my $pump_low_state = ReadingsVal($ctrl_dummy,&#039;pump_low&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pump_low_auto	= FHEM::SolarForecast::ConsumerVal ($name, $pump_low_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Pumpe&lt;br /&gt;
&lt;br /&gt;
	my $pump_high_state = ReadingsVal($ctrl_dummy,&#039;pump_high&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pump_high_auto	= FHEM::SolarForecast::ConsumerVal ($name, $pump_high_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Pumpe&lt;br /&gt;
&lt;br /&gt;
	my $heatpump_state = ReadingsVal($ctrl_dummy,&#039;heatpump&#039;,&#039;on&#039;);&lt;br /&gt;
	my $heatpump_auto	= FHEM::SolarForecast::ConsumerVal ($name, $heatpump_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Wärmepumpe&lt;br /&gt;
	my $pool_heat_protection = ReadingsVal($ctrl_dummy,&#039;heat_protection&#039;,&#039;on&#039;);&lt;br /&gt;
&lt;br /&gt;
	my $pool_kurz_state = ReadingsVal($ctrl_dummy,&#039;pool_kurz&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pool_kurz_auto	= FHEM::SolarForecast::ConsumerVal ($name, $pool_kurz_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus des Pools&lt;br /&gt;
&lt;br /&gt;
	my $pump_low_delay	= FHEM::SolarForecast::ConsumerVal ($name, $pump_low_id, &#039;surpmeth&#039;, &#039;&#039;);&lt;br /&gt;
	if ($pump_low_delay =~ /_(\d+)/) {&lt;br /&gt;
    	$pump_low_delay = int(($1/2 + 1) * 60);&lt;br /&gt;
		Log3 (&amp;quot;SolarForecast&amp;quot;, 1, &amp;quot;SolarForecast: pump_low_delay: $pump_low_delay&amp;quot;);&lt;br /&gt;
	} else {&lt;br /&gt;
    	$pump_low_delay = 220;&lt;br /&gt;
		Log3 (&amp;quot;SolarForecast&amp;quot;, 1, &amp;quot;SolarForecast: warning - surpmeth for pump_low is: $pump_low_delay, but must be given as method_number, using fallback value&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	my $pump_high_delay	= FHEM::SolarForecast::ConsumerVal ($name, $pump_high_id, &#039;surpmeth&#039;, &#039;&#039;);&lt;br /&gt;
	if ($pump_high_delay =~ /_(\d+)/) {&lt;br /&gt;
    	$pump_high_delay = int(($1/2 + 1) * 60);&lt;br /&gt;
	} else {&lt;br /&gt;
    	$pump_high_delay = 160;&lt;br /&gt;
		Log3 (&amp;quot;SolarForecast&amp;quot;, 1, &amp;quot;SolarForecast: warning - surpmeth for pump_high is: $pump_high_delay, but must be given as method_number, using fallback value&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	my $heatpump_delay	= FHEM::SolarForecast::ConsumerVal ($name, $heatpump_id, &#039;surpmeth&#039;, &#039;&#039;);&lt;br /&gt;
	if ($heatpump_delay =~ /_(\d+)/) {&lt;br /&gt;
    	$heatpump_delay = int(($1/2 + 1) * 60);&lt;br /&gt;
	} else {&lt;br /&gt;
    	$heatpump_delay = 290;&lt;br /&gt;
		Log3 (&amp;quot;SolarForecast&amp;quot;, 1, &amp;quot;SolarForecast: warning - surpmeth for heatpump is: $heatpump_delay, but must be given as method_number, using fallback value&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	my $pool_kurz_delay	= FHEM::SolarForecast::ConsumerVal ($name, $pool_kurz_id, &#039;surpmeth&#039;, &#039;&#039;);&lt;br /&gt;
	if ($pool_kurz_delay =~ /_(\d+)/) {&lt;br /&gt;
    	$pool_kurz_delay = int(($1/2 + 1) * 60);&lt;br /&gt;
	} else {&lt;br /&gt;
    	$pool_kurz_delay = 160;&lt;br /&gt;
		Log3 (&amp;quot;SolarForecast&amp;quot;, 1, &amp;quot;SolarForecast: warning - surpmeth for pool_kurz is: $pool_kurz_delay, but must be given as method_number&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
############################&lt;br /&gt;
# Überhitzungsschutz aktiv #&lt;br /&gt;
############################&lt;br /&gt;
&lt;br /&gt;
if($pool_heat_protection eq &#039;on&#039;){&lt;br /&gt;
	if($heatpump_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy heatpump_auto 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	if($heatpump_state eq &amp;quot;on&amp;quot;){&lt;br /&gt;
			fhem(&amp;quot;set $ctrl_dummy heatpump off&amp;quot;)&lt;br /&gt;
	}&lt;br /&gt;
	#################&lt;br /&gt;
	#### on-chain ###&lt;br /&gt;
	#################&lt;br /&gt;
	if($pump_low_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pump_low&#039;,0) &amp;gt; $pump_high_delay &amp;amp;&amp;amp; $pump_high_auto == 0  &amp;amp;&amp;amp; $pool_kurz_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pump_high_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pump_high&#039;,0) &amp;gt; $pool_kurz_delay &amp;amp;&amp;amp; $pool_kurz_auto == 0 &amp;amp;&amp;amp; $pump_high_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pool_kurz_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pool_kurz_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $pool_kurz_auto == 1 &amp;amp;&amp;amp; $pump_high_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	#################&lt;br /&gt;
	### off-chain ###&lt;br /&gt;
	#################&lt;br /&gt;
	if($pool_kurz_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pool_kurz&#039;,0) &amp;gt; $pump_high_delay &amp;amp;&amp;amp; $pool_kurz_auto == 1 &amp;amp;&amp;amp; $pump_high_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pump_high_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high_auto == 1 &amp;amp;&amp;amp; $pool_kurz_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pool_kurz_auto 0&amp;quot;);&lt;br /&gt;
	}elsif($pump_low_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high_auto == 1 &amp;amp;&amp;amp; $pool_kurz_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
##################################&lt;br /&gt;
# Überhitzungsschutz nicht aktiv #&lt;br /&gt;
##################################&lt;br /&gt;
}else{&lt;br /&gt;
	if($heatpump_auto == 0 &amp;amp;&amp;amp; $heatpump_state eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		if($pool_kurz_state eq &amp;quot;on&amp;quot;){&lt;br /&gt;
			fhem(&amp;quot;set $ctrl_dummy pool_kurz off&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if($pool_kurz_auto == 1){&lt;br /&gt;
			fhem(&amp;quot;set $ctrl_dummy pool_kurz_auto 0&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	#################&lt;br /&gt;
	#### on-chain ###&lt;br /&gt;
	#################&lt;br /&gt;
	if($pump_low_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pump_low&#039;,0) &amp;gt; $pump_high_delay &amp;amp;&amp;amp; $pump_high_auto == 0 &amp;amp;&amp;amp; $heatpump_auto == 0 &amp;amp;&amp;amp; $pool_kurz_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pump_high_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pump_high&#039;,0) &amp;gt; $heatpump_delay &amp;amp;&amp;amp; $heatpump_auto == 0 &amp;amp;&amp;amp; $pool_kurz_auto == 0 &amp;amp;&amp;amp; $pump_high_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy heatpump_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($heatpump_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;heatpump&#039;,0) &amp;gt; $pool_kurz_delay &amp;amp;&amp;amp; $pump_high_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $pool_kurz_auto == 0 &amp;amp;&amp;amp; $pump_high_auto == 1 &amp;amp;&amp;amp; $heatpump_auto == 1){&lt;br /&gt;
		# pump_high muss on sein, da sonst die automatik ausgeschaltet wird wenn die pumpe gerade interrupted ist.&lt;br /&gt;
		# Bei unterschiedlichen Medianlängen ist es möglich, dass WP ein ist und pump_high abschaltet wegen surplus == 0&lt;br /&gt;
		# Nachbarpool würde auf EIN warten, aber pump_high dürfte nicht wieder einschalten, obwohl genügend Überschuss da ist.&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 0&amp;quot;);&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pool_kurz_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pool_kurz_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $pool_kurz_auto == 1 &amp;amp;&amp;amp; $heatpump_auto == 1 &amp;amp;&amp;amp; $pump_high_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy heatpump_auto 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	#################&lt;br /&gt;
	### off-chain ###&lt;br /&gt;
	#################&lt;br /&gt;
	if($pool_kurz_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pool_kurz&#039;,0) &amp;gt; $heatpump_delay &amp;amp;&amp;amp; $pool_kurz_auto == 1 &amp;amp;&amp;amp; $heatpump_auto == 0 &amp;amp;&amp;amp; $pump_high_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy heatpump_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($heatpump_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;heatpump&#039;,0) &amp;gt; $pump_high_delay &amp;amp;&amp;amp; $heatpump_auto == 1 &amp;amp;&amp;amp; $pump_high_auto == 0 &amp;amp;&amp;amp; $pool_kurz_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pool_kurz_auto 0&amp;quot;);&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pump_high_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $heatpump_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high_auto == 1 &amp;amp;&amp;amp; $heatpump_auto == 1 &amp;amp;&amp;amp; $pool_kurz_auto == 0){&lt;br /&gt;
#	heatpump muss aus sein, da sonst vor Ablauf der Locktime die Automatik ausgeschaltet wird und die WP nicht mehr ausschalten kann.&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy heatpump_auto 0&amp;quot;);&lt;br /&gt;
	}elsif($pump_low_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high_auto == 1 &amp;amp;&amp;amp; $heatpump_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
#################################################&lt;br /&gt;
# Check hardware-state vs. reading-state&lt;br /&gt;
# re-trigger notify&lt;br /&gt;
#################################################&lt;br /&gt;
my $delay_retrigger = 100; #delay time to wait until re-trigger the notify&lt;br /&gt;
&lt;br /&gt;
if(ReadingsVal($ctrl_dummy,&#039;pool_kurz&#039;,&#039;on&#039;) eq &#039;off&#039; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pool_kurz&#039;,0) &amp;gt; $delay_retrigger &amp;amp;&amp;amp; ReadingsVal($pool_kurz_sw_kurz,&#039;state&#039;,&#039;off&#039;) eq &#039;on&#039;){&lt;br /&gt;
	# re-trigger notify&lt;br /&gt;
	fhem(&amp;quot;trigger dum_valve pool_kurz: off&amp;quot;);&lt;br /&gt;
	Log3 (&amp;quot;SolarForecast&amp;quot;, 1, &amp;quot;SolarForecast: Pool-Kurz-off must be re-triggered&amp;quot;);&lt;br /&gt;
	DebianMail(&#039;clemens@familie-hofbauer.at&#039;,&#039;Notify Pool Kurz&#039;,&amp;quot;Notify hat nicht ausgeschaltet -&amp;gt; re-trigger&amp;quot;);&lt;br /&gt;
}elsif(ReadingsVal($ctrl_dummy,&#039;pool_kurz&#039;,&#039;off&#039;) eq &#039;on&#039; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pool_kurz&#039;,0) &amp;gt; $delay_retrigger &amp;amp;&amp;amp; ReadingsVal($pool_kurz_sw_kurz,&#039;state&#039;,&#039;on&#039;) eq &#039;off&#039;){&lt;br /&gt;
	# re-trigger notify&lt;br /&gt;
	fhem(&amp;quot;trigger dum_valve pool_kurz: on&amp;quot;);&lt;br /&gt;
	Log3 (&amp;quot;SolarForecast&amp;quot;, 1, &amp;quot;SolarForecast: Pool-Kurz-on must be re-triggered&amp;quot;);&lt;br /&gt;
	DebianMail(&#039;clemens@familie-hofbauer.at&#039;,&#039;Notify Pool Kurz&#039;,&amp;quot;Notify hat nicht eingeschaltet -&amp;gt; re-trigger&amp;quot;);&lt;br /&gt;
}elsif((ReadingsVal($pool_kurz_sw_kurz,&#039;state&#039;,&#039;off&#039;) eq &#039;set_on&#039; || ReadingsVal($pool_kurz_sw_kurz,&#039;state&#039;,&#039;off&#039;) eq &#039;set_off&#039;) &amp;amp;&amp;amp; ReadingsAge($pool_kurz_sw_kurz,&#039;state&#039;,0) &amp;gt; $delay_retrigger){&lt;br /&gt;
	# state not clear&lt;br /&gt;
	Log3 (&amp;quot;SolarForecast&amp;quot;, 1, &amp;quot;SolarForecast: Pool-Kurz state unclear&amp;quot;);&lt;br /&gt;
	DebianMail(&#039;clemens@familie-hofbauer.at&#039;,&#039;Status Pool Kurz unklar&#039;,&amp;quot;Status HM-Schalter set_xx&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Erläuterungen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Verzögerungen der einzelnen Stufen:&#039;&#039;&#039;&lt;br /&gt;
** Die delays der einzelnen Stufen werden aus den surpmethods berechnet. Das dient dazu, dass der Median mit den Werten nach dem ein-/ausschalten des vorheriegen Verbrauchers bis zur Hälfte + einen Wert gefüllt wird und somit sicher das Umschalten des vorherigen Verbrauchers den Median nicht mehr beeinflusst.&lt;br /&gt;
* &#039;&#039;&#039;Überhitzungsschutz:&#039;&#039;&#039;&lt;br /&gt;
** Da durch die Wärmepumpe Überschuss &amp;quot;verheizt&amp;quot; wird, der durch das Einspeiselimit gar nicht produziert würde, kann es vorkommen, dass der Pool unangenehm warm wird.&lt;br /&gt;
** Um das zu vermeiden gibt es ein Reading, welches gesetzt wird, wenn der Pool eine gewisse Temperatur überschreitet. Dieses Setzen und Zurücksetzen erfolgt mit einer Hysterese von 0.2°C, um ein Takten der Wärmepumpe zu verhindern. Diese 0.4°C sind bei dieser Wassermenge einige Stunden.&lt;br /&gt;
** Wenn der Überhitzungsschutz aktiv ist, wird die Wärmepumpe in der Kette übersprungen.&lt;br /&gt;
** Wenn sich der Hitzeschutz während des Betriebs ändert, wird die Wärmepumpe bzw. der Pool vom Nachbarn passend ausgeschaltet und die Modi entsprechend gesetzt.&lt;br /&gt;
* &#039;&#039;&#039;On-chain:&#039;&#039;&#039;&lt;br /&gt;
** Wenn am Morgen Pump Low seit $pump_low_delay aktiv ist und alle folgenden Consumer noch nicht, dann wird die nächste Stufe freigegeben. -&amp;gt; Pump High&lt;br /&gt;
** Wenn Pump High seit $pump_high_delay aktiv ist und alle folgenden Consumer noch nicht, wird die Wärmepumpe freigegeben. -&amp;gt; Heatpump&lt;br /&gt;
** Wenn die Wärmepumpe seit $heatpump_delay aktiv ist und der letzte Consumer noch nicht, wird der letzte Verbraucher freigegeben. -&amp;gt; Pool Kurz Gleichzeitig wird die Automatik für Pump High ausgeschaltet, da dieser Verbraucher erst unterbrochen werden darf wenn die Wärmepumpe aus ist!&lt;br /&gt;
** Wenn der letzte Verbraucher aktiviert ist, wird die Automatik der Wärmepumpe deaktiviert, da ja zuerst der letzte Verbraucher (Pool Kurz) wieder ausgeschaltet werden muss, bevor der vorletzte (Wärmepumpe) wieder ausgeschaltet werden darf. Da es keinen nachfolgenden Verbraucher mehr gibt, kann hier auf ein delay verzichtet werden, da es nicht passieren kann, dass zwei Verbraucher wegen sehr hohem Überschuss unmittelbar hintereinander geschaltet werden können.&lt;br /&gt;
[[Datei:Poolsteuerung mit unterschiedlichen Automatikmodi.jpg|alternativtext=Poolsteuerung|mini|Consumer der Poolsteuerung|500x500px]]&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Es dürfen immer nur maximal zwei unterbrechbare Consumer im Automatikmodus sein. Der &amp;quot;aktuelle&amp;quot;, der ja aufgrund von fehlendem Überschuss jederzeit unterbrochen werden kann und der &amp;quot;folgende&amp;quot; Consumer, der auf das Einschalten wartet. Pump Low ist immer im Automatikmodus, da diese nie unterbrochen wird. (mode=must, interruptable=0)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Off-chain:&#039;&#039;&#039;&lt;br /&gt;
** Wenn der letzte Verbraucher seit mindestens der delay-Zeit aufgrund von fehlendem Überschuss inaktiv war, im Automatikmodus ist und der vorherige Verbraucher nicht im Automatikmodus ist, wird der vorherige Verbraucher in den Automatikmodus geschaltet und wartet jetzt auch auf das Ausschalten. Wenn der Überschuss steigt, springt man wieder in die on-chain und der letzte Verbraucher wird eingeschaltet und die Automatik des vorletzten Verbrauchers deaktiviert.&lt;br /&gt;
** Wenn die Wärmepumpe seit mindestens der delay-Zeit aus ist, sich im Automatikmodus befind und Pump High noch nicht im Automatikmodus ist, wird die Automatik für den Nachbarpool ausgeschaltet, da er ja jetzt nicht mehr einschalten darf, da zuerst die Wärmepumpe ein sein müsste. Die Automatik von Pump High wird wieder aktiviert, da diese jetzt auf das Ausschalten wartet. Steigt der Überschuss wieder, wird in den entsprechenden On-chain Zweig gesprungen.&lt;br /&gt;
** Wenn Pump High mindestens die delay-Zeit aus ist, wird die Automatik der Wärmepumpe deaktiviert, da diese ja erst einschalten darf, wenn Pump High wieder läuft. Steigender Überschuss führt wieder zum aktivieren von Pump High und zum Sprung in den entsprechenden On-chain Zweig.&lt;br /&gt;
** Wenn Pump Low ausgeschaltet wird, wird sofort die Automatik für Pump High ausgeschaltet, da durch das spätere Ausschalten von (der evtl. wieder eingeschalteten) Pump High, hardwaremäßig wieder Pump Low aktiviert wird, aber durch SolarForecast nie ausgeschaltet wird, da Pump Low vor ein paar Minuten ja schon logisch ausgeschaltet wurde.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Es dürfen immer nur maximal zwei unterbrechbare Consumer im Automatikmodus sein. Der &amp;quot;aktuelle&amp;quot;, der ja aufgrund von neuem Überschuss jederzeit wieder gestartet werden kann und der &amp;quot;vorherige&amp;quot; Consumer, der auf das Ausschalten wartet.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Synchronisation Hardware vs. Reading:&#039;&#039;&#039;Manchmal passiert es, dass durch die etwas aufwendigen Umschaltprozesse die Hardware dem Reading nicht folgt/folgen kann. Evtl. Gründe sind Funkunterbrechung, verzögerte Umschaltung usw. Daher wird bei jedem Zyklus der Status geprüft und evtl. das event nochmal getriggert, um die Umschaltung erneut auszuführen.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hilfs-Notifys für die Automatik&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Da durch das Verwenden von swoffcond die Verbraucher beim Ausschalten auch ausgeplant werden, aber eigentlich &amp;quot;nur&amp;quot; unterbrochen werden sollen, müssen sie wieder neu eingeplant werden. Dazu sind notifys nötig. Wichtig: IDs müssen zweistellig angegeben werden!&lt;br /&gt;
&lt;br /&gt;
Wärmepumpe:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:heatpump:.off sleep 10; set energy_mgmt consumerNewPlanning 05&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Nachbar Pool:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:pool_kurz:.off sleep 10; set energy_mgmt consumerNewPlanning 07&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Eine Pumpe mit einem Energiezähler als zwei Consumer verwenden&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
Die verwendete Pumpe hat vier Betriebsarten mit unterschiedlichen Leistungen. Da sie als zwei Consumer abgebildet wird, führt das dazu, dass die Leistung fälschlicherweise von SolarForecast auch zweimal gezählt wird. Die Lösung sind Dummy-Readings, welche die Leistungsdaten passend auseinander rechnen.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Pool_Strom_Pumpe:Pool_Pin31_monotonic_count_PowerCurrent:.* {&lt;br /&gt;
my $power = $EVTPART1;&lt;br /&gt;
my $pump_low = ReadingsVal(&#039;dum_valve&#039;,&#039;pump_low&#039;,&#039;off&#039;);&lt;br /&gt;
my $pump_high = ReadingsVal(&#039;dum_valve&#039;,&#039;pump_high&#039;,&#039;off&#039;);&lt;br /&gt;
my $power_low_sim = 250;&lt;br /&gt;
&lt;br /&gt;
if($pump_low eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $pump_high eq &amp;quot;on&amp;quot;){	&lt;br /&gt;
	my $power_low = $power_low_sim; #fiktiver Verbrauch der niedrigen Stufe&lt;br /&gt;
	my $power_high = $power - $power_low_sim;&lt;br /&gt;
	fhem(&amp;quot;set dum_valve pump_low_power $power_low&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set dum_valve pump_high_power $power_high&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
elsif($pump_low eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $pump_high eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_low_power $power&amp;quot;);&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_high_power 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
elsif($pump_low eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_low_power 0&amp;quot;);&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_high_power 0&amp;quot;);&lt;br /&gt;
}elsif($pump_low eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high eq &amp;quot;on&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_low_power 0&amp;quot;);&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_high_power $power&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Es sind alle vier Möglichkeiten der zwei Pumpenlevel abgebildet.&lt;br /&gt;
* Wenn die Automatik deaktiviert ist und die Level 1-4 von extern geschaltet werden, zählen sie dadurch korrekterweise nicht zu diesen beiden Consumern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notifys für das hardwaremäßige Schalten der Consumer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es werden einige Notifys verwendet, die die Umsetzung vom Dummy-Device auf die Hardware erledigen, da ein logisches Ein teilweise hardwaremäßig einige Dinge erfordert.&lt;br /&gt;
&lt;br /&gt;
Notify für Pump Low:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:pump_low:.* {&lt;br /&gt;
	if($EVTPART1 eq &amp;quot;on&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin26 on; sleep 60; set Pool_Pin25 on; sleep 1; set Pool_Pin26 off&amp;quot;);&lt;br /&gt;
	}elsif($EVTPART1 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin14 off; sleep 5; set Pool_Pin12 off; sleep 15; set Pool_Pin25 off&amp;quot;);&lt;br /&gt;
	}else{&lt;br /&gt;
	Log3 (&amp;quot;Pool&amp;quot;, 4, qq{Notify Level1 - parameter is not on or off});&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Beim Einschalten ist es nötig für eine Minute Pump High zu aktivieren, um Luft aus der Elektrolysezelle zu spülen, bevor Pump Low aktiv sein darf. (Pin26 und Pin25 sind die Steuerpins auf der Interfacekarte der Pumpe für die beiden Level.)&lt;br /&gt;
* Beim Ausschalten werden zuerst die Salzanlage (Pin14) und die pH-Anlage (Pin12) deaktiviert, damit noch 15 Sekunden lang die Elektrolysezelle mit frischem Wasser gespült wird, um das verbleibende Chlor auszuspülen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Notify für Pump High:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:pump_high:.* {&lt;br /&gt;
	if($EVTPART1 eq &amp;quot;on&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin26 on; sleep 1; set Pool_Pin25 off&amp;quot;);&lt;br /&gt;
	}elsif($EVTPART1 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin25 on; sleep 1; set Pool_Pin26 off&amp;quot;);&lt;br /&gt;
	}else{&lt;br /&gt;
	Log3 (&amp;quot;Pool&amp;quot;, 4, qq{Notify Level 2- parameter is not on or off});&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterung:&lt;br /&gt;
&lt;br /&gt;
* Da die Interfacekarte immer auf den höchsten Level reagiert, wird beim Umschalten zuerst Pump High aktiviert und nach einer Sekunde Pump Low deaktiviert, um ein &amp;quot;stufenloses&amp;quot; (ohne Ausschalten) Umschalten zu ermöglichen. Beim Ausschalten genauso.&lt;br /&gt;
&lt;br /&gt;
Notify für die Wärmepumpe:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:heatpump:.* {&lt;br /&gt;
	if($EVTPART1 eq &amp;quot;on&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin6 on&amp;quot;);&lt;br /&gt;
	}elsif($EVTPART1 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin6 off&amp;quot;);&lt;br /&gt;
	}else{&lt;br /&gt;
	Log3 (&amp;quot;Pool&amp;quot;, 4, qq{Notify heatpump - parameter is not on or off});&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterung:&lt;br /&gt;
&lt;br /&gt;
* Hier reicht ein dirketes Übernehmen aus dem Dummy.&lt;br /&gt;
&lt;br /&gt;
Notify für den Nachbar-Pool:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:pool_kurz:.* {&lt;br /&gt;
	if($EVTPART1 eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsVal(&amp;quot;Shelly_Plug_S_1&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;on&amp;quot;) eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set PwSw_Schalter off; sleep 3;{if(ReadingsAge(\&amp;quot;PwSw_Schalter\&amp;quot;,\&amp;quot;state\&amp;quot;,0)&amp;lt;4 &amp;amp;&amp;amp; ReadingsVal(\&amp;quot;PwSw_Schalter\&amp;quot;,\&amp;quot;state\&amp;quot;,\&amp;quot;on\&amp;quot;) eq \&amp;quot;off\&amp;quot;){fhem(\&amp;quot;set Shelly_Plug_S_1 on\&amp;quot;)}}; sleep 5; set PwSw_Schalter on&amp;quot;);&lt;br /&gt;
	}elsif($EVTPART1 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; ReadingsVal(&amp;quot;Shelly_Plug_S_1&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set PwSw_Schalter off; sleep 3;{if(ReadingsAge(\&amp;quot;PwSw_Schalter\&amp;quot;,\&amp;quot;state\&amp;quot;,0)&amp;lt;4 &amp;amp;&amp;amp; ReadingsVal(\&amp;quot;PwSw_Schalter\&amp;quot;,\&amp;quot;state\&amp;quot;,\&amp;quot;on\&amp;quot;) eq \&amp;quot;off\&amp;quot;){fhem(\&amp;quot;set Shelly_Plug_S_1 off\&amp;quot;)}}; sleep 5; set PwSw_Schalter on&amp;quot;);&lt;br /&gt;
	}else{&lt;br /&gt;
	Log3 (&amp;quot;Pool&amp;quot;, 4, qq{Notify Pool Kurz - parameter is not on or off});&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterung&lt;br /&gt;
&lt;br /&gt;
* Da hier eine Pumpe durch einen 3-poligen Umschalter zwischen zwei Hausanspeisungen umgeschaltet wird, ist es wichtig, dass die Pumpe dazwischen &#039;&#039;&#039;gesichert&#039;&#039;&#039; zum Stehen gebracht wird! Sonst führt die rotierende Pumpe als Generator zu einem gewaltigen Kurzschluss mit der &amp;quot;fremden&amp;quot; Phase. War nicht schön ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sonderprogramme für den Poolbetrieb&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hier ist das Aus- und Einschalten der Solarforcast-Automatik zu sehen. Es werden alle Stati gespeichert. Danach kann von beliebigen &amp;quot;Sonderfunktionen&amp;quot; (Reinigung des Filters, Massagefunktion, usw.) auf die Hardware zugegriffen werden. Wenn wieder in den Automatikmodus zurückgewechselt wird, wird hardwaremäßig wieder der Zustand der Automatik von vorher hergestellt, die Stati wieder zurück geschrieben und die Automatik wieder aktiviert.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
##############################################&lt;br /&gt;
# Status speichern und Automatik ausschalten #&lt;br /&gt;
##############################################&lt;br /&gt;
sub PoolAutoOff{&lt;br /&gt;
	my $pump_low_id			= sprintf &amp;quot;%02d&amp;quot;, 1;&lt;br /&gt;
	my $pump_high_id		= sprintf &amp;quot;%02d&amp;quot;, 3;&lt;br /&gt;
	my $heatpump_id			= sprintf &amp;quot;%02d&amp;quot;, 5;&lt;br /&gt;
	my $pool_kurz_id		= sprintf &amp;quot;%02d&amp;quot;, 7;&lt;br /&gt;
	my $sf				= &#039;energy_mgmt&#039;;&lt;br /&gt;
&lt;br /&gt;
		&lt;br /&gt;
#	my $pump_low_state = ReadingsVal($valve_dummy,&#039;pump_low&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pump_low_auto	= FHEM::SolarForecast::ConsumerVal ($sf, $pump_low_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Pumpe&lt;br /&gt;
#	my $pump_high_state = ReadingsVal($valve_dummy,&#039;pump_high&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pump_high_auto	= FHEM::SolarForecast::ConsumerVal ($sf, $pump_high_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Pumpe&lt;br /&gt;
#	my $heatpump_state = ReadingsVal($valve_dummy,&#039;heatpump&#039;,&#039;on&#039;);&lt;br /&gt;
	my $heatpump_auto	= FHEM::SolarForecast::ConsumerVal ($sf, $heatpump_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Wärmepumpe&lt;br /&gt;
#	my $pool_kurz_state = ReadingsVal($valve_dummy,&#039;pool_kurz&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pool_kurz_auto	= FHEM::SolarForecast::ConsumerVal ($sf, $pool_kurz_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus des Pools&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pump_low_auto 0&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pump_high_auto 0&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy heatpump_auto 0&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pool_kurz_auto 0&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy sf_automatic 0&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pump_low $pump_low_auto&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pump_high $pump_high_auto&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_heatpump $heatpump_auto&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pool_kurz $pool_kurz_auto&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	my $last_pump_level_1 = ReadingsVal($valve_dummy,&amp;quot;pump_low&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_2 = ReadingsVal($valve_dummy,&amp;quot;pump_high&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_3 = ReadingsVal($pump_level_3,&amp;quot;value&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_4 = ReadingsVal($pump_level_4,&amp;quot;value&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_heatpump = ReadingsVal($valve_dummy,&amp;quot;heatpump&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_1 $last_pump_level_1&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_2 $last_pump_level_2&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_3 $last_pump_level_3&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_4 $last_pump_level_4&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_heatpump $last_heatpump&amp;quot;); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
##########################################&lt;br /&gt;
# Status laden und Automatik einschalten #&lt;br /&gt;
##########################################&lt;br /&gt;
sub PoolAutoOn{&lt;br /&gt;
	my $last_pump_level_4 = ReadingsVal($valve_dummy,&amp;quot;last_pump_level_4&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_3 = ReadingsVal($valve_dummy,&amp;quot;last_pump_level_3&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_2 = ReadingsVal($valve_dummy,&amp;quot;last_pump_level_2&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_1 = ReadingsVal($valve_dummy,&amp;quot;last_pump_level_1&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_heatpump = ReadingsVal($valve_dummy,&amp;quot;last_heatpump&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $pump_level_4 $last_pump_level_4&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;set $pump_level_3 $last_pump_level_3&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $pump_level_2 $last_pump_level_2&amp;quot;);&lt;br /&gt;
	if($last_pump_level_1 eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $last_pump_level_2 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_3 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_4 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set $pump_level_2 on; sleep 1; set $pump_level_1 $last_pump_level_1; sleep 28; set $pump_level_2 off; set $valve_dummy sf_automatic 1&amp;quot;);&lt;br /&gt;
	}elsif($last_pump_level_1 eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $last_pump_level_2 eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $last_pump_level_3 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_4 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set $pump_level_1 off; set $valve_dummy sf_automatic 1&amp;quot;); &lt;br /&gt;
	}elsif($last_pump_level_1 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_2 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_3 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_4 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set $pump_level_1 off; set $valve_dummy sf_automatic 1&amp;quot;); &lt;br /&gt;
	}&lt;br /&gt;
	fhem(&amp;quot;sleep 10; set $heatpump $last_heatpump&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_1 none&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_2 none&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_3 none&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_4 none&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_heatpump none&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy valve_position normal&amp;quot;);&lt;br /&gt;
	my $last_auto_pump_low = ReadingsVal($valve_dummy,&amp;quot;last_auto_pump_low&amp;quot;,0);&lt;br /&gt;
	my $last_auto_pump_high = ReadingsVal($valve_dummy,&amp;quot;last_auto_pump_high&amp;quot;,0);&lt;br /&gt;
	my $last_auto_heatpump = ReadingsVal($valve_dummy,&amp;quot;last_auto_heatpump&amp;quot;,0);&lt;br /&gt;
	my $last_auto_pool_kurz = ReadingsVal($valve_dummy,&amp;quot;last_auto_pool_kurz&amp;quot;,0);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pump_low_auto $last_auto_pump_low&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pump_high_auto $last_auto_pump_high&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy heatpump_auto $last_auto_heatpump&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pool_kurz_auto $last_auto_pool_kurz&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pump_low none&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pump_high none&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_heatpump none&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pool_kurz none&amp;quot;);&lt;br /&gt;
}		&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* pump_level_1 ist Pump Low, pump_level_2 ist Pump High, pump_level_3 und pump_level_4 sind Sonderfunktionen (Filterreinigung, Massage)&lt;br /&gt;
* Beim Wiedereinschalten von Pump Low ist es wieder nötig kurz Pump High zu aktivieren, um Luft auszuspülen.&lt;br /&gt;
* Es wird der Zustand von Solarforecast gespeichert und danach auf die Hardware geschrieben. -&amp;gt; Stellt sicher, dass nach dem Einschalten der Automatik der logical switchstate zum physical switchstate passt.&lt;br /&gt;
&lt;br /&gt;
== Tips &amp;amp; Tricks ==&lt;br /&gt;
* Interruptable verhält sich völlig anders, wenn der Perlcode 1 oder 0 liefert, als wenn man 1 oder 0 in der Config hinterlegt. -&amp;gt; siehe commandref&lt;br /&gt;
* Rückgabewert bei swoncond und swoffcond wird mit dem Readingswert verglichen und nicht dirket verwendet. Bsp. wenn das Reading 100 enthält muss auch der Rückgabewert des Perlcodes 100 liefern, um true zu ergeben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== weiterführende Links ==&lt;br /&gt;
* Forenthema &amp;quot;{{Link2Forum|Topic=137058|LinkText=76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support}}&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;
* Photovoltaik Ingenieurbüro Junge: https://www.ing-büro-junge.de/html/photovoltaik.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung&amp;diff=40491</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=40491"/>
		<updated>2025-11-10T15:08:46Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Hinweis|Die vorliegende Wiki-Seite befindet sich im Aufbau.}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Solarprognose und Verbrauchersteuerung&lt;br /&gt;
|ModType=d&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 Prognosewerte können die SolCast API, OpenMeteo API, Forecast.Solar API, Victron VRM Portal API oder alternativ DWD Stahlungswerte-Stationen verwendet werden&lt;br /&gt;
&lt;br /&gt;
::* optionale KI Unterstützung der PV-Prognose bei Verwendung von geeigneten Solar-API&#039;s&lt;br /&gt;
&lt;br /&gt;
::* es wird sowohl die Erzeugungsprognose als auch eine Verbrauchsprognose sowie SoC Prognose (bei Batterie-Integration) erstellt&lt;br /&gt;
&lt;br /&gt;
::* Wetterdaten werden über DWD Wetter-Stationen oder verschiedene API integriert. Es können verschiedene API zur Gewinnung von Solar- und Wetterdaten kombiniert werden. &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 FHEM-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 Integration von bis zu 4 Inverter und Smartloader (DC-DC Batterieladegeräte) ist möglich&lt;br /&gt;
&lt;br /&gt;
::* eine Integration von bis zu 3 nicht PV-Energieerzeugern wie BHKW, Windrädern oder Notstromaggregaten ist möglich&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;
::* Einbindung von bis zu drei Batteriespeichersystemen&lt;br /&gt;
&lt;br /&gt;
::* Bereitstellung von Leitwerten zur optimalen Einstellung/Steuerung von Batteriespeichersystemen&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 Benutzererlebnis 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;
Das Wiki gibt allgemeingültige und teilweise sehr spezifische bzw. tiefgehende Informationen und Handlungsempfehlungen zum SolarForecast Modul. Die dargestellten Informationen beziehen sich auf den zum Zeitpunkt der Wiki-Erstellung vorhandenen Entwicklungsstand des Moduls. Durch die stetige Weiterentwicklung können sich Abweichungen zum beschriebenen Inhalt ergeben oder zur Obsoleszenz dieser Inhalte führen. &lt;br /&gt;
&lt;br /&gt;
Vergleiche deshalb die Informationen immer mit der aktuellen Befehls-Referenz zum Modul!&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Ein SolarForecast Device wird mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 define &amp;lt;Name&amp;gt; SolarForecast &lt;br /&gt;
&lt;br /&gt;
angelegt. Nach der Definition wird der User durch einen Dialog geführt, der einige unerlässliche Einstellungen abfragt und in den entsprechenden Attributen und Readings persistiert. Alle Attribute und Readings die eine Einstellung der Anlage bewirken, sind mit dem Präfix &amp;quot;setup&amp;quot; versehen. &lt;br /&gt;
&lt;br /&gt;
Die Verwendung von setup-Readings gestattet es die Anlagenparameter dynamisch im Betrieb zu verändern. So kann mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringAzimuth   bzw.&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringDeclination &lt;br /&gt;
&lt;br /&gt;
die Ausrichtung und der Neigungswinkel der PV-Module ständig angepasst werden, was zum Beispiel bei einer dem Sonnenstand nachgeführten Anlage von Bedeutung ist.&lt;br /&gt;
&lt;br /&gt;
Die abgefragten Einstellungen während des Dialoges sind ausführlich in den entsprechenden Attributen bzw. Set-Kommandos erläutert. Die benötigten Informationen sind anhängig von der gewählten Prognose-API und können im Umfang variieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 213257.png|right|thumb|400px|Anlagenprüfung über Drucktaste in der Kopfgrafik]]&lt;br /&gt;
&lt;br /&gt;
Sobald alle verlangten Einstellungen vorgenommen sind, sollte eine Anlagenprüfung mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; plantConfiguration check&lt;br /&gt;
&lt;br /&gt;
oder über die angebotene Drucktaste in der Grafik durchgeführt werden. Es wird eine Plausibilitätsprüfung vorgenommen und das Ergebnis sowie eventuelle Hinweise bzw. Fehler ausgegeben.&lt;br /&gt;
Die Prüfung kann beliebig wiederholt werden und sollte sich bei jeder Einstellungsänderung der Anlage durchgeführt werden. Dadurch wird die Wahrscheinlichkeit von fehlerhaften Einstellungen minimiert.&lt;br /&gt;
&lt;br /&gt;
Neben den grundlegenden Einstellungen können im Device weitere sekundäre Anlagenkomponenten wie Batteriesystem(e) (Attribut setupBatteryDev1 - setupBatteryDev3), weitere Wetter-Devices (Attribut setupWeatherDev1 - setupWeatherDev3) oder sonstige Erzeuger (z.B. BHKW, Winderzeugung, Notstromaggregat) integriert werden (Attribut setupOtherProducer01 - setupOtherProducer03).&lt;br /&gt;
&lt;br /&gt;
Die verlangten Parameter der Anlage werden in der Online-Hilfe umfassend beschrieben und deren Funktion erschließt sich zum größten Teil selbst. Dennoch soll nachfolgend auf einige Punkte im Zusammenhang der Einrichtung eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Hinweise zur Struktur der Attribute ===&lt;br /&gt;
&lt;br /&gt;
Durch die umfangreichen Funktionen des Moduls würde bei Nutzung der im FHEM herkömmlich vorhandenen Attributstruktur die Anzahl der benötigten Attribute extrem stark steigen und nicht sinnvoll genutzt werden können. Deshalb gibt es neben den &#039;&#039;gewöhnlichen&#039;&#039; Attributen mit einfachen Werteauswahlmöglichkeiten oder Eingaben (z.B. ctrlDebug, ctrlSpecialReadings) sogenannte &#039;&#039;zusammengesetzte&#039;&#039; Attribute, deren Inhalt durch &#039;&#039;&#039;Schlüssel=Wert Paare&#039;&#039;&#039; gebildet wird und dadurch deutlich mehr Funktionen und Informationen transportieren als ein gewöhnliches Attribut.&lt;br /&gt;
&lt;br /&gt;
Für zusammengesetzte Attribute besteht die zusätzliche Möglichkeit, gewünschte Änderungen der Schlüssel=Wert Paare selektiv vornehmen zu können, ohne das gesamte Attribut aufrufen und ändern zu müssen. Die Vorgang, der vor allem für programmtechnische Manipulationen gedacht ist, kann durch eine Set-Funktion ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; attrKeyVal &amp;lt;Attribut&amp;gt; [&amp;lt;Gerät&amp;gt;] &amp;lt;Schlüssel=Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiele für zusammengesetzte Attribute sind:&lt;br /&gt;
&lt;br /&gt;
* aiControl&lt;br /&gt;
* plantControl&lt;br /&gt;
* setup* Attribute&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktionen der Attribute werden durch einen Präfix geclustert und so inhaltlich, aber vor allem auch in der Attribute Drop-Down Liste, strukturiert dargestellt.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der &#039;&#039;&#039;Präfixe&#039;&#039;&#039; sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ai&#039;&#039;&#039; - Steuerungsfunktionen für KI (z.B. aiControl)&lt;br /&gt;
* &#039;&#039;&#039;consumer&#039;&#039;&#039; - Registrierung und Einstellungen für Verbraucher (z.B. consumer02, consumerControl)&lt;br /&gt;
* &#039;&#039;&#039;ctrl&#039;&#039;&#039; - Steuerungsfunktion allgemeiner Art (z.B. ctrlDebug, ctrlSpecialReadings, ctrlUserExitFn)&lt;br /&gt;
* &#039;&#039;&#039;flowGraphic&#039;&#039;&#039; - Einstellungen für die Energieflußgrafik (z.B. flowGraphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphic&#039;&#039;&#039; - Einstellung für die Grafik allgemein (z.B. graphicSelect, graphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphicBeam&#039;&#039;&#039; -  Einstellungen bestimmte Balkeneigenschaften in der Balkengrafik (z.B. graphicBeamHeightLevel1)&lt;br /&gt;
* &#039;&#039;&#039;plant&#039;&#039;&#039; - übergreifende Einstellungen betreffend der gesamten PV-Anlage bzw. des SolarForecast-Devices (z.B. plantControl)&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039; - Registrierung von Geräten in der Gesamtanlage und Einstellung deren Eigenschaften (Inverter, Zähler, Batterien usw.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Einrichtung der Wechselrichter mit setupInverterDevXX ===&lt;br /&gt;
&lt;br /&gt;
Mit den Attributen setupInverterDev01 bis setupInverterDevXX werden die vorhandenen Wechselrichter der Anlage registriert.&lt;br /&gt;
Das Modul unterscheidet verschiedene Wechselrichter-Typen, die sich durch ihre Arbeitsweise innerhalb der Anlage unterscheiden. Die Schlüssel=Wert Paare in den Attributen können mehrzeilig organisiert werden. Das erleichtert die Übersicht wenn viele dieser Parameter eingegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;PV-Wechselrichter: Es ist der Standard Wechselrichter in einer PV-Anlage. An ihn sind die Solarzellen bzw. Strings angeschlossen. Die zugeordneten Strings können mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ohne diese Angabe werden diesem Gerät alle definierten Strings (siehe Attribut &#039;&#039;setupInverterStrings&#039;&#039;) zugeordnet. Der Wechselrichter liefert seine Energie in das Hausnetz. Alternativ kann mit der Angabe &#039;&#039;&#039;feed=grid&#039;&#039;&#039; die Funktion des Wechselrichters geändert werden. Diese Angabe sagt aus, dass dieser Wechselrichter ausschließlich in das öffentliche Netz einspeist.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel-Setup eines PV-Wechselrichters (SMA STP):&lt;br /&gt;
&lt;br /&gt;
 STP_5000 pvIn=string_1_pdc:kW pvOut=total_pac:kW etotal=etotal:kWh capacity=5000 strings=Süddach asynchron=1 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Solar-Ladegeräte: Solar-Ladegeräte sind DC-DC Wandler und liefern die Energie der angeschlossenen Solarzellen nicht in das Wechselstromnetz, sondern laden direkt eine Batterie bzw. versorgen einen Batteriewechselrichter auf der Gleichstromseite. Die Funktion als Solar-Ladegerät wird mit &#039;&#039;&#039;feed=bat&#039;&#039;&#039; aktiviert, die relevanten Strings können ebenfalls mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ein Beispiel eines Solar-Ladegerätes ist ein Victron SmartSolar MPPT. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel für das Setup eines Solar-Ladegeräts (SmartSolar Charger MPPT):&lt;br /&gt;
&lt;br /&gt;
 MQTT2_cerboGX_c0619ab34e08_solarcharger_Common pv=Yield_Power_value:W etotal=Yield_System_value:kWh capacity=2080 strings=Schleppdach feed=bat synchron=0 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Batterie-Wechselrichter: Dieses Gerät hat keine angeschlossenen Solarzellen und arbeitet als DC-AC bzw. AC-DC Wandler zwischen einer Batterie (=Gleichstromquelle) und dem Wechselstrom-Hausnetz. Die Funktion als Batterie-Wechselrichter wird mit der Angabe &#039;&#039;&#039;strings=none&#039;&#039;&#039; aktiviert. Die Schlüssel &#039;&#039;etotal&#039;&#039; und &#039;&#039;pv&#039;&#039; können bei einem Batterie-Wechselrichter ohne zugeordnete Solarzellen nicht gesetzt werden. Ein Beispiel eines Batterie-Wechselrichter ist der Victron MultiPlus II.&lt;br /&gt;
&lt;br /&gt;
Ein Setup-Beispiel für einen Batterie-Wechselrichter (Victron MultiPlus II):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dc2ac=DC_IN:W&lt;br /&gt;
ac2dc=DC_OUT:W&lt;br /&gt;
capacity=7200&lt;br /&gt;
strings=none&lt;br /&gt;
icon=inverter@darkorange:inverter@grey&lt;br /&gt;
asynchron=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Eigenschaften des Wechselrichters werden durch eine Reihe von &amp;lt;Schlüssel=Wert&amp;gt; Paaren festgelegt. Auf einige dieser Paramter soll hier eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Ausgewählte Schlüssel=Wert Paare ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;pvIn=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvIn&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell zugeführte PV-Leistung bereitstellt. Der Schlüssel ist optional und dient in erster Linie dazu den entsprechenden Input-Wert in der Flußgrafik anzuzeigen sofern man das Attribut flowGraphicControl-&amp;gt;showGenerators=1 setzt. Dadurch ist auch der Eigenverbrauch des Inverters bzw. dessen Wandlungsverlust visuell abschätzbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pvOut=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvOut&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell erzeugte Leistung als positiven Wert liefert. Für einen PV-Wechselrichter (DC-&amp;gt;AC) oder Solar-Ladegerät (DC-&amp;gt;DC) ist es die erzeugte PV-Leistung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ac2dc=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter vom Hausnetz in Richtung Batterie (AC-&amp;gt;DC) wandelt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;dc2ac=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter aus einer Gleichstromquelle, d.h. einer Batterie oder einem Solar-Ladegerät, in Richtung des Hausnetzes (AC) wandelt . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;capacity=&amp;lt;max. WR-Leistung&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In dem Schlüssel &#039;&#039;capacity&#039;&#039; wird die maximal mögliche Leistung in Watt (ohne Einheit) angegeben, die der Wechselrichter lt. seinem Datenblatt in der Lage ist zu leisten. &lt;br /&gt;
&lt;br /&gt;
Die Angabe &#039;&#039;capacity&#039;&#039; hat in erster Linie die Aufgabe, die max. mögliche PV-Leistung für die Prognose zu begrenzen. Oft sind die installierten Peak-Leistungen der PV-Module höher als die angeschlossene Wechselrichter-Leistung bzw. kommt es vor, dass die KI / (korrigierte) API-Prognose über der maximal möglichen Wechselrichter-Leistung liegt. In diesen Fällen wird die Prognose auf die angegebene &#039;&#039;capacity&#039;&#039; begrenzt.&lt;br /&gt;
&lt;br /&gt;
Der Wert in diesem Schlüssel kann, wie andere Schlüssel auch, dynamisch zur Laufzeit mit dem Set-Befehl &amp;quot;[[#Hinweise zur Struktur der Attribute|set &amp;lt;Name&amp;gt; attrKeyVal ...]]&amp;quot; geändert werden. Ein Beispiel zur Anwendung ergibt sich aus folgendem Szenario.&lt;br /&gt;
&lt;br /&gt;
Gegeben sei eine Anlage die aus Solarzellen (1300 W Peak) mit einem Solar-Ladegerät mit max. 1800 W Leistung, einer Batterie und einem Batterie-Wechselrichter besteht. Die Anlage versorgt nur das Hausnetz. Eine Netzeinspeisung ist nicht vorgesehen oder nicht erlaubt.  &lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, es ist ein Tag voller Sonnenschein prognostiziert und die Batterie ist zunächst entladen. Der Haushalt verbraucht 300 W. Dann würden die PV-Module Module ihre volle Leistung von 1300 W Peak leisten können, die sich auch in der Balken-Vorhersage niederschlägt. Die Leistung wird nicht begrenzt, weil:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* sie niedriger ist als die nominale und angegebene Wechselrichter Kapazität von &#039;&#039;capacity=1800&#039;&#039;&lt;br /&gt;
* die erzeugte Energie anteilig für die Verorgung des Hauses und die Aufladung der Batterie verwendet wird&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders verhält es sich wenn nach einer gewissen Zeit die Batterie voll ist und weiterhin volle PV Leistung zur Verfügung steht. In diesem Fall würde der Haushalt seine benötigte Leistung von 300 W abnehmen, aber das Solar-Ladegerät kann keine weitere Leistung mehr abgeben, da die Batterie bereits voll geladen ist, d.h. die Anlagensteuerung würde die PV-Anlage abregeln. In diesem Fall, wenn es einen längeren Zeitraum betrifft, muß auch die Prognose PV-Energie auf 300 Wh (bzw. den durchschnittlichen Energieverbrauch des Hauses pro Stunde) begrenzt werden, damit die PV-Prognose nach unten angepasst wird und so eine realitätsnahere Prognose ermöglicht wird. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;icon=&amp;lt;aktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;][:&amp;lt;inaktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Jeder Wechselrichter wird im Standard durch ein Icon getrennt nach Tag und Nacht, d.h. je nach Aktiv-Status und Inaktiv-Status, symbolisiert.&lt;br /&gt;
&lt;br /&gt;
;Tag bzw. Aktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Sonnensymbol im Standard verwendet. Batterie-Wechselrichter verwenden ein gefärbtes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
;Nacht bzw. Inaktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Symbol der aktuellen Mondphasen im Standard verwendet. Batterie-Wechselrichter verwenden ein ausgegrautes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie angegeben, kann man für Tag und Nacht jeweils ein Wunsch-Icon, wenn gewünscht mit einer alternativen Färbung, auswählen.&lt;br /&gt;
&lt;br /&gt;
 icon=inverter@darkorange:inverter@gray&lt;br /&gt;
&lt;br /&gt;
Soll nur das Icon für die Nacht bzw. Inaktivät geändert werden, kann dies in dieser Form angegeben werden:&lt;br /&gt;
&lt;br /&gt;
 icon=:inverter@gray  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(beachte den führenden &#039;:&#039;)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Definition von Hybrid-Wechselrichtern  ====&lt;br /&gt;
&lt;br /&gt;
Zur Zeit der Erstellung dieses Abschnittes ist es in der SolarForecast Version 1.58.x nicht möglich, einen Hybridwechselrichter nativ zu definieren. Als Workaround wird eine passende Kombination aus PV-Wechselrichter und Batterie-Device oder einer Kombination aus PV-Wechselrichter + Batterie-Wechselrichter und Batterie-Device erstellt.&lt;br /&gt;
&lt;br /&gt;
Bei allen benutzten Methoden ist es sehr wichtig!, dass die geforderten Inhalte der jeweilige Attributschlüssel beachtet und eingehalten werden. So ist zum Beispiel die Angabe von:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pvOut&#039;&#039;&#039; - Ein Reading, welches die aktuelle Leistung aus PV-Erzeugung, die an das Hausnetz oder öffentliche Netz geliefert wird, bereitstellt. Es wird ein positiver numerischer Wert erwartet.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
bei einem PV-Wechselrichter ein Reading welches ausschließlich die Leistung liefert, die von den Solarzellen-Generatoren erzeugt wird. Elemente von Batterieleistungen oder Gridbestandteile dürfen hier nicht enthalten sein. Sind in den Gerätemodulen diese Readings in dieser Form nicht enthalten, bietet es sich an, userReadings zur Erstellung von zusätzlichen Readings in den Quellendevices zu nutzen um den nötigen Input für SolarForecast bereitzustellen. &lt;br /&gt;
&lt;br /&gt;
So wird zum Beispiel bei einem 	Batterie-Wechselrichter gefordert, dass die Readings &#039;&#039;&#039;ac2dc&#039;&#039;&#039; (AC-&amp;gt;DC-Leistung Hausnetz zur Batterie) und &#039;&#039;&#039;dc2ac&#039;&#039;&#039; (DC-&amp;gt;AC-Leistung (Batterie zum Hausnetz) &#039;&#039;&#039;jeweils als als positiver Wert&#039;&#039;&#039; anzugeben ist. Manche Batterie-Devices stellen allerdings nur ein Reading zur Verfügung, welches vorzeichenbehaftet die Leistungen in die Batterie bzw. aus der Batterie heraus liefert. Mit einem userReadings Attribut kann aus diesem Reading zwei neue Readings erzeugt werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; userReadings  BatIn:DC_Power_value.* {&lt;br /&gt;
                          my $pwr = ReadingsVal ($name, &#039;DC_Power_value&#039;, 0);&lt;br /&gt;
                          $pwr    = $pwr &amp;gt; 0 ? $pwr : 0;&lt;br /&gt;
                          $pwr&lt;br /&gt;
                          },&lt;br /&gt;
                          BatOut:DC_Power_value.* {&lt;br /&gt;
                          my $pwr = ReadingsVal ($name, &#039;DC_Power_value&#039;, 0);&lt;br /&gt;
                          $pwr    = $pwr &amp;lt; 0 ? - $pwr : 0;&lt;br /&gt;
                          $pwr&lt;br /&gt;
                          },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist das Quellenreading &#039;&#039;DC_Power_value&#039;&#039; positiv, stellt der Wert AC-&amp;gt;DC-Leistung dar und wird als neues Reading BatIn bereitgestellt. Mit einem negativen Vorzeichen ist es eine DC-&amp;gt;AC-Leistung und wird in dem neuen Reading BatOut &#039;&#039;&#039;ebenfalls als positiver Wert&#039;&#039;&#039; bereitgestellt. Auch hier gilt der Grundsatz, dass zum Beispiel BatOut nur die von der Batterie gelieferte Energie und keinen Mix aus Batterie- und PV-Energie enthalten darf.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
===== Integration eines DEYE SUN-12K-SG04LP3-EU =====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-09-23 203955.png|right|thumb|400px|DEYE SUN-12K-SG04LP3-EU Grundlegende Systemarchitektur]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der DEYE vereint wie wohl alle bzw. die meisten Hybrid-Wechselrichter die Anschlüsse:&lt;br /&gt;
&lt;br /&gt;
* Eingang Solar-Strings&lt;br /&gt;
* Anschluß Batteriespeicher&lt;br /&gt;
* AC-Anschluß öffnetliches Netz&lt;br /&gt;
* AC-Anschluß Ersatzlast (wird bei Netzausfall weiter versorgt)&lt;br /&gt;
* AC-Anschluß Notstromgenerator bzw. netzgekoppelter anderer Wechselrichter (hier ist ein Growatt Micro-Wechselrichter angeschlossen)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Integration werden die setup-Attribute durch das FHEM Device &#039;&#039;Deye_Inverter&#039;&#039; besetzt:&lt;br /&gt;
&lt;br /&gt;
* setupInverterStrings zur Definition der vorhandenen Solarstrings&lt;br /&gt;
* setupInverterDev01 zur Definition der Inverteranschlüsse und Eigenschaften&lt;br /&gt;
* setupBatteryDev01 integriert die Batterie&lt;br /&gt;
* setupMeterDev liefert die Daten für Netzbezug und Netzeinspeisung&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das nachfolgend verwendete Device &#039;&#039;Deye_Inverter&#039;&#039; ist ein MQTT-Device. Es bekommt Daten vom Deye-Hybridwechselrichter per MQTT und sendet Einstellungen zum Deye, bspw. maximaler Lade/Entladestrom des Akkus, Laden des Akkus aus dem Netz, Ein- und Ausschalten des Micro-Inverter-Ports.&lt;br /&gt;
Das Reading &#039;&#039;Deye_Growatt_power&#039;&#039; im Schlüssel &#039;&#039;pvOut&#039;&#039; ist eine Addition aus den Daten des Deye WR und des angeschlossenen Growatt Micro-Wechselrichters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupInverterStrings Sueddach,Garagendach&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupInverterDev01 Deye_Inverter pvOut=Deye_Growatt_power:W capacity=15200 etotal=total_pv_production:kWh&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupBatteryDev01 Deye_Inverter pin=-pout pout=battery_output_power:W intotal=total_charge_of_the_battery:kWh outtotal=total_discharge_of_the_battery:kWh cap=15200 charge=SOC_jkbms&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupMeterDev Deye_Inverter gcon=total_grid_power:W contotal=total_energy_bought:kWh gfeedin=-gcon feedtotal=total_energy_sold:kWh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;setupInverterStrings&#039;&#039; benennt alle vorhandenen Solarstrings. Werden mehrere Inverter definiert, kann mit dem hier nicht verwendeten Schlüssel &#039;&#039;strings&#039;&#039; eine Zuordnung der Strings zum angeschlossenen Inverter vorgenommen werden.&lt;br /&gt;
&lt;br /&gt;
Im Attribut &#039;&#039;setupInverterDev01&#039;&#039; ist der allgemeine Schlüssel &#039;&#039;capacity&#039;&#039; zur Festlegung der Inverterleistung von 15200 Watt gesetzt. Die spezifischen Schlüssel &#039;&#039;pvOut&#039;&#039; und &#039;&#039;etotal&#039;&#039; teilen dem Modul die aktuell erzeugte PV-Leistung sowie die gesamte erzeugte PV-Energie mit. Letzteres dient unter anderem dazu die stündlich real erzeugte PV-Energie festzuhalten und mit der Prognose zu vergleichen. Die in den schlüsseln hinterlegten dürfen keine Battrie- oder Netzanteile enthalten.&lt;br /&gt;
&lt;br /&gt;
Das Attr &#039;&#039;setupBatteryDev01&#039;&#039; implementiert alle relevanten Batteriewerte. Das Reading &#039;&#039;battery_output_power&#039;&#039; im Schlüssel &#039;&#039;pout&#039;&#039; liefert den Batterie-Output als positiven Wert. Als Besonderheit kann der Wert &#039;&#039;pin&#039;&#039;, die Batterie-Ladeleistung, den Wert des Readings in &#039;&#039;pout&#039;&#039; übernehmen wenn dieser Wert ein negatives Vorzeichen hat. Die Schlüssel &#039;&#039;intotal&#039;&#039; und &#039;&#039;outtotal&#039;&#039; liefern die summierten Totalwerte für Batterie Ladung bzw. Entladung. Die Kapazität &#039;&#039;cap&#039;&#039; wird für verschiedene Aspekte der SoC- und Ladesteuerung verwendet. &lt;br /&gt;
&lt;br /&gt;
Abschließend liefern die angebenen Readings in den Schlüsseln des Attributes &#039;&#039;setupMeterDev&#039;&#039; alle notwendigen Werte des Netzbezugs und der Netzeinspeisung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nachfolgende Links liefern &#039;&#039;&#039;weitere Infos&#039;&#039;&#039; wie man Daten aus dem Deye WR ausliest und Einstellungen des Deye WR verändert:&lt;br /&gt;
&lt;br /&gt;
* https://github.com/klatremis/esphome-for-deye&lt;br /&gt;
* https://github.com/philipphenkel/esphome-config&lt;br /&gt;
* https://github.com/bagges/deye-esp32-bridge&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für eine weiterführende Automation soll der Akku netzdienlich in der Mittagszeit geladen werden. Dazu wurde durch den Anwender folgendes userReadings &#039;&#039;MaxBattCharge_Request&#039;&#039; im Device &#039;&#039;Deye_Inverter&#039;&#039; für den maximalen Ladestrom definiert (bei 90% SOC und bei 100% SOC):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MaxBattCharge_Request:SOC_jkbms.* {&lt;br /&gt;
                                    if ((ReadingsNum(&#039;mySolarForecast&#039;,&#039;RestOfDayPVforecast&#039;,&#039;&#039;)&lt;br /&gt;
                                         - ReadingsNum(&#039;mySolarForecast&#039;,&#039;special_todayConForecastTillSunset&#039;,&#039;&#039;)&lt;br /&gt;
                                         - (90-ReadingsNum(&#039;JK_BMS&#039;,&#039;capacity_remaining&#039;,&#039;&#039;))/100*310*51.2) &amp;lt; 400&lt;br /&gt;
                                         and ReadingsAge(&#039;JK_BMS&#039;,&#039;capacity_full_timestamp&#039;,&#039;&#039;) &amp;lt; 561600)&lt;br /&gt;
                                    {100}&lt;br /&gt;
                                    elsif ((ReadingsNum(&#039;mySolarForecast&#039;,&#039;RestOfDayPVforecast&#039;,&#039;&#039;)&lt;br /&gt;
                                            - ReadingsNum(&#039;mySolarForecast&#039;,&#039;special_todayConForecastTillSunset&#039;,&#039;&#039;)&lt;br /&gt;
                                            - (100-ReadingsNum(&#039;JK_BMS&#039;,&#039;capacity_remaining&#039;,&#039;&#039;))/100*310*51.2) &amp;lt; 400&lt;br /&gt;
                                            and ReadingsAge(&#039;JK_BMS&#039;,&#039;capacity_full_timestamp&#039;,&#039;&#039;) &amp;gt;= 561600)&lt;br /&gt;
                                    {100}&lt;br /&gt;
                                    elsif ((ReadingsNum(&#039;mySolarForecast&#039;,&#039;RestOfDayPVforecast&#039;,&#039;&#039;)&lt;br /&gt;
                                            - ReadingsNum(&#039;mySolarForecast&#039;,&#039;special_todayConForecastTillSunset&#039;,&#039;&#039;)&lt;br /&gt;
                                            - (90-ReadingsNum(&#039;JK_BMS&#039;,&#039;capacity_remaining&#039;,&#039;&#039;))/100*310*51.2) &amp;gt;= 400&lt;br /&gt;
                                            and ReadingsAge(&#039;JK_BMS&#039;,&#039;capacity_full_timestamp&#039;,&#039;&#039;) &amp;lt; 561600)&lt;br /&gt;
                                    {ceil ((90-ReadingsNum(&#039;JK_BMS&#039;,&#039;capacity_remaining&#039;,&#039;&#039;))/100*310/3.5)}&lt;br /&gt;
                                    elsif ((ReadingsNum(&#039;mySolarForecast&#039;,&#039;RestOfDayPVforecast&#039;,&#039;&#039;)&lt;br /&gt;
                                            - ReadingsNum(&#039;mySolarForecast&#039;,&#039;special_todayConForecastTillSunset&#039;,&#039;&#039;)&lt;br /&gt;
                                            - (100-ReadingsNum(&#039;JK_BMS&#039;,&#039;capacity_remaining&#039;,&#039;&#039;))/100*310*51.2) &amp;gt;= 400&lt;br /&gt;
                                            and ReadingsAge(&#039;JK_BMS&#039;,&#039;capacity_full_timestamp&#039;,&#039;&#039;) &amp;gt;= 561600)&lt;br /&gt;
                                    {ceil ((100-ReadingsNum(&#039;JK_BMS&#039;,&#039;capacity_remaining&#039;,&#039;&#039;))/100*310/3.0)}&lt;br /&gt;
                                  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das userReading wird in einer Automation benutzt, um den maximalen Ladestrom einzustellen; Ladebeginn bei ausreichend Sonne ist ab 11:30 eingestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Integration eines Fronius Symo GEN24 10.0 Plus mit (virtuellen) Batterie-Wechselrichter =====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-10-04 162422.png|right|thumb|400px|Flußgrafik mit eingebauten Hybrid-Wechselrichter]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Integration des Wechselrichters Fronius Symo GEN24 10.0 Plus benötigt zunächst eine Anbindung in FHEM, was mit dem Modul 98_fronius.pm vorgenommen wurde.&lt;br /&gt;
&lt;br /&gt;
Das Ziel der Kurzdokumentation ist neben der Darstellung eines Hybridwechselrichters aufzuzeigen, wie man den Wandlungsverlust eines PV-Wechselrichters (pvIn – pvOut) in Näherung visualisieren kann.  &lt;br /&gt;
&#039;&#039;&#039;pvIn&#039;&#039;&#039; ist dabei die Summe der Produkte aus den DC Strom- und Spannungswerten der einzelnen Strings (hier 2109 W), &#039;&#039;&#039;pvOut&#039;&#039;&#039; (hier 2065 W) ist die an den Inverterknoten (hier 1105 W) plus die an die Batterie abgegebene Leistung (hier 960 W). Bei dieser Implementierung wird mit einem zusätzlichen (virtuellen) Batterie-Wechselrichter gearbeitet. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In Vorbereitung werden die beiden anzugebenden Readings &#039;&#039;&amp;lt;pvIn&amp;gt;&#039;&#039; und &#039;&#039;&amp;lt;pvOut&amp;gt;&#039;&#039; zum Beispiel als userReadings erstellt, wobei &#039;&amp;lt;pvIn&amp;gt;&#039;&#039; und &#039;&#039;&amp;lt;pvOut&amp;gt;&#039;&#039; natürlich durch Readingnamen ersetzt werden müssen. Diese beiden Readings werden wie folgt berechnet / erstellt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;pvOut&amp;gt; = Inverter_Common_PAC_Value - PowerFlow_Site_P_Akku&lt;br /&gt;
&amp;lt;pvIn&amp;gt; = Inverter_Common_IDC_Value * Inverter_Common_UDC_Value + Inverter_Common_IDC_2_Value * Inverter_Common_UDC_2_Value&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der &#039;&#039;&#039;PV-Wechselrichter&#039;&#039;&#039; wird mit dem Attribut setupInverterDev01 definiert, wobei die angelegten Readingnamen in den Schlüsseln &#039;&#039;pvIn&#039;&#039; bzw. &#039;&#039;pvOut&#039;&#039; verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SymGen24 icon=inverter@#ff8c00:inverter@grey capacity=10000 strings=suedwest,nordost etotal=User_Produced_PV:kWh pvOut=&amp;lt;pvOut&amp;gt;:W pvIn=&amp;lt;pvIn&amp;gt;:W&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dem PV-Wechselrichter sind die Strings &#039;&#039;suedwest&#039;&#039; und &#039;&#039;nordost&#039;&#039; zugewiesen.&lt;br /&gt;
&lt;br /&gt;
Der zusätzliche &#039;&#039;&#039;Batterie-Wechselrichter&#039;&#039;&#039; wird mit dem Attribut setupInverterDev02 hinzugefügt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SymGen24 icon=inverter@#ff8c00:inverter@grey strings=none ac2dc=-PowerFlow_Site_P_Akku:W  dc2ac=PowerFlow_Site_P_Akku:W capacity=7680&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bemerkungen:&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
- strings=none sowie die Schlüssel ac2cd und dc2ac sind typisch für einen Batterie-WR bzw. kennzeichnen einen WR als Batterie-Wechselrichter &amp;lt;br&amp;gt;&lt;br /&gt;
- die an die Batterie abgegebene Leistung ist negativ&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Einbindung eines Fronius Symo GEN24 10.0 Plus mit BYD Batterie ohne (virtuellen) Batterie-Wechselrichter =====&lt;br /&gt;
Diee Implementierung ist komplett in diesem verlinkten [https://wiki.fhem.de/wiki/Solaranlage_Komplettbeispiel_Fronius_BYD Wiki Beitrag] beschrieben.&lt;br /&gt;
&lt;br /&gt;
Zur Integration des &#039;&#039;Fronius Symo&#039;&#039; in FHEM wird das Modul &#039;&#039;fronius.pm&#039;&#039; verwendet und in dem definierten Device &#039;&#039;Fronius_Symo_Gen24&#039;&#039; diverse userReadings erzeugt. Diese Readings werden in den korrespondierenden Schlüsseln des Attributes &#039;&#039;setupInverterDev01&#039;&#039; angegeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setupInverterDev01 Fronius_Symo_Gen24 etotal=User_Produced_PV_Energie:kWh pvOut=PowerFlow_Site_P_PV:W capacity=6000 strings=Dach_Ost,Dach_West&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Am Wechselrichter Fronius Symo Gen24 ist eine BYD Batterie angeschlossen. Das Device &#039;&#039;[https://wiki.fhem.de/wiki/Solaranlage_Komplettbeispiel_Fronius_BYD#PV_Batterie PV-Batterie]&#039;&#039; wird per [https://wiki.fhem.de/wiki/ModbusAttr ModbusAttr] angelegt und gemanaged. Die entsprechenden Readings werden im Attribut &#039;&#039;SetupBatteryDev01&#039;&#039; hinterlegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PV_Batterie&lt;br /&gt;
cap=10240&lt;br /&gt;
charge=BatteryChargePercent&lt;br /&gt;
icon=@dyn:@dyn:@dyn:@dyn&lt;br /&gt;
intotal=Summe_Ladung:Wh&lt;br /&gt;
outtotal=Summe_Entladung:Wh&lt;br /&gt;
pin=BatteryChargeWatt:W&lt;br /&gt;
pout=BatteryDischargeWatt:W&lt;br /&gt;
pinmax=10000&lt;br /&gt;
show=2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Einbindung eines SMA - Hybrid Sunny Tripower Smart Energy  =====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-10-05 083530.png|right|thumb|400px|SMAInverter.pm]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der genannte Wechselrichter wird über das Modul SMAInverter.pm in FHEM integriert. Die nebenstehende Abbildung zeigt und benennt die einzelnen Readings des Moduls welche in den entsprechenden Schlüsseln der SolarForecast Attribute &#039;&#039;setupInverterDevXX&#039;&#039; und &#039;&#039;setupBatteryDevXX&#039;&#039; zugeordnet werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Readings des SMAInverter Moduls können vor der Verwendung über geeignete Methoden (userReadings) in Readings mit sprechenden Namen überführt werden um sie mit diesen Namen in die genannten Attributschlüssel einzufügen. In der vorliegenden Lösung befinden sich die  Anwendungen SolarForecast und und die Inverter-Steuerung jeweils auf unterschiedlicher Hardware. Als Verbindungslayer wird MQTT genutzt, wobei dadurch bereits die dargestellten Readingnamen entstehen. &lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Der integrierte SolarForecast Grafikbereich ==&lt;br /&gt;
Das SolarForecast Modul beinhaltet eine Grafikdarstellung die sich in mehrere Bereiche gliedert. Diese Bereiche können über Attribute ein- bzw. ausgeblendet sowie die Inhalte festgelegt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 223545.png|right|thumb|400px|Bereiche der integrierten Grafik]]&lt;br /&gt;
&lt;br /&gt;
Der nebenstehende Screenshot gibt die Gliederung der Grafikbereiche wieder:&lt;br /&gt;
&lt;br /&gt;
 1 - der Kopfbereich (Graphic Header)&lt;br /&gt;
 2 - durch den Nutzer selbst definierbarer Inhalt (Graphic Header Own Specification) als Teil des Kopfbereiches&lt;br /&gt;
 3 - Bereich Verbraucherdarstellung (Consumer Legend)&lt;br /&gt;
 4 - Bereich Balkengrafik (Beam Graphic)&lt;br /&gt;
 5 - Energieflußgrafik (Flow Graphic)&lt;br /&gt;
&lt;br /&gt;
Jeder dieser Bereiche hat spezifische Steuerungsattribute zur Anpassung des Verhaltens und ggf. des Inhalts.&lt;br /&gt;
&lt;br /&gt;
=== 1 - Der Grafik Kopfbereich ===&lt;br /&gt;
Im Kopfbereich befinden sich fest verankerte Informationen zur verwendeten Vorhersage-API sowie deren Status, Informationen zum Sonnenaufgang und Sonnenuntergang, dem aktuellen Gesamtstatus des SolarForecast Devices, Abweichungskennzahlen der PV Vorhersage sowie weitere Kennzeichen zur Verfügung.&lt;br /&gt;
Über zwei Drucktasten kann eine Anlagenprüfung durchgeführt und in den Spportthread des Moduls im FHEM Forum abgesprungen werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;graphicHeaderShow&#039;&#039;&#039; kann der gesamte Kopfbereich 1 und 2 (nutzereigener Teilbereich) ausgeblendet werden. Wird der Kopbereich ausgeblendet, ist es hilfreich mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;showLink&#039;&#039;&#039; einen Link zur Detailgrafik einzufügen da der in der Kopfgrafik integrierte Link in diesem Fall nicht mehr zur Verfügung steht. &lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;graphicHeaderDetail&#039;&#039;&#039; definiert welche Bereiche des Grafikkopfes angezeigt werden sollen. Es kann die Anzeige des Energieverbrauches, der PV-Erzeugung und der vom Nutzer selbst definierte Inhalt miteinander frei kombiniert werden.&lt;br /&gt;
&lt;br /&gt;
=== 2 - Der Bereich mit selbst definierbarem Inhalt (Graphic Header Own Specification) ===&lt;br /&gt;
In diesem Bereich kann der User beliebige Readings, Set-Kommandos und Attribute des SolarForecast Devices oder anderer Devices, die sich im gleichen FHEM-System wie das SolarForecast Device befinden, anzeigen lassen.&lt;br /&gt;
&lt;br /&gt;
Dieser Bereich ist als Tabelle mit einer beliebigen Anzahl von Zeilen organisiert. Jede Zeile beinhaltet ein Kommentarfeld und vier Nutzfelder zur Darstellung ausgewähler Werte + Label. Der Bereich bzw. der Inhalt des Bereiches wird mit dem Attribut &#039;&#039;&#039;graphicHeaderOwnspec&#039;&#039;&#039; definiert.  &lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt ein real gesetztes graphicHeaderOwnspec Attribut. Die Leerzeilen sind nicht notwendig, erhöhen aber die Lesbarkeit der Struktur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
Autarkierate:Current_AutarkyRate&lt;br /&gt;
PV&amp;amp;nbsp;übermorgen:special_dayAfterTomorrowPVforecast&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;Sunset:special_todayConForecastTillSunset&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;nächsten&amp;amp;nbsp;Sunrise:special_conForecastTillNextSunrise&lt;br /&gt;
&lt;br /&gt;
#Batterie&lt;br /&gt;
BatteryLive&amp;amp;nbsp;Status:userFn_BatLive_State&lt;br /&gt;
SoC&amp;amp;nbsp;Limit:Settings_CGwacs_BatteryLife_MinimumSocLimit_value@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SoC&amp;amp;nbsp;Ist:SOC_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
SOC&amp;amp;nbsp;Optimum:Battery_OptimumTargetSoC&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
aktuelle&amp;amp;nbsp;Ladung:userFn_Bat_EnergyState&lt;br /&gt;
Verfügbar:userFn_BatLive_UsableEnergy&lt;br /&gt;
benötigte&amp;amp;nbsp;Ladeenergie:userFn_Bat_EnergyRemain&lt;br /&gt;
Ladefreigabe:Battery_ChargeRecommended&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
akt.&amp;amp;nbsp;DC&amp;amp;nbsp;Strom:DC_Current_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
Restladezeit&amp;amp;nbsp;Ziel:userFn_Bat_HoursUntilChargeFinish&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Soll:userFn_Bat_MaxChargeCurrent_set&lt;br /&gt;
:&lt;br /&gt;
&lt;br /&gt;
#Settings&lt;br /&gt;
Batterie&amp;amp;nbsp;Lademanagement:userFn_BatteryChargeManagement&lt;br /&gt;
SoC&amp;amp;nbsp;Management:userFn_BatterySoCManagement&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Ist:MaxChargeCurrent@MQTT2_cerboGX_c0619ab34e08_vebus&lt;br /&gt;
SmartSolar&amp;lt;br&amp;gt;Einspeisung:OvervoltageFeedIn@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
MPII&amp;amp;nbsp;Limit&amp;lt;br&amp;gt;Einspeisung&amp;amp;nbsp;(W):MaxFeedInPower@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SOC&amp;amp;nbsp;Limit&amp;amp;nbsp;Soll:MinimumSocLimit@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Verbr.&amp;amp;nbsp;Neuplanung:consumerNewPlanning&lt;br /&gt;
Wetteranzeige:graphicShowWeather &lt;br /&gt;
&lt;br /&gt;
Anzeige&amp;amp;nbsp;Nachtstunden:graphicShowNight&lt;br /&gt;
hist.&amp;amp;nbsp;Stunden:graphicHistoryHour&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto&lt;br /&gt;
Victron&amp;amp;nbsp;BatteryLife&amp;lt;br&amp;gt;(1=an,10=aus):BatteryLife@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Debug:ctrlDebu&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Kommentarfeld am Beginn einer Zeile wird durch ein &#039;&#039;&#039;#&#039;&#039;&#039; gekennzeichnet. Folgt dem # ein String, wird dieser String als Kommentarangabe gewertet und in der Grafik ausgegeben. Ein leeres Kommentarfeld wird lediglich durch ein # gefolgt von einem Leerzeichen oder NL beschrieben:&lt;br /&gt;
&lt;br /&gt;
 #:&amp;lt;Text&amp;gt;  (bzw nur # für einen &#039;leeren&#039; Titel)&lt;br /&gt;
&lt;br /&gt;
Ein Netzfeld bzw. ein Datensatz wird durch die Angabe von einem Label und dem darzustellenden Wert getrennt durch &#039;:&#039; definiert:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Label&amp;gt;:&amp;lt;Reading, Attribut oder Set-Kommando&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das System erkennt selbständig, ob es sich bei der Angabe um ein Reading, Attribut oder ein Set-Kommando handelt. Sollen Readings, Set-Kommandos und Attribute anderer Devices als dem SolarForecast-Device angezeigt werden, kann dies einfach durch Zusatz von&lt;br /&gt;
&lt;br /&gt;
 ....@&amp;lt;Device-Name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
an den Parameter erreicht werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-12-05 203916.png|right|thumb|400px|Darstellung eigener Grafikbereich]]&lt;br /&gt;
Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten &amp;quot;Wh&amp;quot; bzw. &amp;quot;kWh&amp;quot; werden entsprechend der Einstellung des Attributs &#039;&#039;&#039;graphicEnergyUnit&#039;&#039;&#039; umgerechnet. Im Label sind Leerzeichen durch &amp;quot;&amp;amp;amp;nbsp;&amp;quot; einzufügen, ein Zeilenumbruch durch &amp;quot;&amp;amp;lt;br&amp;amp;gt;&amp;quot;. Ein leeres Feld in einer Zeile wird durch &amp;quot;:&amp;quot; ohne eine weitere Angabe erzeugt.&lt;br /&gt;
&lt;br /&gt;
Die nebenstehende Abbildung zeigt die reale Darstellung der oben angegebenen Struktur im Attribut graphicHeaderOwnspec.&lt;br /&gt;
&lt;br /&gt;
==== Formatierung der Inhalte im Bereich &amp;quot;Graphic Header Own Specification&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
Die angezeigten Inhalte, wie z.B. Readingwerte, des User eigenen Bereiches (Attribut graphicHeaderOwnspec) können durch Spezifikationen im Attribut &#039;&#039;&#039;graphicHeaderOwnspecValForm&#039;&#039;&#039; manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
Die Online-Hilfe zum Attribut graphicHeaderOwnspecValForm erläutert die verfügbaren Möglichkeiten und Optionen.&lt;br /&gt;
Als Beispiel hier einige mögliche Notationen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &#039;userFn_Bat_HoursUntilChargeFinish&#039;                        =&amp;gt; &amp;quot;($VALUE).&#039; Stunden&#039;&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_battery.SOC_value&#039;             =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Settings_CGwacs_BatteryLife_MinimumSocLimit_value&#039;        =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Info_MaxChargeCurrent_value&#039;                              =&amp;gt; &amp;quot;($VALUE).&#039; A&#039;&amp;quot;,&lt;br /&gt;
  &#039;DC_Current_value&#039;                                         =&amp;gt; &amp;quot;%.0f A&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common.Regulated&#039; =&amp;gt; &amp;quot;($VALUE eq &#039;1&#039; ? &#039;Ja&#039; : &#039;Nein&#039;)&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine Besonderheit besteht bei darzustellenden Werten die die Einheiten &#039;Wh&#039; bzw. &#039;kWh&#039; besitzen. Diese Werte und Einheiten werden automatisch entsprechend des gesetzten Attributes graphicEnergyUnit umgerechnet und angezeigt.&lt;br /&gt;
&lt;br /&gt;
Soll in diesen Fällen eine automatische Formatierung umgangen werden, kann eine solche Notation verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &#039;Today_PVforecast&#039; =&amp;gt; &amp;quot;(sprintf &#039;%.1f &amp;amp;amp;nbsp;kWh&#039;, ($VALUE / 1000))&amp;quot;,&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Die Angabe von &amp;amp;amp;nbsp; vor &#039;kWh&#039; verhindert die Erkennung der Einheit und so auch die automatische Umsetzung durch das Modul. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 3 - Bereich Verbraucherdarstellung (Consumer Legend) ===&lt;br /&gt;
Dieser Grafikbereich zeigt die im Modul registrierten Verbraucher sowie deren Status und weitere Informationen an. Sind die Voraussetzungen gegeben, d.h. entsprechende Schlüssel in der ConsumerXX-Attributen gesetzt, können die Verbraucher über das Paneel manuell geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Zur Anpassung der Darstellung sind verschiedene Attribute verfügbar:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;consumerControl-&amp;gt;showLegend: Definiert die Lage bzw. Darstellungsweise der Verbraucherlegende sofern Verbraucher im SolarForecast Device registriert sind.&lt;br /&gt;
;consumerControl-&amp;gt;adviceIcon: Definiert die Art der Information über die geplanten Schaltzeiten eines Verbrauchers in der Verbraucherlegende. &lt;br /&gt;
;consumerControl-&amp;gt;detailLink: Wenn gesetzt, ist der jeweilige Verbraucher klickbar um direkt zur Detailansicht des jeweiligen Geräts auf einer neuen Browserseite zu gelangen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Standard wird das Verbraucherpaneel zwischen dem Kopfbereich und der ersten Balkengrafik Ebene dargestellt. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;showLegend&#039;&#039;&#039; und Argument &#039;&#039;&#039;icon_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_bottom&#039;&#039;&#039; kann das Verbraucherpaneel an das Ende des Grafikbereiches verschoben werden.&lt;br /&gt;
Die Verwendung von &#039;&#039;&#039;text_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_top&#039;&#039;&#039; blendet die Icon-Spalte im Verbraucherpaneel aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Screenshot 2025-02-08 093239.png|Darstellung mit consumerControl showLegend=icon_top (default)&lt;br /&gt;
File:Screenshot 2025-02-08 093646.png|Darstellung mit consumerControl showLegend=icon_bottom&lt;br /&gt;
File:Screenshot 2025-02-08 152018.png|Darstellung mit consumerControl showLegend=text_top bzw. text_bottom&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 213634.png|right|thumb|400px|]]&lt;br /&gt;
Ein Mouse-Over über das Uhrensymbol zeigt nähere Informationen zum Status, den Planungsdaten, Modus und weitere Daten des Verbrauchers. Der Schalter &amp;quot;Aus/Ein&amp;quot; visualisiert den Schaltzustand des Verbrauchers und können auch zum manuellen Schalten des Verbrauchers dienen. Voraussetzung ist, dass im consumer-Attribut die Schlüssel &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; mit den Set-Kommandos zum Schalten des Verbrauchers defininiert sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 222210.png|right|thumb|300px|]]&lt;br /&gt;
Der Auto-Schieberegler zeigt einerseits den Freigabestatus zum Schalten des Verbrauchers durch das SolarForecast Modul und kann andererseits manuell betätigt werden. Der Status des Reglers korrespondiert mit dem im zugehörigen Consumer Attribut vorhandenen Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; angegebenen Reading-Wert.&lt;br /&gt;
&lt;br /&gt;
Die Verbraucherbezeichnungen in dem Paneel können in der Standardkonfiguration angeklickt werden um direkt zur Detailansicht des Devices zu gelangen. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;detailLink&#039;&#039;&#039; kann der Link zur Detailansicht deaktiviert werden.&lt;br /&gt;
&lt;br /&gt;
Das Uhrensymbol kann mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;adviceIcon&#039;&#039;&#039; geändert und/oder dessen Farbe angepasst, sowie einen Informationstext statt eines Icons angezeigt werden. &lt;br /&gt;
&lt;br /&gt;
=== 4 - Bereich Balkengrafik (Beam Graphic) ===&lt;br /&gt;
&lt;br /&gt;
Die Balkengrafik des Moduls ist ein wesentliches Visualisierungshilfsmittel. Im Auslieferungszustand existiert eine Balkengrafikebene, die &#039;&#039;&#039;Ebene 1&#039;&#039;&#039;.&lt;br /&gt;
Jede Ebene kann zwei Balkendiagramme mit auswählbaren Inhalten, Farben und einstellbarem LayoutTyp darstellen. In Ebene 1 kann die Wettervorhersage eingebettet oder, bei Vorhandensein von Batteriegeräten, die zukünftigen Zeiten mit empfohlener Ladefreigabe und SoC-Prognose eingeblendet werden. &lt;br /&gt;
&lt;br /&gt;
Welche Daten in welchen Zeiträumen dargestellt werden sollen, die Bestimmung des Layouts, die Gestaltung der Balken und einiges mehr wird durch Attribute gesteuert. Ein Teil dieser Einstellungen wird über das zusammengesetzete Attribut &#039;&#039;&#039;graphicControl-&amp;gt;&#039;Schlüssel&#039;=&#039;Wert&#039;&#039;&#039;&#039; eingestellt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;grundsätzliche Layout Definitionen&#039;&#039;&#039;&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204342.png|right|thumb|400px|Standardanzeige mit Wetter-Icons, gesetzen Attributen graphicBeam1Color=D4C177, graphicHistoryHour=11]]&lt;br /&gt;
&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingTop:Legt den Platz in px im Balkendiagramm fest, der zwischen dem oberen Rand der jeweiligen Balkengrafik Ebene und der ersten Text- oder Iconreihe dieser Ebene eingefügt wird.&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingBottom:Legt den Platz in px im Balkendiagramm fest, der zwischen der letzten Text- oder Iconreihe der jeweiligen Balkengrafik Ebene und dem unteren Rand dieser Ebene eingefügt wird. &lt;br /&gt;
;graphicControl-&amp;gt;layoutType:Layout-Optionen zur grundlegenden Gestaltung der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourStyle:Format der Zeitangabe in der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourCount:Anzahl der darzustellenden Balken/Stunden in der Balkengrafk&lt;br /&gt;
[[Datei:Screenshot Screenshot 2025-05-21 153613.png|right|thumb|400px|Erweiterung des oberen und unteren Abstandes mit den Attributen graphicControl-&amp;gt;beamPaddingTop und graphicControl-&amp;gt;beamPaddingBottom]]&lt;br /&gt;
;graphicControl-&amp;gt;energyUnit:definiert die Einheit zur Anzeige der elektrischen Leistung in der Grafik&lt;br /&gt;
;graphicHistoryHour:Anzahl der vorangegangenen Stunden die in der Balkengrafik dargestellt werden&lt;br /&gt;
;graphicControl-&amp;gt;beamWidth:Vorgabe Breite der Balken der Balkengrafik in px (sonst automatische Bestimmung) &lt;br /&gt;
;graphicBeamHeightLevel1:Multiplikator zur Festlegung der maximalen Balkenhöhe der jeweiligen Ebene (hier Ebene 1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;Definition der Inhalte und Balkeneigenschaften&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204756.png|right|thumb|400px|Wie oben aber mit gesetzem Attribut graphicShowNight=1]]&lt;br /&gt;
;graphicBeam1Color:Farbauswahl des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2Color:Farbauswahl des sekundären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam1Content:Legt den darzustellenden Inhalt des primären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam2Content:Legt den darzustellenden Inhalt des sekundären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam1FontColor:Auswahl der Schriftfarbe des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2FontColor:Auswahl der Schriftfarbe des sekundären Balkens (Ebene 1)&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 205024.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=0 (ohne Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;zusätzliche Optionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;graphicShowNight:Anzeigen oder Verbergen der Nachtstunden in der Balkengrafik&lt;br /&gt;
;graphicShowWeather:Wettericons in der Balkengrafik anzeigen/verbergen (nur Ebene 1)&lt;br /&gt;
;graphicWeatherColor:Farbe der Wetter-Icons für die Tagesstunden&lt;br /&gt;
;graphicWeatherColorNight:Farbe der Wetter-Icons für die Nachtstunden&lt;br /&gt;
;graphicShowDiff:Zusätzliche Anzeige der Differenz &amp;quot;&amp;lt;primärer Balkeninhalt&amp;gt; - &amp;lt;sekundärer Balkeninhalt&amp;gt;&amp;quot; im Kopf- oder Fußbereich der Balkengrafik&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die genaue Beschreibung und deren Optionen sind der aktuellen Online-Hilfe zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Für alle Ebenen gilt:&#039;&#039;&#039; Ein Attribut mit einer ungeraden Balkennummer (z.B. graphicBeam1Content) bezieht sich immer auf den primären Balken, ein Attribut mit einer geraden Balkennummer (z.B. graphicBeam2Content) bezieht sich immer auf den sekundären Balken.&lt;br /&gt;
&lt;br /&gt;
Die Balken haben, wie die meisten Elemente in der Balkengrafik, eine Mouse-Over Eigenschaft welche relevante Informationen zu den dargestellten Werten anzeigt. &lt;br /&gt;
&lt;br /&gt;
Sind die Nachtunden mit &#039;&#039;&#039;graphicShowNight&#039;&#039;&#039; ausgeblendet, werden keine Balken angezeigt sofern es keine Werte anzuzeigen gibt. Sollten dennoch Werte ungleich 0 anzuzeigen sein, werden diese Werte auch trotz ausgeblendeter Nachstunden angezeigt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 2 ====&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 211741.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=01 (mit Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 2&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam3Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam4Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 4 für Balken 4) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wetter-Icons können nur in Ebene 1 integriert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 2 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 2 gibt, eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgende Ebene.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 3 ====&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 3&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam5Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam6Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 5 für Balken 5) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 3 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 3 gibt, ist eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgenden Ebenen, d.h. auch auf die Ebene 3.&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 5 - Die Energieflußgrafik (Flow Graphic) ===&lt;br /&gt;
[[Datei:Screenshot 2025-02-13 213424.png|right|thumb|400px|Energieflußgrafik mit Verbrauchern in der Nachtdarstellung (Mondphasen) nach Sonnenuntergang]]&lt;br /&gt;
&lt;br /&gt;
Die Energieflußgrafik stellt die registrierten Erzeuger, Batterien, Netzzugänge und Verbraucher strukturiert in mehreren Ebenen dar:&lt;br /&gt;
&lt;br /&gt;
;Ebene 1: In der oberen Ebene befinden sich die PV-Generatoren, Smart-Loader sowie sonstigen Erzeuger &lt;br /&gt;
;Ebene 2: Die mittlere Ebene organisiert den Zugang zum öffentlichen Netz, dem Hausknoten, dem Batterieknoten sowie einem Dummy-Verbraucher (Lampensymbol) für den Energieverbrauch des Hauses der keinem der registrierten Verbraucher zugeordnet werden kann.&lt;br /&gt;
;Ebene 3: In der unteren Ebene werden die registrierten Verbraucher dargestellt. Unterhalb der Verbrauchersymbole werden der aktuelle Verbrauch (bzw. der On/Off-Zustand) sowie darunter die Restlaufzeit (Minuten) des Verbrauchers, sofern er durch das Modul geplant und gestartet wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Position und Gestaltung der Grafikelemente ist umfangreich über das Attribut &#039;&#039;&#039;flowGraphicControl&#039;&#039;&#039; und den darin verfügbaren Schlüsseln einstellbar.&lt;br /&gt;
Die Bedeutung der Schlüssel ist in der Online-Hilfe zum Attribut mit einem Beispiel beschrieben. &lt;br /&gt;
&lt;br /&gt;
Darüber hinaus enthalten die Setup-Attribute &#039;&#039;&#039;setupInverterDevXX&#039;&#039;&#039;, &#039;&#039;&#039;setupOtherProducerXX&#039;&#039;&#039; und &#039;&#039;&#039;consumerXX&#039;&#039;&#039; weitere Einstellungsmöglichkeiten um deren Icons und Färbungen in der Flußgrafik individuell einstellen zu können. So sind zum Beispiel die Icons der PV-Inverter und deren Färbung mit dem Schlüssel &#039;&#039;&#039;icon&#039;&#039;&#039; der setupInverterDevXX-Attribute in Abhängigkeit von Tag und Nacht separat definierbar.&lt;br /&gt;
&lt;br /&gt;
In den Verbraucher-Attributen ist mit dem Schlüssel &#039;&#039;&#039;noshow&#039;&#039;&#039; die Sichtbarkeit in der Flußgrafik definierbar.&lt;br /&gt;
&lt;br /&gt;
Generell steuert das Attribut &#039;&#039;&#039;graphicSelect&#039;&#039;&#039; die Ein- bzw. Ausblendung der gesamten Flußgrafik.&lt;br /&gt;
&lt;br /&gt;
== Die Verbrauchsprognose ==&lt;br /&gt;
Im Gegensatz zu der PV Prognose gibt es keine API oder andere externen Datenquellen die für die Verbrauchsprognose herangezogen werden könnten.&lt;br /&gt;
&lt;br /&gt;
Zum Zweck der Verbrauchsermittlung verwendet das Modul die Meterdaten aus dem Attribut &#039;&#039;setupMeterDev&#039;&#039; sowie den weiteren setup-Attributen &#039;&#039;setupInverterDevXX&#039;&#039;. &lt;br /&gt;
Sind auch andere Erzeuger (BHKW, Windanlagen, etc.) bzw. eine Batterie vorhanden, sind ebenfalls die Attribute &#039;&#039;setupOtherProducerXX&#039;&#039; bzw. &#039;&#039;setupBatteryDev&#039;&#039; für die Berechnung des Hausverbrauchs relevant. In diesen Attributen gibt es die Schlüssel &#039;&#039;*total&#039;&#039; die teilweise optional sind. Für die Verbrauchsprognose bilden sie jedoch die Berechnungsgrundlage und sind deswegen für diese Funktionalität wichtig anzugeben.&lt;br /&gt;
&lt;br /&gt;
Die Verbrauchswerte werden stundengenau erfasst und im Datenspeicher &#039;&#039;pvHistory&#039;&#039; für 31 Tage, sowie im Datenspeicher &#039;&#039;pvCircular&#039;&#039; 210 Tage gespeichert. Die beiden Datenspeicher übernehmen unterschiedliche Aufgaben im Rahmen der Prognoseerstellung. Auf Grundlage der gespeicherten und somit historischen Verbrauchswerte erstellt das Modul eine Prognose für die kommende Zeit.&lt;br /&gt;
&lt;br /&gt;
Mit dem Kommando &lt;br /&gt;
&lt;br /&gt;
   &amp;quot;get ... pvHistory [Tag]&amp;quot; &lt;br /&gt;
&lt;br /&gt;
wird der Inhalt aufgelistet. Die Schlüssel &#039;&#039;confc&#039;&#039;, &#039;&#039;con&#039;&#039; und &#039;&#039;gcon&#039;&#039; zeigen die Verbrauchsprognose, den Verbrauch und den Netzbezug der jeweiligen Stunde des gewählten Tages.&lt;br /&gt;
Die Stunde &amp;quot;99&amp;quot; zeigt die Summen dieser Schlüsssel für den Tag:&lt;br /&gt;
&lt;br /&gt;
      99 =&amp;gt; etotal: , pvfc: 782, pvrl: 0, rad1h: -&lt;br /&gt;
            confc: 14540, con: 13873, gcon: 13873, gfeedin: 0&lt;br /&gt;
            batintotal: , batin: 0, batouttotal: , batout: 0&lt;br /&gt;
            batmaxsoc: -, batsetsoc: -&lt;br /&gt;
            wid: , wcc: , wrp: , pvcorrf: , dayname: So&lt;br /&gt;
            cyclescsm01: 0&lt;br /&gt;
            cyclescsm02: 0&lt;br /&gt;
            cyclescsm03: 0&lt;br /&gt;
            cyclescsm04: 1, hourscsme04: 0.00&lt;br /&gt;
            cyclescsm05: 0&lt;br /&gt;
            cyclescsm06: 0&lt;br /&gt;
            cyclescsm07: 1, hourscsme07: 0.00&lt;br /&gt;
            cyclescsm08: 1, hourscsme08: 0.00&lt;br /&gt;
            cyclescsm09: 1, hourscsme09: 0.03 &lt;br /&gt;
&lt;br /&gt;
In dem Beispiel wurden für den Tag 14540 Wh Verbrauch prognostiziert, 13873 Wh tatsächlich verbraucht und davon 13873 Wh aus dem Netz bezogen. Leider war an diesem Tag keinerlei PV Ertrag vorhanden, was man auch an dem Schlüssel &#039;&#039;pvrl&#039;&#039; erkennen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Inhalt des pvCircular-Speichers kann mit dem Befehl  &lt;br /&gt;
&lt;br /&gt;
     &amp;quot;get ... pvCircular [Tag]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Das nachfolgende Beispiel zeigt die Ausgabe für die Tagesstunde 23:&lt;br /&gt;
&lt;br /&gt;
 23 =&amp;gt; pvapifc: 0, pvaifc: -, pvfc: 0, aihit: 0, pvrl: 0&lt;br /&gt;
       batin01: 0, batin02: -, batin03: -&lt;br /&gt;
       batout01: 619, batout02: -, batout03: -&lt;br /&gt;
       confc: 650, gcon: 23, gfeedin: 0, wcc: 40, rr1c: 0.00&lt;br /&gt;
       temp: -6.00, wid: 100, wtxt: Bewölkungsentwicklung nicht beobachtet&lt;br /&gt;
       pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
       ... &lt;br /&gt;
       con_all =&amp;gt; Sa  @ 617 762&lt;br /&gt;
                  Di  @ 693 645&lt;br /&gt;
                  Mo  @ 620 679&lt;br /&gt;
                  So  @ 669 666 636&lt;br /&gt;
                  Mi  @ 701 626&lt;br /&gt;
                  Do  @ 612 642&lt;br /&gt;
                  Fr  @ 615 606&lt;br /&gt;
&lt;br /&gt;
Der Schüssel &#039;&#039;con_all&#039;&#039; enthält einen Hash aus Arrays die für jeden Wochentag (Mo..So) bis zu 30 Verbrauchswerte (in Wh) für die angezeigte Stunde speichern. Wie hier erkennbar ist, wurden an den drei vergangenen Sonntagen jweils 669 Wh, 666 Wh bzw. 636 Wh in der Stunde 23 (22:00-22:59) verbraucht.&lt;br /&gt;
Der Median aus diesen Werten geht in die Verbrauchsprognose ein. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wochentagsnamen Mo..So sind von den installierten Locales auf Betriebsystemebene abhängig. Ist keine deutsche locale installiert, werden die englischen Wochentagsnamen Mon..Sun verwendet. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Wie wird der Verbrauch des Hauses ermittelt und gespeichert? ===&lt;br /&gt;
Die Verbrauchsdaten des Hauses werden auf Stundenbasis ermittelt und gespeichert. Das &amp;quot;Haus&amp;quot; steht als Synonym aller im Kontext des Solarforecast Devices zusammengeführten Inverter (setupInverterDevXX), sonstigen Erzeuger (setupOtherProducerXX), Netzanschlüsse (setupMeterDev), Verbraucher (consumerXX) und Batterien (setupBatteryDev).&lt;br /&gt;
&lt;br /&gt;
Alle diese Daten werden durch das Modul mit jedem ausgeführten Zyklus (Attribut plantControl-&amp;gt;cycleInterval) und, wenn ein Event eines als &#039;asynchron&#039; definierten Devices auftritt, gesammelt und daraus permanent ein aktualisierter Verbrauch berechnet. Die Berechnung beschreibt folgende Formel:&lt;br /&gt;
&lt;br /&gt;
 PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung - Verbrauch = 0&lt;br /&gt;
&lt;br /&gt;
bzw.&lt;br /&gt;
 &lt;br /&gt;
 Verbrauch (Wh) = PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung&lt;br /&gt;
            con = PV           + PP                 - GridIn          + GridCon   - BatIn          + BatOut&lt;br /&gt;
&lt;br /&gt;
Die PV-Erzeugung beinhaltet die Summe aller durch die angegebnen Inverter (setupInverterDev01 .. setupInverterDevXX) erzeugten Energien. Die &amp;quot;sonstige Erzeugung&amp;quot; summiert sich aus den Werten aller angegebenen Producer (setupOtherProducer01 .. setupOtherProducerXX). Der Verbrauch wird durch die registrierten Geräte consumerXX teilweise direkt erfasst, ist aber grundsätzlich unvollständig da nicht alle Verbrauchswerte im &amp;quot;Haus&amp;quot; gemessen und durch das Modul erfasst werden können.&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel zeigt das Ergebnis bei 300 Wh PV-Erzeugung und gleichzeitige 500 Wh Netzbezug:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 300 + 0 - 0 + 500 - 0 + 0 = 800 Wh&lt;br /&gt;
&lt;br /&gt;
Bei 1300Wh PV-Erzeugung, 100 Wh Netzeinspeisung sowie 200 Wh Batterieladung ergibt sich der Verbrauch zu:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 1300 + 0 - 100 + 0 - 200 + 0 = 1000 Wh&lt;br /&gt;
&lt;br /&gt;
Ohne Erzeugung, aber mit der Energielieferung von 500 Wh aus der Batterie, 800 Wh Netzbezug (mit einem Anteil Batterienachladung aus dem Netz von 200 Wh) sieht die Verbrauchsrechnung wie folgt aus: &lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 0 + 0 - 0 + 800 - 200 + 500 = 1100 Wh&lt;br /&gt;
&lt;br /&gt;
Der so ermittelte Verbrauchsert wird mit jedem Zyklus in der pvHistory im Schlüssel &amp;quot;con&amp;quot; gespeichert. Man kann sich die gespeicherten Werte mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;name&amp;gt; pvHistory [&amp;lt;Tag&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Nachfolgendes Beispiel zeigt einen Datensatz für die Stunde 8 eines Tages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      08 =&amp;gt; pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotali01: 62940734, etotali02: 2928860, etotali03: -&lt;br /&gt;
            pvrl01: 0, pvrl02: 0, pvrl03: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 630, con: 962, gcons: 962, conprice: 0.2958&lt;br /&gt;
            gfeedin: 0, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 120, sunalt: -3&lt;br /&gt;
            batintotal: 3713815.07742543, batouttotal: 3604468.26993988, batin: 0, batout: 0&lt;br /&gt;
            wid: 161, wcc: 89, rr1c: 0.00, pvcorrf: 0.27/0.00 temp: 7.40, &lt;br /&gt;
            csmt01: 110996.12, csme01: 32.1399999999994, minutescsm01: 30&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 2513.67, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1581293.6, csme04: 136.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 1662.17, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 90.53, csme06: 0, minutescsm06: 0&lt;br /&gt;
            csmt07: 39.75, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 38050, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 131627, csme09: 33.2000000000116, minutescsm09: 39&lt;br /&gt;
            minutescsm10: 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Schlüssel &amp;quot;con&amp;quot; ist der gespeicherte Verbrauch von 962 Wh ersichtlich.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit bekommt man mit dem Attribut &#039;&#039;ctrlDebug=collectData&#039;&#039; einen Einblick in die Verbrauchsermittlung bei jedem Zyklus und kann so die Eingangswerte und das daraus resultierende Ergebnis im FHEM Log nachverfolgen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
2024.11.28 11:38:20.080 1: SolCast DEBUG&amp;gt; EnergyConsumption input -&amp;gt; PV: 96, PP: 0, GridIn: 0, GridCon: 582, BatIn: 5, BatOut: 0&lt;br /&gt;
2024.11.28 11:38:20.081 1: SolCast DEBUG&amp;gt; EnergyConsumption result -&amp;gt; 673 Wh&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie wird die Verbrauchsprognose erstellt? ===&lt;br /&gt;
&lt;br /&gt;
Aus den gespeicherten con-Werten (Verbrauchsdaten) der pvCircular (Schlüssel con_all) sowie Einträgen der pvHistory wird der Median der historischen Tage ermittelt und für den kommenden Tag bzw. die kommen Stunden zur Prognose angewendet. Dabei geht per default jeder verfügbare historische Tag gleichberechtigt in die Prognose ein. Mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039; kann festgelegt werden, dass nur gleiche Wochentage (Mo..So) für die Prognose verwendet werden. Hierbei spielt die Vermutung, dass das Verbrauchsverhalten eine gewisse Korrelation zum Wochentag hat, eine Rolle. &lt;br /&gt;
&lt;br /&gt;
Verwendet man die Einstellung consForecastIdentWeekdays=1, hat es sich als vorteilhaft erwiesen, das Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays&#039;&#039;&#039; auf einen niedrigeren Wert als den Default zu setzen. Eine Einstellung auf &#039;8&#039; zum Beispiel verwendet den Median der gleichen Wochentage der vergangenenen 8 Wochen. Dadurch wird nicht zu weit in die Vergangenheit verzweigt und so eine langsame Veränderung des Verbrauchsmedian, zum Beispiel hervorgerufen durch den Übergang vom Winter in das Frühjahr hinein, abgebildet.&lt;br /&gt;
&lt;br /&gt;
Weiteren Einfluß auf die Verbrauchsprognose kann mit dem Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; im Consumerattribut genommen werden. Insbesondere bei der unregelmäßigen Nutzung von Verbrauchern mit hoher Leistung kann die Projektion der aufgezeichneten historischen Werte in die Prognose zu unverhältnismäßig hohen Verbrauchswerwartunden führen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Möglicherweise führt in Fällen die Verwendung eine der nachfolgenden Optionen zu einem besseren Ergebnis:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;1 -&#039;&#039;&#039; die allgemeine Verbrauchsprognose wird um die gespeicherten Energieverbrauchsanteile reduziert.&lt;br /&gt;
* &#039;&#039;&#039;2 -&#039;&#039;&#039; wie bei &#039;1&#039;, jedoch gehen die Planungsdaten des Verbrauchers bei der Prognose der kommenden Stunden wieder mit ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;&#039;exconfc&#039;&#039;&#039; in einem der Consumer verwendet, sollte&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays=4&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
eingestellt werden. Hintergrund ist, dass die Verbrauchsanteile der jeweiligen Verbraucher nur maximal 31 Tage in der pvHistory verfügbar sind. Für längere Zeiträume stehen nur Gesamtsummen des Verbrauchs in der pvCircular zu Verfügung.  &lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=1&#039;&#039;&#039; werden die in der Historie aufgezeichneten Verbrauchsbestandteile aus einer Prognose herausgerechnet. Konkret werden die in der pvHistory aufgezeichneten Verbrauchsbestandteile für die relevante Stunde ermittelt und daraus ein Durchschnitt gebildet der vom Prognosewert subtrahiert wird. Mit dem Attributwert plantControl-&amp;gt;consForecastIdentWeekdays=1 werden wiederum nur identische Wochentage (Mo .. So) zusammengefasst.&lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=2&#039;&#039;&#039; erfolgt ebenso die Eliminierung des Verbrauchsanteils, es wird jedoch auf die Planungsdaten für diesen Verbraucher zugegriffen und die geplanten Energieanteile wiederum der Verbrauchsprognose für die kommenden Stunden hinzugerechnet.&lt;br /&gt;
&lt;br /&gt;
In beiden Anwendungsfällen ist es notwendig, dass dem Modul durch die Angabe entsprechender Readings der Energieverbrauch im Setup des Consumers bekannt gemacht wird damit diese Energieanteile registriert werden können. Allgemein funktioniert die Verbrauchsprognose gut wenn Verbrauchsprozesse regelmäßig in einem wiederkehrenden Zeitraster ablaufen, der Verbrauch durch persönliche Rituale bestimmt ist. So zum Beispiel könnte am Dienstag und Samstag gewöhnlich die Waschmaschine laufen, das E-Auto täglich aufgeladen werden und gebügelt wird oft am Sonntag Nachmittag.&lt;br /&gt;
&lt;br /&gt;
Unregelmäßige Nutzung, vor allem vom Großverbrauchern, lässt sich nur sehr schwer und ungenügend auf zukünftige Verbrauchsprognosen projizieren.&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis der Prognose wird im Kopf der Grafik in der Zeile &#039;&#039;Verbrauch&#039;&#039; sowie in diversen Readings wie &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RestOfDayConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den Rest des Tages)&lt;br /&gt;
* &#039;&#039;&#039;NextHours_Sum04_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für die nächsten 4 Stunden)&lt;br /&gt;
* &#039;&#039;&#039;Tomorrow_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den kommenden Tag)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
angezeigt.&lt;br /&gt;
&lt;br /&gt;
Weitere Aggregationen kann man sich über das Attribut &#039;&#039;&#039;ctrlStatisticReadings&#039;&#039;&#039; bei Bedarf zuschalten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;conForecastTillNextSunrise&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
* &#039;&#039;&#039;todayConForecastTillSunset&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
* &#039;&#039;&#039;todayConsumptionForecast&#039;&#039;&#039; - Verbrauchsprognose aufgesplittet pro Stunde des aktuellen Tages (01-24) &lt;br /&gt;
 &lt;br /&gt;
==== Debugging der Verbrauchsprognose ====&lt;br /&gt;
Um sich einen Einblick über die Erstellung der Verbrauchsprognose zu verschaffen, bietet sich die Einschaltung von:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
an. Mit diesem gesetzten Attribut wird die Erstellung der Prognose im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; ################### Start Consumption forecast ###################&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; Basics - installed locale: de_DE.UTF-8, used scheme: DE&lt;br /&gt;
2025.02.27 19:52:00.064 1: SolCast DEBUG&amp;gt; process Today dayname: Do, Tomorrow dayname: Fr&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 01 - 74.43 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 10 - 290.77 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 24 - 660.70 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 20, hod: 07 - 459.93 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;07&#039; register for exclude day 20, hod: 02 - 0.33 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 30, hod: 08 - 264.78 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next Hours (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; excl. hist 74 Wh for Hour 01, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; estimated cons of Hour 01: 436 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; excl. hist 0 Wh for Hour 02, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 02: 428 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 03: 458 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 04: 503 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 05: 489 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 06: 482 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; excl. hist 460 Wh for Hour 07, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 07: 274 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 265 Wh for Hour 08, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 08: 441 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 09: 558 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 291 Wh for Hour 10, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 10: 443 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 11: 881 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 12: 794 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 13: 840 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 14: 660 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 15: 812 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 16: 752 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 17: 597 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 18: 652 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 19: 634 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 20: 628 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 21: 713 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 22: 596 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 23: 629 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; excl. hist 661 Wh for Hour 24, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons of Hour 24: 660 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons Tomorrow: 16848 Wh, Individual hourly values considered: 72, exclude: 0 Wh (avg of 0 entities)&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Store Consumption forecast values (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour00&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;20&#039; confc: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour01&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;21&#039; confc: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour02&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;22&#039; confc: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour03&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;23&#039; confc: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store &#039;NextHour04&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;24&#039; confc: 660&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour05&#039; hod &#039;01&#039; confc: 436, confcEx: 436&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour06&#039; hod &#039;02&#039; confc: 428, confcEx: 428&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour07&#039; hod &#039;03&#039; confc: 458, confcEx: 458&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour08&#039; hod &#039;04&#039; confc: 503, confcEx: 503&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour09&#039; hod &#039;05&#039; confc: 489, confcEx: 489&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour10&#039; hod &#039;06&#039; confc: 482, confcEx: 482&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour11&#039; hod &#039;07&#039; confc: 274, confcEx: 274&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour12&#039; hod &#039;08&#039; confc: 441, confcEx: 441&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour13&#039; hod &#039;09&#039; confc: 558, confcEx: 558&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour14&#039; hod &#039;10&#039; confc: 443, confcEx: 443&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour15&#039; hod &#039;11&#039; confc: 881, confcEx: 881&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour16&#039; hod &#039;12&#039; confc: 794, confcEx: 794&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour17&#039; hod &#039;13&#039; confc: 840, confcEx: 840&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour18&#039; hod &#039;14&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour19&#039; hod &#039;15&#039; confc: 812, confcEx: 812&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour20&#039; hod &#039;16&#039; confc: 752, confcEx: 752&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour21&#039; hod &#039;17&#039; confc: 597, confcEx: 597&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour22&#039; hod &#039;18&#039; confc: 652, confcEx: 652&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour23&#039; hod &#039;19&#039; confc: 634, confcEx: 634&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour24&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour25&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour26&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour27&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour28&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; consumption calculated - day: 27, hod: 20, con: 574 Wh&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; write pvCircular consumption - hod: 99, todayConsumption: 11210 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe startet mit &#039;&#039;&amp;quot;Start Consumption forecast&#039;&#039;&amp;quot;, es werden die zu exkludierenden historischen Daten für jeden Consumer bzgl. jedem Tag (day) und Stunde des Tages (hod) getrennt registriert. Diese Werte werden durch die gespeicherte Einträge in der pvHistory (max. 31 historische Tage) geliefert. &lt;br /&gt;
&lt;br /&gt;
Im nächsten Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next Hours (new median)&amp;quot;&#039;&#039; werden die Prognosen für die nächsten Stunden kalkuliert und die zuvor registrierten Excludes angewendet. Die Prognose für den kommenden Tag ist im Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next day (new median)&amp;quot;&#039;&#039; protokolliert. Die Prognose für den kommenden Tag ist nicht einfach die Summe der Prognose der nächsten Stunden, denn in den kommenden Stunden werden auch die verfügbaren Planungen der Consumer einbezogen. Für den kommenden Tag können diese Werte unter Umständen nicht einbezogen werden da sie zum Zeitpunkt X noch nicht verfügbar sind.&lt;br /&gt;
&lt;br /&gt;
Im Abschnitt &#039;&#039;&amp;quot;Store Consumption forecast values (new median)&amp;quot;&#039;&#039; erscheinen die effektiv gespeicherten Werte. Diese sind die Grandlage für die grafische Darstellung sowie weiteren Kalkulationen.&lt;br /&gt;
&lt;br /&gt;
=== Wie kann eine fehlerhafte Verbrauchsprognose korrigiert werden? ===&lt;br /&gt;
Wie im vorherigen Abschnitt beschrieben, wird die Prognose aus den gespeicherten &amp;quot;con&amp;quot;-Werten der vergangenen Tage (bzw. Stunden) abgeleitet. &lt;br /&gt;
Grundsätzlich muß zunächst sichergestellt werden, dass die auszulesenden Readings der angegebenen Energiezähler sowie deren Einheiten! korrekt eingestellt sind. Das gilt ebenfalls für die registrierten Verbraucher im Modul.&lt;br /&gt;
&lt;br /&gt;
Für einen ersten Überblick bietet sich das Debug Attribut an zu setzen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
Beispielausgabe des Debug:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2024.09.21 13:28:27.041 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day ###################&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;01&amp;lt; considering possible exclusions: 14082&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;08&amp;lt; considering possible exclusions: 16446&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;15&amp;lt; considering possible exclusions: 14568&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;25&amp;lt; considering possible exclusions: 15522&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; estimated Consumption for tomorrow: 15154, days for avg: 4&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next hours ###################&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 14 -&amp;gt; 850 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 14 -&amp;gt; 643 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 14 -&amp;gt; 590 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 14 -&amp;gt; 522 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 13:00:00, confc: 651, days for avg: 4, hist. consumption registered consumers: 560.97&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 15 -&amp;gt; 720 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 15 -&amp;gt; 743 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 15 -&amp;gt; 897 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 15 -&amp;gt; 557 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 14:00:00, confc: 729, days for avg: 4, hist. consumption registered consumers: 620.97&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 16 -&amp;gt; 676 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 16 -&amp;gt; 790 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 16 -&amp;gt; 785 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 16 -&amp;gt; 581 Wh&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 15:00:00, confc: 708, days for avg: 4, hist. consumption registered consumers: 647.29&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 17 -&amp;gt; 622 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 17 -&amp;gt; 639 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 17 -&amp;gt; 646 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 17 -&amp;gt; 572 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 16:00:00, confc: 619, days for avg: 4, hist. consumption registered consumers: 618.30&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 18 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 18 -&amp;gt; 614 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 18 -&amp;gt; 580 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 18 -&amp;gt; 480 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 17:00:00, confc: 567, days for avg: 4, hist. consumption registered consumers: 583.41&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 19 -&amp;gt; 615 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 19 -&amp;gt; 1659 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 19 -&amp;gt; 597 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 19 -&amp;gt; 618 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 18:00:00, confc: 872, days for avg: 4, hist. consumption registered consumers: 636.97&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 20 -&amp;gt; 611 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 20 -&amp;gt; 1124 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 20 -&amp;gt; 546 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 20 -&amp;gt; 479 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 19:00:00, confc: 690, days for avg: 4, hist. consumption registered consumers: 578.87&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 21 -&amp;gt; 1474 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 21 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 21 -&amp;gt; 619 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 21 -&amp;gt; 433 Wh&lt;br /&gt;
2024.09.21 13:28:27.058 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Im ersten Teil wird die erwartete Consumption für den nächsten Tag unter Berücksichtigung möglicher Ausschlüsse von Verbrauchern ausgegeben. Ausschlüsse von Verbrauchern ergeben sich wenn in dem Verbraucherattribut der Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; gesetzt ist. Er besagt, dass die Verbrauchswerte des Verbrauchers in eine zukünftige Prognose nicht eingehen sollen. Zum Beispiel wenn ein Verbraucher mit sehr hohen Verbrauchswerten nur sporadisch eingesetzt wird und dadurch die Prognose stark verfälschen würde. Es ist auch zu sehen, dass bedingt durch das Attribut &#039;&#039;&#039;affectConsForecastIdentWeekdays = 1&#039;&#039;&#039; nur die historischen Tage 01, 08, 15 und 25 berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Teil wird die berechnete Erwartung für die nächsten Stunden ausgegeben. &lt;br /&gt;
Zur Beschreibung der Fehlersuche gehen wir davon aus, dass die Prognose von 780 Wh am 2024-09-21 20:00:00 zu hoch erscheint weil am Tag &amp;quot;07&amp;quot; ein Wert von 1474 Wh gespeichert ist:&lt;br /&gt;
&lt;br /&gt;
 SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt geben wir die historischen Werte für den Tag 07 aus:&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;Name&amp;gt; pvHistory 07&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz interessiert die Stunde 21. Sie resultiert aus der obigen Angabe &amp;quot;starttime: xxxx-xx-xx 20:00:00&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      21 =&amp;gt; etotal: 64354660, pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 496, con: 1474, gcons: 23, conprice: 0.2958&lt;br /&gt;
            gfeedin: 5, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 289, sunalt: -8&lt;br /&gt;
            batintotal: 3064096.92456668, batouttotal: 2958021.37946804, batin: 0, batout: 1460&lt;br /&gt;
            wid: 101, wcc: 20, rr1c: 0.00, pvcorrf: 1.00/-temp: 26.00, &lt;br /&gt;
            csmt01: 64262.43, csme01: 28.8099999999977, minutescsm01: 25&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 0, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1389417.4, csme04: 94.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 0, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 290.15, csme06: 6.66999999999996, minutescsm06: 54&lt;br /&gt;
            csmt07: 0, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 32800, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 103987.8, csme09: 38, minutescsm09: 43&lt;br /&gt;
            csmt10: 9151.24999999783, csme10: 3.99999999997999, minutescsm10: 60&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz sind die Energieverbrauchsanteile der im Device registrierten Verbraucher mit dem Schlüssel &amp;quot;csmeXX&amp;quot; gespeichert. Dabei ist &amp;quot;XX&amp;quot; die Verbrauchernummer. In dem Beispiel existieren die Anteile csme01 und csme03 - csme10. Keiner dieser Verbraucher hat einen auffälligen Verbrauchswert gespeichert, d.h. die Messung der Verbraucher scheidet als Problemquelle aus. Wäre ein unverhältmismäßig hoher Verbrauch bei einem der Verbraucher feststellbar, müssten die Schlüssel &#039;&#039;&#039;pcurr&#039;&#039;&#039; und &#039;&#039;&#039;etotal&#039;&#039;&#039; im consumerXX-Attribut geprüft, sowie die Datenlieferung des Consumerdevices selbst geprüft werden.  &lt;br /&gt;
&lt;br /&gt;
Es wurde offensichtlich ein hoher Verbrauch von einem nicht registrierten Verbraucher verursacht oder durch die Übertragung eines Meßfehlers des Devices, angegeben im Attribut &#039;&#039;&#039;setupMeterDev&#039;&#039;&#039;, in das SolarForecast Device übertragen. Eine weitere Analyse ist an dieser Stelle nicht möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Behebung des falschen Wertes kann ein Reset der gespeicherten Consumption der relevanten Stunde durchgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; reset consumptionHistory 07 21&lt;br /&gt;
&lt;br /&gt;
== Modulinterne Datenstrukturen ==&lt;br /&gt;
Das Modul speichert die verschiedenen historischen und aktuellen Daten wie PV-Prognose, Witterungsdaten (Regen, Bewölkung), Strahlungsdaten, Einspeisung, Bezug, reale Erzeugungsdaten und vieles mehr zur Laufzeit im Arbeitsspeicher. Dadurch ist die Verarbeitung dieser Daten im Vergleich zu Lesevorgängen aus dem Filesystem bzw. einer Datenbank sehr performant. Allerdings würden diese Daten bei einem FHEM Absturz bzw. bei einem regulären Shutdown verlorengehen.&lt;br /&gt;
&lt;br /&gt;
Deswegen werden die relevanten Daten regelmäßig in Dateien gesichert und bei Bedarf wiederhergestellt. Diese Dateien befinden sich im Verzeichnis &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; und heißen &#039;&#039;&#039;.*_SolarForecast_.*&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Die Daten werden in jedem Zyklus der Zentralschleife (CentralTask) gesammelt bzw. berechnet. Der Zyklus wird mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;cycleInterval&#039;&#039;&#039; eingestellt.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit können diese Daten über get-Kommandos abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvHistory [Tag]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der pvHistory Datenspeicher enthält die vergangenen Kennwerte der letzten 31 Tage mit einer Genauigkeit von einer Stunde. Es werden die Prognosewerte für Erzeugung und Verbrauch, die realen Werte für Erzeugung und Verbrauch sowie ebenso die Laufzeiten jedes einzelnen Verbrauchers (Consumer) festgehalten. Für jeden Tag gibt es die Stunde &amp;quot;99&amp;quot; die eine Summierung der Stundenwerte des Tages bzw. Sonderschlüssel enthält.&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf lässt sich mit dem Befehl &amp;quot;set ... reset pvHistory&amp;quot; der gesamte Inhalt des Speichers löschen (nicht empfohlen). Selektiver funktioniert die Datenlöschung mit &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt;&amp;quot; (Daten eines bestimmten Tages löschen) bzw. &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt; &amp;lt;Stunde&amp;gt;&amp;quot; (Daten der Stunde  eines bestimmten Tages löschen). Die letzten beiden Kommandos müssen über die Kommandozeile im Browser ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvCircular &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Ringspeicher enthält Daten der letzten 24 Stunden sowie fortwährend berechnete Werte wie Korrekturfaktoren der PV-Erzeugung und Prognosequalität.&lt;br /&gt;
Neue Stundenwerte des Tages überschreiben die gespeicherten Schüssel des vorangegangenen Tages sofern es sich nicht um fortwährend berechnete Werte handelt. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... nextHours&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Speicher enthält sämtliche Prognosewerte der kommenden Stunden beginnend mit der aktuellen Stunde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... radiationApiData&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Abhängig von der ausgewählten Strahlungsdaten API enthält dieser Speicher die von der API gelieferten Rohdaten sowie evtl. weitere für die Funktion benötigte Daten wie API-Keys, Response Messages, Anzahl der API Abruf und weitere.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valCurrent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Struktur wird nicht regelmäßig im Filesystem gespeichert und enthält immer aktuell gesammelte oder berechnete/gelieferte Daten wie z.B. die Autarkierate, letze Laufzeit der Zentralschleife (CentralTask), Zeit des Sonnenauf- und untergangs sowie weitere Betriebsdaten. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valConsumerMaster [XX]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zeigt die Daten der aktuell im SolarForecast Device registrierten Verbraucher. Mit der Nummer &#039;&#039;&#039;XX&#039;&#039;&#039; kann ein bestimmter Verbraucher angesprungen werden. Die Nummer korrespondiert mit dem entsprechenden &#039;&#039;&#039;consumerXX&#039;&#039;&#039; Attribut.&lt;br /&gt;
Neben anderen Betriebs- und Energiedaten werden insbesondere folgende Daten ermittelt, die für die zukünftige Planung der Verbraucherschaltzeiten relevant sind:&lt;br /&gt;
&lt;br /&gt;
* epieces - prognostizierte Energiescheiben pro Betriebsstunde &lt;br /&gt;
&lt;br /&gt;
Ausgehend von gespeicherten historischen Verbrauchsdaten des Verbrauchers wird der Energieverbrauch des Verbrauchers in seiner ersten Betriebsstunde prognostiziert, was insbesondere für die Planung der optimalen Startzeit des Verbrauchers in Bezug zu der prognostizierten PV Energie und den Verbrauchswerten weiterer vorhandener bzw. zu planender Verbraucher Berücksichtigung findet. Weitere Informationen zur Verbrauchersteuerung in diesem  [[#Verbrauchersteuerung_-_Registrieren_und_visualisieren_von_Verbrauchern|Abschnitt]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Schnittstelle für Modulautoren bzw. eigenen Code ===&lt;br /&gt;
&lt;br /&gt;
Die im vorherigen Artikel beschriebenen internen Datenstrukturen können durch externen Code abgefragt und ausgewertet werden.&lt;br /&gt;
Dazu stehen die folgenden Funktionen zur Verfügung. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]BatteryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Bn&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valBattery&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CurrentVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valCurrent&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]InverterVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valInverter&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ProducerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valProducer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]HistoryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Day&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvHistory&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CircularVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvCircular&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]NexthoursVal (&#039;&amp;lt;Name&amp;gt;&#039;, &amp;lt;nhr&amp;gt;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... nextHours&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ConsumerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valConsumerMaster&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]RadiationAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;DateTime&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... radiationApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]WeatherAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;TimeCode&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... weatherApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StatusAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;QTag&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... statusApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StringVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valStrings&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Angabe des Packages (FHEM::SolarForecast::) ist nur notwendig wenn die Funktionen von außerhalb des SolarForecast-Devices aufgerufen werden. Innerhalb des Devices (Code-Ausführung im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039;) kann darauf verzichtet werden.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der Platzhalter sind:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     &amp;lt;Name&amp;gt;     - Name des SolarForecast Devices&lt;br /&gt;
     &amp;lt;Day&amp;gt;      - abzufragender Tag (01 - 31)&lt;br /&gt;
     &amp;lt;Bn&amp;gt;       - Batterie Nummer (01, 02, ...)&lt;br /&gt;
     &amp;lt;DateTime&amp;gt; - Startzeit der Form YYYY-MM-DD hh:00:00&lt;br /&gt;
     &amp;lt;TimeCode&amp;gt; - Zeitwert der Form fcX_XX (z.B. fc1_19)&lt;br /&gt;
     &amp;lt;APIname&amp;gt;  - Hauptname der API gemäß setupWeatherDev1 (z.B. OpenMeteo)&lt;br /&gt;
     &amp;lt;String&amp;gt;   - Name des PV-Modulstrings wie im Attribut &#039;setupInverterStrings&#039;&lt;br /&gt;
     &amp;lt;QTag&amp;gt;     - Question Tag, z.B. &#039;?All&#039;&lt;br /&gt;
     &amp;lt;Nr&amp;gt;       - laufende Nummer des Verbrauchers / Gerätes (01, 02, 03, 04,...)&lt;br /&gt;
     &amp;lt;HoD&amp;gt;      - abzufragende Stunde (01 - 24, 99)&lt;br /&gt;
     &amp;lt;nhr&amp;gt;      - nächste Stunde (NextHour00, NextHour01,...)&lt;br /&gt;
     &amp;lt;Key&amp;gt;      - der abzufragende Schlüssel &lt;br /&gt;
     &amp;lt;default&amp;gt;  - def default-Rückgabewert&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Beispiel Auslesen der Batterieladestrategie und Anlegen eines Readings ====&lt;br /&gt;
&lt;br /&gt;
Als Praxisbeispiel soll die aktuelle gesetzte Ladestrategie für Batterie &amp;quot;01&amp;quot; ausgelesen und mit dem Wert ein Reading im SolarForecast Device angelegt werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Dazu wird der folgende Code im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; hinterlegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  my $wert = NexthoursVal ($name, &#039;NextHour00&#039;, &#039;strategybat01&#039;, &#039;loadRelease&#039;);&lt;br /&gt;
  storeReading (&#039;Ladestrategie&#039;, $wert);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei jedem Zyklus des SF-Devices wird der aktuelle Wert von &#039;&#039;strategybat01&#039;&#039; gelesen und im Reading &#039;&#039;Ladestrategie&#039;&#039; gespeichert. Die Paket-Definition &#039;&#039;FHEM::SolarForecast::&#039;&#039; braucht nicht verwendet werden, da der Aufruf im Attribut ctrlUserExitFn innerhalb des SolarForecast-Paketes erfolgt.&lt;br /&gt;
&lt;br /&gt;
Für andere Batterienummern ist der NexthoursVal-Schlüssel &#039;&#039;strategybat01&#039;&#039; entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Auswerten von internen Arrays ===&lt;br /&gt;
&lt;br /&gt;
Die meisten der internen Datenstrukturen liefern bei der Abfrage einen einfachen String oder numerischen Wert der ausgewertet werden kann. Es gibt allerdings auch intern gespeicherte Wertelisten. Werden die Listenstrukturen mit den oben beschriebenen Befehlen abgefragt, wird eine Referenz auf die Liste geliefert sofern sie vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
Um auf die Werte einer solchen Liste zuzugreifen, ist am Beispiel des Arrays &#039;&#039;surplusslidereg&#039;&#039; aus dem Current-Speicher (get ... valCurrent) dargestellt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
my $splref = CurrentVal ($name, &#039;surplusslidereg&#039;, &#039;.&#039;);&lt;br /&gt;
my $spser  = ref $splref eq &#039;ARRAY&#039; ? join &#039; &#039;, @{$splref} : undef;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Variable $spser enthält bei Vorhandensein der Liste einen String, der die Listenelemente von &#039;surplusslidereg&#039; durch Leerzeichen getrennt enthält.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backup und Wiederherstellung der Moduldaten ==&lt;br /&gt;
Neben der Datenhaltung in den Attributen und Readings des SolarForecast Devices, erzeugt jedes SolarForecast Device Dateien im Verzeichnis  &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; mit folgenden Inhalten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PVH_SolarForecast_&amp;lt;name&amp;gt;        - PV History&lt;br /&gt;
PVC_SolarForecast_&amp;lt;name&amp;gt;        - PV Circular&lt;br /&gt;
PVCfg_SolarForecast_&amp;lt;name&amp;gt;      - PV Anlagenkonfiguration&lt;br /&gt;
PVCsm_SolarForecast_&amp;lt;name&amp;gt;      - Consumer Status&lt;br /&gt;
ScApi_SolarForecast_&amp;lt;name&amp;gt;      - Strahlungswerte aus verwendeter API&lt;br /&gt;
StatApi_SolarForecast_&amp;lt;name&amp;gt;    - Statusdaten der verwendeten API&#039;s&lt;br /&gt;
WeatherApi_SolarForecast_&amp;lt;name&amp;gt; - Wetterdaten der gewählten Wetter-API (außer DWD-Device)&lt;br /&gt;
AItra_SolarForecast_&amp;lt;name&amp;gt;      - KI Entscheidungsquelle (trainierte Daten)&lt;br /&gt;
AIraw_SolarForecast_&amp;lt;name&amp;gt;      - KI Input Daten = Raw Trainigsdaten&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nach Ausprägung und eingesetzten Features des SolarForecast Devices sind alle oder nur ein Teil dieser Dateien vorhanden. Dabei ist &#039;&#039;&#039;&amp;lt;name&amp;gt;&#039;&#039;&#039; der Name des SolarForecast Devices.&lt;br /&gt;
&lt;br /&gt;
Bei einem Filebackup des FHEM-Servers ist darauf zu achten, dass diese Dateien in dem Backup enthalten sind. Der Inhalt der Dateien ist nicht statisch, sondern kann sich dynamisch aktualisieren. Um im Bedarfsfall einen aktuellen Datenstand zu haben, ist mindestens ein tägliches Backup dieser Dateien empfehlenswert. Eventuell auch öfter mit Hilfe einer Versionierung welche z.B. immer die letzten 3 Versionen aufbewahrt.&lt;br /&gt;
&lt;br /&gt;
Beim Start von FHEM werden bestimmte Dateien automatisch gelesen und in das SolarForecast Device importiert. &lt;br /&gt;
Der Vorgang ist mit verbose=3 im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2023.10.02 09:57:07.967 3: SolCast6 - cached data &amp;quot;pvHistory&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.969 3: SolCast6 - cached data &amp;quot;pvCircular&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;consumerMaster&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;radiationApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;statusApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;weatherApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.974 3: SolCast6 - cached data &amp;quot;aiTrainedData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.976 3: SolCast6 - cached data &amp;quot;aiRawData&amp;quot; restored&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bestimmte Betriebsdaten, wie z.B. die witterungsabhängigen Korrekturfaktoren (circular) oder die KI-Daten (aitrained/airaw), bauen sich über die Zeit immer granularer auf und stellen einen wertvollen Datenbestand dar.&lt;br /&gt;
&lt;br /&gt;
Wird das SolarForecast Device gelöscht und anschließend wieder neu mit dem gleichen Namen definiert, können die bisher verfügbaren Daten sehr einfach wiederhergestellt werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices, d.h. ein einfaches &amp;quot;define &amp;lt;Name&amp;gt; SolarForecast&amp;quot;, und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. Anpassen der Dateieigentümer und Berechtigungen: chown fhem:dialout /opt/fhem/FHEM/FhemUtils/*,  chmod 774 /opt/fhem/FHEM/FhemUtils/*&lt;br /&gt;
* 5. starten von FHEM (bestimmte Daten werden automatisch importiert)&lt;br /&gt;
* 6. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
* 7. FHEM Konfiguration sichern und restarten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
Das zuvor beschriebene Verfahren kann auch angewendet werden um das SolarForcast Device von einer FHEM Installation in eine andere Installation umzuziehen. In diesem Fall ist aber besonders darauf zu achten, vorab alle in den SF-Attributen referenzierten Devices wie Inverter, Meter oder DWD-Devices mit den zutreffenden Namen in der neuen Installation anzulegen.&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Soll das neue SolarForecast Device mit einem anderen Namen oder weitere SolarForecast Devices erstellt werden, welche die Betriebsdaten des primären Devices verwenden sollen, ist wie folgt vorzugehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices, d.h. ein einfaches &amp;quot;define &amp;lt;Name&amp;gt; SolarForecast&amp;quot;, und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. umbenenen der Dateien, wobei &amp;lt;name&amp;gt; durch den Namen des neuen SolarForecast Devices ersetzt wird&lt;br /&gt;
* 5. Anpassen der Dateieigentümer und Berechtigungen: chown fhem:dialout /opt/fhem/FHEM/FhemUtils/*,  chmod 774 /opt/fhem/FHEM/FhemUtils/*&lt;br /&gt;
* 6. starten von FHEM (bestimmte Daten werden automatisch importiert)&lt;br /&gt;
* 7. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
* 8. FHEM Konfiguration sichern und restarten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn sich die SolarForecast Devices hinsichtlich ihres Models oder der integrierten Consumer unterscheiden, sind die Dateien &amp;quot;PVCsm_SolarForecast_&amp;lt;name&amp;gt; &amp;quot; , &amp;quot;ScApi_SolarForecast_&amp;lt;name&amp;gt;&amp;quot; von dem Verfahren auszuschließen.&lt;br /&gt;
&lt;br /&gt;
== Batterieintegration und -steuerung ==&lt;br /&gt;
&lt;br /&gt;
=== Wie eine Batterie eingebunden wird ===&lt;br /&gt;
Wie immer muß die Batterieanlage zunächst mit einem für die Batterie spezifischen FHEM-Device in FHEM definiert sein.&lt;br /&gt;
In diesem Device werden Readings erwartet die folgende Werte bereitstellen:&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieentladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die installierte Batteriekapazität liefert (&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; dieser Schlüssel ist für die Aktivierung des Batterie SOC-Managements und die grafische Anzeige des SOC wesentlich!)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Lade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Entlade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* Reading welches den aktuellen Ladezustand (SOC in Prozent) liefert (optional)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Batterie, bzw. das Batteriedevice wird mit dem Attribut &#039;&#039;&#039;setupBatteryDev&#039;&#039;&#039; im SolarForecast Device registriert. Die Syntax des Attributes ist in  der Online-Hilfe zum Attribut umfassend erläutert. &lt;br /&gt;
Auch wenn manche Readings optional sind, wird empfohlen alle Werte bereitzustellen um alle Batterie-Funktionen im Modul nutzen zu können. Durch die Weiterentwicklung des Moduls können optionale Readings später auch obligatorisch werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Visualisierung der Batterie in der Balkengrafik ====&lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;setupBatteryDevXX&#039;&#039;&#039; verfügt über den Schlüssel &#039;&#039;&#039;show&#039;&#039;&#039;, mit dem die Einblendung des bzw. der Batteriesymbole in den Ebenen der Balkengrafik gesteuert werden kann:&lt;br /&gt;
[[Datei:Screenshot 2025-02-23 192002.png|right|thumb|400px|Einblendung der Batterieleiste und Darstellung des Batterie-SoC als Balkencontent in der zweiten Ebene]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 0 - keine Anzeige des Gerätes (default)&lt;br /&gt;
* 1 - Anzeige des Gerätes in der Balkengrafik Ebene 1&lt;br /&gt;
* 2 - Anzeige des Gerätes in der Balkengrafik Ebene 2 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Symbole und die Farbgebung der Batterie(n) können mittels des Schlüssels &#039;&#039;&#039;icon&#039;&#039;&#039; verändert werden. Die Online-Hilfe gibt weitere Informationen zur Ausgestaltung. &lt;br /&gt;
&lt;br /&gt;
In der Batteriedarstellung wird das Symbol der aktuellen Stunde hervorgehoben. Ein Mouse-Over zeigt wesentliche Betriebszustände der Batterie. Die Batteriesymbole vergangener Stunden zeigen mit einem Mouse-Over die erreichten SoC (State of Charge) Stände. Die kommenden Stunden visualisieren die folgenden Prognosen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der prognostizierte SoC unter Berücksichtigung der PV-Prognose und der [[#Aktivierung_des_Batterie_SOC-Managements|Batteriesteuerung]] sofern sie im Modul aktiviert ist.&lt;br /&gt;
* eine Freigabe bzw. Empfehlung der Batterieladung zur [[#Unterstützung_eines_netzdienlichen_Verhaltens|Unterstützung eines netzdienlichen Verhaltens]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Neben der Einblendung der Batterieleiste über der Balkengrafik selbst können bestimmte Batteriekennwerte als Balkeninhalt dargestellt werden. Die Auswahl erfolgt über das Attribut &#039;&#039;&#039;graphicBeamXContent&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Aktivierung des Batterie SOC- und Lade-Managements ===&lt;br /&gt;
Das integrierte SOC- und Lade-Management verfolgt insbesondere diese Ziele: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* den Ladezustand der Batterie(n) zu optmimieren, was besonders in den Monaten mit geringerer PV-Erzeugung einen wertvollen Beitrag zur Erhöhung der Autarkierate und Batteriepflege leisten kann&lt;br /&gt;
 &lt;br /&gt;
* eine PV-Prognose und Verbrauch optimierte Beladungssteuerung, die in den Monaten mit hoher PV-Erzeugung hilft eine evtl. Abregelung der Anlage zu verhindern, die Batterie ausgewogen über den Tag zu laden und ein netzdienliches Verhalten zu unterstützen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese Aspekte der Batteriesteuerung werden in den folgenden Abschnitten beschrieben. Sind mehrere Batterien installiert, kann die Steuerung getrennt für jede einzelne Batterie aktiviert und eingestellt werden. Dabei ist zu beachten, dass vom Modul nur Signale und Readings bereitgestellt werden, die durch eine entsprechende Routine ausgewertet werden können um spezifische Befehle zur Umsetzung der Steuerung an das Batteriesystem zu senden. &lt;br /&gt;
 &lt;br /&gt;
Für eine Aktivierung des Managements muß zunächst das Batterie-Device wie im vorigen Abschnitt im SolarForecast Device registriert werden.&lt;br /&gt;
Das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; aktiviert die im Modul integrierte SOC- und Lade-Management Routine: &lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; ctrlBatSocManagementXX lowSoc=&amp;lt;Wert&amp;gt; upSoC=&amp;lt;Wert&amp;gt; [maxSoC=&amp;lt;Wert&amp;gt;] [careCycle=&amp;lt;Wert&amp;gt;] [loadAbort=&amp;lt;SoC1&amp;gt;:&amp;lt;MinPwr&amp;gt;:&amp;lt;SoC2&amp;gt;] [safetyMargin=&amp;lt;Wert&amp;gt;[:&amp;lt;Wert&amp;gt;]] ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die einzelnen Schlüssel werden der Kalkulationsroutine als Steuerungsparameter übergeben und bedeuten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;lowSoc:unterer Mindest-SoC, die Batterie wird nicht tiefer als dieser Wert entladen (muß &amp;gt; 0 sein). Dieser Wert kann zum Beispiel dazu dienen, stets eine Mindestenergiemenge für den Fall eines Stromausfalls im öffentlichen Netz in den Batterien vorzuhalten.&lt;br /&gt;
&lt;br /&gt;
;upSoC:oberer Mindest-SoC, Der übliche Wert des optimalen SoC bewegt sich in Perioden mit hohen PV-Überschuß tendenziell zwischen &#039;lowSoC&#039; und &#039;upSoC&#039;, in Perioden mit geringer PV-Ausbeute bzw. geringem PV Energieüberschuß bewegt sich der optimale SoC tendenziell zwischen &#039;upSoC&#039; und &#039;maxSoC&#039;. Die Einstellung von upSoC=50 für ein ausgewogenes Verhalten kann als guter Startwert dienen.&lt;br /&gt;
&lt;br /&gt;
;maxSoC:maximaler Mindest-SoC, d.h. der SoC Wert der mindestens im Abstand von &#039;careCycle&#039; Tagen erreicht werden muß um den Ladungsausgleich im Speicherverbund auszuführen. Die Angabe ist optional (muß &amp;lt;= 100 sein, default: 95)&lt;br /&gt;
&lt;br /&gt;
;stepSoC: Optionale Schrittweite zur optimalen SoC-Berechnung (Battery_OptimumTargetSoC_XX) in %. Mit der Angabe &#039;stepSoC=0&#039; wird das SoC-Management deaktiviert und Battery_OptimumTargetSoC_XX auf den Wert &#039;lowSoC&#039; gesetzt. &#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Beziehung &#039;careCycle * stepSoC = 100&#039; sollte eingehalten werden! Wert: 0..5, default: 5 &lt;br /&gt;
&lt;br /&gt;
;careCycle:maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens &#039;maxSoC&#039; auftreten darf. Die Angabe ist optional. (default: 20)&lt;br /&gt;
&lt;br /&gt;
;lcSlot: Es wird ein tägliches Zeitfenster festgelegt, in dem die Ladesteuerung des Moduls für diese Batterie aktiv sein soll. Außerhalb des Zeitfensters wird die Batterieladung mit voller Leistung freigegeben. Das SoC-Management der Batterie ist davon nicht betroffen. Wert: &amp;lt;hh:mm&amp;gt;-&amp;lt;hh:mm&amp;gt;, default: ganztägig&lt;br /&gt;
&lt;br /&gt;
;loadAbort: definiert eine vom Anwender gewünnschte Bedingung für einen generellen Ladeabbruch und Wiederfreigabe der Lademöglichkeit. Die Abbruchbedingung ist erfüllt, wenn der angegebene SoC1 (%) erreicht bzw. überschritten ist &#039;&#039;&#039;UND&#039;&#039;&#039; die angegebene Ladeleistung &amp;lt;MinPwr&amp;gt; (W) unterschritten wurde -&amp;gt; Reading Battery_ChargeAbort_XX=1. Fällt der aktuelle SoC wieder unter den SoC2, wird Battery_ChargeAbort_XX=0 gesetzt. Ist SoC2 nicht angegeben, gilt SoC2=SoC1.  &lt;br /&gt;
&lt;br /&gt;
;loadStrategy: Abhängig von der gewählten Ladestrategie wird die Prognose der Batterieladung und ggf. die Generierung der Steuerreadings beeinflusst. Die Angabe ist optional. Wert: loadRelease | optPower | smartPower, default: loadRelease&lt;br /&gt;
	&lt;br /&gt;
;loadTarget: Optionaler Ziel-SoC in % für die Berechnung der Ladefreigabe bzw. der optimalen Ladeleistung. Der Zielwert ist eine kalkulatorische Rechengröße. Der reale SoC kann situativ in Grenzen über- oder unterschritten werden. Der höhere Wert aus Reading Battery_OptimumTargetSoC_XX und &#039;loadTarget&#039; hat für die Berechnung Vorrang. Wert: 0..100, default: 100 &lt;br /&gt;
&lt;br /&gt;
;safetyMargin: Bei der Berechnung der Ladefreigabe und optimierten Ladeleistung werden Sicherheitszuschläge auf den prognostizierten Ladungsbedarf berücksichtigt. Abweichend vom Default können mit diesem Parameter individuelle Sicherheitszuschläge getrennt für die Berechnung der Ladefreigabe und optimierten Ladeleistung angegeben werden. Der erste Wert ist der Zuschlag bei der Berechnung der Ladefreigabe, der zweite Wert der Zuschlag bei der Berechnung der optimierten Ladeleistung. Beide Angaben sind Prozentwerte von 0..100.&lt;br /&gt;
&lt;br /&gt;
;weightOwnUse: Optionale Gewichtung der stündlichen Verbrauchsprognose als zusätzlich verwendbaren Anteil zur Batterieladung in %. Technisch wird der verfügbare PV-Überschuß zur Berechnung der optimierten Ladeleistung erhöht indem der kalkulierte Verbrauch um den angegebenen Prozentsatz gesenkt wird. Wert: 0..100 default: 0 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle SoC-Werte sind ganze Zahlen in %. Dabei gilt: &lt;br /&gt;
&lt;br /&gt;
 lowSoc &amp;lt; upSoC &amp;lt; maxSoC&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====  Erläuterung der Batterie-Steuerungsreadings ==== &lt;br /&gt;
&lt;br /&gt;
Für die Steuerung des Batteriesystems gibt es im SolarForecast einen Satz an Readings, die unterschiedliche Zustände signalisieren und für entsprechende Steuerungsaufgaben bezüglich der Batteriesysteme eingesetzt werden können. In den nachfolgenden Abschnitten werden diese Zusammenhänge noch dataillierter beschrieben.&lt;br /&gt;
&lt;br /&gt;
;Hinweis: SolarForecast stellt lediglich Steuerungsinformationen zur Verfügung. Die Umsetzung des Eingriffs in das Batteriesystem erfolgt durch den Anwender selbst über entsprechende Skripte. In den thematischen Abschnitten werden Beispiele für solche Steuerungsskripte vorgestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle erstellten Readings gelten für ein Batteriesystem, es können mehrere Batteriesysteme in SolarForecast integriert sein. Die Endung &#039;&#039;XX&#039;&#039; der Readings beschreibt die Nummer des Batteriesystems und korrespondiert mit der Endung des entsprechenden Attributes &#039;&#039;ctrlBatSocManagementXX&#039;&#039; bzw. &#039;&#039;setupBatteryDevXX&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Battery_OptimumTargetSoC_XX: Mit den im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; hinterlegten Parametern unter Berücksichtigung von PV- und Verbrauchsprognosen wird ein optimaler SOC-Wert errechnet. Dieser Wert dient zur Einstellung des unteren SOC des Batteriesystems.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeRequest_XX: Dieses Reading signalisiert mit 1 eine Anforderung zur Zwangsladung der Batterie um die Batterie vor Schäden zu schützen (wenn der SOC unter ctrlBatSocManagementXX-&amp;gt;lowSoc gefallen ist) oder wenn der aktuelle SOC unter den berechneten Mindest-SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeUnrestricted_XX: Dieses Reading kann den Wert &#039;&#039;&#039;0&#039;&#039;&#039; oder &#039;&#039;&#039;1&#039;&#039;&#039; einnehmen. Ist der Wert 0, sollte die Batterie nur geladen werden, wenn der im Attribut &#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039; definierte Wert überschritten wird. Ist der Wert 1, sollte die Batterie mit der vollen zur Verfügung stehenden Ladeleistung angesteuert werden, um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten. Der Fokus der Steuerung mit diesem Reading ist es, die Speicherkapazität der Batterie optimal zur Verhinderung der Überschreitung von Einspeiselimits einzusetzen und dennoch einen maximal möglichen SoC am Tagesende zu erreichen. (siehe das beschriebene [[SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#PV-Prognose_und_Verbrauch_optimierte_Beladungssteuerung_unter_Berücksichtigung_einer_Wirkleistungsbegrenzung|Nutzungsbeispiel]])&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeOptTargetPower_XX: Dieses Reading enthält einen Richtwert für die optimierte Ladeleistung für jede Batterie. Die Aufladung wird prognosegeführt über den gesamten Tag verteilt, wobei der Fokus auf eine kontinuierliche, aber möglichst niederige Ladeleistung gelegt wird. (siehe diesen [[SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#leistungsoptimierte_Beladungssteuerung_mit_dem_Fokus_geringe_Verlustleistung_und_Verschleiß|Abschnitt]])  &lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeAbort_XX: Im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; kann mit dem Schlüssel &#039;&#039;loadAbort&#039;&#039; eine Bedingung definiert werden, bei deren Eintritt die Ladung der Batterie abgebrochen werden soll. In diesem Fall wird &#039;&#039;Battery_ChargeAbort_XX=1&#039;&#039; gesetzt. Mit einem entsprechenden Befehl kann der Anwender das Batteriesystem anweisen den Ladevorgang abzubrechen. &lt;br /&gt;
&lt;br /&gt;
;Battery_TargetAchievable_XX: Diese Reading enthält einen Boolean Wert 0|1 und signalisiert ob der im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX-&amp;gt;loadTarget&#039;&#039;&#039; gesetzte Ziel-SoC lt. Prognose am aktuellen Tag tatsächlich erreicht werden kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Nutzung des Batterie SOC-Management ====&lt;br /&gt;
&lt;br /&gt;
Oftmals wird durch die Anlagenhersteller ein hoher statischer SOC eingestellt bzw. empfohlen, der eine längere Verharrungszeit auf einem tiefen SOC-Wert verhindern soll. Allerdings wechseln sich in auch in den Herbst-, Frühlings- und Wintermonaten Zeiten mit wenig PV-Erzeugung mit Phasen stärkerer Solarstrahlung bei klarem Himmel und Sonnenschein ab.&lt;br /&gt;
&lt;br /&gt;
Ein statischer SOC würde dazu führen, dass in den erwähnten Phasen zuviel Energie in das öffentliche Netz eingespeist wird. Dies soll verhindert werden da die wertvolle Energie besser im eigenen Netz gespeichert und in Dunkelphasen verwendet werden kann. Andererseits soll die Batterie nicht zu lange auf einem tiefen SOC verbleiben und außerdem in gewissen Abständen auf einen so hohen SOC geladen werden der den internen Zellausgleich ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Die SOC Kalkulationsroutine des Moduls errechnet unter Berücksichtigung des prognostizierten PV-Ertrages der kommenden Tage, des aktuellen SOC und der im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; (nachfolgend beschrieben) angegebenen Steuerparameter den Vorschlag für eine optimale SOC-Einstellung. Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert.&lt;br /&gt;
&lt;br /&gt;
Durch das Modul selbst findet keine Steuerung der Batterie statt. Es stellt entsprechende Readings zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen SoC.&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SoC unter den optimalen SoC gefallen ist. In diesem Fall sollte die Batterie, unter Umständen mit Netzstrom, zwangsgeladen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Readings können zur Steuerung des SoC (State of Charge) sowie zur Steuerung des verwendeten Ladestroms der Batterie verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ermittlung des optimalen SOC erfolgt nach folgender Logik:&lt;br /&gt;
&lt;br /&gt;
# 	Ausgehend von &#039;lowSoc&#039; wird der Mindest-SoC kurz vor Sonnenuntergang um 5% inkrementiert sofern am laufenden Tag &#039;maxSoC&#039; nicht erreicht wurde und die PV-Prognose keinen hinreichenden Ertrag des kommenden Tages vorhersagt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Wird &#039;maxSoC&#039; (wieder) erreicht, wird Mindest-SoC um 5%, aber nicht tiefer als &#039;lowSoc&#039;, verringert. Ist der berechnete Mindest-SoC größer als &#039;upSoc&#039;, wird der Mindest-SoC auf &#039;upSoc&#039; gesetzt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#   Mindest-SoC wird soweit verringert, dass die prognostizierte PV Energie des aktuellen bzw. des folgenden Tages von der Batterie aufgenommen werden kann. Mindest-SoC wird typisch auf &#039;upSoc&#039; und nicht tiefer als &#039;lowSoc&#039; verringert.  &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Das Modul erfasst den letzten Zeitpunkt am &#039;maxSoC&#039;-Level, um eine Ladung auf &#039;maxSoC&#039; mindestens alle &#039;careCycle&#039; Tage zu realisieren. Zu diesem Zweck wird der optimierte SoC in Abhängigkeit der Resttage bis zum nächsten &#039;careCycle&#039; Zeitpunkt derart verändert, dass durch eine tägliche 5% SoC-Steigerung &#039;maxSoC&#039; am &#039;careCycle&#039; Zeitpunkt rechnerisch erreicht wird. Wird zwischenzeitlich &#039;maxSoC&#039; erreicht, beginnt der &#039;careCycle&#039; Zeitraum erneut. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im fünften Schritt werden die Grenzen &#039;lowSoc&#039; und &#039;upSoc&#039; berücksichtigt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im letzten Schritt erfolgt Generierung des Readings &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; zur Signalisierung einer eventuell empfohlenen Zwangsladung auf den berechneten Min-SoC. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei sehr wenig Erzeugungungsprognose, d.h. wenn sich der berechnete Min-SoC oberhalb von &#039;upSoC&#039; bewegt, wird &#039;upSoC&#039; eingestellt. Liegt der berechnete Min-SoC unterhalb von &#039;upSoC&#039;, ist jedoch größer als &#039;lowSoC&#039;, wird der berechnete SOC im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; eingestellt. Somit eignet sich die Angabe im Schlüssel &#039;upSoC&#039; um in Zeiten geringer Solarenergieerzeugung die Batterie für eine Notstromerzeugung auf mindestens diesem Wert zu halten. Sollte die PV-Prognose kurzfristig einen größeren Ertrag vorhersagen als die Batterie durch die Einhaltung von &#039;upSoC&#039; aufnehmen kann, wird der Min-SoC unter &#039;upSoC&#039; abgesenkt um möglichst allen PV-Überschuß in der Batterie zu speichern und somit dem Eigenverbrauch zuzuführen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der berechnete Mindest-SoC ist immer nur ein unterer Grenzwert. Die Batterie kann durch Ladevorgänge natürlich jederzeit einen höheren als den im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; dargestellten optimalen SoC haben. Der optimale SoC sollte nicht unterschritten werden um die oben genannten Zusammenhänge abbilden zu können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Die dynamische SOC Steuerung mit Umsetzungsbeispiel =====&lt;br /&gt;
Das Modul bietet eine Unterstützung zur automatisierten Einstellung eines optimalen SoC Wertes.&lt;br /&gt;
&lt;br /&gt;
Ziel ist es, den Minimum SoC in Abhängigkeit der zu erwartenden Solarerträge des aktuellen und des folgenden Tages so einzustellen, dass der prognostizierte Solarertrag von der Batterie aufgenommen werden kann. Die Einspeisung in das öffentliche Netz soll minimiert werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin soll ein unterer SoC nicht unterschritten, sowie ein oberer Minimum SoC im Normalfall nicht überschritten werden. Der obere Grenzwert stellt sicher, dass die Batterie mindestens bis zu diesem Wert wieder entladen werden kann. Dadurch bleibt innerhalb der Batterie immer genügend Kapazität verfügbar um unvorhergesehene PV Energie aufnehmen zu können.&lt;br /&gt;
&lt;br /&gt;
Aktiviert wird die Unterstützung der Batteriesteuerung durch das Setzen des Attributes &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; z.B. mit diesen Angaben:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagementXX lowSoc=x upSoC=x maxSoC=x careCycle=x &lt;br /&gt;
&lt;br /&gt;
so zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=98 careCycle=20&lt;br /&gt;
&lt;br /&gt;
Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert. &lt;br /&gt;
Ist dieses Attribut gesetzt, werden Steuerungs-Readings erstellt, die der Nutzer auswerten und seine Batterieanlage z.B. via notify oder DOIF steuern kann. &amp;lt;bR&amp;gt;&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen Mindest-SoC.&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SOC unter den optimalen SOC bzw. minimalen SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
Die Schlüssel &#039;&#039;&#039;lowSoc&#039;&#039;&#039; und &#039;&#039;&#039;upSoC&#039;&#039;&#039; sind die unteren und oberen Grenzen, zwischen denen sich der Minimum SoC im normalen Betrieb bewegen soll.&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;maxSoC&#039;&#039;&#039; stellt eine Ladungsgrenze dar, die mindestens alle X (careCycle) Tage erreicht werden soll. Zu diesem Zweck errechnet das Modul die Anzahl der nötigen Erhöhungen der Minimum Batterieladung von 5% pro Tag um ausgehend vom aktuellen SoC-Level. Der resultierende Minimum SoC Wert wird entsprechend angepasst. Wurde der einstellte maxSoC Level erreicht, startet der Wartungszyklus (careCycle) erneut. &amp;lt;br&amp;gt;&lt;br /&gt;
Der maxSoC in Verbindung mit dem durch &#039;&#039;&#039;careCycle&#039;&#039;&#039; definierten Zyklus soll sicherstellen, dass der Batterieverbund in regelmäßigen Abständen einen Ladungsausgleich vollziehen kann. &lt;br /&gt;
&lt;br /&gt;
Durch die Modullogik erfolgt eine 5 protentige Anhebung des Minimum SoC wenn am Vortag maxSoC nicht erreicht wurde. Die Anhebung erfolgt aber nicht über upSoC. upSoC ist die obere Grenze des Minimum SoC. Wird am Vortag mindestens die maxSoC Ladung erreicht, verringert sich der Minimum SoC wieder schrittweise um 5%, aber nicht tiefer als lowSoc.&lt;br /&gt;
&lt;br /&gt;
Ergänzt wird die Logik noch um die PV Vorhersage. Dabei wird die obige Minimum SoC Berechnung um die Erwartung der PV Erwartung am aktuellen und folgenden Tag korrigiert. Das bedeutet, dass der Minimum SoC z.B. von heute 50% auf 10% abgesenkt und dadurch die gespeicherte Energie dem Haushalt zugeführt wird, wenn am heutigen oder kommenden Tag eine entsprechende PV Energie zu erwarten ist um die Batterie wieder vollständig zu zuladen.&lt;br /&gt;
Dadurch ist immer genügend &amp;quot;Freiplatz&amp;quot; in der Batterie und andererseits hat die Batterie in langen Dunkelphasen eine Reserve für einen eventuellen Stromausfall (falls der abgesichert werden soll) und wird vor einem dauerhaften tiefen SoC geschützt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Umsetzungsbeispiel =====&lt;br /&gt;
&lt;br /&gt;
Wie das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; genutzt werden kann, wird am Beispiel einer Victron Batterieanlage gezeigt. Die Anlage wird durch Cerbo GX Gerät gesteuert. Der Cerbo GX ist per MQTT2 in FHEM eingebunden. Umgesetzt ist die Steuerung der Batterie &#039;01&#039;, d.h. die Angabe &#039;XX&#039; ist durch &#039;01&#039; ersetzt.&lt;br /&gt;
&lt;br /&gt;
Die folgende kleine Logik ist in einem &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; File eingebaut und wird regelmäßig mit&lt;br /&gt;
&lt;br /&gt;
 batSocChargeMgmnt (&#039;&amp;lt;Name SolarForecast Device&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
aufgerufen. Der Aufruf erfolgt durch Angabe der Routine im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; des SolarForecast Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
  # Hinweis: die Zeichen &#039;::&#039; vor der Routine sind durch das SolarForecast Package bedingt&lt;br /&gt;
  ::batSocChargeMgmnt ($name);&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Routine wird dadurch automatisch am Ende jedes Zyklus (siehe Attribut plantControl-&amp;gt;cycleInterval) ausgeführt.&lt;br /&gt;
Um die SOC Managementfunktion nach Bedarf ein- bzw. ausschalten zu können wird zunächst im SolarForecast Device ein userattr zur Steuerung der SOC-Logik angelegt:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; userattr userFn_BatterySoCManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
Die Perl Routine &#039;&#039;&#039;batSocChargeMgmnt&#039;&#039;&#039; ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#      Batterie SOC und Max. Ladestrom Management&lt;br /&gt;
############################################################################&lt;br /&gt;
sub batSocChargeMgmnt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $bn   = &#039;01&#039;;                                                                      # Batterienummer (evtl. im Aufruf mitgeben)&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vebus   = &#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;;                                     # Victron Vebus Device&lt;br /&gt;
  my $vicsets = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                                  # Victron Einstellungen&lt;br /&gt;
&lt;br /&gt;
  my $maxcspc = 105;                                                                    # max. Ladestrom (A) für Victron MPII Verbund&lt;br /&gt;
  my $preduce = FHEM::SolarForecast::BatteryVal ($name, $bn, &#039;bpinreduced&#039;, $maxcspc);  # reduzierte Ladeleistung aus Bat-Konfig (W)&lt;br /&gt;
  my $actmcc  = ReadingsNum ($vicsets, &#039;MaxChargeCurrent&#039;, undef);                      # akt. Ladestromeinstellung&lt;br /&gt;
  my $load    = $actmcc // $maxcspc;                                                    # Soll-Ladestrom (A)  &lt;br /&gt;
&lt;br /&gt;
  ## Battery SoC Management&lt;br /&gt;
  ###########################&lt;br /&gt;
  my $ubsm = AttrVal ($name, &#039;userFn_BatterySoCManagement&#039;, &#039;aus&#039;); &lt;br /&gt;
  &lt;br /&gt;
  if ($ubsm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name,    &#039;Battery_ChargeRequest_&#039;.$bn,     0);&lt;br /&gt;
    my $csoc = ReadingsNum ($vicsets, &#039;MinimumSocLimit&#039;,               10);             # akt. SoC&lt;br /&gt;
    my $osoc = ReadingsNum ($name,    &#039;Battery_OptimumTargetSoC_&#039;.$bn, 10);             # Soll-SoC&lt;br /&gt;
	my $surp = ReadingsNum ($name,    &#039;Current_Surplus&#039;,                0);             # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if ($csoc != $osoc) {&lt;br /&gt;
      CommandSet (undef, &amp;quot;$vicsets MinimumSocLimit $osoc&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn SoCMgmnt -&amp;gt; MinimumSocLimit in $vicsets set to $osoc %});&lt;br /&gt;
    }&lt;br /&gt;
	                                           &lt;br /&gt;
    if ($bcrq &amp;amp;&amp;amp; $surp &amp;lt; 1000) {                                                       # max. Ladestrom (A) b. Battery_ChargeRequest&lt;br /&gt;
      $load = $preduce / 48;                                                           # bei 48V Batteriesystem&lt;br /&gt;
    }&lt;br /&gt;
	else {&lt;br /&gt;
	  $load = $maxcspc;&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Einstellung MPII Verbund MaxChargeCurrent&lt;br /&gt;
  ##############################################&lt;br /&gt;
  if ($actmcc &amp;amp;&amp;amp; $load != $actmcc) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$vicsets MaxChargeCurrent $load&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
    Log3 ($name, 3, qq{$name - userFn ChargeMgmnt -&amp;gt; MaxChargeCurrent in $vicsets set }.&lt;br /&gt;
                    qq{from old $actmcc A to $load A});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_MPII_MaxChargeCurrent_set&#039;, $load, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist im SolarForecast Device das Reading  &#039;&#039;&#039;Battery_ChargeRequest_01&#039;&#039;&#039; gesetzt, ist der aktuelle SOC kleiner als der optimale SOC und die Batterie wird (eventuell aus dem öffentlichen Netz) geladen. Das kann automatisch durch den Cerbo GX bzw. in anderen Anlagen durch einen entsprechenden Befehl erfolgen.&lt;br /&gt;
Damit die Netzbeladung nicht mit der vollen Ladestromstärke geschieht, wird der Ladestrom auf den gewünschten Wert (hier 21 A -&amp;gt; ca. 1000 W bei einem 48V System) reduziert sofern kein oder zu wenig PV-Überschuß vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== weitere mögliche Aspekte der SOC- und Batterieladesteuerung ====&lt;br /&gt;
&lt;br /&gt;
SolarForecast liefert durch seine internen Logiken bereits sehr hilfreiche Signale zur Steuerung von Batteriesystemen in Form von Readings an. Abhängig von den individuellen Möglichkeiten der vorhandenen Anlage käme zum Beispiel zusätzlich zu einer Steurung des optimalen SOC oder der Zeitfenster für die Batterieaufladung auch eine Steuerung des Ladestroms bzw. der verwendeten Ladeleistung in Betracht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hintergründe:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Das Laden eines Akkus mit möglichst gleichbleibender und geringer Leistung wirkt sich positiv auf dessen Langlebigkeit aus, was u.a. auch daran liegt, dass der Temperaturstreß im Akku bei langsamer Energiezuführung nur gering ist.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom führt zu einem geringen Absacken der Akkuspannung beim (ggf, temporären) Abschalten des Ladestroms, was sich positiv auf die SOC-Schätzung auswirkt.&lt;br /&gt;
    &lt;br /&gt;
* Ein geringer Ladestrom führt, insb. bei Nutzung passiver Balancer (sind in den Akku-Systemen üblicherweise verbaut), zu einer geringen Differenz zwischen den einzelnen Zellspannungen und damit zu einer besseren Kapazitätsausnutzung eins Akkus.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom kann zu einem zeitlich punktgenauen Zielfüllstand (im Winter 100%, ansonsten natürlich weniger) am Ende des Tages führen.&lt;br /&gt;
    &lt;br /&gt;
* Eine geringer Ladestrom führt auch zu geringen Leitungsverlusten, da der Strom quadratisch zu den Leitungsverlusten beiträgt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann auch die Verweildauer oder die Begrenzung des SOC, auf den die Batterie maximal geladen werden soll, Gegenstand von Optimierungen sein.&lt;br /&gt;
&lt;br /&gt;
Die häufig zu findende Empfehlung, Akkus nicht zu lange bei einem SOC von 100% verweilen zu lassen, liegt weniger an dem SOC als solchem, sondern daran, dass &#039;&#039;SOC=100%&#039;&#039; üblicherweise dadurch ermittelt wird, dass eine Zelle im Akku einen Spannungsschwellenwert überschreitet, der – würde dieser Schwellenwert zeitlich länger überschritten sein – zu einer Schädigung des Akkus führen könnte. Schädlich sind insbesondere häufige Nachladevorgänge bei Werten um die 100% SOC, da Zellen dann ja häufiger und damit - integral gesehen - auch länger den o.g. Schwellenwert überschreiten.&lt;br /&gt;
&lt;br /&gt;
Einige Akku-Hersteller, z.B. BYD, haben auf o.g, Grund in der (neueren) Firmware Ihrer Systeme einen SOC-Threshold (bei BYD liegt dieser bei 95%) eingebaut. Dieser Wert muss nach einem erreichten SOC von 100% unterschritten  werden, bevor überhaupt eine weitere Ladung erfolgt. Insbesondere in der dunklen Jahreszeit kann es daher sinnvoll sein, den Akku unter Verwendung von PV-Leistung so zu füllen, dass dieser möglichst nur einmal vor Einbruch der Dunkelheit auf &#039;&#039;SOC=100%&#039;&#039; geladen wird. Hierbei sollte darauf geachtet werden, dass der Ladeschlussstrom des jeweiligen Systems nicht unterschritten wird. &lt;br /&gt;
&lt;br /&gt;
SolarForecast unterstützt die oben betrachtete Batteriesteuerung durch die optionale Angabe von &#039;&#039;&#039;loadAbort&#039;&#039;&#039; im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039;. Das in diesem Kontext erstellte Reading &#039;&#039;&#039;Battery_ChargeAbort_XX&#039;&#039;&#039; stellt die auswertbaren Steuerungsinformationen zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== PV-Prognose und Verbrauch optimierte Beladungssteuerung unter Berücksichtigung einer Wirkleistungsbegrenzung ====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-04-25 143910.png|right|thumb|400px|Batterie Popup &amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Die in diesem Abschnitt beschriebene Ladestrategie &#039;&#039;&#039;loadRelease&#039;&#039;&#039; wird im Modul als &#039;&#039;&#039;Ladefreigabe&#039;&#039;&#039; bezeichnet.&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Batterie geladen. sobald PV-Überschuß vorhanden ist ohne eine Prognose zu berücksichtigen. Dadurch sind die Batterien im Sommer unter Umständen schon um 10-12 Uhr voll geladen und die Anlage liefert ihre mehr oder weniger volle Energie (je nach Ausrichtung) in das öffentliche Netz. Dann könnte es zu einer Begrenzung der PV-Leistung durch einen Schwellenwert (z.B. 70%-Regelung) oder eventuell Zwangsabregelung durch den Netzbetreiber kommen.&lt;br /&gt;
&lt;br /&gt;
Hintergrund dieser Erweiterung ist das Bestreben, eine optimale Unterstützung bei der Maximierung des Eigenverbrauchs zu geben und einen Beitrag zur Netzstabilität zu leisten.&lt;br /&gt;
Das Ziel der Beladungssteuerung der Batterie ist es, die Ladung der Batterie über den Tag verteilt so zu steuern, dass die Batterie erst dann geladen wird, wenn durch den PV-Überschuß eine Netzeinspeisung erfolgen würde bzw. ein Grenzwert erreicht werden würde, der zu einer Abregelung der PV-Anlage führen könnte.&lt;br /&gt;
Es kann auch zu einer Zwangsabregelung durch den Netzbetreiber führen, was vermieden werden soll.&lt;br /&gt;
 &lt;br /&gt;
Die interne Kalkulationslogik erstellt zu diesem Zweck ein Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039;.&lt;br /&gt;
Dieses Reading gibt dem User ein Signal, ob zu der aktuellen Stunde der Ladevorgang der Batterie freigegeben (1) oder nicht freigegeben werden sollte (0). Die Freigabe zur Ladung bedeutet dass:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; die Batterie mit ihrer vollen, oder der im Reading [[SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#leistungsoptimierte_Beladungssteuerung_mit_dem_Fokus_geringe_Verlustleistung_und_Verschleiß|Battery_ChargeOptTargetPower_XX]] angegebenen Ladeleistung angesteuert werden sollte um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten..&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=0&#039;&#039;&#039; die Batterie nur geladen werden sollte wenn der im Attribut plantControl-&amp;gt;feedinPowerLimit definierte Wert überschritten wird&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ist keine Freigabe zur Ladung vorhanden, kann bzw. sollte dennoch eine Ladung der Batterie vorgenommen werden, sofern eine über dem im &amp;lt;br&amp;gt;&lt;br /&gt;
Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limit liegende Einspeiseleistung vorhanden ist. In diesem Status sollte die Batterie nur mit der Differenzleistung von vorhandener Einspeiseleistung und dem gesetzen Einspeiselimit geladen werden und damit das gesetzte Einspeiselimit einhalten ohne die Anlage abzuregeln. Ist die Batterie in einer Balkengrafikebene dargestellt, wird im Mouse-Over Popup die Battrie mit &#039;&#039;&amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;&#039;&#039; gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Möglichkeiten der Batteriesteuerung sind stark von der individuellen Anlage abhängig und können hier nicht beschrieben werden. Ein Umsetzungsbeispiel mit einer Victron-Anlage mit Pylontech Batterie ist weiter unten dargestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Aktivierung und Arbeitsweise =====&lt;br /&gt;
&lt;br /&gt;
Die implementierte Logik zur optimierten Batterie Beladungssteuerung wird aktiviert, wenn folgende Kriterien erfüllt sind: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;capacity&#039;&#039;&#039; in den setupInverterDevXX Atributen ist gesetzt&lt;br /&gt;
* das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; für die jeweilige Batterie ist gesetzt&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;cap&#039;&#039;&#039; im Attribut setupBatteryDevXX der jeweiligen Batterie ist gesetzt&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Die Logik arbeitet wie folgt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Der resultierende Schwellenwert der Wirkleistungsbegrenzung: der Gesamtanlage wird durch die Auswertung der in den Inverter-Attributen setupInverterDevXX  gesetzen Schlüssel limit (optional) und capacity ermittelt. Inverter mit gesetztem Schlüssel feed = grid (deren Energie wird ausschließlich in das öffentlich Netz eingespeist) werden von der Betrachtung in diesem Kontext ausgeschlossen.&lt;br /&gt;
&lt;br /&gt;
;Die benötigte Beladung bis zu maxSoC (im Attribut setupBatteryDevXX) : wird ermittelt und mit der zu erwartenden PV Tagesprognose in Beziehung gesetzt. Sofern die PV-Erzeugung abzgl. Verbrauch noch nicht das Wirkleistungbegrenzungs-Limit erreicht UND noch genügend PV-Überschuß für eine Ladung auf &#039;&#039;maxSoC&#039;&#039; im Laufe der kommenden Stunden des Tages zu erwarten ist, bleibt das Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 0&#039;&#039;&#039;. Die erreichte Qualität der Steuerungslogik ist stark von der Prognosequaliät abhängig. Um die Steuerung resilienter zu gestalten, wird per default ein Sicherheitsaufschlag von 50% auf die prognostizierte benötigte Ladeenenergie auf Stundenbasis einkalkuliert. Dieser Wert kann mit dem Attribut &#039;&#039;&#039;ctrlBatSocManagementXX-&amp;gt;safetyMargin&#039;&#039;&#039; individuell angepasst werden.&lt;br /&gt;
&lt;br /&gt;
;Wird das Wirkleistungbegrenzungs-Limit erreicht/überschritten und/oder die PV-Überschußprognose: zzgl. eines Sicherheitspuffers unterschritten, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 1&#039;&#039;&#039; gesetzt. Der User kann darauf reagieren und den Batterie Ladevorgang aktivieren. Die Möglichkeiten der Aktivierung sind natürlich von der installierten Anlage abhängig. Das SolarForecast Device greift nicht in die Batteriesteuerung direkt ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders ausgedrückt erfolgt immer dann eine Ladefreigabe, wenn einer der nachfolgenden Sachverhalte &#039;&#039;wahr&#039;&#039; ist:&lt;br /&gt;
&lt;br /&gt;
- die benötigte Ladeenergie (aller installierten Batterien) &amp;gt;= PV-Restüberschuß des Tages (Reading RestOfDayPVforecast) zzgl. Sicherheitsaufschlag&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- der Zeitpunkt des PV-Erzeugungszenit des laufenden Tages überschritten ist (Reading Today_MaxPVforecastTime)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn die aktuelle PV Leistung &amp;gt;= einer eventuellen Wechselrichter-Leistungsbegrenzung ist (Summe aller WR-Begrenzungen)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn das BatSoc-Management _nicht_ aktiviert ist (nicht alle oben genannten Aktivierungskriterien erfüllt sind)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind mehrere Batterien installiert und durch das Management einer Batterie die Einhaltung der genannten Kriterien bzw. Sachverhalte erwirkt wird, bleiben die weiteren Batterien im Modus Ladefreigabe (Battery_ChargeUnrestricted_XX=1).  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Umsetzungsbeispiel Batterie Ladesteuerung mit Victron GX Venus über den Grid Setpoint =====&lt;br /&gt;
&lt;br /&gt;
Ziel der Steuerung ist es abhängig vom Wert des Readings Battery_ChargeUnrestricted_XX (z.B. Battery_ChargeUnrestricted_01) die Ladung des angeschlossenen Batteriesystems zu aktivieren bzw. zu deaktivieren.&lt;br /&gt;
Das vorliegende Beispiel soll umzusetzen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 0 -&amp;gt; Batterie nicht aufladen bzw. nur laden wenn Einspeiselimit überschritten (Attribut plantControl-&amp;gt;feedinPowerLimit)&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 1 -&amp;gt; Batterie aufladen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Grid Setpoint ist ein Parameter in den Victron Systemeinstellungen. Das Victron System wird den eingestellten Grid Setpoint versuchen einzuhalten und bei einem positiven Wert Energie aus dem Netz beziehen bzw. bei einem negativen Grid Setpoint Energie in das Netz einspeisen.&lt;br /&gt;
&lt;br /&gt;
Normalerweise wird das Victron System die erzeugte PV Energie zunächst zur Deckung des Hausverbrauchs verwenden, ist dann noch ein PV Überschuß vorhanden, die Batterien aufladen und bei weiter vohandenen PV Überschuß diese Energie in das öffentliche Netz einspeisen sofern dem System eine Einspeisung erlaubt ist. Anderenfalls werden die Wechselrichter oder MPPT Smartloader heruntergeregelt bzw. limitiert. &lt;br /&gt;
&lt;br /&gt;
In der Standardeinstellung ist beim Victron System ein Grid Setpoint von ca. 20 bis 50 Watt, d.h. das System strebt danach diese Vorgabe zu erfüllen zieht ständig Energie in diesem Bereich aus dem öffentlich Netz von einem gelegentlichen Überschwingen der Regelung abgesehen. Damit ein eventueller PV Überschuß nicht zum Laden der Batterie verwendet, sondern statt dessen in das öffentliche Netz eingespeist wird, muß der Grid Setpoint um diesen Betrag abgesenkt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-24 114403.png|right|thumb|400px|Integration des Grid Setpoint-Managements in den Own_Spec-Bereich]]&lt;br /&gt;
&lt;br /&gt;
Damit man später per Attribut bzw. über den [[#Formatierung_der_Inhalte_im_Bereich_&amp;quot;Graphic_Header_Own_Specification&amp;quot;|Own_Spec-Bereich]] die automatische Ladesteuerung über den Grid Setpoint ein- bzw. ausschalten kann, legen wir ein userattr an:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 userattr &amp;lt;Name&amp;gt; userFn_GridSetpointManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin sind einige Vorbereitungen im Device MQTT2_cerboGX_c0619ab34e08_settings vorzunehmen. Dieses Device ist im vorliegenden Beispiel ein in FHEM vorhandenes MQTT2_DEVICE, über das die Victron CerboGX Einstellungen zugreifbar sowie einstellbar sind. Die Vorgehensweise zur Erstellung des MQTT2_DEVICE ist hier nicht beschrieben und wird vorausgesetzt.&lt;br /&gt;
&lt;br /&gt;
Damit ein entsprechender Set-Befehl zur Einstellung des Grid Setpoints vorhanden ist, werden folgende Attribute gesetzt:&lt;br /&gt;
&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings jsonMap Settings_CGwacs_AcPowerSetPoint_value:GridSetpoint&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings setList GridSetpoint W/c0619ab34e08/settings/0/Settings/CGwacs/AcPowerSetPoint {&amp;quot;value&amp;quot;:$EVTPART1}&lt;br /&gt;
&lt;br /&gt;
Nach dieser Attributierung kann mit einem &amp;quot;&#039;&#039;set MQTT2_cerboGX_c0619ab34e08_settings GridSetpoint &amp;lt;Wert&amp;gt;&#039;&#039;&amp;quot; der Grid Setpoint eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Das Attribut userFn_GridSetpointManagement kann nun im Perl Code ausgewertet werden um das Grid Setpoint-Management ein- bzw. auszuschalten.&lt;br /&gt;
Der nachfolgende Code wird in die Datei &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; eingefügt. Ist diese Datei nicht vorhanden, legen wir sie vorab als Kopie der ausgelieferten 99_myUtils.pm an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible mw-collapsed&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Code Management Batterieladung über Victron Grid Setpoint -&amp;gt;&#039;&#039;&#039; &amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Steuerung Start/Stop der Batterieladung über den Victron Grid Setpoint&lt;br /&gt;
############################################################################&lt;br /&gt;
sub gridSetpointMgmt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vicsets   = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                               # Device Victron Einstellungen&lt;br /&gt;
  my $gspdef    = 20;                                                                  # Default Einstellung des Grid Setpoint&lt;br /&gt;
  my $targetgsp = $gspdef;                                                             # Voreinstellung Grid Setpoint&lt;br /&gt;
  my $neggspmax = FHEM::SolarForecast::CurrentVal ($name, &#039;feedinPowerLimit&#039;, 5000);   # max. gewünschte Einspeiseleistung in Watt&lt;br /&gt;
  $neggspmax    = $neggspmax * -1;&lt;br /&gt;
  my $gspm      = AttrVal ($name, &#039;userFn_GridSetpointManagement&#039;, &#039;aus&#039;);             # Freischaltung des Grid Setpoint-Managements&lt;br /&gt;
  my $curgsp    = ReadingsNum ($vicsets, &#039;GridSetpoint&#039;,         $gspdef);             # aktuelle Einstellung Grid Setpoint&lt;br /&gt;
  &lt;br /&gt;
  if ($gspm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name, &#039;Battery_ChargeUnrestricted_01&#039;, 0);         # Ladefreigabe (1 -&amp;gt; Bat Ladefreigabe)&lt;br /&gt;
    my $surp = ReadingsNum ($name, &#039;Current_Surplus&#039;,               0);         # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if (!$bcrq) {                                                               # Grid Setpoint absenken wenn keine .. &lt;br /&gt;
        $targetgsp = $gspdef - $surp;                                           # ..Batterie Ladefreigabe&lt;br /&gt;
        $targetgsp = $neggspmax if($targetgsp &amp;lt; $neggspmax);                    # Begrenzung der Einspeiseleistung&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($curgsp != $targetgsp) {&lt;br /&gt;
	  fhem (&amp;quot;set $vicsets GridSetpoint $targetgsp&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn gridSetpointMgmt -&amp;gt; GridSetpoint in $vicsets set to $targetgsp});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Victron_GridSetpoint_set&#039;, $targetgsp, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Vergleich des Setpoints mit der Vorgabe von &#039;&#039;$neggspmax&#039;&#039; dient dazu die maximale Einspeiseleistung in das öffentliche Netz zu begrenzen. Ist diese Grenze erreicht, wird der noch verbleibende Überschuß in die Batterie geladen. Dadurch wird eine Abregelung der Anlage vermieden wenn der Schwellenwert &#039;&#039;$neggspmax&#039;&#039;erreicht ist sofern die Batterie aufnahmefähig ist und nicht voll geladen ist. &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::gridSetpointMgmt  ($name);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zum Management des automatischen Grid Setpoint und der Anzeige des eingestellten Wertes wird das Attribut und die Readinganzeige in den Own_Spec-Bereich eingebunden, z.B.:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; graphicHeaderOwnspec  #Settings&lt;br /&gt;
                                   SetPoint&amp;amp;nbsp;Management:userFn_GridSetpointManagement&lt;br /&gt;
                                   Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== leistungsoptimierte Beladungssteuerung mit dem Fokus geringe Verlustleistung und Verschleiß ====&lt;br /&gt;
&lt;br /&gt;
Über das Attribut ctrlBatSocManagementXX kann mit dem Schlüssel loadStrategy die Ladestrategie &#039;&#039;&#039;optPower&#039;&#039;&#039; oder &#039;&#039;&#039;smartPower&#039;&#039;&#039; eingestellt werden.&lt;br /&gt;
Das SF-Modul bietet ein weiteres Reading &#039;&#039;&#039;Battery_ChargeOptTargetPower_XX&#039;&#039;&#039; zur Batteriesteuerung an. Dieses Reading liefert eine kalkulierte optimale Ladeleistung in Watt.&lt;br /&gt;
&lt;br /&gt;
Die in diesem Abschnitt beschriebene Ladestrategie &#039;&#039;&#039;optPower&#039;&#039;&#039; wird im Modul als &#039;&#039;&#039;optimierte Ladeleistung&#039;&#039;&#039;, die Ladestrategie &#039;&#039;&#039;smartPower&#039;&#039;&#039; als &#039;&#039;&#039;zieloptimierte Ladeleistung&#039;&#039;&#039; bezeichnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beide Strategien kalkulieren die Ladeleistung kontinuierlich neu und berücksichtigen dabei:&lt;br /&gt;
&lt;br /&gt;
* die Prognose der PV-Erzeugung der nächsten Stunden und des (Rest-)Tages&lt;br /&gt;
* den prognostizierten Verbrauch auf Stunden- bzw. Tagesbasis&lt;br /&gt;
* eine eventuell mögliche Überschreitung des gesetzten Einspeiselimits (plantControl-&amp;gt;feedinPowerLimit)&lt;br /&gt;
* die gesetzten Leistungsparameter der Batterie &lt;br /&gt;
* das Ziel, am Tagesende einen möglichst maximalen SoC der Batterie erreicht zu haben bzw. den eingestellten Ziel-SoC &#039;&#039;&#039;loadTarget&#039;&#039;&#039;&lt;br /&gt;
* die Effizienz der Batterieanlage (Einstellung &#039;&#039;&#039;setupBatteryDevXX-&amp;gt;efficiency&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Fokus der implementierten Logik liegt dabei auf einer kontinuierlichen Ladeleistung, die aber unter den oben genannten Gesichtspunkten möglichst (relativ) gering sein soll um den Batterieverschleiß und die Verlustleistung zu minimieren. Die im Reading angezeigte Ladeleistung kann mit geeigneten Mitteln direkt in die Leistungssteuerung der Batterie eingebracht werden. Natürlich kann die Leistung auch vorab in einen optimalen Ladestrom umgerechnet werden.&lt;br /&gt;
&lt;br /&gt;
Da das Ergebnis der Kalkulation stark von den Prognosen abhängt, ist zur Erhöhung der Resilienz per Default ein Sicherheitszuschlag von 20% eingebaut. Dieser Wert kann mit dem Attribut &#039;&#039;&#039;ctrlBatSocManagementXX-&amp;gt;safetyMargin&#039;&#039;&#039; individuell angepasst werden. &lt;br /&gt;
&lt;br /&gt;
Ist kein PV-Überschuß (mehr) vorhanden / prognostiziert oder das Ladeziel erreicht, erfolgt ein Rückfall der Ladeleistung im Reading Battery_ChargeOptTargetPower_XX auf den  im Attribut &#039;&#039;&#039;setupBatteryDevXX-&amp;gt;pinmax&#039;&#039;&#039; angegebenen Wert. Ist dieser Wert nicht gesetzt, erfolgt der Rückfall auf &amp;quot;Unendlich&amp;quot; (9223372036854775807). &lt;br /&gt;
 &lt;br /&gt;
Im Reading Battery_ChargeOptTargetPower_XX wird der Wert des Parameters &#039;&#039;&#039;setupBatteryDevXX-&amp;gt;pinreduced&#039;&#039;&#039; gesetzt, wenn weniger Ladeleistung als pinreduced berechnet wurde (Einhaltung einer Mindestladeleistung) oder wenn der SoC der Batterie &amp;lt;= [[#Aktivierung_des_Batterie_SOC-_und_Lade-Managements|lowSoC]] beträgt.&lt;br /&gt;
Somit wird die Batterie bei einer Anforderungsladung bei Unterschreitung von lowSoC mit nur wenig Leistung aus dem Grid geladen falls es nötig sein sollte.&lt;br /&gt;
Es ist demzufolge ratsam den optionalen Parameter &#039;&#039;&#039;setupBatteryDevXX-&amp;gt;pinreduced&#039;&#039;&#039; zu setzen, da ansonsten ebenfalls ein Rückfall auf &#039;&#039;&#039;setupBatteryDevXX-&amp;gt;pinmax&#039;&#039;&#039; bzw. &amp;quot;Unendlich&amp;quot; erfolgt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beide Strategien, optPower und smartPower, setzen die zuvor beschriebene Arbeitsweise um.&lt;br /&gt;
Ergänzend wird bei der Ladestrategie &#039;&#039;&#039;smartPower&#039;&#039;&#039; die generelle Erreichbarkeit des Ladeziels bei der Festlegung der Ladeleistung berücksichtigt. Es führt dazu dass:&lt;br /&gt;
&lt;br /&gt;
* die Ladeleistung im Reading Battery_ChargeOptTargetPower_XX auf einen tendenziell höheren Wert als bei der optPower-Strategie gesetzt wird, wenn/solange das eingestellte Ladeziel als unerreichbar kalkuliert wird&lt;br /&gt;
* bei kalkulierter Erreichbarkeit des Ladeziels der Sicherheitsaufschlag linear absenkend proportional zum Kehrwert des verfügbaren PV-Überschusses auf die Ladeleistung angewendet wird&lt;br /&gt;
&lt;br /&gt;
Der nächste Abschnitt erläutert die smartPower Funktionen etwas eingehender.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== smartPower - die zieloptimierte Ladeleistung  =====&lt;br /&gt;
Die hinter smartPower liegende Anpassungslogik wird nachfolgend etwas näher beschrieben.&lt;br /&gt;
Ausgangspunkt ist das Ergbnis einer Ratio-Funktion aus dem (Rest)Tages-PV-Überschuß und benötigter Energie zur Erlangung des Batterie Ladeziels.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lineare Interpolation zwischen pinmax und abgesicherter minpower&#039;&#039;&#039;  &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Variablen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;P&#039;&#039;&#039;: resultierende Leistung.&lt;br /&gt;
* &#039;&#039;&#039;pinmax&#039;&#039;&#039;: maximale Ladeleistung.&lt;br /&gt;
* &#039;&#039;&#039;limpower&#039;&#039;&#039;: Leistungslimit, d.h. Ladeleistungssollwert.&lt;br /&gt;
* &#039;&#039;&#039;r&#039;&#039;&#039;: Verhältnis in Prozent (r = spday·100 / whneed).&lt;br /&gt;
* &#039;&#039;&#039;otpMargin&#039;&#039;&#039;: Prozentwert der Bandbreite, über die die Absenkung linear verläuft (die Steilheit kann mit dem Attributwert ctrlBatSocManagementXX-&amp;gt;safetyMargin im Device eingestellt werden).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Kennlinie der für smartPower eingesetzten Funktion ist stückweise definiert über das Verhältnis Ratio &#039;&#039;𝑟 = spday x 100 / &amp;lt;benötigte Ladeenergie bis Ziel&amp;gt;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* Für 𝑟 ≤ 100: &#039;&#039;𝑃 = pinmax&#039;&#039;, Interpretation: Es ist viel Bedarf vorhanden bzw. Überschuss ≤ 100 % des Bedarfs → maximal laden.&lt;br /&gt;
* Für 𝑟 ≥ 100 + otpMargin: &#039;&#039;𝑃 = limpower ⋅ (1 + otpMargin / 100 )&#039;&#039;&lt;br /&gt;
* Für 100 &amp;lt; 𝑟 &amp;lt; 100 + otpMargin: lineare Absenkung von &#039;&#039;&#039;P&#039;&#039;&#039; mit zunehmendem &#039;&#039;&#039;r&#039;&#039;&#039; für den Bereich 100 &amp;lt; 𝑟 &amp;lt; 100 + otpMargin. &#039;&#039;&#039;P&#039;&#039;&#039; wird bei 𝑟 = 100 gleich &#039;&#039;&#039;pinmax&#039;&#039;&#039; und bei 𝑟 = 100 + otpMargin gleich &#039;&#039;limpower ⋅ ( 1 + otpMargin/100 )&#039;&#039;, Interpretation: Sobald der Überschuss über den Bedarf hinausgeht (ratio &amp;gt; 100), wird das Ladeleistungslimit schrittweise von pinmax Richtung limpower reduziert; die Reduktion erfolgt gleichmäßig über die Margin-Spanne.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lineare Interpolation und Steigung&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Die Differenz &#039;&#039;(pinmax − limpower)&#039;&#039; wird gleichmäßig auf die otpMargin-Prozentpunkte verteilt. Die Steigung der Geraden ist&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
slope = − (pinmax − limpower) / otpMargin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
das heißt die Leistung sinkt um diesen Betrag pro Prozentpunkt von &#039;&#039;&#039;r&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nach Umformung ist der Zusammenhang wie folgt darstellbar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
𝑃 = pinmax − ( pinmax − limpower) ⋅ ((𝑟 − 100) / otpMargin)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und ist äquivalent zu&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
𝑃 = pinmax + ( 𝑟 − 100 ) ⋅ slope&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Numerisches Beispiel&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;limpower&#039;&#039;&#039; = 1000 W, &#039;&#039;&#039;pinmax&#039;&#039;&#039; = 3000 W, &#039;&#039;&#039;otpMargin&#039;&#039;&#039; = 20&lt;br /&gt;
* Unterschied = 2000 W, Steigung = −2000/20 = −100 W/%&lt;br /&gt;
* Für &#039;&#039;&#039;r = 105&#039;&#039;&#039;: 𝑃 = 3000 − 2000 ⋅ ( 5 / 20 ) = 3000 − 500 = 2500 W&lt;br /&gt;
* Für &#039;&#039;&#039;r = 120&#039;&#039;&#039; ergibt die Formel den abgesicherten Endwert 1200 W&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Formel sorgt dafür, dass die Zielleistung stufenlos und vorhersehbar reduziert wird, wenn der relative Rest-Überschuss des Tages über 100% steigt, und erreicht bei Ende der otpMargin den geplanten abgesicherten Wert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Ratio Kennlinie.png|right|thumb|200px|abfallend proportionale Anpassungsfunktion]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In einem grafischen Diagramm stellt sich die abfallend proportionale Anpassungsfunktion der resultierenden Soll-Ladeleistung wie nebenstehend abgebildet dar. Dabei entspricht pow=100 dem jeweiligen pinmax Wert (hier 3000 W). So ist auch pow=0 mit dem abgesicherten Endwert (hier 1200 W) gleichzusetzen. Die Linie verläuft waagerecht bei pinmax solange das das Ratio  r ≤ 100 % und knickt an r == 100 mit steigenden r nach unten. Es verringert sich pow linear von pinmax zu limpower zzgl. otpMargin.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Durch diese Maßnahmen wird eine flexible Lademöglichkeit bis pinmax erreicht, die sich bei unvorhergesehenen Aufklarungen mit starker Sonneneintrahlung bei ansonsten sehr bedeckten Himmel positiv auswirkt. Andererseits wird die Erhöhung der Ladeleistung weiter begrenzt, wenn viel PV-Überschuß in Verbindung mit einer generellen Erreichbarkeit des Ladeziels zum Ende des Tages prognostiziert ist. Man könnte die Ladestrategie &#039;&#039;&#039;smartPower&#039;&#039;&#039; in ihrer Wirkung als einen Mix aus &#039;&#039;&#039;optPower&#039;&#039;&#039; und &#039;&#039;&#039;loadRelease&#039;&#039;&#039; ansehen.&lt;br /&gt;
&lt;br /&gt;
Zusammenfassend ist optPower vorwiegend für die Nutzergruppe geeignet, die eine tendenziell sparsamere Ladeleistung bevorzugen und dafür bereit sind eventuelle &amp;quot;Verluste&amp;quot; in Form von Einspeisung zu akzeptieren. &amp;lt;br&amp;gt;&lt;br /&gt;
Demgegenüber eignet sich das aggressivere smartPower für Anwender, die bei niedrigen PV-Erträgen bewusst das Maximum an Batterieladung anstreben und dafür in Kauf nehmen, dass Ladeleistungen weniger knapp kalkuliert sind. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Unterstützung des Modus &amp;quot;Eigennutzung&amp;quot; bei Hybrid-Wechselrichtern =====&lt;br /&gt;
Viele Hybrid-Wechselrichter verteilen die zur Verfügung stehende PV-Leistung nach folgendem Prioritäten, wenn der (übliche) Modus &amp;quot;Eigennutzung&amp;quot; aktiviert ist:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Nutzung der Leistung zur Deckung des Hausverbrauchs,&lt;br /&gt;
# Nutzung der Leistung zur Ladung des bzw. der angeschlossenen Speicher.&lt;br /&gt;
# Einspeisung der Leistung in das öffentliche Netz.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Da in aller Regel die Leistung, mit der ein angeschlossener Speicher geladen wird, limitiert werden kann, lassen sich die o.g. Priorität bzgl. des Speichers zugunsten einer Überschusseinspeisung aufweichen. Ein entstehender &amp;quot;Überschuss&amp;quot; steht also ggf. nur deshalb zur Verfügung, weil die Ladeleistung des Speichers begrenzt wurde.&lt;br /&gt;
&lt;br /&gt;
Ab Version 1.58.6 bietet SolarForecat die Möglichkeit, prognostizierte Verbräuche nicht mehr komplett bei der Bestimmung der &#039;&#039;optimalen Ladeleistung&#039;&#039; zu berücksichtigen, sondern nur noch zu einem prozentualen Anteil von 0..100 %. Hierzu muss der Attribut-Schlüssel &#039;&#039;&#039;ctrlBatSocManagementXX-&amp;gt;weightOwnUse=&amp;lt;Percentage&amp;gt;&#039;&#039;&#039; entsprechend gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
So führt beispielsweise weightOwnUse=100 dazu, dass bei der Berechnung der optimalen Ladeleistung prognostizierte Verbräuche nicht mehr berücksichtigt werden indem sie bei der Bestimmung des stündlichen PV-Überschusses unberücksichtigt bleiben. Eine derartige Einstellung kann z.B. sinnvoll sein, wenn alle ansonsten täglich laufende Verbraucher zugunsten einer Batterieladung ausgeschaltet werden können.&lt;br /&gt;
&lt;br /&gt;
Ein Wert von zum Beispiel weightOwnUse=30 lässt 30% der stündlichen Verbrauchslast unberücksichtigt, sodass sich der kalkulierte PV-Überschuß pro Stunde um 30% des prognostizierten Verbrauchs erhöht. Da die Berechnung der optimierten Ladeleistung mit dem zur Verfügung stehenden PV-Überschuß gewichtet erfolgt, würde sich die kalkulierte Ladeleistung in den meisten Fällen ebenfalls um einen gewissen Betrag erhöhen sofern andere Faktoren dies nicht verhindern. Das kann beispielweise der Fall sein, wenn die kalkulierte Ladeleistung zu gering ist und automatisch aif mindestens &#039;&#039;&#039;setupBatteryDevXX-&amp;gt;pinreduced&#039;&#039;&#039; angehoben wurde.&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Welche Ladestrategie soll ich wählen? - eine Möglichkeit zur Best-Practice Findung mit Codebeispiel ====&lt;br /&gt;
&lt;br /&gt;
In den vorangegangenen Abschnitten wurden die verschiedenen Möglichkeiten zur Steuerung der Batterieladung und dem SoC vorgestellt. Diese Steuerungsvarianten optimieren die Arbeitweise der Batterie, haben aber jeweils einen eigenen Fokus auch wenn es gewisse Überschneidungen gibt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Steuerungsvarianten lassen sich folgendermaßen klassifizieren:&lt;br /&gt;
&lt;br /&gt;
# Steuerung der Batterieladung über eine Ladefreigabe, die durch bestimmte Indikatoren festgelegt wird. Diese Variante ist in [[SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#PV-Prognose_und_Verbrauch_optimierte_Beladungssteuerung_unter_Berücksichtigung_einer_Wirkleistungsbegrenzung|diesem]] Abschnitt beschrieben.&lt;br /&gt;
# Steuerung der Batterieladung durch eine optimierte maximale Ladeleistung. Diese Variante ist in [[SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#leistungsoptimierte_Beladungssteuerung_mit_dem_Fokus_geringe_Verlustleistung_und_Verschleiß|diesem]] Abschnitt dargelegt. Zu dieser Variante gehören die Strategien &#039;&#039;optPower&#039;&#039; sowie &#039;&#039;smartPower&#039;&#039;. Die Unterschiede beider Strategien sind ebenfalls in dem verlinkten Abschnitt beschrieben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die &#039;&#039;&#039;Variante 1.)&#039;&#039;&#039; gibt die Ladung der Batterie frei wenn der (verbleibende) PV-Überschuß des Tages kleiner oder gleich dem Ladungsbedarf der Batterie ist um einen SoC von 100% bzw. den maximal möglichen SoC am Ende des Tages zu erreichen. Dadurch wird die in der Batterie vorhandene freie Kapazität so lange wie möglich der Einhaltung von besonderen Grenzwerten, z.B. des Einspeiselimits (plantControl-&amp;gt;feedinPowerLimit), vorbehalten. Nebeneffekt ist, dass plötzlich und unerwartet auftretende hohe Erzeugungsleistungen in die Batterie geladen werden können und nicht unerwünscht in das öffentliche Netz eingespeist werden. &lt;br /&gt;
&lt;br /&gt;
Die &#039;&#039;&#039;Variante 2.)&#039;&#039;&#039; lässt die Batterie kontinuierlich laden, wobei die Ladeleistung auf ein optimiertes Minimum reduziert wird ohne das Ziel, einen maximalen SoC am Tagesende zu erreichen, zu ignorieren. Dadurch wird die Batterie schonend, mit möglichst wenig Verlustleistung und verschleißarm geladen. Die Vorhaltung der freien Kapaziäten der Batterie sind in dieser Variante nicht die Prämisse. Die Einhaltung des gesetzten Enispeiselimits wird auch in dieser Variante beachtet sofern es der Ladezustand der Batterie zulässt. Technisch bedingt kann diese Variante nur ungenügend auf unerwartete PV-Überschüsse reagieren, was zu einer Einspeisung in das öffentliche Netz oder im ungünstigsten Fall zur Abregelung der Anlage führen kann. Mit dem Attribut &#039;&#039;&#039;ctrlBatSocManagementXX-&amp;gt;safetyMargin&#039;&#039;&#039; kann man diesem negativen Aspekt in gewissem Maße entgegenwirken.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ausgehend von diesen unterschiedlichen Optimierungszielen bietet sich die Variante 1.) vorwiegend in den Übergangs- und Wintermonaten an. Durch die beschriebenen Eigenschaften dieser Variante ist bei tendeziell weniger PV-Überschuß über den Tag die Ladung der Batterie komplett freigegeben, wodurch bei plötzlich auftretenden sonnige Abschnitten und Aufklarungen die Batterie sofort mit dem verfügbaren PV-Überschuß geladen wird. Auch eine Einspeisung über das Einspeiselimit hinaus kann verhindert werden. In der übrigen Zeit wird die Ladeleistung durch den verfügbaren PV-Überschuß begrenzt. &lt;br /&gt;
Weiterhin soll der SoC nicht dauerhaft tief absinken und ebenfalls nicht auf einem zu hohen Level verharren was auch einer maximal möglichen Energiespeicherung an sonnigen Tagen entgegenwirken würde.&lt;br /&gt;
In dieser Zeit ist die Nutzung der Kombination von [[SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#Nutzung_des_Batterie_SOC-Management|SoC-Management]] und Variante 1.) wohl am Besten geeignet um die Ziele zu verwirklichen sowie Notreserven in den Batterien vorzuhalten. &lt;br /&gt;
&lt;br /&gt;
In den Sommermonaten hingegen ist üblicherweise sehr viel PV-Energie und Überschuß vorhanden. In dieser Periode würden die Batterien mit sehr hoher Leistung sehr zeitig am Tag vollgeladen. Die Variante 1.) ist im Prinzip ebenfalls gut geeignet den Zeitpunkt der Vollladung hinauszuzögern, jedoch erscheint die Varinte 2.) in dieser Zeit besser geeignet mit einer über den gesamten Tag verteilten moderaten Ladeleistung den Ziel-SoC zu erreichen. Auch diese Variante versucht eine Überschreitung des Einspeiselimits zu verhindern sofern der Ladezustand der Batterie dies ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Codebeispiel bietet die Möglichkeit über ein Attribut die Ladevariante auszuwählen, über ein weiteres Attribut die SoC-Steuerung zu aktivieren/deaktivieren und integriert auch die Ladesteuerung für eine Batterie-Anforderungsladung bei Unterschreitung von ctrlBatSocManagementXX-&amp;gt;lowSoc. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die gesteuerte Batterieanlage besteht aus:&lt;br /&gt;
&lt;br /&gt;
* 3 x Victron MultiPlusII 3000/48&lt;br /&gt;
* Steuergerät CerboGX (in FHEM über MQTT eingebunden)&lt;br /&gt;
* einem Batteriestack bestehend aus Pylontech US3000C (wird durch CerboxGX gesteuert)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zur Umschaltung bzw. Auswahl der Ladestrategie und des SoC-Managements werden zwei User-Attribute im SolarForecast Device angelegt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr ... userattr userFn_BatterySoCManagement:Ein,Aus userFn_BatteryLoadManagement:Aus,loadRelease,optPower,smartPower&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Code werden diese Attribute ausgewertet. Das nachfolgende Script vereint folgende Funktionalitäten:&lt;br /&gt;
&lt;br /&gt;
* die Aktivierung/Deaktivierung des SoC-Managements via Attribut userFn_BatterySoCManagement&lt;br /&gt;
* die Auswahl der Ladestrategie oder Deaktivierung der Ladesteuerung via attribut userFn_BatteryLoadManagement&lt;br /&gt;
* Integration einer Anforderungsladung bei Signalisierung durch Reading Battery_ChargeRequest_XX&lt;br /&gt;
* Generierung von Readings userFn_Victron_GridSetpoint_set und userFn_MPII_MaxChargeCurrent_set zur Dokumentation der eingestellten Soll-Werte&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
Bei der Nachnutzung des Scripts sind zunächst die &#039;&#039;&#039;Konstanten&#039;&#039;&#039; und das Device &#039;&#039;&#039;MQTT2_cerboGX_c0619ab34e08_setting&#039;&#039;&#039;s sowie dessen Readings im Block &#039;&#039;&#039;aktuelle Indikatoren&#039;&#039;&#039; anzupassen.&lt;br /&gt;
&lt;br /&gt;
Das Script wird in die Datei &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; eingetragen und im SolarForecast Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; hinterlegt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr ... ctrlUserExitFn {&lt;br /&gt;
                          ::batLoadMgmnt ($name, &#039;01&#039;);&lt;br /&gt;
                          # ::batLoadMgmnt ($name, &#039;02&#039;);   # optional für eine weitere Batterie &#039;02&#039;&lt;br /&gt;
                          # ::batLoadMgmnt ($name, &#039;0X&#039;);   # optional für weitere Batterien&lt;br /&gt;
                        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit diesem Script ist der Nutzer in der Lage, das Batterie Lademanagement entsprechend seiner Motivation und gegebenenfalls abhängig von der Jahreszeit umzustellen und das Ergebnis bzw. die Zielerreichung zu testen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;userFn_BatteryLoadManagement&#039;&#039;&#039; selektiert die gewünschte Ladestrategie:&lt;br /&gt;
&lt;br /&gt;
;Aus: das Lademangement ist ausgeschaltet &lt;br /&gt;
&lt;br /&gt;
;loadRelease: das Lademangement Variante 1.) Ladestrategie Ladefreigabe ist aktiviert &lt;br /&gt;
&lt;br /&gt;
;optPower: das Lademangement Variante 2.) Ladestrategie optimierte Ladeleistung ist aktiviert &lt;br /&gt;
&lt;br /&gt;
;smartPower: das Lademangement Variante 2.) Ladestrategie zieloptimierte Ladeleistung ist aktiviert&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die selektierte Ladestrategie wird im Script in das SolarForecast Device repliziert, d.h. der Attributschlüssel ctrlBatSocManagement01-&amp;gt;loadStrategy wird identisch zum Wert des Attributes userFn_BatteryLoadManagement gesetzt. Dazu wird das Set-Kommando &#039;&#039;attrKeyVal&#039;&#039; verwendet. Das globale Attribut &#039;&#039;autosave&#039;&#039; sollte aus diesem Grund NICHT explizit auf &amp;quot;0&amp;quot; gesetzt sein um eine reibungslose Funktion zu ermöglichen. &lt;br /&gt;
&lt;br /&gt;
Hat man die individuell passende Management-Strategie gefunden, bietet sich auch eine automatische (zum Beispiel durch einen Kalender oder Sonnenstand (Elevation) zur Mittagszeit) Umschaltung der Ladestrategie an. Die Unterschreitung der Elevation unter einen bestimmten Wert würde den Beginn des Winterhalbjahres und reverse Überschreitung den Beginn des Sommerhalbjahres kennzeichnen. Entsprechend würde dann die gewünschte Ladestrategie selektiert. Alternativ könnte auch die PV-Überschußprognose für den aktuellen Tag über das Reading &#039;&#039;Today_PVforecast&#039;&#039; für eine Entscheidung bzgl. der Ladestrategie herangezogen werden.&lt;br /&gt;
&lt;br /&gt;
Das SoC-Management kann über das gesamte Jahr aktiviert bleiben, hat jedoch nach bisherigen Erfahrungen nur im Winterhalbjahr eine starke Relevanz.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible mw-collapsed&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Code Lademanagement -&amp;gt;&#039;&#039;&#039; &amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#      Komplettes Batterie Lademanagement&lt;br /&gt;
############################################################################&lt;br /&gt;
sub batLoadMgmnt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $bn   = shift // &#039;01&#039;;                                                             # Batterienummer&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  ## Konstanten&lt;br /&gt;
  ###############  &lt;br /&gt;
  use constant {&lt;br /&gt;
    GSPDEF    =&amp;gt; 20,                                                                    # Einstellung des Grid Setpoint&lt;br /&gt;
    FINDEF    =&amp;gt; 5000,                                                                  # Default Einspeiselimit&lt;br /&gt;
    MINSOCDEF =&amp;gt; 10,                                                                    # Default Minimum SoC&lt;br /&gt;
    MAXPLDEF  =&amp;gt; 105,                                                                   # max. Ladestrom (A) Victron MPII &lt;br /&gt;
    SYSVOLTAG =&amp;gt; 48,                                                                    # Batterie Systemspannung&lt;br /&gt;
  };&lt;br /&gt;
  &lt;br /&gt;
  my $batsocmgmt  = AttrVal ($name, &#039;userFn_BatterySoCManagement&#039;,  &#039;Aus&#039;);             # SoC-Management Vorgabe&lt;br /&gt;
  my $batloadmgmt = AttrVal ($name, &#039;userFn_BatteryLoadManagement&#039;, &#039;Aus&#039;);             # Lademanagement Vorgabe&lt;br /&gt;
  my $vicsets     = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                              # Victron CerboGX Einstellungen&lt;br /&gt;
&lt;br /&gt;
  ## Ladestrategie Ist-Einstellung und Soll-Abgleich&lt;br /&gt;
  ####################################################&lt;br /&gt;
  my $cgbt     = AttrVal ($name, &#039;ctrlBatSocManagement&#039;.$bn, undef);&lt;br /&gt;
  my $strategy = &#039;loadRelease&#039;; &lt;br /&gt;
&lt;br /&gt;
  if ($cgbt) {&lt;br /&gt;
    my $parsed = FHEM::SolarForecast::__parseAttrBatSoc ($name, $cgbt);                 # aktuell gesetzte Strategie ermitteln&lt;br /&gt;
    $strategy  = $parsed-&amp;gt;{loadStrategy} // $strategy;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($batloadmgmt ne &#039;Aus&#039; &amp;amp;&amp;amp; $strategy ne $batloadmgmt) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$name attrKeyVal ctrlBatSocManagement${bn} loadStrategy=$batloadmgmt&amp;quot;);              &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  ## aktuelle Indikatoren&lt;br /&gt;
  ##########################&lt;br /&gt;
  my $surp    = ReadingsNum ($name, &#039;Current_Surplus&#039;,            0);                   # aktueller PV-Überschuß&lt;br /&gt;
  my $bcrq    = ReadingsNum ($name, &#039;Battery_ChargeRequest_&#039;.$bn, 0);                   # Notfallladung&lt;br /&gt;
  my $curgsp  = ReadingsNum ($vicsets, &#039;GridSetpoint&#039;, GSPDEF);                         # aktuelle Einstellung Grid Setpoint&lt;br /&gt;
  my $finplim = FHEM::SolarForecast::CurrentVal ($name, &#039;feedinPowerLimit&#039;,   FINDEF);  # Limit plantControl-&amp;gt;feedinPowerLimit&lt;br /&gt;
  my $preduce = FHEM::SolarForecast::BatteryVal ($name, $bn, &#039;bpinreduced&#039;, MAXPLDEF);  # reduzierte Ladeleistung Bat-Konfig&lt;br /&gt;
  my $actmcc  = ReadingsNum ($vicsets, &#039;MaxChargeCurrent&#039;,     0);                      # akt. maximale Ladestromeinstellung&lt;br /&gt;
  my $actmcp  = ReadingsNum ($vicsets, &#039;MaxChargePower&#039;,   undef);                      # akt. Ladeleistungseinstellung&lt;br /&gt;
  my $load    = MAXPLDEF;                                                               # initialer Soll-Ladestrom (A)&lt;br /&gt;
  &lt;br /&gt;
  my $targetgsp = GSPDEF;                                                               # Voreinstellung Grid Setpoint&lt;br /&gt;
  my $ctype     = &#039;default&#039;;                                                            # Voreinstellung Steuerungstyp  &lt;br /&gt;
&lt;br /&gt;
  ## Battery SoC Management&lt;br /&gt;
  ###########################  &lt;br /&gt;
  if ($batsocmgmt eq &#039;Ein&#039;) { &lt;br /&gt;
    my $csoc = ReadingsNum ($vicsets, &#039;MinimumSocLimit&#039;,               MINSOCDEF);     # akt. SoC&lt;br /&gt;
    my $osoc = ReadingsNum ($name,    &#039;Battery_OptimumTargetSoC_&#039;.$bn, MINSOCDEF);     # optimierter Mindest-SoC&lt;br /&gt;
	&lt;br /&gt;
    if ($csoc != $osoc) {&lt;br /&gt;
      CommandSet (undef, &amp;quot;$vicsets MinimumSocLimit $osoc&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn SoCMgmnt -&amp;gt; MinimumSocLimit in $vicsets set to $osoc %});&lt;br /&gt;
    }                                       &lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Steuerung nach Ladungsfreigabe&lt;br /&gt;
  ###################################    &lt;br /&gt;
  if ($batloadmgmt eq &#039;loadRelease&#039;) {&lt;br /&gt;
    $ctype         = &#039;loadRelease&#039;;    &lt;br /&gt;
    my $unrestrict = ReadingsNum ($name, &#039;Battery_ChargeUnrestricted_&#039;.$bn, 0);         # Ladefreigabe (1 -&amp;gt; Ladefreigabe)&lt;br /&gt;
	&lt;br /&gt;
    if (!$unrestrict) {                                                                 # Grid Setpoint absenken wenn keine .. &lt;br /&gt;
        $targetgsp    = GSPDEF - $surp;                                                 # ..Batterie Ladefreigabe&lt;br /&gt;
        my $neggspmax = -1 * $finplim;&lt;br /&gt;
		$targetgsp    = $neggspmax if($targetgsp &amp;lt; $neggspmax);                         # Begrenzung der Einspeiseleistung&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($curgsp != $targetgsp) {                                                          # GridSetpoint setzen&lt;br /&gt;
	  fhem (&amp;quot;set $vicsets GridSetpoint $targetgsp&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn ChargeMgmnt &#039;loadRelease&#039; -&amp;gt; GridSetpoint in $vicsets set to $targetgsp});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Victron_GridSetpoint_set&#039;, $targetgsp, 0); &lt;br /&gt;
  &lt;br /&gt;
  ## Steuerung nach optimaler Ladeleistung&lt;br /&gt;
  ##########################################&lt;br /&gt;
  if ($batloadmgmt =~ /(?:opt|smart)Power/xs) {&lt;br /&gt;
    $ctype  = &#039;optPower&#039;; &lt;br /&gt;
    my $otp = ReadingsNum ($name, &#039;Battery_ChargeOptTargetPower_&#039;.$bn, $preduce);      # optimale Ladeleistung (W)&lt;br /&gt;
    $load   = sprintf &amp;quot;%.0f&amp;quot;, ($otp / SYSVOLTAG);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Anforderungsladung&lt;br /&gt;
  ####################### &lt;br /&gt;
  if ($bcrq) {                                                                         # max. Ladeleistung...&lt;br /&gt;
    $ctype = &#039;requestCharging&#039;;                                                        # bei Battery_ChargeRequest&lt;br /&gt;
    my $p;&lt;br /&gt;
    &lt;br /&gt;
	if ($surp &amp;lt; $preduce) {&lt;br /&gt;
	  $p = $preduce;&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
      $p = ReadingsNum ($name, &#039;Battery_ChargeOptTargetPower_&#039;.$bn, $preduce);         # optimale Ladeleistung (W) &lt;br /&gt;
    }&lt;br /&gt;
	&lt;br /&gt;
    $load = sprintf &amp;quot;%.0f&amp;quot;, ($p / SYSVOLTAG);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Stromeinstellung umsetzen&lt;br /&gt;
  #############################  &lt;br /&gt;
  if ($load != $actmcc) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$vicsets MaxChargeCurrent $load&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
    Log3 ($name, 3, qq{$name - userFn ChargeMgmnt &#039;$ctype&#039; -&amp;gt; MaxChargeCurrent in $vicsets set }.&lt;br /&gt;
                    qq{from old $actmcc A to $load A});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_MPII_MaxChargeCurrent_set&#039;, $load, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== sequentielle Batterie-Ladung mehrerer Batterien mit lcSlot ====&lt;br /&gt;
&lt;br /&gt;
Der Parameter &#039;&#039;&#039;ctrlBatSocManagementXX-&amp;gt;lcSlot&#039;&#039;&#039; (&amp;quot;load control Slot&amp;quot;) definiert eine Zeitperiode am aktuellen Tag in der die Steuerungslogik für die Batteriesteuerung aktiviert ist. Ist dieser Parameter nicht gesetzt, ist das eingestellte Lademanagement über den gesamten Tag aktiert und wäre identisch mit der Einstellung:&lt;br /&gt;
&lt;br /&gt;
 lcSlot=00:00-23:59&lt;br /&gt;
&lt;br /&gt;
Somit ist die Ladesteuerung per default über den gesamten Tag aktiv.&lt;br /&gt;
&lt;br /&gt;
Durch das Setzen von lcSlot auf einen täglichen Slot wird die Ladesteuerung auf diese Periode eingegrenzt. In der übrigen Zeit ist die Ladung der Batterie freigegeben (Reading Battery_ChargeUnrestricted_XX) bzw. auf die maximal konfigurierte Ladeleistung eingestellt (Reading Battery_ChargeOptTargetPower_XX). Diese Readings können je nach verwendeter Ladestrategie ausgewertet und zur Steuerung der Batterie(n) verwendet werden.  &lt;br /&gt;
Die SoC-Steuerung wird durch die lcSlot-Angabe nicht beeinflusst.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit lcSlot kann zum Beispiel ein sequentielles Laden von mehreren Batterien umgesetzt werden. Nachfolgend wird ein solches Szenario mit drei Batterien  skizziert:&lt;br /&gt;
&lt;br /&gt;
1. die Batterie 1 soll mit voller Leistung geladen werden, die anderen Batterien nur bei weiterem Überschuß. Man würde die jeweiligen &lt;br /&gt;
ctrlBatSocManagementXX-&amp;gt;lcSlot Schlüssel definieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement01 lcSlot=23:00-23:10&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement02 lcSlot=00:00-23:59&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement03 lcSlot=00:00-23:59&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Wie ist der Ablauf: Die Batterie 1 unterliegt keiner Steuerung (nur von 23:00 bis 23:10 als Dummy-Periode). Das Reading Battery_ChargeUnrestricted_01 wird &amp;quot;1&amp;quot; gesetzt, d.h. die Batterie 1 wird zur Ladung uneingeschränkt freigegeben. Die anderen Batterien unterliegen der Steuerung -&amp;gt; Battery_ChargeUnrestricted_02 / 03 sind &amp;quot;0&amp;quot; und sollen nur geladen werden falls ein gesetztes Einspeiselimit überschritten wird.&lt;br /&gt;
&lt;br /&gt;
Ist das Ladeziel der Batterie 1 erreicht, setzt man um die Batterie 2 vollzuladen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement01 lcSlot=00:00-23:59&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement02 lcSlot=23:00-23:10&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement03 lcSlot=00:00-23:59&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Batterien 1 und 3 unterliegen der Steuerung, d.h. Battery_ChargeUnrestricted_01 / 03 haben den Wert &amp;quot;0&amp;quot;. Demgegenüber ist Battery_ChargeUnrestricted_02=1 und soll uneingeschränkt geladen werden.&lt;br /&gt;
&lt;br /&gt;
Ist auch die Batterie 2 voll geladen, würde man das Laden der Batterie 3 aktivieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement01 lcSlot=00:00-23:59&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement02 lcSlot=00:00-23:59&lt;br /&gt;
set ... attrKeyVal ctrlBatSocManagement03 lcSlot=23:00-23:10&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Setzens via &#039;&#039;&#039;attrKeyVal&#039;&#039;&#039; hat den Vorteil, dass die Zeitfenster-Syntax (Anfangszeit kleiner Endezeit usw.) im Hintergrund peprüft und ggf. ein Fehler zurückgegeben wird, den der Nutzer in seinem Script auswerten kann. Weiterhin werden die Attribute implizit gespeichert sofern global-&amp;gt;autosave nicht explizit auf &amp;quot;0&amp;quot; gesetzt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Unterstützung eines netzdienlichen Verhaltens ====&lt;br /&gt;
&lt;br /&gt;
Der Steuerungsprozess der Batterieanlage leistet insgesamt einen kleinen Beitrag zur Netzstabilität, indem die Speicherladung in den Zeitraum der meisten prognostizierten Überschußeinspeisung gelegt wird. Im Sommer kann sich dieser Zeitraum in die Zeit nach dem Maxmimum des prognostizierten PV-Überschusses verlagern, wenn auch danach noch genügend Überschußenergie zu Volladung der Batterie prognostiziert wird. In dem Zusammenhang sollte im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; ein Einspeiselimit gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zur Verdeutlichung soll das Beispiel dienen:&lt;br /&gt;
&lt;br /&gt;
* die Batterie ist zu 60% geladen &lt;br /&gt;
* der User hat upSoC=40 eingestellt&lt;br /&gt;
* der User hat maxSoC=90 eingestellt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Am Vormittag ist genügend Sonne vohanden, das Maximumum der Energie über die Zeit wird aber noch erwartet. &lt;br /&gt;
Zu diesem Zeitpunkt wird das Reading  &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039; auf den Wert &amp;quot;0&amp;quot; gesetzt. Durch den Nutzer erfolgt daraufhin, zum Beipiel über ein Notify, ein anlagenspezifischer Befehl &amp;quot;Ladestop&amp;quot; an die Batterieanlage. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ab diesem Moment wird:&lt;br /&gt;
&lt;br /&gt;
# die Batterie nicht geladen&lt;br /&gt;
# die erzeugte PV-Energie dem Haushalt zur Verfügung gestellt bzw. der verbleibende Überschuß eingespeist, sofern der Überschuß unterhalb des im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limits liegt.&lt;br /&gt;
# ein eventuell über dem Limit &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; vorhandener Überschuß in die Batterie geladen und so die Netzlast verringert sowie die Batterie schonend geladen. (dieser Punkt trifft in den Monaten mit wenig PV-Erzeugung eher nicht zu)  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig liefert die Batterie Energie an das Hausnetz und wird von 60% bis maximal einem SoC-Wert entladen, der durch die [[#Die_dynamische_SOC_Steuerung_mit_Umsetzungsbeispiel|dynamische SOC Steuerung]] bestimmt wird. Dazu muß diese Steuerung natürlich implementiert sein. Sofern der berechnete SoC größer als upSoC ist, wird der maximale Entladungs-SoC auf upSoC gesetzt. &lt;br /&gt;
&lt;br /&gt;
Zusätzlich überprüft das Modul permanent bei jedem Zyklus die Differenz des aktuell vorhandenen SoC zum eingestellten maxSoC.&lt;br /&gt;
Sie soll nicht größer sein um mit dem (noch) zu erwartenden PV-überschuß des Tages der eingestellte maxSoC bzw. dessen Nähe wahrscheinlich erreicht werden kann. &lt;br /&gt;
Sollte der Differenz-Grenzwert erreicht sein, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; gesetzt und der Nutzer sollte dann über einen geeigneten Befehl seine Anlage in den Modus &amp;quot;Laden&amp;quot; umschalten.&lt;br /&gt;
Dieser Vorgang kann beliebig oft während des Tages alternieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Nutzung von batteryTrigger ===&lt;br /&gt;
Ergänzt werden die Möglichkeiten durch das set-Kommando: &lt;br /&gt;
&lt;br /&gt;
 batteryTrigger &amp;lt;1on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;1off&amp;gt;=&amp;lt;Wert&amp;gt; [&amp;lt;2on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;2off&amp;gt;=&amp;lt;Wert&amp;gt; ...] &lt;br /&gt;
&lt;br /&gt;
Das Kommando setzt Triggerpunkte bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %).&lt;br /&gt;
&lt;br /&gt;
Der verwendete SoC wird als resultierender SoC als Summe der aktuellen Ladung aller registrierten Batterie-Geräte im Verhältnis zur installierten Gesamtkapazität gebildet. Das bedeutet, dass alle einzelnen Batterie-Geräte als ein gemeinsamer Cluster betrachtet werden. &lt;br /&gt;
&lt;br /&gt;
Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise definiert werden.&lt;br /&gt;
Überschreiten die letzten drei SoC-Messungen eine definierte Xon-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = on&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
Unterschreiten die letzten drei SoC-Messungen eine definierte Xoff-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = off&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
&lt;br /&gt;
Der Inhalt der Readings kann durch ein User-Programm oder, bei Erzeugung von entsprechenden Events, mittels notify-Device ausgewertet werden um bei Eintreten eines definierten Ereignisses entsprechende Reaktionen auszulösen. Das kann zum Beispiel die Freigabe eines Heizstabes oberhalb eines bestimmten SOC sein oder ein Entladeverbot der Batterie unterhalb eines SOC-Wertes um Reserven für einen eventuellen Stromausfall zu behalten.&lt;br /&gt;
&lt;br /&gt;
Damit die Batterietrigger dynamisch geändert werden können, ist die Einstellung als Set-Kommando und nicht als Attribut ausgeführt.   &lt;br /&gt;
&lt;br /&gt;
Alle Triggerpunkte können mit dem set-Befehl:&lt;br /&gt;
&lt;br /&gt;
 reset batteryTriggerSet&lt;br /&gt;
&lt;br /&gt;
wieder gelöscht werden.&lt;br /&gt;
&lt;br /&gt;
== Verbrauchersteuerung - Registrieren und visualisieren 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;
Die Eigenschaften und das Schaltverhalten wird durch die Angabe der verfügbaren Schlüssel gesteuert. Die Möglichkeiten sind sehr umfangreich. Die nachfolgenden Abschnitte beschreiben die Verwendung am Beispiel oft vorkommender bzw. nachgefragter Sachverhalte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die Phasen der Verbrauchersteuerung ===&lt;br /&gt;
&lt;br /&gt;
Jeder Zyklus eines Verbrauchers durchläuft im Modul die folgenden Phasen:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Planung&#039;&#039;&#039; der Aktivzeiten des Verbrauchers, d.h. wann der Verbraucher geplant eingeschaltet sowie geplant ausgeschaltet wird und damit der Zyklus beendet wird.&lt;br /&gt;
# &#039;&#039;&#039;Start&#039;&#039;&#039; des Zyklus, d.h. Einschalten des Verbrauchers entsprechend der Planungsdaten sofern weitere, in den Consumer-Schlüsseln definierbare Rahmenbedingungen das Einschalten nicht verhindern (z.B. kein oder zu wenig PV-Energieerzeugung / PV-Überschuss)&lt;br /&gt;
# &#039;&#039;&#039;Permanente Überprüfung von&#039;&#039;&#039; eventuell vorhandenen &#039;&#039;&#039;Interruptbedingungen&#039;&#039;&#039; die den Verbraucher temporär ausschalten und, sofern die Interruptbedingung nicht mehr vorliegt, den Verbraucher wieder einschalten und so den gestarteten Zyklus fortsetzen.&lt;br /&gt;
#  &#039;&#039;&#039;Beendigung&#039;&#039;&#039; der Zyklus. Die Beendigung erfolgt entweder (normalerweise) wenn die geplante Endezeit der Zyklus erreicht ist oder eine optionale Endebedingung erfüllt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Steuerung der Phasen ====&lt;br /&gt;
Der Ablauf der Phasen kann durch verschiedene Schlüssel-Wert Paare beeinflusst und gesteuert werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; kann eine &#039;&#039;&#039;zusätzliche externe Bedingung&#039;&#039;&#039; definiert werden um den Einschaltvorgang des Consumers freizugeben. Ist die Bedingung (Regex) nicht erfüllt, erfolgt kein Einschalten des Verbrauchers auch wenn die sonstigen Voraussetzungen wie Zeitplanung, on-Schlüssel, auto-Mode und aktuelle PV-Leistung gegeben sind. Es erfolgt somit eine &#039;&#039;&#039;UND-Verknüpfung&#039;&#039;&#039; des Schlüssels swoncond mit den Planungsdaten und weiteren Einschaltbedingungen.&lt;br /&gt;
&lt;br /&gt;
Der optionale Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; definiert eine &#039;&#039;&#039;vorrangige Ausschaltbedingung&#039;&#039;&#039; (Regex). Sobald diese Bedingung erfüllt ist, wird der Consumer ausgeschaltet auch wenn die geplante Endezeit (consumerXX_planned_stop) noch nicht erreicht ist (&#039;&#039;&#039;ODER-Verknüpfung&#039;&#039;&#039;). Weitere Bedingungen wie off-Schlüssel und auto-Mode müssen zum automatischen Ausschalten erfüllt sein.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; kann während der geplanten Einschaltzeit eine automatische Unterbrechung sowie Wiedereinschaltung des Verbrauchers vorgenommen werden. Der Verbraucher wird temporär ausgeschaltet (interrupted) und wieder eingeschaltet (continued) wenn die Interrupt-Bedingung nicht mehr vorliegt. Die verbleibende Laufzeit wird durch einen Interrupt nicht beeinflusst! &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;power&#039;&#039;&#039; gibt die nominale Leistungsaufnahme des Verbrauchers gemäß seines Datenblattes an. Dieser Wert wird verwendet um die Schaltzeiten des Verbrauchers zu planen und das Schalten in Abhängigkeit des tatsächlichen PV-Überschusses zum Einplanungszeitpunkt zu steuern. Ist &#039;&#039;&#039;power=0&#039;&#039;&#039; gesetzt, wird der Verbraucher unabhängig von einem zum Zeitpunkt des Zyklus-Start eventuell nicht ausreichend vorhandenem PV-Überschuss wie geplant eingeschaltet und somit der Zyklus gestartet.&lt;br /&gt;
&lt;br /&gt;
Durch die Schlüssel &#039;&#039;&#039;notbefore&#039;&#039;&#039; und &#039;&#039;&#039;notafter&#039;&#039;&#039; kann der Startzeitpunkt des Verbrauchers so gesteuert werden, dass der Start des Zyklus nicht vor bzw. nach der angegebenen Zeit eingeplant wird. Diese Steuerung bezieht sich auf die &#039;&#039;Planung&#039;&#039;, d.h. der eigentliche Start des Verbrauchers kann sich unter Umständen durch vorhandene Rahmenbedingungen verzögern. &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; legt die geplanten Einschaltzeit, d.h. die Laufzeit des Zyklus fest. Der Name &#039;&#039;&#039;mintime&#039;&#039;&#039; ist nicht als MInimum-Zeit zu deuten, sondern beschreibt die angegebene Zeit in Minuten die der Zyklus dauern soll.&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist optional, da sich die Standard-Laufzeit des Verbrauchers von dessen Typ abgeleitet wird. Diese Standard Laufzeiten sind:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|dryer&lt;br /&gt;
|90 Minten&lt;br /&gt;
|-&lt;br /&gt;
|dishwasher&lt;br /&gt;
|180 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|washingmachine&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|heater&lt;br /&gt;
|240 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|charger&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|other&lt;br /&gt;
|60 Minuten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Der Verbraucher wurde nicht gestartet obwohl die Startzeit der Einplanung erreicht wurde ===&lt;br /&gt;
&lt;br /&gt;
Wenn die Startzeit des Consumers entsprechend der Einplanung erreicht oder überschritten ist, wird der Consumer eingeschaltet wenn die weiteren Voraussetzungen wahr sind:&lt;br /&gt;
&lt;br /&gt;
* es ist aktuell ein PV-Überschuss vorhanden und der PV-Überschuss deckt die kalkulierten Leistungsaufnahme des Verbrauchers ab. Mit den Schlüsseln &#039;&#039;&#039;power&#039;&#039;&#039; und &#039;&#039;&#039;spignorecond&#039;&#039;&#039; kann die Einschaltung trotz fehlendem PV-Überschuss ermöglicht werden. &lt;br /&gt;
&lt;br /&gt;
* die Angabe im Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; ist wahr (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* das Schalten ist über den Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; freigegeben (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* im Schlüssel &#039;&#039;&#039;on&#039;&#039;&#039; ist ein valides Einschaltkommando hinterlegt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind diese zusätzlichen Bedingungen nicht erfüllt, erfolgt kein Start des eingeplanten Zyklus. Der Verbraucher verbleibt in diesem Fall weiterhin im Status &#039;&#039;planned&#039;&#039; oder &#039;&#039;suspended&#039;&#039;. Die Startbedingungen werden regelmäßig reviewed und der Consumer gestartet sobald alle Startbedingungen wahr sind bzw. Start verhindernde Bedingungen entfallen sind. &lt;br /&gt;
&lt;br /&gt;
Dieser Vorgang erfolgt bis das geplante Ende des Verbaucherzyklus erreicht ist oder die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; zutrifft. Sobald die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; wahr ist, wird der gesamte Planungszyklus des Consumers beendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Kann manuell / automatisiert in den Planungszyklus eines Verbrauchers eingegriffen werden? ===&lt;br /&gt;
&lt;br /&gt;
Die Einplanung und die darauf aufbauenden Schaltprozesse laufen gemäß den hinterlegten Schlüsseloptionen im Modul automatatisch ab ohne dass ein Eingriff durch den Anwender erfolgen muß.&lt;br /&gt;
&lt;br /&gt;
Dennoch kann es gewünscht sein eine Neuplanung oder eine Sofortplanung eines Consumers vorzunehmen weil der Bedarf dazu besteht. Zu diesem Zweck stehen die Set-Kommandos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* consumerNewPlanning &lt;br /&gt;
&lt;br /&gt;
* consumerImmediatePlanning &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
zur Verfügung. &lt;br /&gt;
Beide Befehle initiieren die Consumer-Neuplanung, wobei mit dem Befehl &#039;&#039;consumerImmediatePlanning&#039;&#039; die eventuell im consumerXX Attribut gesetzten Schlüssel notbefore, notafter bzw. mode werden nicht beachtet werden. Dagenen beachtet der Befehl &#039;&#039;consumerNewPlanning&#039;&#039; alle definierten Schlüsseloptionen und dient gewöhnlich dazu einen abgeschlossenen Verbraucherzyklus wiederholt ausführen zu lassen weil die aktuelle Witterungslage dazu geeignet ist. &lt;br /&gt;
&lt;br /&gt;
Ein Anwendungsbeispiel dafür ist zum Beispiel die Ausführung von mehreren Waschmaschinen-Zyklen an einem langen, sonnigen Sommertag.&lt;br /&gt;
Diese beiden Set-Befehle können zum Beispiel über ein auf einen Schalter/Taster reagierendes Notify oder DOIF Device ausgeführt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung eines Verbrauchers mit getrennten Geräten für Messung und Schalten ===&lt;br /&gt;
&lt;br /&gt;
Es existieren in FHEM Geräte, die über verschiedene Kanäle für unterschiedliche Aufgaben verfügen. Diese Kanäle werden jeweils in einem gesonderten Device abgebildet. HomeMatic oder readingsProxy sind Beispiele für solche Varianten.&lt;br /&gt;
&lt;br /&gt;
Um solche Verbraucher einzubinden gibt es im consumerXX Attribut den Schlüssel &#039;&#039;&#039;switchdev&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Bei der Registrierung gibt man als Consumerdevice das Gerät für die Messung an und im Schüssel switchdev das entsprechende FHEM-Device, welches für die Schaltvorgänge benutzt wird. &lt;br /&gt;
Ist switchdev angegeben, beziehen sich die weiteren Schlüssel on, off, swstate, auto und asynchron auf dieses Gerät.&lt;br /&gt;
&lt;br /&gt;
In dem nachfolgenden Beispiel (Homematic) ist &#039;&#039;eg.az.fridge_Pwr&#039;&#039; FHEM Device für die Energiemessung. Die Schlüssel &#039;&#039;pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; geben Readings in diesem Device an damit SolarForecast den Verbrauch und die Energiemengen auslesen kann. Demgegenüber ist im Schlüssel &#039;&#039;switchdev&#039;&#039; das zugehörige Schalter-Device der Kombination angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eg.az.fridge_Pwr&lt;br /&gt;
type=noSchedule switchdev=eg.az.fridge_Sw power=0 icon=fridge pcurr=power:W:5 etotal=energyCalc:Wh &lt;br /&gt;
swstate=state:on:off auto=automatic&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung von Verbrauchern ohne Zeitplanung und aktivem Schalten ===&lt;br /&gt;
Manchmal besteht der Wunsch, Verbraucher in SolarForecast zu integrieren um lediglich folgende Sachverhalte abzubilden:&lt;br /&gt;
&lt;br /&gt;
* Visualisierung des Schaltstatus in der Consumer Legende und/oder der Energieflußgrafik&lt;br /&gt;
* Darstellung des aktuellen Energieverbrauchs in der Energieflußgrafik&lt;br /&gt;
* Erfassung der (externen) Schaltzeiten, d.h. der Zeiten der Gerätenutzung sowie der Verbrauchsdaten um deren Einfluß bei den Planungszeiten anderer Geräte durch SolarForecast berücksichtigen zu lassen&lt;br /&gt;
&lt;br /&gt;
In solchen Fällen werden bei der Registrierung die Schlüssel &#039;&#039;swstate, pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; zur Erfassung der Schaltzustände und der Energieverbrauchs angegeben, jedoch zur Verhinderung der Zeitplanung durch SolarForecast der Schlüssel &#039;&#039;&#039;type=noSchedule&#039;&#039;&#039; gesetzt sowie die Schlüssel &#039;&#039;on&#039;&#039; und &#039;&#039;off&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt eine mögliche Registrierung eines Zwischensteckers (Shelly) zur Erfassung der Daten eines Gefrierschrankes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Shelly.shellyplug4&lt;br /&gt;
type=noSchedule power=65 asynchron=1&lt;br /&gt;
icon=gefrierschrank &lt;br /&gt;
swstate=state:.*on.*:.*off.* &lt;br /&gt;
pcurr=relay_0_power:W:5 etotal=relay_0_energy_Wh:Wh&lt;br /&gt;
&amp;lt;/pre&amp;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;
&lt;br /&gt;
 Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off&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;
&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;
&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. Alternativ kann die Berücksichtigung des zwangsweisen PV Überschuss mit dem Schlüssel &amp;quot;spignorecond&amp;quot; im Consumer-Attribut ausgesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== zusätzliche Readings bzw. Erzeugung von statistischen Readings ==&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den zahlreichen im Modul per Standard erzeugten Readings kann der Anwender weitere Readings generieren lassen.&lt;br /&gt;
Diese zusätzlichen Readings geben entweder einen bestimmten Sachverhalt (Laufzeit, Status der API-Abfragen, etc.) oder einen statistischen Wert, z.B. die Batterieentladung des aktuellen Tages, wieder.&lt;br /&gt;
&lt;br /&gt;
Die zusätzlich erstellten Readings sind durch den Präfix &#039;&#039;&#039;special_&#039;&#039;&#039; im Device gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Diese zusätzlichen Informationen können durch das Setzen einer oder mehrerer Kennzeichen im Attribut &#039;&#039;&#039;ctrlSpecialReadings&#039;&#039;&#039; erzeugt werden. Die mögliche Auswahl wird je nach Bedarf ausgebaut und umfasst zum aktuellen Zeitpunkt (07.02.2025) diese Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;BatPowerIn_Sum: 	die Summe der momentanen Batterieladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;BatPowerOut_Sum: 	die Summe der momentanen Batterieentladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;allStringsFullfilled: 	Erfüllungsstatus der fehlerfreien Generierung aller Strings&lt;br /&gt;
;conForecastTillNextSunrise: 	Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
;currentAPIinterval: 	das aktuelle Abrufintervall der gewählten Strahlungsdaten-API in Sekunden&lt;br /&gt;
;currentRunMtsConsumer_XX: 	die Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; seit dem letzten Einschalten. (letzter Laufzyklus)&lt;br /&gt;
;dayAfterTomorrowPVforecast: 	liefert die Vorhersage der PV Erzeugung für Übermorgen (sofern verfügbar) ohne Autokorrektur (Rohdaten).&lt;br /&gt;
;daysUntilBatteryCare_XX: 	Tage bis zur nächsten Batterie XX Pflege (Erreichen der Ladung &#039;maxSoC&#039; aus Attribut ctrlBatSocManagementXX)&lt;br /&gt;
;lastretrieval_time: 	der letzte Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;lastretrieval_timestamp: 	der Timestamp der letzen Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;response_message: 	die letzte Statusmeldung der gewählten Strahlungsdaten-API&lt;br /&gt;
;runTimeAvgDayConsumer_XX: 	die durchschnittliche Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; an einem Tag&lt;br /&gt;
;runTimeCentralTask: 	die Laufzeit des letzten SolarForecast Intervalls (Gesamtprozess) in Sekunden&lt;br /&gt;
;runTimeTrainAI: 	die Laufzeit des letzten KI Trainingszyklus in Sekunden&lt;br /&gt;
;runTimeLastAPIAnswer: 	die letzte Antwortzeit des Strahlungsdaten-API Abrufs auf einen Request in Sekunden&lt;br /&gt;
;runTimeLastAPIProc: 	die letzte Prozesszeit zur Verarbeitung der empfangenen Strahlungsdaten-API Daten&lt;br /&gt;
;SunMinutes_Remain: 	die verbleibenden Minuten bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;SunHours_Remain: 	die verbleibenden Stunden bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;todayConsumptionForecast: 	Verbrauchsprognose pro Stunde des aktuellen Tages (01-24)&lt;br /&gt;
;todayConForecastTillSunset: 	Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
;todayDoneAPIcalls: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Calls&lt;br /&gt;
;todayDoneAPIrequests: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Requests&lt;br /&gt;
;todayConsumption: 	der gesamte Energieverbrauch (Wh) des Hauses am aktuellen Tag&lt;br /&gt;
;todayGridConsumption: 	die aus dem öffentlichen Netz bezogene Energie am aktuellen Tag&lt;br /&gt;
;todayGridFeedIn: 	die in das öffentliche Netz eingespeiste PV Energie am aktuellen Tag&lt;br /&gt;
;todayMaxAPIcalls: 	die maximal mögliche Anzahl Strahlungsdaten-API Calls. Ein Call kann mehrere API Requests enthalten.&lt;br /&gt;
;todayRemainingAPIcalls: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Calls&lt;br /&gt;
;todayRemainingAPIrequests: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Requests&lt;br /&gt;
;todayBatIn_XX: 	die am aktuellen Tag in die Batterie XX geladene Energie&lt;br /&gt;
;todayBatInSum: 	Summe der am aktuellen Tag in alle Batterien geladene Energie&lt;br /&gt;
;todayBatOut_XX: 	die am aktuellen Tag aus der Batterie XX entnommene Energie&lt;br /&gt;
;todayBatOutSum: 	Summe der am aktuellen Tag aus allen Batterien entnommene Energie&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Manche Angaben sind im Setup des Moduls optional, d.h. sie müssen nicht zwingend beim Setup angegeben werden. Allerdings sind diese Angaben für die Erstellung eines zusätzlichen Readings unter Umständen Voraussetzung. Es empfiehlt sich deshalb bei Setup so viele Informationen wie möglich zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
So ist zum Beispiel für die sinnvolle Erstellung der Informationen &#039;&#039;&#039;todayBatInSum&#039;&#039;&#039; und &#039;&#039;&#039;todayBatOutSum&#039;&#039;&#039; (Readings special_todayBatInSum und special_todayBatOutSum) das Vorhandensein der Schlüssel &#039;&#039;intotal&#039;&#039; und &#039;&#039;outtotal&#039;&#039; im Attribut setupBatteryDevXX notwendig (Beispiel):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupBatteryDev01 MQTT2_cerboGX_c0619ab34e08_battery &lt;br /&gt;
                              pin=BatIn:W pout=BatOut:W charge=SOC_value intotal=BatInTotal:Wh outtotal=BatOutTotal:Wh &lt;br /&gt;
                              cap=InstalledCapacity_Wh:Wh asynchron=1 show=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Fehlersuche ==&lt;br /&gt;
Das Modul SolarForecast ist sehr komplex und es die verschiedensten Datenquellen ausgewertet, zusammengeführt und daraus Ergebnisse berechnet und/oder visualisiert. Wird etwas nicht wie erwartet durch das Modul geliefert, können die Ursachen vielfältig sein. Natürlich kann ein Fehler im Modulcode vorliegen, oftmals gibt es aber andere Ursachen.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgenden Hinweise sollen Hilfe zur Selbsthilfe geben und sind eine Zusammenfassung von realen Fällen die mit dem beschriebenen Wegen und Verfahren gelöst wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die erwartete erzeugte PV-Energie ist im Modul zu gering und wird im Balkendiagramm nicht angezeigt === &lt;br /&gt;
&lt;br /&gt;
Die erzeugte PV-Energie wird nicht richtig angezeigt: Am Vormittag sind keine Werte vorhanden und, wenn dann etwas kommt, ist die Anzeige zu gering. Für 13 und 14 Uhr wurden ca. 5.000Wh erwartet (im Vergleich mit den Daten aus einer anderen Auswertungsquelle). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lösungsweg:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Aus dem List des Devices wurden die für den Fall wesentlichen Readings herausgezogen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVforecast 152 Wh&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVforecast 1400 Wh&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVforecast 2500 Wh&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVforecast 4392 Wh&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVforecast 4000 Wh&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVreal 300 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVforecast 6415 Wh&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVreal 3200 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVforecast 5629 Wh&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVreal 2700 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVforecast 3958 Wh&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVreal 900 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVforecast 945 Wh&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVreal 500 Wh&lt;br /&gt;
   &lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour18_PVforecast 59 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man sieht dass bis 12:00 keine erzeugte Energie vom WR gemeldet wird. Deswegen wird in der Balkengrafik nichts dargestellt. Auch danach bleibt die registrierte PV-Energie hinter den Erwartungen zurück. Zuständig für die Lieferung der PV-Energie an das Modul ist das Reading im Schlüssel:&lt;br /&gt;
&lt;br /&gt;
 setupInverterDev01 SH10rt pv=Total_DC_Power:W &amp;lt;mark&amp;gt;etotal=Total_Export_Energy_from_PV:kWh&amp;lt;/mark&amp;gt; capacity=10000 strings=Hauptdach,Flachdach&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Welche Änderungen es zwischen den Stunden gab, sieht man mit einem &amp;quot;get ... pvHistory XX&amp;quot; (&amp;quot;XX&amp;quot; steht für das Datum, d.h. den Tag, z.B. 02). &amp;lt;br&amp;gt;&lt;br /&gt;
Hier ein Beispiel für die Stunden 10 (9:00 - 9:59) und 11 (10:00 - 10:59). &amp;lt;br&amp;gt;&lt;br /&gt;
Wichtig ist hier der Key etotali01 für den ersten Inverter. Die Differenz zwischen den Werten beider Stunden ist die in der Stunde erzeugte Energie (hier 380 Wh). Diese 380 Wh findest du auch im Key pvrl01 als PVReal für diese Stunde. Das Modul rechnet intern immer mit Wh, kWh werden vorher in Wh umgerechnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
10 =&amp;gt; pvfc: 365, pvrl: 530, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63364714&amp;lt;/mark&amp;gt;, etotali02: 3044110, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;pvrl01: 380&amp;lt;/mark&amp;gt;, pvrl02: 150, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 574, con: 518, gcons: 22, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 1, feedprice: 0.1269&lt;br /&gt;
&lt;br /&gt;
            DoN: 1, sunaz: 137, sunalt: 12&lt;br /&gt;
&lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
      11 =&amp;gt; pvfc: 2966, pvrl: 1862, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63365094&amp;lt;/mark&amp;gt;, etotali02: 3044260, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            pvrl01: 1392, pvrl02: 470, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 774, con: 609, gcons: 25, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 4, feedprice: 0.1269&lt;br /&gt;
           &lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
D.h. wenn zwischen den beiden Stunden keine Differenzen zu finden sind, liegt es sehr wahrscheinlich am Input des Readings:&lt;br /&gt;
&lt;br /&gt;
 etotal=Total_Export_Energy_from_PV:kWh&lt;br /&gt;
&lt;br /&gt;
welches sich in den ersten Stunden nicht ändert und danach auch nur wenig.&lt;br /&gt;
&lt;br /&gt;
Man kann mit dem Attribut:&lt;br /&gt;
&lt;br /&gt;
 ctrlDebug=collectData&lt;br /&gt;
&lt;br /&gt;
die Datensammlung verfolgen (leider entstehen viele Daten im Log). Man sieht welche Werte von dem Inverter/Reading geliefert werden:&lt;br /&gt;
 &lt;br /&gt;
 ....&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; collect Inverter 01 data - device: STP_5000, delivery: default =&amp;gt;&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; pv: 0 W, &amp;lt;mark&amp;gt;etotal: 63378810 Wh&amp;lt;/mark&amp;gt;&lt;br /&gt;
 ....&lt;br /&gt;
&lt;br /&gt;
Dieser Wert muß bei PV Erzeugung kontinuierlich hochzählen. Wenn nicht, muss das angegebene Reading, d.h. die Quelle überprüft werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ergebnis der Prüfung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tatsächlich wurde ein Reading benutzt, das ungeeignet war: Statt &amp;quot;Total_PV_Generation&amp;quot; wurde &amp;quot;Total_export_energy_from_PV&amp;quot; genutzt. In diesem Reading wurde immer die in die Batterie gespeicherte Energie von der gesamten erzeugten Energie abgezogen. Daher war auch vormittags alles 0, da in dieser Periode alle PV-Energie in die Batterie geladen wurde bzw. in weiteren Stunden ein Anteil der dann bei dem PV-Erzeugungswert fehlte.&lt;br /&gt;
&lt;br /&gt;
Nachdem die Ursache beseitigt war, zeigt SolarForecast wieder die erwarteten PV-Erzeugungswerte an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Konfigurationsbeispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Visualisierung solare Vorhersage und reale Erzeugung ===&lt;br /&gt;
&lt;br /&gt;
Zu Beginn jedes neuen Tages gegen 00:00 Uhr werden durch das SolarForecast Device Events für die initiale PV Prognose des kommenden Tages erstellt.&lt;br /&gt;
Der Readingteil dieser Events heißt&lt;br /&gt;
&lt;br /&gt;
 AllPVforecastsToEvent&lt;br /&gt;
&lt;br /&gt;
Die Uhrzeiten der Events sind so aufbereitet und können direkt geloggt werden um sie in einen SVG Plot zu integrieren.&lt;br /&gt;
Im SolarForecast Device ist dieses Reading nicht sichtbar, nur die Events werden erstellt.&lt;br /&gt;
&lt;br /&gt;
Die meteorologischen Bedingungen verändern sich über den Tag permanent. Je nach gewählter Strahlungsdatenquelle (eine API oder DWD Device) erfolgt eine mehr oder weniger dynamische Anpassung der Prognose an die sich verändernde Umwelt.&lt;br /&gt;
&lt;br /&gt;
Aktuelle Prognosedaten sowie die reale PV Erzeugung der vergangenen Stunde können über die Readings&lt;br /&gt;
&lt;br /&gt;
 LastHourPVforecast&lt;br /&gt;
 LastHourPVreal&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-10-20 134050.png|right|thumb|400px|Übersicht solare Vorhersage]]&lt;br /&gt;
geloggt werden. &lt;br /&gt;
&lt;br /&gt;
Werden alle drei Werte in einem SVG kombiniert, kann die Entwicklung der Prognose über den Tag und die Beziehung von Prognose zu realer PV Erzeugnung pro Stunde visualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Für das rechts abgebildete Beispiel des Plots aus einer Datenbank &amp;quot;LogDBShort&amp;quot; sieht das gplot-File wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Created by FHEM/98_SVG.pm, 2024-03-08 15:05:31&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;TL&amp;gt;&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid&lt;br /&gt;
set ylabel &amp;quot;Wh&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Wh&amp;quot;&lt;br /&gt;
set yrange [0:7500]&lt;br /&gt;
set y2range [0:7500]&lt;br /&gt;
&lt;br /&gt;
#LogDBShort SolCast:LastHourPVforecast:::&lt;br /&gt;
#LogDBShort SolCast:LastHourPVreal:::&lt;br /&gt;
#LogDBShort SolCast:AllPVforecastsToEvent:::&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;aktuelle PV Vorhersage&#039; ls l6fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;reale PV Erzeugung&#039; ls l2fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;initiale PV Vorhersage&#039; ls l4 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; In manchen Fällen werden die Vorhersagewerte im SVG-Plot nicht angezeigt wenn FileLog verwendet wird. Ein Setzen des Attribute &amp;quot;fixedrange=3days +1&amp;quot; im SVG löst das Problem. Die Definition des SVG-Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_LogDBShort_SolCast SVG LogDBShort:SVG_LogDBShort_SolCast:HISTORY&lt;br /&gt;
attr SVG_LogDBShort_SolCast fixedrange 3days +1&lt;br /&gt;
attr SVG_LogDBShort_SolCast room Energie-&amp;gt;SolarPrognose&lt;br /&gt;
attr SVG_LogDBShort_SolCast sortby 2&lt;br /&gt;
attr SVG_LogDBShort_SolCast title &amp;quot;Übersicht solare Vorhersage&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Technisch bedingt werden an einem Tag X kurz nach 00:00 Uhr die am Vortag für den Tag X erzeugten Events aktualisiert. Diese Daten erzeugen in der Datenbank einen zweiten Satz an Daten mit dem gleichen Timestamp was für die Anzeige unvorteilhaft ist. &lt;br /&gt;
Um nur die aktualisierten Events von &#039;&#039;&#039;AllPVforecastsToEvent&#039;&#039;&#039; in der Datenbank zu erhalten, bietet sich ein DbRep-Device an. Die nachfolgende Vorschlagsdefinition kann per at-Device jeden Tag kurz vor Mitternacht (z.B. 23:57:10) ausgeführt werden. Es werden immer die in der Vergangenheit geschriebenen (veralteten) Daten aus der Datenbank gelöscht, doppelte Datesätze vermieden und immer die aktuellste initiale Prognose gespeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.Del.AllPVforecastsToEvent DbRep LogDBShort&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent alias Löschen Readings AllPVforecastsToEvent des Folgetages&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent comment ermöglicht dass die Readings AllPVforecastsToEvent am Folgetag wieder neu und aktuell geschrieben werden können&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent devStateIcon initialized:control_3dot_hor_s connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent disable 0&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent event-on-update-reading state&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent icon edit_delete&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent showproctime 1&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent device TYPE=SolarForecast&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_begin next_day_begin&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_end next_day_end&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das angegebene DbLog-Device &#039;&#039;&#039;LogDBShort&#039;&#039;&#039; ist natürlich anzupassen.&lt;br /&gt;
&lt;br /&gt;
Das at-Device zum Starten der Datenbankbereinigung sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define At.Del.AllPVforecastsToEvent at *23:58:10 set Rep.Del.AllPVforecastsToEvent delEntries&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent alias Start Löschen Readings AllPVforecastsToEventn LogDBShort&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent icon clock&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich sind auch hier die eigenen Devicenamen entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
Ab SolarForecast Version 1.51.7 kann die Eventerzeugung für bestimmte SVG Plot-Typen optimiert werden. &amp;lt;br&amp;gt; &lt;br /&gt;
Die Aktivierung dieser Optimierungen ist in der Online Hilfe zum Attribut &#039;&#039;&#039;plantControl-&amp;gt;genPVforecastsToEvent&#039;&#039;&#039; beschrieben. Bei Nutzung des Attributes plantControl-&amp;gt;genPVforecastsToEvent ist ebenfalls das Attribut &#039;&#039;&#039;event-on-update-reading=AllPVforecastsToEvent&#039;&#039;&#039; zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispielkonfiguration 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;
Bitte dabei diese DWD-Version aus dem [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter Contrib] von DS_Starter dazu nutzen&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|55_DWD_OpenData.pm&lt;br /&gt;
|136.2 KB ​&lt;br /&gt;
|29260  &lt;br /&gt;
|DS_Starter&lt;br /&gt;
|55_DWD_OpenData: contrib 1.17.7&lt;br /&gt;
|}&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 downloadTimeout 120&lt;br /&gt;
attr DWD comment Im DWD Wetterdevice verwendet Solarforecast : \&lt;br /&gt;
TTT,Neff,RR1c,ww,SunUp,SunRise,SunSet \&lt;br /&gt;
zusätzlich ist jedoch auch noch Rad1h notwendig \&lt;br /&gt;
wenn dieses DWD-Device als Strahlungsdevice genutzt wird.\&lt;br /&gt;
Die Station 10418 (Lüdenscheid) überträgt aktuell am 09.03.2025 (noch) Rad1h.\&lt;br /&gt;
attr DWD downloadTimeout 120&lt;br /&gt;
attr DWD forecastDays 7&lt;br /&gt;
attr DWD forecastProperties SunUp, SunRise, SunSet, Rad1h, R101, RR1c, TTT, Tx, Tn, Tg, DD, FX1, RR6c, R600, RRhc, Rh00, ww, wwd, Neff&lt;br /&gt;
attr DWD forecastRefresh 1&lt;br /&gt;
attr DWD forecastResolution 1&lt;br /&gt;
attr DWD forecastStation 10418&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 fc_description  -(state fc_time)&lt;br /&gt;
attr DWD verbose 2&lt;br /&gt;
&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;
defmod InverterDummy dummy&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;
defmod 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 feedinPrice 0.08&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 powerCost 0.25&lt;br /&gt;
attr SMA_Energymeter room 015_Zaehler,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;
defmod 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;
attr BatteryDummy userReadings total_pac, power_out, power_in, chargestatus, bat_rated_capacity, bat_loadtotal, bat_unloadtotal&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;
defmod N.PV.TotalConsumption.Dum.Energy notify SMA_Energymeter:Saldo_Wirkleistung:.* {\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung_2 Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&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;MB_USRW610_004&amp;quot;,&amp;quot;Power_Sum__W&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;
fhem &amp;quot;setreading InverterDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(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;
#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;
 # Batterie-total_pac  InverterDummy\&lt;br /&gt;
my $wert7 = sprintf(&amp;quot;%.3f&amp;quot;,((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy bat_rated_capacity &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert7));;\&lt;br /&gt;
 # möglicher Aufruf einer Batterie-Bebladung-Routine....SMABatteryChargewithTibber();;\&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;
defmod Forecast SolarForecast&lt;br /&gt;
attr Forecast DbLogExclude .*&lt;br /&gt;
attr Forecast DbLogInclude Current_BatCharge999&lt;br /&gt;
attr Forecast affectBatteryPreferredCharge 30&lt;br /&gt;
attr Forecast affectConsForecastLastDays 31&lt;br /&gt;
attr Forecast affect70percentRule 0&lt;br /&gt;
attr Forecast comment &amp;quot;wget -qO ./FHEM/76_SolarForecast.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/76_SolarForecast.pm&amp;quot;\&lt;br /&gt;
&amp;quot;wget -qO ./FHEM/55_DWD_OpenData.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/55_DWD_OpenData.pm&amp;quot;\&lt;br /&gt;
&amp;quot;13.01.2025 mit der Version 76_SolarForecast.pm:v1.43.2-s29518/2025-01-12&amp;quot;&lt;br /&gt;
attr Forecast graphicHeaderOwnspec PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal Verbrauch&amp;amp;nbsp;;bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast  Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest FCU-Erzeugung&amp;amp;nbsp;;:Current_PP01\&lt;br /&gt;
attr Forecast consumer01 FBDECT_fbahahttp_11657_0127183 icon=scene_washing_machine@orange type=washingmachine power=10 swstate:state notbefore=09 notafter=20 pcurr=power:W:3 etotal=energy:Wh interruptable=1 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer02 FBDECT_fbahahttp_E8_DF_70_07_3E_57 icon=light_floor_lamp@orange type=other power=15 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer03 FBDECT_fbahahttp_E8_DF_70_07_42_0B icon=raspberrypi@orange type=other power=8 swstate:state pcurr=power:W:1 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer04 FBDECT_fbahahttp_11657_0067275 icon=springbrunnen_icon@orange type=other power=50 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer05 FBDECT_fbahahttp_34_31_C4_D4_31_37 icon=sani_domestic_waterworks@orange type=other power=10 swstate:state pcurr=power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer06 tuya_local_bf5037060f450bdbd4rl0q icon=scene_clothes_dryer@orange type=dryer power=10 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer07 tuya_local_bfac44fb487476efd1vhdu icon=weather_sunset@orange type=noSchedule power=5 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumerControl adviceIcon=light_light_dim_100@gold&lt;br /&gt;
attr Forecast consumerControl showLegend=icon_top&lt;br /&gt;
attr Forecast consumerControl detailLink=1&lt;br /&gt;
attr Forecast ctrlAIdataStorageDuration 1825&lt;br /&gt;
attr Forecast ctrlAIshiftTrainStart 2&lt;br /&gt;
attr Forecast ctrlBatSocManagement01 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlBatSocManagement02 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlDebug none&lt;br /&gt;
attr Forecast plantControl genPVdeviation=continuously&lt;br /&gt;
attr Forecast plantControl cycleInterval=15&lt;br /&gt;
attr Forecast ctrlNextDayForecastReadings 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24&lt;br /&gt;
attr Forecast ctrlNextHoursSoCForecastReadings 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23&lt;br /&gt;
attr Forecast ctrlSpecialReadings BatPowerIn_Sum,BatPowerOut_Sum,SunHours_Remain,SunMinutes_Remain,allStringsFullfilled,conForecastTillNextSunrise,currentAPIinterval,currentRunMtsConsumer_01,currentRunMtsConsumer_02,currentRunMtsConsumer_03,currentRunMtsConsumer_04,currentRunMtsConsumer_05,currentRunMtsConsumer_06,currentRunMtsConsumer_07,dayAfterTomorrowPVforecast,daysUntilBatteryCare_01,daysUntilBatteryCare_02,lastretrieval_time,lastretrieval_timestamp,response_message,runTimeAvgDayConsumer_01,runTimeAvgDayConsumer_02,runTimeAvgDayConsumer_03,runTimeAvgDayConsumer_04,runTimeAvgDayConsumer_05,runTimeAvgDayConsumer_06,runTimeAvgDayConsumer_07,runTimeCentralTask,runTimeLastAPIAnswer,runTimeLastAPIProc,runTimeTrainAI,todayBatIn_01,todayBatIn_02,todayBatOut_01,todayBatOut_02,todayConForecastTillSunset,todayConsumptionForecast,todayDoneAPIcalls,todayDoneAPIrequests,todayGridConsumption,todayGridFeedIn,todayMaxAPIcalls,todayRemainingAPIcalls,todayRemainingAPIrequests&lt;br /&gt;
attr Forecast disable 0&lt;br /&gt;
attr Forecast event-min-interval .*:1800&lt;br /&gt;
attr Forecast event-on-change-reading .*&lt;br /&gt;
attr Forecast flowGraphicControl animate=1 consumerdist=80 h2consumerdist=50 shiftx=0  shifty=0 showconsumer=1 showconsumerdummy=1 showconsumerpower=1 showconsumerremaintime=0 size=400 strokewidth=12&lt;br /&gt;
attr Forecast graphicBeam1Color 3C14FF&lt;br /&gt;
attr Forecast graphicBeam1Content pvReal&lt;br /&gt;
attr Forecast graphicBeam2Color 19FF29&lt;br /&gt;
attr Forecast graphicBeam2Content pvForecast&lt;br /&gt;
attr Forecast graphicBeam3Color D60924&lt;br /&gt;
attr Forecast graphicBeam3Content batsocforecast_02&lt;br /&gt;
attr Forecast graphicBeam3FontColor FFFF0D&lt;br /&gt;
attr Forecast graphicBeam4Color FFFF1F&lt;br /&gt;
attr Forecast graphicBeam4Content batsocforecast_01&lt;br /&gt;
attr Forecast graphicBeam4FontColor 000000&lt;br /&gt;
attr Forecast graphicBeamHeightLevel1 200&lt;br /&gt;
attr Forecast graphicBeamHeightLevel2 200&lt;br /&gt;
attr Forecast graphicHeaderDetail all&lt;br /&gt;
attr Forecast graphicHeaderOwnspec #PV\&lt;br /&gt;
PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal\&lt;br /&gt;
PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast\&lt;br /&gt;
PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast\&lt;br /&gt;
:\&lt;br /&gt;
#\&lt;br /&gt;
AutarkyRate:Current_AutarkyRate\&lt;br /&gt;
Überschuss:Current_Surplus\&lt;br /&gt;
aktueller&amp;amp;nbsp;;Netzbezug:Current_GridConsumption\&lt;br /&gt;
:\&lt;br /&gt;
#Verbrauch\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenuntergang:special_todayConForecastTillSunset\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie01\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_01\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_01\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_01\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_01\&lt;br /&gt;
#Batterie01_tmp\&lt;br /&gt;
Current_PowerBatIn_01:Current_PowerBatIn_01\&lt;br /&gt;
Current_PowerBatOut_01:Current_PowerBatOut_01\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie02\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_02\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_02\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_02\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_02\&lt;br /&gt;
#Batterie02_tmp\&lt;br /&gt;
Current_PowerBatIn_02:Current_PowerBatIn_02\&lt;br /&gt;
Current_PowerBatOut_02:Current_PowerBatOut_02\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Settings\&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto \&lt;br /&gt;
Wetter:graphicShowWeather\&lt;br /&gt;
History:graphicHistoryHour\&lt;br /&gt;
ShowNight:graphicShowNight\&lt;br /&gt;
Debug:ctrlDebug\&lt;br /&gt;
FCU-Modus:FCU-Betriebsmodus@FCU&lt;br /&gt;
attr Forecast graphicHistoryHour 4&lt;br /&gt;
attr Forecast graphicHourCount 24&lt;br /&gt;
attr Forecast graphicLayoutType double&lt;br /&gt;
attr Forecast graphicShowDiff top&lt;br /&gt;
attr Forecast graphicShowNight 1&lt;br /&gt;
attr Forecast graphicShowWeather 1&lt;br /&gt;
attr Forecast group Energy Meter&lt;br /&gt;
attr Forecast room 020_PV,Energie&lt;br /&gt;
attr Forecast setupBatteryDev01 SBS25 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupBatteryDev02 SBS25_2 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupInverterDev01 SB25 pv=total_pac:kW etotal=etotal:kWh capacity=2500 strings=GarageSE limit=70&lt;br /&gt;
attr Forecast setupInverterDev02 SB30 pv=total_pac:kW etotal=etotal:kWh capacity=3000 strings=GarageNW,HausNW limit=70&lt;br /&gt;
attr Forecast setupInverterDev03 SB40 pv=total_pac:kW etotal=etotal:kWh capacity=4000 strings=HausSE1,HausSE2,HausSW limit=70&lt;br /&gt;
attr Forecast setupInverterStrings GarageSE,GarageNW,HausNW,HausSW,HausSE1,HausSE2&lt;br /&gt;
attr Forecast setupMeterDev SMA_Energymeter gcon=Bezug_Wirkleistung:W contotal=Bezug_Wirkleistung_Zaehler:kWh gfeedin=Einspeisung_Wirkleistung:W feedtotal=Einspeisung_Wirkleistung_Zaehler:kWh conprice=0.25:€ feedprice=0.08123:€&lt;br /&gt;
attr Forecast setupOtherProducer01 icon=Heizung_FCU_green@red MB_USRW610_004 pcurr=Power_L1__W:W etotal=Energy_L1_import__kWh:kWh&lt;br /&gt;
attr Forecast setupRadiationAPI DWD&lt;br /&gt;
attr Forecast setupStringPeak GarageSE=2.75 GarageNW=3.200 HausNW=2.230 HausSW=2.230 HausSE1=2.200 HausSE2=2.200&lt;br /&gt;
attr Forecast setupWeatherDev1 DWD&lt;br /&gt;
attr Forecast stateFormat Current_PV&lt;br /&gt;
attr Forecast userReadings Current_BatCharge999 {((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))) / ( (ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0) * 1000)  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0)*1000))*100}&lt;br /&gt;
attr Forecast verbose 2&lt;br /&gt;
&lt;br /&gt;
setstate Forecast 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .FCU_FCU-Betriebsmodus 2&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_ctrlDebug none&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicHistoryHour 4&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowNight 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowWeather 1&lt;br /&gt;
setstate Forecast 2025-01-13 08:24:25 .associatedWith SMA_Energymeter FBDECT_fbahahttp_11657_0127183 FBDECT_fbahahttp_E8_DF_70_07_3E_57 FBDECT_fbahahttp_E8_DF_70_07_42_0B FBDECT_fbahahttp_11657_0067275 FBDECT_fbahahttp_34_31_C4_D4_31_37 tuya_local_bf5037060f450bdbd4rl0q tuya_local_bfac44fb487476efd1vhdu SBS25 SBS25_2 SB25 SB30 SB40 DWD MB_USRW610_004&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .lastupdateForecastValues 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .pvCorrectionFactor_Auto_Soll on_complex_ai&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .signaldone_01 done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .signaldone_02 done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .signaldone_03 done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .signaldone_04 done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .signaldone_05 done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .signaldone_06 done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .signaldone_07 done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .signaldone_08 done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .signaldone_09 done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .signaldone_10 done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .signaldone_11 done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .signaldone_12 done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .signaldone_13 done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .signaldone_14 done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .signaldone_15 done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .signaldone_16 done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .signaldone_17 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .signaldone_18 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_01 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_02 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_01 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_02 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_AutarkyRate 83 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 Current_BatCharge999 10&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_01 12 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_02 8 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Consumption 626 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridConsumption 2 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridFeedIn 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PP_01 746.0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PV 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_01 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_02 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_01 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_02 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumption 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumptionRate 0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Surplus 120 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourGridconsumptionReal 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_ConsumptionForecast 2944 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayConsumptionForecast 3609 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_01 272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PPreal_01 748 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PPreal_01 787 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_01 271 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PPreal_01 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PPreal_01 745 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_01 267 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PPreal_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_01 255 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PPreal_01 752 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_01 226 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_01 50 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PPreal_01 681 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_02 233 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_01 845 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridConsumption 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_01 37 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_02 90 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_01 351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_02 188 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridConsumption 447 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVforecast 127 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridConsumption 1650 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVforecast 478 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVreal 26 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridConsumption 513 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVforecast 868 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVreal 97 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridConsumption 576 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVforecast 1157 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVreal 320 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_01 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_02 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridConsumption 1272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridFeedIn 7 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVforecast 1238 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVreal 945 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_01 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_02 53 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridConsumption 955 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridFeedIn 31 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PPreal_01 562 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVforecast 1168 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVreal 1410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_01 703 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_02 500 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_01 22 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_02 18 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridConsumption 32 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridFeedIn 71 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PPreal_01 777 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVreal 1416 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_01 296 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_02 70 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_01 74 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_02 258 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridConsumption 13 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridFeedIn 17 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PPreal_01 732 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVforecast 880 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVreal 1051 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_01 47 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_02 126 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_01 102 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_02 75 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridConsumption 15 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridFeedIn 23 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PPreal_01 771 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVforecast 117 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVreal 86 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_02 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_02 67 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridConsumption 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridFeedIn 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PPreal_01 723 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_01 349 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_02 124 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_01 73 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_02 450 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridConsumption 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridFeedIn 6 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PPreal_01 671 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecastTime 2025-01-13 14:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVdeviation 30.17 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVforecast 7663 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVreal 5351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunRise 08:28&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunSet 16:46&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_ConsumptionForecast 17043 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour05_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour06_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour07_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour08_PVforecast 10 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour09_PVforecast 161 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour10_PVforecast 275 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour11_PVforecast 532 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour12_PVforecast 730 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour13_PVforecast 1252 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour14_PVforecast 818 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour15_PVforecast 1465 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour16_PVforecast 303 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour17_PVforecast 20 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour18_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour19_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour20_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour21_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour22_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour23_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour24_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_PVforecast 5566 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunRise 08:27&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunSet 16:47&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01 name=&#039;_Waschmaschine&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_start 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_stop 14.01.2025 11:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02 name=&#039;_Esszimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_currentPower 15.3 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03 name=&#039;_FCU&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_currentPower 7.15 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04 name=&#039;_Brunnen&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05 name=&#039;_Zisterne&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06 name=&#039;SW Trockner&#039; state=&#039;unknown&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_stop 14.01.2025 08:30:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07 name=&#039;SW Urlaubslicht-Wohnzimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;noSchedule&#039; info=&#039;von extern umgeschaltet&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 nextCycletime 18:54:09&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 pvCorrectionFactor_10 0.53 (automatic - old factor: 1.00, Sun Alt range: 5, Cloud range: 75, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 pvCorrectionFactor_11 0.56 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 70, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 pvCorrectionFactor_12 0.64 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 pvCorrectionFactor_13 0.88 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 pvCorrectionFactor_14 1.10 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 50, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 pvCorrectionFactor_15 1.01 (automatic - old factor: 1.06, Sun Alt range: 15, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 pvCorrectionFactor_16 1.09 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 45, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 pvCorrectionFactor_17 0.28 (automatic - old factor: 0.52, Sun Alt range: 0, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 pvCorrectionFactor_Auto on_complex_ai&lt;br /&gt;
setstate Forecast 2024-10-30 19:42:19 setupStringAzimuth GarageSE=-55 GarageNW=125 HausNW=125 HausSW=35 HausSE1=-55 HausSE2=-55&lt;br /&gt;
setstate Forecast 2024-10-30 19:37:38 setupStringDeclination GarageSE=40 GarageNW=40 HausNW=50 HausSW=50 HausSE1=50 HausSE2=50&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerIn_Sum 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerOut_Sum 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunHours_Remain 0.00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunMinutes_Remain 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_allStringsFullfilled 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_conForecastTillNextSunrise 9467 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentAPIinterval 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_01 132 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_02 184 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_03 329512 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_04 200 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_05 27 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_06 193 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_07 106 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_dayAfterTomorrowPVforecast 7344 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_01 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_02 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_time 2025-01-13 18:53:54&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_timestamp 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_response_message success&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_01 545.94 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_02 382.10 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_03 1430.13 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_04 262.05 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_05 28.80 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_06 622.63 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_07 276.51 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeCentralTask 0.3744&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIAnswer -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIProc -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeTrainAI 1.2529&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_01 3683.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_02 1617.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_01 2287.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_02 1057.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConForecastTillSunset 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 special_todayConsumptionForecast_01 509 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 special_todayConsumptionForecast_02 499 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 special_todayConsumptionForecast_03 501 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 special_todayConsumptionForecast_04 511 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 special_todayConsumptionForecast_05 503 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 special_todayConsumptionForecast_06 495 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 special_todayConsumptionForecast_07 504 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 special_todayConsumptionForecast_08 561 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 special_todayConsumptionForecast_09 768 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 special_todayConsumptionForecast_10 783 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 special_todayConsumptionForecast_11 692 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 special_todayConsumptionForecast_12 791 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 special_todayConsumptionForecast_13 910 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 special_todayConsumptionForecast_14 1022 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 special_todayConsumptionForecast_15 965 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 special_todayConsumptionForecast_16 812 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 special_todayConsumptionForecast_17 884 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 special_todayConsumptionForecast_18 928 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_19 874 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_20 763 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_21 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_22 765 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_23 643 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_24 601 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIcalls 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIrequests 4532&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridConsumption 5500.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridFeedIn 178.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayMaxAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIrequests n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 state updated&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So sollte es dann als Ergebnis aussehen:&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13.png|zentriert|mini|Ergebnis nach kompletter Einrichtung]]&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13 Teil II.png|alternativtext=Unterer Teil der Anzeige|zentriert|mini]]&lt;br /&gt;
&lt;br /&gt;
== Praxisbeispiele und Lösungsansätze für Steuerungen ==&lt;br /&gt;
=== Fallstudie: Trockner darf pausiert werden, wenn nicht genug PV-Überschuss vorhanden ist, soll aber nach spätestens X Stunden fertig sein ===&lt;br /&gt;
Für diese Aufgabenstellung sind mehrere Schlüssel essentiell wichtig, &#039;&#039;&#039;power&#039;&#039;&#039;, &#039;&#039;&#039;mintime&#039;&#039;&#039;, &#039;&#039;&#039;mode&#039;&#039;&#039; und &#039;&#039;&#039;interruptable&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Die Bedingung, dass der Trockner nach spätestens X Stunden fertig sein soll, steht in einem Widerspruch zu der Möglichkeit den Trockner bei zu wenig PV-Überschuss unterbrechen zu können. Im Extremfall könnte nach dem Start die gesamte Planungszeit ungenügender Überschuss vorliegen und der Trockner nicht arbeiten. Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; (in Minuten) wird nun wie folgt angesetzt:&lt;br /&gt;
&lt;br /&gt;
 mintime = 2,5 x &amp;lt;gewöhnliche Betriebszeit für einen Trockengang (mneed, z.B. 120)&amp;gt; = 300 Minuten&lt;br /&gt;
&lt;br /&gt;
Das bedeutet, der Trockner wird nach 300 Minuten Laufzeit abgeschaltet werden bzw. vom Netz getrennt. Der Trockenvorgang wird natürlich bereits nach 120 Minuten beendet sein, sofern nach Start keine Unterbrechnung des Vorganges erfolgte. Wurde der Vorgang unterbrochen, soll der Trockner innerhalb &lt;br /&gt;
&lt;br /&gt;
 X+120 bis X+300 &lt;br /&gt;
&lt;br /&gt;
fertig sein. &lt;br /&gt;
&lt;br /&gt;
Demnach ist die ausgeführte Laufzeit des Trockners permanent zu überwachen, zu summieren (rtsum) und die notwendige Restzeit (mneed - rtsum) mit der noch verbleibenden Restzeit (mrest) bis zur geplanten Abschaltung des Consumers zu vergleichen. Ist der Consumer gestartet, wird die Laufzeit in der pvHistory für jede Stunde des Tages im Schlüssel &#039;&#039;minutescsmXX&#039;&#039; (XX = Consumernummer) aufgezeichnet und kann darüber ausgewertet werden. Somit ist:&lt;br /&gt;
&lt;br /&gt;
 msum = for (01 .. 24) {Summe von minutescsmXX} des aktuellen Tages&lt;br /&gt;
&lt;br /&gt;
Solange die Bedingung &lt;br /&gt;
&lt;br /&gt;
 mrest &amp;gt;= (mneed - msum)&lt;br /&gt;
&lt;br /&gt;
zutrifft, darf der Trockner unterbrochen werden, anderenfalls darf er nicht mehr unterbrochen werden da die Restzeit evtl. nicht ausreichen könnte um den Vorgang abzuschließen. Für die Planung des Trockners wird der Consumer wie gewöhnlich nach dem Bedarf im Modul registriert. Für die Steuerung der Unterbrechbarkeit wird noch ein Code erstellt, welcher im Trockner-Device &#039;&#039;Dryerdev&#039;&#039; das Reading &#039;&#039;SF_Int&#039;&#039; zur Unterbrechnungssteuerung verwaltet. Dieses Reading wird dem Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; übergeben. Für das Beispiel wird der Consumer &#039;07&#039; verwendet, es kann natürlich jede andere freie Nummer verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Dryerdev:Trockner&lt;br /&gt;
                        icon=scene_cloves_dryer type=dryer power=2000 mode=must mintime=300 &lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic asynchron=1&lt;br /&gt;
                        interruptable=Dryerdev:SF_Int:1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Kombination &#039;&#039;&#039;auto=automatic&#039;&#039;&#039; eröffnet die Möglickeit, in der Consumer-Legende den Trockner-Start zusätzlich manuell freizugeben oder zu verbieten. &lt;br /&gt;
&lt;br /&gt;
Im nachfolgenden Code werden modulinterne Subroutinen verwendet. Diese sind inklusive dem Paket &#039;&#039;FHEM::SolarForecast::&#039;&#039; anzugeben. Die erstellte Subroutine wird in die 99_mySolarForecastUtils.pm eingefügt. Die Datei 99_mySolarForecastUtils.pm wird vorher von 99_myUtils.pm kopiert und enthält für die Übersichtlichkeit nur Routinen für SolarForecast.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Trocknersteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub dryControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # gewöhlich benötigte Zeit für &lt;br /&gt;
                                                                                  # einen Trockengang, z.B. 120 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $dryer     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename des Trockners&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Trockner-Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit des Trockners&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      my $dhash = $defs{$dryer};&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 1, 0);                        # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 0, 0);                        # keine Interrupt-Freigabe&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die gewöhnliche Laufzeit des Trockners für einen Trockenvorgang (120 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::dryControl ($name, &#039;07&#039;, 120);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Fallstudie: Umwälzpumpe Pool soll X Stunden am Tag laufen. Ist kein PV-Überschuß vorhanden, müssen die X Stunden/Tag trotzdem erreicht werden ===&lt;br /&gt;
&lt;br /&gt;
Die Vorgehensweise ähnelt der Fallstudie zuvor. Verändernd kommt hinzu, dass der Planungszeitraum bewusst sehr lang angesetzt wird mit der Option, den Zyklus des Consumers vorfristig zu beenden sobald die Laufzeit von X Stunden am Tag erreicht ist. &lt;br /&gt;
Im folgenden Beispiel soll die Pumpe 5 Stunden am Tag (300 Minuten) laufen und dabei mögliche PV-Überschüsse ausnutzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Pump:Zirkulationspumpe&lt;br /&gt;
                        icon=sani_pump type=other power=50 mode=must mintime=780 notafter=09&lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic &lt;br /&gt;
                        interruptable=1 swoffcond=Pump:SF_Abort:1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit dieser Registrierung wird die Pumpe ca. 09 Uhr täglich starten. Wenn kein bzw. ungenügender PV-Überschuß vorhanden ist, erfolgt eine Unterbrechung nach dem Start. Ist genügender PV-Überschuß (wieder) vorhanden, erfolgt keine Unterbrechnung (mehr). Zusätzlich wird über den Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; eine vorfristige Beendigung veranlasst, sobald die gewünschte Tageslaufzeit erreicht ist.&lt;br /&gt;
&lt;br /&gt;
Zur Verwaltung des Schlüssels &#039;&#039;interruptable&#039;&#039; und des Readings &#039;&#039;SF_Abort&#039;&#039; verwenden wir eine leicht veränderte Subroutine aus dem vorhergehenden Fallbeispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Pumpensteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub pumpControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # Soll-Pumpenzeit, z.B. 300 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $pump      = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename der Pumpe&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;);&lt;br /&gt;
  my $intbl     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;interruptable&#039;, 1); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
  my $dhash     = $defs{$pump};&lt;br /&gt;
&lt;br /&gt;
  readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 0, 0);                                # default keine Zyklusbeendigung&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Pumpen Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit der Pumpe&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
     &lt;br /&gt;
      if ($msum &amp;gt;= $mneed) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 1, 0);                       # vorfristige Zyklusbeendigung&lt;br /&gt;
          return;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=1&amp;quot;) if(!$intbl);  # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=0&amp;quot;) if($intbl);   # keine Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Befehl &#039;&#039;attrKeyVal&#039;&#039; setzt den Schlüssel &#039;&#039;interruptable&#039;&#039; im Attribut &#039;&#039;consumer07&#039;&#039; dynamisch. Diese Strukturänderung wird automatisch im System gespeichert, sofern &#039;&#039;global-&amp;gt;autosave=1&#039;&#039; gesetzt ist. Diese Einstellung ist der FHEM default.  &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die Mindestlaufzeit der Umwälzpumpe (300 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::pumpControl ($name, &#039;07&#039;, 300);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamische Ladestromsteuerung eines Victron MultiPlus II Chargers mit Pylontech Batterie ===&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;
&lt;br /&gt;
 set &amp;lt;Device&amp;gt; MaxChargeCurrent &amp;lt;Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
eingestellt bzw. variiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Modul bietet dem Nutzer die Möglichkeit in dem Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltene Code wird am Ende jedes Zyklus (siehe Attribut &#039;&#039;plantControl-&amp;gt;cycleInterval&#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;
&lt;br /&gt;
&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 $mppt1   = &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common&#039;;              # SmartLoader Device&lt;br /&gt;
  my $maxcspc = 105;                        # max. Ladesollstrom (A) nominal&lt;br /&gt;
  my $spcorr  = 0.9;                        # Korrekturfaktor Überschuss 90%&lt;br /&gt;
  my $sch     = 0.25;                       # Verkürzungsfaktor Zeit bis Vollladung vor Sunset             &lt;br /&gt;
  &lt;br /&gt;
  my $cclvl0  = 15;                         # Ladestrom Level 0 max. 5  A (240 W) pro WR  (720  W)&lt;br /&gt;
  my $cclvl1  = 27;                         # Ladestrom Level 1 max. 9  A (432 W) pro WR  (1296 W)&lt;br /&gt;
  my $cclvl2  = 54;                         # Ladestrom Level 2 max. 18 A (864 W) pro WR  (2592 W)&lt;br /&gt;
  my $cclvl3  = 81;                         # Ladestrom Level 3 max. 27 A (1296 W) pro WR (3888 W)&lt;br /&gt;
  ###############&lt;br /&gt;
  &lt;br /&gt;
  my $cofc   = ReadingsNum ($name,  &#039;special_todayConForecastTillSunset&#039;, 0);&lt;br /&gt;
  my $pvfc   = ReadingsNum ($name,  &#039;RestOfDayPVforecast&#039;, 0);&lt;br /&gt;
  my $cpv    = ReadingsNum ($name,  &#039;Current_PV&#039;,          0);&lt;br /&gt;
  my $mppt1c = ReadingsNum ($mppt1, &#039;DC_0_Current_value&#039;,  0);             # Load I MPPT1 (max. 44 A)&lt;br /&gt;
  my $ssts   = CurrentVal  ($hash,  &#039;sunsetTodayTs&#039;,        0);&lt;br /&gt;
  my $srts   = CurrentVal  ($hash,  &#039;sunriseTodayTs&#039;,       0);&lt;br /&gt;
  my $sdiff  = ($ssts - $srts) / 3600;                                     # Sonnengang heute in h &lt;br /&gt;
  &lt;br /&gt;
  my $solh   = ReadingsNum ($name, &#039;special_SunHours_Remain&#039;, 0);          # h bis SunSet&lt;br /&gt;
  $solh      = $solh - ($sdiff * $sch);                                    # h bis SunSet - X&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;              # Ah Bat bis SOC&lt;br /&gt;
  $ahrem     = sprintf &amp;quot;%.0f&amp;quot;, $ahrem;&lt;br /&gt;
  &lt;br /&gt;
  my $fcdiff = ($pvfc - $cofc) * $spcorr;     # Korrektur d. noch prognostizierten Überschussenergie &lt;br /&gt;
  $fcdiff    = $fcdiff &amp;lt; 0 ? 0 : $fcdiff;     # Wh&lt;br /&gt;
  &lt;br /&gt;
  my $loadcur = $maxcspc;&lt;br /&gt;
  &lt;br /&gt;
  if ($cpv &amp;amp;&amp;amp; $solh &amp;amp;&amp;amp; $ahrem &amp;amp;&amp;amp; $fcdiff &amp;gt; $ahrem) {  # Ladeanforderung und Überschuss übersteigt &lt;br /&gt;
                                                      # Lademenge&lt;br /&gt;
      my $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($ahrem / $solh);    # A = Ah / h -&amp;gt; A Soll Schätzung&lt;br /&gt;
&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Battery charging process should be completed }.&lt;br /&gt;
                      qq{in &amp;gt;$solh&amp;lt; hours});&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; raw Target charging current: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($cspc - $mppt1c);      # SmartLoader IST berücksichtigen&lt;br /&gt;
	  &lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Charge Current minus MPPT load Current &amp;gt;$mppt1c&amp;lt;: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $loadcur = $cspc &amp;lt;= 0       ? 0       :     # nur MPPT Ladung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl0 ? $cclvl0 :     # Übergangsbereich&lt;br /&gt;
                 $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;
	  Log3 ($name, 3, qq{$name - userFn -&amp;gt; MaxChargeCurrent calculated: $loadcur});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent&#039;,       $loadcur.&#039; A&#039;,          1);&lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_HoursUntilChargeFinish&#039;, sprintf (&amp;quot;%.2f&amp;quot;,$solh), 1);&lt;br /&gt;
  CommandSet           (undef, &amp;quot;$vebus MaxChargeCurrent $loadcur&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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. 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;special_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;special_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;Verkürzungsfaktor Zeit bis Vollladung vor Sunset&#039;&#039;) reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche mindest Ladestromstärke ermittelt.&lt;br /&gt;
&lt;br /&gt;
&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 auch während der MQTT Intergration 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;
=== Poolheizung in Abhängigkeit von vorhandenem Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren) ===&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;consumer01&#039;&#039; wird beispielhaft wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr Forecast consumer01 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;&lt;br /&gt;
&lt;br /&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. &lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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, einen 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 Überschuss 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;. &lt;br /&gt;
&lt;br /&gt;
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;
=== PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) ===&lt;br /&gt;
[https://evcc.io evcc] ist ein Energie-Management-System, mit dem u.a. Überschussladen von Elektroautos möglich ist. Hier ist beschreiben, wie die SolarForecast-Vorhersagedaten per API von evcc abgerufen werden.&lt;br /&gt;
Lege im SolarForecast-Device ein User-Reading mit dem Namen forecast_json an. Es wandelt die Forecast-Werte in JSON und ins UTC-Zeitformat um, so dass evcc die Daten einlesen kann. Der Code wird nur ausgeführt, wenn das Reading nextCycletime ein Event erzeugt.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
forecast_json:nextCycletime.* {&lt;br /&gt;
&lt;br /&gt;
    use strict;&lt;br /&gt;
    use warnings;&lt;br /&gt;
    use JSON;&lt;br /&gt;
    use DateTime;&lt;br /&gt;
    use DateTime::Format::Strptime;&lt;br /&gt;
&lt;br /&gt;
    my $hour = 0;&lt;br /&gt;
    my $last_start_ts;    &lt;br /&gt;
    my @output;&lt;br /&gt;
    &lt;br /&gt;
    # Parser für Datum mit CET/CEST&lt;br /&gt;
    my $parser = DateTime::Format::Strptime-&amp;gt;new(&lt;br /&gt;
        pattern   =&amp;gt; &amp;quot;%Y-%m-%d %H:%M:%S&amp;quot;,&lt;br /&gt;
        time_zone =&amp;gt; &amp;quot;Europe/Berlin&amp;quot;,&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    # Alle NextHour-Daten durchsuchen (als Fallback zur Vermeidung einer Endlosschleife auf max. 100 Std. begrenzen)&lt;br /&gt;
    while ($hour &amp;lt; 100) {&lt;br /&gt;
        my $hour_str = sprintf(&amp;quot;NextHour%02d&amp;quot;, $hour);&lt;br /&gt;
        my $start_str = FHEM::SolarForecast::NexthoursVal(&amp;quot;$NAME&amp;quot;, $hour_str, &amp;quot;starttime&amp;quot;, &amp;quot;na&amp;quot;);&lt;br /&gt;
        my $pvfc = FHEM::SolarForecast::NexthoursVal(&amp;quot;$NAME&amp;quot;, $hour_str, &amp;quot;pvfc&amp;quot;, &amp;quot;na&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        # Schleife beenden, wenn keine Vorhersage-Werte mehr vorhanden sind&lt;br /&gt;
        last if $start_str eq &amp;quot;na&amp;quot; or $pvfc eq &amp;quot;na&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        my $start_ts = $parser-&amp;gt;parse_datetime($start_str);  # Zeitzone und Sommer/Winterzeit berücksichtigen&lt;br /&gt;
        $last_start_ts = $start_ts-&amp;gt;clone;  # merken für spätere Prüfung&lt;br /&gt;
&lt;br /&gt;
        # Zeit in UTC und ISO 8601 konvertieren und Vorhersagewert ergänzen&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $start_ts-&amp;gt;set_time_zone(&amp;quot;UTC&amp;quot;)-&amp;gt;iso8601() . &amp;quot;Z&amp;quot;,&lt;br /&gt;
            end   =&amp;gt; $start_ts-&amp;gt;add(hours =&amp;gt; 1)-&amp;gt;set_time_zone(&amp;quot;UTC&amp;quot;)-&amp;gt;iso8601() . &amp;quot;Z&amp;quot;,&lt;br /&gt;
            value =&amp;gt; 0 + $pvfc,&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        $hour++;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # Prüfen, ob der letzte Start-Wert 23 Uhr war. Dann zusätzlich 2 Stunden anhängen, damit übermorgen&lt;br /&gt;
    # bei evcc vollständig angezeigt wird (siehe https://github.com/evcc-io/evcc/issues/22979)&lt;br /&gt;
    if (defined $last_start_ts &amp;amp;&amp;amp; $last_start_ts-&amp;gt;hour == 23) {&lt;br /&gt;
&lt;br /&gt;
        # Zeit nach UTC und ISO 8601 konvertieren und Vorhersagewert ergänzen&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $last_start_ts-&amp;gt;add(hours =&amp;gt; 1)-&amp;gt;set_time_zone(&amp;quot;UTC&amp;quot;)-&amp;gt;iso8601() . &amp;quot;Z&amp;quot;,&lt;br /&gt;
            end   =&amp;gt; $last_start_ts-&amp;gt;add(hours =&amp;gt; 1)-&amp;gt;set_time_zone(&amp;quot;UTC&amp;quot;)-&amp;gt;iso8601() . &amp;quot;Z&amp;quot;,&lt;br /&gt;
            value =&amp;gt; 0,&lt;br /&gt;
        };&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $last_start_ts-&amp;gt;set_time_zone(&amp;quot;UTC&amp;quot;)-&amp;gt;iso8601() . &amp;quot;Z&amp;quot;,&lt;br /&gt;
            end   =&amp;gt; $last_start_ts-&amp;gt;add(hours =&amp;gt; 1)-&amp;gt;set_time_zone(&amp;quot;UTC&amp;quot;)-&amp;gt;iso8601() . &amp;quot;Z&amp;quot;,&lt;br /&gt;
            value =&amp;gt; 0,&lt;br /&gt;
        };          &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # Ausgabe als JSON&lt;br /&gt;
    my $json = JSON-&amp;gt;new-&amp;gt;utf8-&amp;gt;pretty-&amp;gt;encode(\@output);&lt;br /&gt;
    return $json;&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Datei:Screenshot 2025-08-04 104835.png|right|thumb|300px|Darstellung der PV-Vorhersage in evcc auf Basis der SolarForecast-Daten]]&lt;br /&gt;
Die Kommunikation läuft über den integrierten FHEM-Webserver, der die JSON-Daten aus dem Reading forecast_json veröffentlicht. Dazu wird in FHEM eine separate Webinstanz auf einem neuen Port erstellt, die ohne [[CsrfToken-HowTo|CSFR-Token]] (Achtung, Auswirkungen auf die Sicherheit beachten!) und nur von localhost aufrufbar ist (Voraussetzung: evcc läuft auf derselben Maschine wie FHEM):&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
define WEBapi FHEMWEB 8089&lt;br /&gt;
attr WEBapi csrfToken none&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;In der [https://docs.evcc.io/docs/tariffs#pv-vorhersage evcc-Konfig unter tariffs] steht die Quelle für die Solar-Vorhersage. Der FHEM-Befehl {ReadingsVal(&#039;solarforecast_dev&#039;,&#039;forecast_json&#039;,&#039;[]&#039;)} wird encoded und in die uri eingetragen. Trage statt solarforecast_dev den passenden Namen deines SolarForecast-Device ein. evcc holt die Daten aus dem Reading forecast_json dann regelmäßig ab.&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
solar:&lt;br /&gt;
  type: custom&lt;br /&gt;
  interval: 20m    &lt;br /&gt;
  forecast:&lt;br /&gt;
    source: http&lt;br /&gt;
    uri: http://localhost:8089/fhem?cmd=%7BReadingsVal%28%27solarforecast_dev%27%2C%27forecast_json%27%2C%27%5B%5D%27%29%7D&amp;amp;XHR=1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Zur Verbesserung der Sicherheit kann das neue WEBapi Device auch ein [[CsrfToken-HowTo#csrfToken festlegen|festes CSFR-Token]] verwenden. Dieses Token muss dann in der evcc-Konfiguration an die uri mittels &amp;amp;fwcsrf=&amp;lt;festes token&amp;gt; angehängt werden.&lt;br /&gt;
&lt;br /&gt;
=== Poolsteuerung inkl. Eigenverbrauchsoptimierung und zusätzlichem Verbraucher, um Einspeiselimit zu vermeiden + manuelle Steuerung durch Sonderprogramme ===&lt;br /&gt;
&#039;&#039;&#039;Vorhandene Hardware:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Poolpumpe, die über mehrere Stufen verfügt. Hier werden zwei verwendet.&lt;br /&gt;
** Pump Low: Energiesparprogramm um den Pool umzuwälzen, auch wenn nicht genug PV Leistung zur Verfügung steht. -&amp;gt; ca. 250W&lt;br /&gt;
** Pump High: Normalbetrieb wenn genug PV Überschuss zur Verfügung steht. -&amp;gt; ca. 800W zusätzlich&lt;br /&gt;
* Poolheizung: Wärmepumpe -&amp;gt; ca. 1,5kW elektrisch&lt;br /&gt;
* Nachbars Pool: Pumpe + Salzanlage +pH-Regler -&amp;gt; ca. 650W&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Anforderungen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Pool muss täglich mindestens 1x umgewälzt werden.&lt;br /&gt;
* Im Idealfall wird der Pool &amp;gt; 2x umgewälzt.&lt;br /&gt;
* Bei genügend Überschuss soll der Pool geheizt werden. Es soll nur Sonnenstrom für die Poolheizung verwendet werden.&lt;br /&gt;
* Um das Einspeiselimit zu vermeiden, soll auch geheizt werden, wenn der Pool schon warm genug ist. (&amp;gt;28,5 °C)&lt;br /&gt;
* Sollte trotzdem noch das Einspeiselimit erreicht werden, soll auch der Pool des Nachbarn versorgt werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Herausforderungen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Verbraucher dürfen nur in einer gewissen Reihenfolge geschaltet werden, auch wenn der Überschuss eine andere Reihenfolge ergeben würde.&lt;br /&gt;
* Pumpe mit mehreren Stufen muss als zwei Consumer abgebildet werden, um die Schaltlogik in SolarForecast abzubilden. Würde die Trennung außerhalb von Solarforecast realisiert, könnte Solarforecast den Verbraucher schlechter &amp;quot;lernen&amp;quot;, denn dann wäre es ein Consumer mit ständig wechselndem Verbrauch.&lt;br /&gt;
* Pool des Nachbarn darf nicht laut der benötigten Leistung geschaltet werden, sondern in Abhängigkeit der Einspeisebegrenzung.&lt;br /&gt;
&lt;br /&gt;
In diesem Solarforcast-Device sind 16 Verbraucher definiert. Im Weiteren werden jedoch nur die verwendeten betrachtet. Da diese Reglung mittlerweile recht komplex ist, werden auch viele Dinge, die nicht SolarForcast betreffen, aber trotzdem dazu gehören, gezeigt. Es trägt zum Verständnis bei und man kann sich hier sicher Ideen holen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ergebnis:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In den folgenden beiden Bildern sieht man das Regelverhalten recht gut.&lt;br /&gt;
[[Datei:Mustertag ohne Wolken.jpg|zentriert|mini|823x823px|Wolkenloser Tag]]&lt;br /&gt;
Hier erkennt man gut das Einschalten der jeweiligen Verbraucher (Pump Low, Pump High, Wärmepumpe und Nachbar Pool). Die Wärempumpe schaltet erst bei 5kW Überschuss ein, da der Pool eigentlich schon warm genug ist. Sie dient &amp;quot;nur&amp;quot; dazu, das EInspeiselimit zu verhindern.Auch das Auschalten ist wieder deutlich zu erkennen. Die Regleung folgt dem Überschuss recht gut. (Die Leistungsspitzen auf dem Plateau sind normale Großverbraucher im Haus.)&lt;br /&gt;
[[Datei:Wechselhaft.jpg|zentriert|mini|818x818px|Wechselhafter Tag.]]&lt;br /&gt;
In diesem Bild sieht man das &amp;quot;verzweifelte&amp;quot; Regeln um das wechselhafte Wetter auszugleichen. Hier gibt es keine korrekte Reaktion und es wird durch die Sperrzeiten und andere Delays versucht, ein zu häufiges hin- und herschalten möglichst zu vermeiden. In Summe aber auch bei so einem Wetter ein akzeptables Verhalten.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Definition der Consumer:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemeine Erklärungen zu den Definitionen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;asynchron=0&#039;&#039;&#039;: Da hier die Werte des Überschusses für das Timing der Schaltvorgänge verwendet werden, darf hier keine Eventsteuerung verwendet werden. Sonst kann man nicht mehr sagen, über welchen Zeitraum der Mittelwert oder der Median gebildet wurde. Dafür wurde die Zykluszeit des SolarForecast-Device auf 60 Sekunden geändert, um die Überlegungen zu vereinfachen. Bei Event-Steuerung könnte man nicht sagen ob die letzten 10 Events in den letzten 5 Sekunden oder in den letzten 10 Minuten aufgetreten sind.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;power=xxx&#039;&#039;&#039;: Wurde teilweise etwas höher als der tatsächliche Wert gewählt, um nach dem Einschalten sicherzustellen, dass nicht sofort der gesamte Überschuss &amp;quot;verbraucht&amp;quot; wird und somit gleich wieder abgeschaltet wird.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;auto=xxx&#039;&#039;&#039;: Jeder Verbraucher benötigt sein eigenes auto-Reading, da die Automatik für die Regelung in verschiedenen Stufen ein- und ausgeschaltet werden muss.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dum_valve&#039;&#039;&#039;: Dummy-Device in dem die Zustände der Regelung abgebildet werden. Notifys lesen bzw. befüllen diesen Dummy und steuern dann die Hardware bzw. wird der Dummy durch Werte aus der Hardware passend befüllt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;surpmeth=median_xx:&#039;&#039;&#039; Durch das asynchron=0 in allen Consumern und beim Generator wird von Solarforcast genau alle 60 Sekunden ein Zyklus ausgeführt. Das führt dazu, dass der Median genau über xx Minuten gebildet wird.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;locktime=xx:xx&#039;&#039;&#039;: Sicherheitsvorkehrung, dass nicht zu oft geschaltet werden kann. Schont die Hardware und verhindert ein Schwingen. Abhänging vom geschalteten Gerät. z.B. soll die Wärmepumpe möglichst wenig takten, um die Lebensdauer zu verlängern.&lt;br /&gt;
&lt;br /&gt;
Es gibt dann auch noch einige weitere Sicherheitsvorkehrungen, um diese Regelung möglichst stabil und hardwareschonend zu gestalten. Die Schwierigkeit sind nicht die Bilderbuchtage mit einem glatten Verlauf der PV-Leistung, sondern Tage mit ständig wechselndem Überschuss in der Nähe der Schaltgrenzen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;swoncond= dum_valve:sf_true:{main::xxx_On}:&#039;&#039;&#039; Hier werden verschiedene Zustände geprüft, um ein Gerät nur dann einzuschalten, wenn es sinnvoll und sicher ist.&lt;br /&gt;
&lt;br /&gt;
Details unter &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;swoffcond= dum_valve:sf_true:{main::xxx_Off}&#039;&#039;&#039;: Hier werden verschiedene Zustände geprüft, um ein Gerät nur dann auszuschalten, wenn es sinnvoll und sicher ist.&lt;br /&gt;
&lt;br /&gt;
Details unter &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pump Low: (consumer01)&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:Pool+Low&lt;br /&gt;
aliasshort=Low&lt;br /&gt;
asynchron=0&lt;br /&gt;
auto=pump_low_auto&lt;br /&gt;
icon=scene_pool&lt;br /&gt;
interruptable=0&lt;br /&gt;
mintime=SunPath:0:180&lt;br /&gt;
mode=must&lt;br /&gt;
noshow=0&lt;br /&gt;
notafter=08:00&lt;br /&gt;
off=&amp;quot;pump_low off&amp;quot;&lt;br /&gt;
on=&amp;quot;pump_low on&amp;quot;&lt;br /&gt;
pcurr=pump_low_power&lt;br /&gt;
power=250&lt;br /&gt;
surpmeth=median_13&lt;br /&gt;
switchdev=dum_valve&lt;br /&gt;
swoffcond=dum_valve:sf_true:{main::Check_Pump_Low_Off}&lt;br /&gt;
swoncond=dum_valve:sf_true:{main::Check_Pump_Low_On}&lt;br /&gt;
swstate=pump_low:on:off&lt;br /&gt;
type=other&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Die Pumpe soll ab Sonnenaufgang, bis 180 Minuten nach Sonnenuntergang (mintime=SunPath:0:180), bei mindestens 250W Überschuss (power=250) gestartet werden.&lt;br /&gt;
* Die Pumpe muss spätestens um 8:00 eingeplant werden (notafter=08:00), um das Umwälzen auch bei Schlechtwetter zu garantieren.&lt;br /&gt;
* Die Pumpe muss gestartet werden (mode=must) sobald sie eingeplant ist.&lt;br /&gt;
* swoncond sorgt dafür, dass sie vor 8:00 nur bei genügend Überschuss gestartet wird, oder es 8:00 ist. swondcond ist mit der eigentlichen Einschaltbedingung (eingeplant und mode=must) UND verknüpft. -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
* Überschuss wird auch in swoncond mit der gewählten Methode geprüft.&lt;br /&gt;
* Die Pumpe darf, wenn sie gestartet wurde, auch bei fehlendem Überschuss nicht mehr unterbrochen werden. (interruptable=0)&lt;br /&gt;
* Die Pumpe wird am Ende der Einplanung ausgeschaltet oder wenn swoffcond erfüllt ist. swoffcond wird true, wenn eine gewisse Wassermenge umgewälzt wurde oder die Sicherheitsbedingungen nicht (mehr) erfüllt sind. swoffcond ist mit der eigentlichen Ausschaltbedingung (Planung endet) ODER verknüpft. -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
* {&#039;&#039;&#039;main::&#039;&#039;&#039;xxx} dient dazu, um die Funktion xxx in der 99_mySolarForecastUtils.pm aus Solarforecast erreichbar zu machen.&lt;br /&gt;
* dum_valve:sf_true ist ein Reading, das fix 1 ist und als Vergleichswert für den in Klammern folgenden Perlcode dient. Wenn dieses Reading und der Perlcode gleich sind (1==1), ist die swoncond bzw swoffcond erfüllt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pump High: (consumer03)&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:Pool+High&lt;br /&gt;
aliasshort=High&lt;br /&gt;
type=other power=1000 asynchron=0&lt;br /&gt;
auto=pump_high_auto&lt;br /&gt;
icon=scene_pool&lt;br /&gt;
pcurr=pump_high_power&lt;br /&gt;
switchdev=dum_valve&lt;br /&gt;
swstate=pump_high:on:off&lt;br /&gt;
mode=can&lt;br /&gt;
mintime=SunPath&lt;br /&gt;
on=&amp;quot;pump_high on&amp;quot;&lt;br /&gt;
off=&amp;quot;pump_high off&amp;quot;&lt;br /&gt;
surpmeth=median_5&lt;br /&gt;
noshow=0&lt;br /&gt;
locktime=180:300&lt;br /&gt;
interruptable=1&lt;br /&gt;
swoncond=dum_valve:sf_true:{main::Check_Pump_High_On}&lt;br /&gt;
swoffcond=dum_valve:sf_true:{main::Check_Pump_High_Off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Pump HIgh ist die selbe Pumpe, aber eine höhere Durchflussmenge&lt;br /&gt;
* Der Mehrverbrauch beträgt eigentlich 800W wird hier aber mit 1000W angegeben, um eine Hysterese von ca. 200W zu erreichen und damit ein schnelles Abschalten nach dem Einschalten zu verhindern.&lt;br /&gt;
* Diese Stufe wird nur bei genügend Überschuss aktiviert. (mode=can)&lt;br /&gt;
* Diese Stufe wird bei fehlendem Überschuss unterbrochen. (interruptable=1)&lt;br /&gt;
* Diese Stufe wird nur während Sonnenschein eingeplant. (mintime=SunPath)&lt;br /&gt;
* locktime sorgt dafür, dass bei schnell wechselnden Bedingungen, nicht ständig umgeschaltet wird. -&amp;gt; Schonung der Pumpe.&lt;br /&gt;
* swoncond und swoffcond -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Heatpump: (consumer05)&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Pool_Strom_Heizung:Poolheizung&lt;br /&gt;
aliasshort=WP&lt;br /&gt;
type=other power=1800 asynchron=0&lt;br /&gt;
icon=sani_heating_heatpump&lt;br /&gt;
auto=heatpump_auto&lt;br /&gt;
pcurr=Pool_Pin32_monotonic_count_PowerCurrent:W&lt;br /&gt;
etotal=Pool_Pin32_monotonic_count_EnergyMeter:kWh&lt;br /&gt;
switchdev=dum_valve&lt;br /&gt;
swstate=heatpump:on:off&lt;br /&gt;
mode=can&lt;br /&gt;
locktime=600:600&lt;br /&gt;
mintime=SunPath&lt;br /&gt;
on=&amp;quot;heatpump on&amp;quot;&lt;br /&gt;
off=&amp;quot;heatpump off&amp;quot;&lt;br /&gt;
surpmeth=median_13&lt;br /&gt;
noshow=0&lt;br /&gt;
swoncond=dum_valve:sf_true:{main::CheckWPOn}&lt;br /&gt;
interruptable=1&lt;br /&gt;
swoffcond=dum_valve:sf_true:{main::CheckWPOff}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Der Verbrauch ist hier wieder etwas zu hoch angegeben (1800W statt realen 1500W), um eine Hysterese zu erreichen.&lt;br /&gt;
* Da es sich hier um eine Wärmepumpe handelt, die nicht getaktet werden sollte, ist die locktime in beide Schaltrichtungen mit 10 Minuten relativ hoch.&lt;br /&gt;
* Die Ermittlung des Medians ist mit 13 Minuten recht lang, um den Überschuss über lange Zeit zu glätten, damit möglichst selten geschaltet wird. Diese 13 Minuten in Kombination mit der Locktime und der Hysterese führten bei dieser Anlage bisher dazu, dass höchstens 5 Zyklen am Tag geschaltet wurden. -&amp;gt; Hier kann das individuelle Schaltverhalten optimiert werden. Besseres Verfolgen des Überschusses vs. weniger Taktungen der Wärmepumpe.&lt;br /&gt;
* swoncond und swoffcond -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nachbars Pool: (consumer07)&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Shelly_Plug_S_1:Kurz+Pool&lt;br /&gt;
aliasshort=Kurz&lt;br /&gt;
type=other power=650 asynchron=0&lt;br /&gt;
icon=scene_pool&lt;br /&gt;
auto=pool_kurz_auto&lt;br /&gt;
pcurr=power:W&lt;br /&gt;
switchdev=dum_valve&lt;br /&gt;
swstate=pool_kurz:on:off&lt;br /&gt;
mode=can&lt;br /&gt;
mintime=SunPath&lt;br /&gt;
on=&amp;quot;pool_kurz on&amp;quot;&lt;br /&gt;
off=&amp;quot;pool_kurz off&amp;quot;&lt;br /&gt;
surpmeth=median_13&lt;br /&gt;
noshow=0&lt;br /&gt;
interruptable=1&lt;br /&gt;
locktime=600:300&lt;br /&gt;
swoncond=dum_valve:sf_true:{main::Check_Pool_Kurz_On}&lt;br /&gt;
swoffcond=dum_valve:sf_true:{main::Check_Pool_Kurz_Off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Dieser Consumer dient als Einspeisebegrenzungsschutz und wird aktiviert, sobald sich der Überschuss der Einspeisegrenze nähert.  -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
* Verbraucher kann recht träge geschaltet werden. (surpmeth=median_13 und locktime=600:300)&lt;br /&gt;
* Consumer wird ausgeschaltet wenn ein gewisser Überschuss unterschritten wird und somit die Einspeisegrenze wieder weit genug weg ist. -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; &lt;br /&gt;
&#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hier sind die Funktionen, die für diese Regelung verwendet werden, der Übersichtlichkeit halber in einzelnen Blöcken mit Erklärungen dargestellt.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
package main;&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
&lt;br /&gt;
my $pool_dummy = &#039;dum_valve&#039;;&lt;br /&gt;
my $pool_temperature = &#039;Pool_Temp&#039;;&lt;br /&gt;
my $flow_sensor = &#039;Pool_Pin_A0&#039;;&lt;br /&gt;
my $water_counter_l1 = &#039;pump_l1_hc&#039;;&lt;br /&gt;
my $water_counter_l2 = &#039;pump_l2_hc&#039;;&lt;br /&gt;
my $target_temp = 28.4; # maximum temperature for heating, without infeed limit&lt;br /&gt;
my $pool_kurz_sw_hofb = &#039;PwSw_Schalter&#039;; # Homematic switch at pool neighbour&lt;br /&gt;
my $pool_kurz_sw_kurz = &#039;Shelly_Plug_S_1&#039;; # Shelly switch for pool Kurz at home&lt;br /&gt;
&lt;br /&gt;
my $pump_low_id			= sprintf &amp;quot;%02d&amp;quot;, 1;&lt;br /&gt;
my $pump_high_id		= sprintf &amp;quot;%02d&amp;quot;, 3;&lt;br /&gt;
my $heatpump_id			= sprintf &amp;quot;%02d&amp;quot;, 5;&lt;br /&gt;
my $pool_kurz_id		= sprintf &amp;quot;%02d&amp;quot;, 7;&lt;br /&gt;
&lt;br /&gt;
my $switch_delay = 160; # just under three minutes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
SolarForecastUtils_Initialize($$)&lt;br /&gt;
{&lt;br /&gt;
  my ($hash) = @_;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Hier werden die IDs der Geräte definiert, um über sprechende Namen darauf zugreifen zu können.&lt;br /&gt;
* Einige Devices und Parameter, die immer wieder gebraucht werden sind hier angegeben.&lt;br /&gt;
* sprintf wird verwendet um sicherzustellen, dass die IDs zweistellig sind. z.B. 3 -&amp;gt; 03&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pump Low&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
###################&lt;br /&gt;
### Pumpe - LOW ###&lt;br /&gt;
###################&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
Check_Pump_Low_On{&lt;br /&gt;
my $name = &#039;energy_mgmt&#039;;&lt;br /&gt;
my $surplus	= FHEM::SolarForecast::ConsumerVal ($name,$pump_low_id,&#039;surpmethResult&#039;,&#039;&#039;);&lt;br /&gt;
my $nom_power	= FHEM::SolarForecast::ConsumerVal ($name,$pump_low_id,&#039;power&#039;,&#039;&#039;);&lt;br /&gt;
my ($min, $hour) = (localtime())[1,2];&lt;br /&gt;
my $timer = 0;&lt;br /&gt;
if($hour &amp;gt; 8 || ($hour == 8 &amp;amp;&amp;amp; $min &amp;gt;= 0)){$timer=1;}&lt;br /&gt;
&lt;br /&gt;
if(ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;normal&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ($surplus &amp;gt; $nom_power&lt;br /&gt;
		|| $timer&lt;br /&gt;
	)&lt;br /&gt;
)&lt;br /&gt;
	{&lt;br /&gt;
	return 1;}&lt;br /&gt;
else&lt;br /&gt;
	{&lt;br /&gt;
	return 0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
Check_Pump_Low_Off{&lt;br /&gt;
my $bath_mode = ReadingsVal($pool_dummy,&amp;quot;bath_mode&amp;quot;,0);&lt;br /&gt;
my $m3_l1 = ReadingsVal($water_counter_l1,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $m3_l2 = ReadingsVal($water_counter_l2,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $water_volume = AttrVal($pool_dummy,&amp;quot;water_volume&amp;quot;,42); #42m³&lt;br /&gt;
my $desired_cf_l1 = AttrVal($pool_dummy,&amp;quot;desired_cf_l1&amp;quot;,0); #circulation_factor_level1&lt;br /&gt;
my $desired_cf_l2 = AttrVal($pool_dummy,&amp;quot;desired_cf_l2&amp;quot;,0); #circulation_factor_level2&lt;br /&gt;
my $bathmode_factor = AttrVal($pool_dummy,&amp;quot;bathmode_factor&amp;quot;,1);&lt;br /&gt;
my $desired_amount_l1;&lt;br /&gt;
my $desired_amount_l2;&lt;br /&gt;
my $amount = $m3_l1 + $m3_l2;&lt;br /&gt;
if($bath_mode == 1){&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume;&lt;br /&gt;
}else{&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume/$bathmode_factor;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume/$bathmode_factor;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if(($amount &amp;gt; $desired_amount_l1)&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;pump_high&amp;quot;,&amp;quot;on&amp;quot;) eq &amp;quot;off&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;pump_high&amp;quot;,0) &amp;gt;160)&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;normal&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
	{&lt;br /&gt;
		return 1;&lt;br /&gt;
	}else{&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Einschalten:&lt;br /&gt;
&lt;br /&gt;
* Es wird der errechnete Wert für den Überschuss von SolarForecast verwendet und auch der benötigte Überschuss aus dem Consumer ausgelesen.&lt;br /&gt;
* Das Einschalten wird erst durch erfolgreiche Prüfung der Hardwarevoraussetzungen erlaubt. -&amp;gt; Das Motorventil steht richtig und es ist kein Sonderbetrieb (Reinigung, Massage, Winter, o.ä.) aktiv.&lt;br /&gt;
* Es muss entweder genügend Überschuss vorhanden sein oder es ist 8:00.&lt;br /&gt;
&lt;br /&gt;
Ausschalten:&lt;br /&gt;
&lt;br /&gt;
* Wenn der Badebetrieb aktiv ist (bath_mode==1, [bei Außentemperatur &amp;gt; 24°C]) wird nach 90m³ Gesamtumwälzung ausgeschaltet.&lt;br /&gt;
* Wenn der Badebetrieb nicht aktiv ist (bath_mode==0, [bei Außentemperatur &amp;lt; 20°C]) wird bereits nach 42m³ Gesamtumwälzung ausgeschaltet.&lt;br /&gt;
* Prüfung, ob Pump High schon aus ist. Sollte durch die Logik gar nicht möglich sein, aber es könnte manuell oder durch einen (Logik-)Fehler trotzdem eingeschaltet sein.&lt;br /&gt;
* Prüfung, ob alle Hardware-Funktionen in einem für die Automatik geeigneten Zustand sind.&lt;br /&gt;
* Es wird auch geprüft, ob Pump High seit mindestens 3 Minuten aus ist, um zu verhindern, dass wegen fehlendem Überschuss gleich mehrere Geräte ausgeschaltet werden.&lt;br /&gt;
* Da die Zykluszeit 60 Sekunden ist, führen die 160 Sekunden dazu, dass nach drei Minuten(180 Sekunden) ein definierter Wert gilt. Mit 180 Sekunden könnte es manchaml eine Minute mehr sein.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pump High&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
####################&lt;br /&gt;
### Pumpe - HIGH ###&lt;br /&gt;
####################&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
Check_Pump_High_On{&lt;br /&gt;
my $bath_mode = ReadingsVal($pool_dummy,&amp;quot;bath_mode&amp;quot;,0);&lt;br /&gt;
my $m3_l1 = ReadingsVal($water_counter_l1,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $m3_l2 = ReadingsVal($water_counter_l2,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $water_volume = AttrVal($pool_dummy,&amp;quot;water_volume&amp;quot;,42); #42m³&lt;br /&gt;
my $desired_cf_l1 = AttrVal($pool_dummy,&amp;quot;desired_cf_l1&amp;quot;,0); #circulation_factor_level1&lt;br /&gt;
my $desired_cf_l2 = AttrVal($pool_dummy,&amp;quot;desired_cf_l2&amp;quot;,0); #circulation_factor_level2&lt;br /&gt;
my $bathmode_factor = AttrVal($pool_dummy,&amp;quot;bathmode_factor&amp;quot;,1);&lt;br /&gt;
my $desired_amount_l1;&lt;br /&gt;
my $desired_amount_l2;&lt;br /&gt;
my $amount = $m3_l1 + $m3_l2;&lt;br /&gt;
if($bath_mode == 1){&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume;&lt;br /&gt;
}else{&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume/$bathmode_factor;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume/$bathmode_factor;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if(($amount &amp;lt; $desired_amount_l2)&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;normal&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;pump_low&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;pump_low&amp;quot;,0) &amp;gt; $switch_delay)&lt;br /&gt;
)&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
Check_Pump_High_Off{&lt;br /&gt;
my $bath_mode = ReadingsVal($pool_dummy,&amp;quot;bath_mode&amp;quot;,0);&lt;br /&gt;
my $m3_l1 = ReadingsVal($water_counter_l1,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $m3_l2 = ReadingsVal($water_counter_l2,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $water_volume = AttrVal($pool_dummy,&amp;quot;water_volume&amp;quot;,42); #42m³&lt;br /&gt;
my $desired_cf_l1 = AttrVal($pool_dummy,&amp;quot;desired_cf_l1&amp;quot;,0); #circulation_factor_level1&lt;br /&gt;
my $desired_cf_l2 = AttrVal($pool_dummy,&amp;quot;desired_cf_l2&amp;quot;,0); #circulation_factor_level2&lt;br /&gt;
my $bathmode_factor = AttrVal($pool_dummy,&amp;quot;bathmode_factor&amp;quot;,1);&lt;br /&gt;
my $desired_amount_l1;&lt;br /&gt;
my $desired_amount_l2;&lt;br /&gt;
my $amount = $m3_l1 + $m3_l2;&lt;br /&gt;
&lt;br /&gt;
if($bath_mode == 1){&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume;&lt;br /&gt;
}else{&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume/$bathmode_factor;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume/$bathmode_factor;&lt;br /&gt;
}&lt;br /&gt;
if(($amount &amp;gt; $desired_amount_l2)&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;heatpump&amp;quot;,&amp;quot;on&amp;quot;) eq &amp;quot;off&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;heatpump&amp;quot;,0) &amp;gt;160)&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;normal&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Einschalten:&lt;br /&gt;
&lt;br /&gt;
* Prüfung, ob die gewünschte Umwälzung bezüglich des Badebetriebs noch nicht erreicht wurde.&lt;br /&gt;
* Prüfung der Hardwarevoraussetzungen.&lt;br /&gt;
* Prüfung, ob Pump Low schon seit mindestens 3 Minuten aktiv ist. (sollte eigentlich immer der Fall sein, wenn die Automatik für Pump High aktiv ist)&lt;br /&gt;
&lt;br /&gt;
Ausschalten:&lt;br /&gt;
&lt;br /&gt;
* Prüfung, ob die gewünschte Umwälzung bezüglich des Badebetriebs bereits erreicht wurde.&lt;br /&gt;
* Prüfung der Hardwarevoraussetzungen.&lt;br /&gt;
* Prüfung, ob die Wärmepumpe schon seit mindestens 3 Minuten aus ist. Ermöglicht drei Minuten lang, den Median für den Überschuss zu aktualisieren.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wärmepumpe&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
##################&lt;br /&gt;
### Wärempumpe ###&lt;br /&gt;
##################&lt;br /&gt;
sub&lt;br /&gt;
CheckWPOn(){&lt;br /&gt;
my $name = &#039;energy_mgmt&#039;;&lt;br /&gt;
my $surplus_on = 5000; # minimum surplus to avoid infeed limit with heatpump&lt;br /&gt;
my $surplus_restart = 3000; # minimum surplus to re-enable heatpump, when avoidung infeed limit and a big consumer turned the hp off&lt;br /&gt;
&lt;br /&gt;
my $planstate = FHEM::SolarForecast::ConsumerVal ($name,$heatpump_id,&#039;planstate&#039;,&#039;&#039;);&lt;br /&gt;
my $surplus	= FHEM::SolarForecast::ConsumerVal ($name,$heatpump_id,&#039;surpmethResult&#039;,&#039;&#039;);&lt;br /&gt;
if ($planstate =~ /^([^:]+)/) {&lt;br /&gt;
	$planstate = $1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if(ReadingsVal($flow_sensor,&amp;quot;reading&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;&lt;br /&gt;
		|| ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;party&amp;quot;&lt;br /&gt;
	)&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&#039;heat_protection&#039;,&#039;on&#039;) eq &amp;quot;off&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;normal&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;pump_high&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;pump_high&amp;quot;,0) &amp;gt; $switch_delay)&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_temperature,&amp;quot;temperature&amp;quot;,30) &amp;lt; $target_temp &lt;br /&gt;
		|| (ReadingsVal($pool_temperature,&amp;quot;temperature&amp;quot;,15) &amp;gt;= $target_temp&lt;br /&gt;
			&amp;amp;&amp;amp; ( $surplus &amp;gt; $surplus_on&lt;br /&gt;
				|| (($planstate eq &amp;quot;replanned&amp;quot;) &amp;amp;&amp;amp; ($surplus &amp;gt; $surplus_restart))&lt;br /&gt;
			)&lt;br /&gt;
		)&lt;br /&gt;
	)&lt;br /&gt;
)&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
CheckWPOff{&lt;br /&gt;
my $name = &#039;energy_mgmt&#039;;&lt;br /&gt;
my $surplus_off = 1000; #minimum surplus to keep heatpump on, when avoiding infeed limit&lt;br /&gt;
&lt;br /&gt;
my $surplus	= FHEM::SolarForecast::ConsumerVal ($name,$heatpump_id,&#039;surpmethResult&#039;,&#039;&#039;);&lt;br /&gt;
if((ReadingsVal($flow_sensor,&amp;quot;reading&amp;quot;,&amp;quot;on&amp;quot;) eq &amp;quot;off&amp;quot;&lt;br /&gt;
	|| !((ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;) &lt;br /&gt;
		|| (ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;party&amp;quot;)&lt;br /&gt;
	)&lt;br /&gt;
	|| ReadingsVal($pool_dummy,&#039;heat_protection&#039;,&#039;off&#039;) eq &amp;quot;on&amp;quot;&lt;br /&gt;
	|| ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) ne &amp;quot;normal&amp;quot;&lt;br /&gt;
	|| ((ReadingsVal($pool_temperature,&amp;quot;temperature&amp;quot;,15) &amp;gt; $target_temp)&lt;br /&gt;
		&amp;amp;&amp;amp; ($surplus &amp;lt; $surplus_off)&lt;br /&gt;
		)&lt;br /&gt;
	)&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;heatpump&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;heatpump&amp;quot;,0) &amp;gt; $switch_delay)&lt;br /&gt;
)&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Einschalten:&lt;br /&gt;
&lt;br /&gt;
* Prüfung, ob Flussensor ein. (Pool_pin_A0) -&amp;gt; Wasser fließt durch die Wärmepumpe.&lt;br /&gt;
* Prüfung, ob Pool in Normal- oder Partybetrieb ist und das Ventil in Normalposition ist. In beiden Fällen läuft Pump High.&lt;br /&gt;
* Einschalten wenn genug Überschuss da ist und die Temperatur &amp;lt;28.4°C ist oder wenn über 5000W Überschuss (Einspeisebegrenzung bei 5900W) da ist, egal wie warm der Pool ist.&lt;br /&gt;
* Sonderfall: Wenn die Wärmepumpe durch einen/mehrere Großverbrucher &amp;quot;kurz&amp;quot; ausgeschaltet wurde (swoffcond) wird sie ausgeplant. Ein Notify plant sie wieder ein. Wenn das passiert, soll die Wärmepumpe aber wieder bei 3000W Überschuss gestartet werden, um die Energie noch weiter zu nutzen bis der Überschuss unter 1000W fällt. (Hysterese von 500W, da die WP nur 1500W braucht)&lt;br /&gt;
&lt;br /&gt;
Ausschalten:&lt;br /&gt;
&lt;br /&gt;
* Ausschalten sobald hardwaremäßig irgendetwas faul ist. (Betriebsart, Ventilstellung, Durchfluss)&lt;br /&gt;
* Ausschalten wenn kein Überschuss. (interruptable=1)&lt;br /&gt;
* Wenn Wassertemperatur über 28,5°C und der Überschuss kleiner als 1000W ist.&lt;br /&gt;
* Nur schalten, wenn Wärmepumpe läuft und seit mindestens 3 Minuten läuft (Sicherheit). Das verhindert das erneute Triggern des Notifys, wenn die Pumpe schon aus ist. Sollte nicht passieren, aber sicher ist sicher.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nachbar Pool&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
###################&lt;br /&gt;
### Pool - KURZ ###&lt;br /&gt;
###################&lt;br /&gt;
sub&lt;br /&gt;
Check_Pool_Kurz_On{&lt;br /&gt;
my $name = &#039;energy_mgmt&#039;;&lt;br /&gt;
my $surplus	= FHEM::SolarForecast::ConsumerVal ($name,$pool_kurz_id,&#039;surpmethResult&#039;,&#039;&#039;);&lt;br /&gt;
if(($surplus &amp;gt; 3000)&lt;br /&gt;
	&amp;amp;&amp;amp; ((ReadingsVal($pool_dummy,&amp;quot;heatpump&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;heatpump&amp;quot;,0) &amp;gt;160) || ReadingsVal($pool_dummy,&#039;heat_protection&#039;,&#039;off&#039;) eq &#039;on&#039; ))&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
Check_Pool_Kurz_Off{&lt;br /&gt;
my $name = &#039;energy_mgmt&#039;;&lt;br /&gt;
my $surplus	= FHEM::SolarForecast::ConsumerVal ($name,$pool_kurz_id,&#039;surpmethResult&#039;,&#039;&#039;);&lt;br /&gt;
if(($surplus &amp;lt; 1000 )&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;pool_kurz&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;pool_kurz&amp;quot;,0) &amp;gt;160))&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Einschalten:&lt;br /&gt;
&lt;br /&gt;
* Überschuss ist nahe der Einspeisegrenze (5900W) und Wärmepumpe läuft seit mindestens 3 Minuten. Es wird schon bei 3000W eingeschaltet, um dem Nachbarn etwas Gutes zu tun ;-)&lt;br /&gt;
&lt;br /&gt;
Ausschalten:&lt;br /&gt;
&lt;br /&gt;
* Überschuss ist unter 1000W. -&amp;gt; Um noch Reserven für den eigenen Verbrauch zu haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hilfsfunktionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hier erfolgt nach jedem Zyklus die Festlegung der verschiedenen Automatikmodi.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#############################################################&lt;br /&gt;
##################### Exit Function #########################&lt;br /&gt;
#############################################################&lt;br /&gt;
my $ctrl_dummy	= &amp;quot;dum_valve&amp;quot;; # dummy device for pool-control&lt;br /&gt;
my $automatic	= ReadingsNum($ctrl_dummy,&amp;quot;sf_automatic&amp;quot;,1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if($automatic){&lt;br /&gt;
&lt;br /&gt;
	my $pump_low_state = ReadingsVal($ctrl_dummy,&#039;pump_low&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pump_low_auto	= FHEM::SolarForecast::ConsumerVal ($name, $pump_low_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Pumpe&lt;br /&gt;
&lt;br /&gt;
	my $pump_high_state = ReadingsVal($ctrl_dummy,&#039;pump_high&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pump_high_auto	= FHEM::SolarForecast::ConsumerVal ($name, $pump_high_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Pumpe&lt;br /&gt;
&lt;br /&gt;
	my $heatpump_state = ReadingsVal($ctrl_dummy,&#039;heatpump&#039;,&#039;on&#039;);&lt;br /&gt;
	my $heatpump_auto	= FHEM::SolarForecast::ConsumerVal ($name, $heatpump_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Wärmepumpe&lt;br /&gt;
	my $pool_heat_protection = ReadingsVal($ctrl_dummy,&#039;heat_protection&#039;,&#039;on&#039;);&lt;br /&gt;
&lt;br /&gt;
	my $pool_kurz_state = ReadingsVal($ctrl_dummy,&#039;pool_kurz&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pool_kurz_auto	= FHEM::SolarForecast::ConsumerVal ($name, $pool_kurz_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus des Pools&lt;br /&gt;
&lt;br /&gt;
	my $pump_low_delay	= FHEM::SolarForecast::ConsumerVal ($name, $pump_low_id, &#039;surpmeth&#039;, &#039;&#039;);&lt;br /&gt;
	if ($pump_low_delay =~ /_(\d+)/) {&lt;br /&gt;
    	$pump_low_delay = int(($1/2 + 1) * 60);&lt;br /&gt;
		Log3 (&amp;quot;SolarForecast&amp;quot;, 1, &amp;quot;SolarForecast: pump_low_delay: $pump_low_delay&amp;quot;);&lt;br /&gt;
	} else {&lt;br /&gt;
    	$pump_low_delay = 220;&lt;br /&gt;
		Log3 (&amp;quot;SolarForecast&amp;quot;, 1, &amp;quot;SolarForecast: warning - surpmeth for pump_low is: $pump_low_delay, but must be given as method_number, using fallback value&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	my $pump_high_delay	= FHEM::SolarForecast::ConsumerVal ($name, $pump_high_id, &#039;surpmeth&#039;, &#039;&#039;);&lt;br /&gt;
	if ($pump_high_delay =~ /_(\d+)/) {&lt;br /&gt;
    	$pump_high_delay = int(($1/2 + 1) * 60);&lt;br /&gt;
	} else {&lt;br /&gt;
    	$pump_high_delay = 160;&lt;br /&gt;
		Log3 (&amp;quot;SolarForecast&amp;quot;, 1, &amp;quot;SolarForecast: warning - surpmeth for pump_high is: $pump_high_delay, but must be given as method_number, using fallback value&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	my $heatpump_delay	= FHEM::SolarForecast::ConsumerVal ($name, $heatpump_id, &#039;surpmeth&#039;, &#039;&#039;);&lt;br /&gt;
	if ($heatpump_delay =~ /_(\d+)/) {&lt;br /&gt;
    	$heatpump_delay = int(($1/2 + 1) * 60);&lt;br /&gt;
	} else {&lt;br /&gt;
    	$heatpump_delay = 290;&lt;br /&gt;
		Log3 (&amp;quot;SolarForecast&amp;quot;, 1, &amp;quot;SolarForecast: warning - surpmeth for heatpump is: $heatpump_delay, but must be given as method_number, using fallback value&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	my $pool_kurz_delay	= FHEM::SolarForecast::ConsumerVal ($name, $pool_kurz_id, &#039;surpmeth&#039;, &#039;&#039;);&lt;br /&gt;
	if ($pool_kurz_delay =~ /_(\d+)/) {&lt;br /&gt;
    	$pool_kurz_delay = int(($1/2 + 1) * 60);&lt;br /&gt;
	} else {&lt;br /&gt;
    	$pool_kurz_delay = 160;&lt;br /&gt;
		Log3 (&amp;quot;SolarForecast&amp;quot;, 1, &amp;quot;SolarForecast: warning - surpmeth for pool_kurz is: $pool_kurz_delay, but must be given as method_number&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
############################&lt;br /&gt;
# Überhitzungsschutz aktiv #&lt;br /&gt;
############################&lt;br /&gt;
&lt;br /&gt;
if($pool_heat_protection eq &#039;on&#039;){&lt;br /&gt;
	if($heatpump_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy heatpump_auto 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	if($heatpump_state eq &amp;quot;on&amp;quot;){&lt;br /&gt;
			fhem(&amp;quot;set $ctrl_dummy heatpump off&amp;quot;)&lt;br /&gt;
	}&lt;br /&gt;
	#################&lt;br /&gt;
	#### on-chain ###&lt;br /&gt;
	#################&lt;br /&gt;
	if($pump_low_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pump_low&#039;,0) &amp;gt; $pump_high_delay &amp;amp;&amp;amp; $pump_high_auto == 0  &amp;amp;&amp;amp; $pool_kurz_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pump_high_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pump_high&#039;,0) &amp;gt; $pool_kurz_delay &amp;amp;&amp;amp; $pool_kurz_auto == 0 &amp;amp;&amp;amp; $pump_high_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pool_kurz_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pool_kurz_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $pool_kurz_auto == 1 &amp;amp;&amp;amp; $pump_high_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	#################&lt;br /&gt;
	### off-chain ###&lt;br /&gt;
	#################&lt;br /&gt;
	if($pool_kurz_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pool_kurz&#039;,0) &amp;gt; $pump_high_delay &amp;amp;&amp;amp; $pool_kurz_auto == 1 &amp;amp;&amp;amp; $pump_high_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pump_high_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high_auto == 1 &amp;amp;&amp;amp; $pool_kurz_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pool_kurz_auto 0&amp;quot;);&lt;br /&gt;
	}elsif($pump_low_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high_auto == 1 &amp;amp;&amp;amp; $pool_kurz_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
##################################&lt;br /&gt;
# Überhitzungsschutz nicht aktiv #&lt;br /&gt;
##################################&lt;br /&gt;
}else{&lt;br /&gt;
	if($heatpump_auto == 0 &amp;amp;&amp;amp; $heatpump_state eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		if($pool_kurz_state eq &amp;quot;on&amp;quot;){&lt;br /&gt;
			fhem(&amp;quot;set $ctrl_dummy pool_kurz off&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if($pool_kurz_auto == 1){&lt;br /&gt;
			fhem(&amp;quot;set $ctrl_dummy pool_kurz_auto 0&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	#################&lt;br /&gt;
	#### on-chain ###&lt;br /&gt;
	#################&lt;br /&gt;
	if($pump_low_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pump_low&#039;,0) &amp;gt; $pump_high_delay &amp;amp;&amp;amp; $pump_high_auto == 0 &amp;amp;&amp;amp; $heatpump_auto == 0 &amp;amp;&amp;amp; $pool_kurz_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pump_high_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pump_high&#039;,0) &amp;gt; $heatpump_delay &amp;amp;&amp;amp; $heatpump_auto == 0 &amp;amp;&amp;amp; $pool_kurz_auto == 0 &amp;amp;&amp;amp; $pump_high_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy heatpump_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($heatpump_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;heatpump&#039;,0) &amp;gt; $pool_kurz_delay &amp;amp;&amp;amp; $pump_high_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $pool_kurz_auto == 0 &amp;amp;&amp;amp; $pump_high_auto == 1 &amp;amp;&amp;amp; $heatpump_auto == 1){&lt;br /&gt;
		# pump_high muss on sein, da sonst die automatik ausgeschaltet wird wenn die pumpe gerade interrupted ist.&lt;br /&gt;
		# Bei unterschiedlichen Medianlängen ist es möglich, dass WP ein ist und pump_high abschaltet wegen surplus == 0&lt;br /&gt;
		# Nachbarpool würde auf EIN warten, aber pump_high dürfte nicht wieder einschalten, obwohl genügend Überschuss da ist.&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 0&amp;quot;);&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pool_kurz_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pool_kurz_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $pool_kurz_auto == 1 &amp;amp;&amp;amp; $heatpump_auto == 1 &amp;amp;&amp;amp; $pump_high_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy heatpump_auto 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	#################&lt;br /&gt;
	### off-chain ###&lt;br /&gt;
	#################&lt;br /&gt;
	if($pool_kurz_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pool_kurz&#039;,0) &amp;gt; $heatpump_delay &amp;amp;&amp;amp; $pool_kurz_auto == 1 &amp;amp;&amp;amp; $heatpump_auto == 0 &amp;amp;&amp;amp; $pump_high_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy heatpump_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($heatpump_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;heatpump&#039;,0) &amp;gt; $pump_high_delay &amp;amp;&amp;amp; $heatpump_auto == 1 &amp;amp;&amp;amp; $pump_high_auto == 0 &amp;amp;&amp;amp; $pool_kurz_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pool_kurz_auto 0&amp;quot;);&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pump_high_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $heatpump_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high_auto == 1 &amp;amp;&amp;amp; $heatpump_auto == 1 &amp;amp;&amp;amp; $pool_kurz_auto == 0){&lt;br /&gt;
#	heatpump muss aus sein, da sonst vor Ablauf der Locktime die Automatik ausgeschaltet wird und die WP nicht mehr ausschalten kann.&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy heatpump_auto 0&amp;quot;);&lt;br /&gt;
	}elsif($pump_low_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high_auto == 1 &amp;amp;&amp;amp; $heatpump_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
#################################################&lt;br /&gt;
# Check hardware-state vs. reading-state&lt;br /&gt;
# re-trigger notify&lt;br /&gt;
#################################################&lt;br /&gt;
my $delay_retrigger = 100; #delay time to wait until re-trigger the notify&lt;br /&gt;
&lt;br /&gt;
if(ReadingsVal($ctrl_dummy,&#039;pool_kurz&#039;,&#039;on&#039;) eq &#039;off&#039; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pool_kurz&#039;,0) &amp;gt; $delay_retrigger &amp;amp;&amp;amp; ReadingsVal($pool_kurz_sw_kurz,&#039;state&#039;,&#039;off&#039;) eq &#039;on&#039;){&lt;br /&gt;
	# re-trigger notify&lt;br /&gt;
	fhem(&amp;quot;trigger dum_valve pool_kurz: off&amp;quot;);&lt;br /&gt;
	Log3 (&amp;quot;SolarForecast&amp;quot;, 1, &amp;quot;SolarForecast: Pool-Kurz-off must be re-triggered&amp;quot;);&lt;br /&gt;
	DebianMail(&#039;clemens@familie-hofbauer.at&#039;,&#039;Notify Pool Kurz&#039;,&amp;quot;Notify hat nicht ausgeschaltet -&amp;gt; re-trigger&amp;quot;);&lt;br /&gt;
}elsif(ReadingsVal($ctrl_dummy,&#039;pool_kurz&#039;,&#039;off&#039;) eq &#039;on&#039; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pool_kurz&#039;,0) &amp;gt; $delay_retrigger &amp;amp;&amp;amp; ReadingsVal($pool_kurz_sw_kurz,&#039;state&#039;,&#039;on&#039;) eq &#039;off&#039;){&lt;br /&gt;
	# re-trigger notify&lt;br /&gt;
	fhem(&amp;quot;trigger dum_valve pool_kurz: on&amp;quot;);&lt;br /&gt;
	Log3 (&amp;quot;SolarForecast&amp;quot;, 1, &amp;quot;SolarForecast: Pool-Kurz-on must be re-triggered&amp;quot;);&lt;br /&gt;
	DebianMail(&#039;clemens@familie-hofbauer.at&#039;,&#039;Notify Pool Kurz&#039;,&amp;quot;Notify hat nicht eingeschaltet -&amp;gt; re-trigger&amp;quot;);&lt;br /&gt;
}elsif((ReadingsVal($pool_kurz_sw_kurz,&#039;state&#039;,&#039;off&#039;) eq &#039;set_on&#039; || ReadingsVal($pool_kurz_sw_kurz,&#039;state&#039;,&#039;off&#039;) eq &#039;set_off&#039;) &amp;amp;&amp;amp; ReadingsAge($pool_kurz_sw_kurz,&#039;state&#039;,0) &amp;gt; $delay_retrigger){&lt;br /&gt;
	# state not clear&lt;br /&gt;
	Log3 (&amp;quot;SolarForecast&amp;quot;, 1, &amp;quot;SolarForecast: Pool-Kurz state unclear&amp;quot;);&lt;br /&gt;
	DebianMail(&#039;clemens@familie-hofbauer.at&#039;,&#039;Status Pool Kurz unklar&#039;,&amp;quot;Status HM-Schalter set_xx&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Erläuterungen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Verzögerungen der einzelnen Stufen:&#039;&#039;&#039;&lt;br /&gt;
** Die delays der einzelnen Stufen werden aus den surpmethods berechnet. Das dient dazu, dass der Median mit den Werten nach dem ein-/ausschalten des vorheriegen Verbrauchers bis zur Hälfte + einen Wert gefüllt wird und somit sicher das Umschalten des vorherigen Verbrauchers den Median nicht mehr beeinflusst.&lt;br /&gt;
* &#039;&#039;&#039;Überhitzungsschutz:&#039;&#039;&#039;&lt;br /&gt;
** Da durch die Wärmepumpe Überschuss &amp;quot;verheizt&amp;quot; wird, der durch das Einspeiselimit gar nicht produziert würde, kann es vorkommen, dass der Pool unangenehm warm wird.&lt;br /&gt;
** Um das zu vermeiden gibt es ein Reading, welches gesetzt wird, wenn der Pool eine gewisse Temperatur überschreitet. Dieses Setzen und Zurücksetzen erfolgt mit einer Hysterese von 0.2°C, um ein Takten der Wärmepumpe zu verhindern. Diese 0.4°C sind bei dieser Wassermenge einige Stunden.&lt;br /&gt;
** Wenn der Überhitzungsschutz aktiv ist, wird die Wärmepumpe in der Kette übersprungen.&lt;br /&gt;
** Wenn sich der Hitzeschutz während des Betriebs ändert, wird die Wärmepumpe bzw. der Pool vom Nachbarn passend ausgeschaltet und die Modi entsprechend gesetzt.&lt;br /&gt;
* &#039;&#039;&#039;On-chain:&#039;&#039;&#039;&lt;br /&gt;
** Wenn am Morgen Pump Low seit $pump_low_delay aktiv ist und alle folgenden Consumer noch nicht, dann wird die nächste Stufe freigegeben. -&amp;gt; Pump High&lt;br /&gt;
** Wenn Pump High seit $pump_high_delay aktiv ist und alle folgenden Consumer noch nicht, wird die Wärmepumpe freigegeben. -&amp;gt; Heatpump&lt;br /&gt;
** Wenn die Wärmepumpe seit $heatpump_delay aktiv ist und der letzte Consumer noch nicht, wird der letzte Verbraucher freigegeben. -&amp;gt; Pool Kurz Gleichzeitig wird die Automatik für Pump High ausgeschaltet, da dieser Verbraucher erst unterbrochen werden darf wenn die Wärmepumpe aus ist!&lt;br /&gt;
** Wenn der letzte Verbraucher aktiviert ist, wird die Automatik der Wärmepumpe deaktiviert, da ja zuerst der letzte Verbraucher (Pool Kurz) wieder ausgeschaltet werden muss, bevor der vorletzte (Wärmepumpe) wieder ausgeschaltet werden darf. Da es keinen nachfolgenden Verbraucher mehr gibt, kann hier auf ein delay verzichtet werden, da es nicht passieren kann, dass zwei Verbraucher wegen sehr hohem Überschuss unmittelbar hintereinander geschaltet werden können.&lt;br /&gt;
[[Datei:Poolsteuerung mit unterschiedlichen Automatikmodi.jpg|alternativtext=Poolsteuerung|mini|Consumer der Poolsteuerung|500x500px]]&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Es dürfen immer nur maximal zwei unterbrechbare Consumer im Automatikmodus sein. Der &amp;quot;aktuelle&amp;quot;, der ja aufgrund von fehlendem Überschuss jederzeit unterbrochen werden kann und der &amp;quot;folgende&amp;quot; Consumer, der auf das Einschalten wartet. Pump Low ist immer im Automatikmodus, da diese nie unterbrochen wird. (mode=must, interruptable=0)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Off-chain:&#039;&#039;&#039;&lt;br /&gt;
** Wenn der letzte Verbraucher seit mindestens der delay-Zeit aufgrund von fehlendem Überschuss inaktiv war, im Automatikmodus ist und der vorherige Verbraucher nicht im Automatikmodus ist, wird der vorherige Verbraucher in den Automatikmodus geschaltet und wartet jetzt auch auf das Ausschalten. Wenn der Überschuss steigt, springt man wieder in die on-chain und der letzte Verbraucher wird eingeschaltet und die Automatik des vorletzten Verbrauchers deaktiviert.&lt;br /&gt;
** Wenn die Wärmepumpe seit mindestens der delay-Zeit aus ist, sich im Automatikmodus befind und Pump High noch nicht im Automatikmodus ist, wird die Automatik für den Nachbarpool ausgeschaltet, da er ja jetzt nicht mehr einschalten darf, da zuerst die Wärmepumpe ein sein müsste. Die Automatik von Pump High wird wieder aktiviert, da diese jetzt auf das Ausschalten wartet. Steigt der Überschuss wieder, wird in den entsprechenden On-chain Zweig gesprungen.&lt;br /&gt;
** Wenn Pump High mindestens die delay-Zeit aus ist, wird die Automatik der Wärmepumpe deaktiviert, da diese ja erst einschalten darf, wenn Pump High wieder läuft. Steigender Überschuss führt wieder zum aktivieren von Pump High und zum Sprung in den entsprechenden On-chain Zweig.&lt;br /&gt;
** Wenn Pump Low ausgeschaltet wird, wird sofort die Automatik für Pump High ausgeschaltet, da durch das spätere Ausschalten von (der evtl. wieder eingeschalteten) Pump High, hardwaremäßig wieder Pump Low aktiviert wird, aber durch SolarForecast nie ausgeschaltet wird, da Pump Low vor ein paar Minuten ja schon logisch ausgeschaltet wurde.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Es dürfen immer nur maximal zwei unterbrechbare Consumer im Automatikmodus sein. Der &amp;quot;aktuelle&amp;quot;, der ja aufgrund von neuem Überschuss jederzeit wieder gestartet werden kann und der &amp;quot;vorherige&amp;quot; Consumer, der auf das Ausschalten wartet.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Synchronisation Hardware vs. Reading:&#039;&#039;&#039;Manchmal passiert es, dass durch die etwas aufwendigen Umschaltprozesse die Hardware dem Reading nicht folgt/folgen kann. Evtl. Gründe sind Funkunterbrechung, verzögerte Umschaltung usw. Daher wird bei jedem Zyklus der Status geprüft und evtl. das event nochmal getriggert, um die Umschaltung erneut auszuführen.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hilfs-Notifys für die Automatik&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Da durch das Verwenden von swoffcond die Verbraucher beim Ausschalten auch ausgeplant werden, aber eigentlich &amp;quot;nur&amp;quot; unterbrochen werden sollen, müssen sie wieder neu eingeplant werden. Dazu sind notifys nötig. Wichtig: IDs müssen zweistellig angegeben werden!&lt;br /&gt;
&lt;br /&gt;
Wärmepumpe:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:heatpump:.off sleep 10; set energy_mgmt consumerNewPlanning 05&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Nachbar Pool:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:pool_kurz:.off sleep 10; set energy_mgmt consumerNewPlanning 07&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Eine Pumpe mit einem Energiezähler als zwei Consumer verwenden&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
Die verwendete Pumpe hat vier Betriebsarten mit unterschiedlichen Leistungen. Da sie als zwei Consumer abgebildet wird, führt das dazu, dass die Leistung fälschlicherweise von SolarForecast auch zweimal gezählt wird. Die Lösung sind Dummy-Readings, welche die Leistungsdaten passend auseinander rechnen.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Pool_Strom_Pumpe:Pool_Pin31_monotonic_count_PowerCurrent:.* {&lt;br /&gt;
my $power = $EVTPART1;&lt;br /&gt;
my $pump_low = ReadingsVal(&#039;dum_valve&#039;,&#039;pump_low&#039;,&#039;off&#039;);&lt;br /&gt;
my $pump_high = ReadingsVal(&#039;dum_valve&#039;,&#039;pump_high&#039;,&#039;off&#039;);&lt;br /&gt;
my $power_low_sim = 250;&lt;br /&gt;
&lt;br /&gt;
if($pump_low eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $pump_high eq &amp;quot;on&amp;quot;){	&lt;br /&gt;
	my $power_low = $power_low_sim; #fiktiver Verbrauch der niedrigen Stufe&lt;br /&gt;
	my $power_high = $power - $power_low_sim;&lt;br /&gt;
	fhem(&amp;quot;set dum_valve pump_low_power $power_low&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set dum_valve pump_high_power $power_high&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
elsif($pump_low eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $pump_high eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_low_power $power&amp;quot;);&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_high_power 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
elsif($pump_low eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_low_power 0&amp;quot;);&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_high_power 0&amp;quot;);&lt;br /&gt;
}elsif($pump_low eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high eq &amp;quot;on&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_low_power 0&amp;quot;);&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_high_power $power&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Es sind alle vier Möglichkeiten der zwei Pumpenlevel abgebildet.&lt;br /&gt;
* Wenn die Automatik deaktiviert ist und die Level 1-4 von extern geschaltet werden, zählen sie dadurch korrekterweise nicht zu diesen beiden Consumern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notifys für das hardwaremäßige Schalten der Consumer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es werden einige Notifys verwendet, die die Umsetzung vom Dummy-Device auf die Hardware erledigen, da ein logisches Ein teilweise hardwaremäßig einige Dinge erfordert.&lt;br /&gt;
&lt;br /&gt;
Notify für Pump Low:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:pump_low:.* {&lt;br /&gt;
	if($EVTPART1 eq &amp;quot;on&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin26 on; sleep 60; set Pool_Pin25 on; sleep 1; set Pool_Pin26 off&amp;quot;);&lt;br /&gt;
	}elsif($EVTPART1 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin14 off; sleep 5; set Pool_Pin12 off; sleep 15; set Pool_Pin25 off&amp;quot;);&lt;br /&gt;
	}else{&lt;br /&gt;
	Log3 (&amp;quot;Pool&amp;quot;, 4, qq{Notify Level1 - parameter is not on or off});&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Beim Einschalten ist es nötig für eine Minute Pump High zu aktivieren, um Luft aus der Elektrolysezelle zu spülen, bevor Pump Low aktiv sein darf. (Pin26 und Pin25 sind die Steuerpins auf der Interfacekarte der Pumpe für die beiden Level.)&lt;br /&gt;
* Beim Ausschalten werden zuerst die Salzanlage (Pin14) und die pH-Anlage (Pin12) deaktiviert, damit noch 15 Sekunden lang die Elektrolysezelle mit frischem Wasser gespült wird, um das verbleibende Chlor auszuspülen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Notify für Pump High:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:pump_high:.* {&lt;br /&gt;
	if($EVTPART1 eq &amp;quot;on&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin26 on; sleep 1; set Pool_Pin25 off&amp;quot;);&lt;br /&gt;
	}elsif($EVTPART1 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin25 on; sleep 1; set Pool_Pin26 off&amp;quot;);&lt;br /&gt;
	}else{&lt;br /&gt;
	Log3 (&amp;quot;Pool&amp;quot;, 4, qq{Notify Level 2- parameter is not on or off});&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterung:&lt;br /&gt;
&lt;br /&gt;
* Da die Interfacekarte immer auf den höchsten Level reagiert, wird beim Umschalten zuerst Pump High aktiviert und nach einer Sekunde Pump Low deaktiviert, um ein &amp;quot;stufenloses&amp;quot; (ohne Ausschalten) Umschalten zu ermöglichen. Beim Ausschalten genauso.&lt;br /&gt;
&lt;br /&gt;
Notify für die Wärmepumpe:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:heatpump:.* {&lt;br /&gt;
	if($EVTPART1 eq &amp;quot;on&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin6 on&amp;quot;);&lt;br /&gt;
	}elsif($EVTPART1 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin6 off&amp;quot;);&lt;br /&gt;
	}else{&lt;br /&gt;
	Log3 (&amp;quot;Pool&amp;quot;, 4, qq{Notify heatpump - parameter is not on or off});&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterung:&lt;br /&gt;
&lt;br /&gt;
* Hier reicht ein dirketes Übernehmen aus dem Dummy.&lt;br /&gt;
&lt;br /&gt;
Notify für den Nachbar-Pool:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:pool_kurz:.* {&lt;br /&gt;
	if($EVTPART1 eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsVal(&amp;quot;Shelly_Plug_S_1&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;on&amp;quot;) eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set PwSw_Schalter off; sleep 3;{if(ReadingsAge(\&amp;quot;PwSw_Schalter\&amp;quot;,\&amp;quot;state\&amp;quot;,0)&amp;lt;4 &amp;amp;&amp;amp; ReadingsVal(\&amp;quot;PwSw_Schalter\&amp;quot;,\&amp;quot;state\&amp;quot;,\&amp;quot;on\&amp;quot;) eq \&amp;quot;off\&amp;quot;){fhem(\&amp;quot;set Shelly_Plug_S_1 on\&amp;quot;)}}; sleep 5; set PwSw_Schalter on&amp;quot;);&lt;br /&gt;
	}elsif($EVTPART1 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; ReadingsVal(&amp;quot;Shelly_Plug_S_1&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set PwSw_Schalter off; sleep 3;{if(ReadingsAge(\&amp;quot;PwSw_Schalter\&amp;quot;,\&amp;quot;state\&amp;quot;,0)&amp;lt;4 &amp;amp;&amp;amp; ReadingsVal(\&amp;quot;PwSw_Schalter\&amp;quot;,\&amp;quot;state\&amp;quot;,\&amp;quot;on\&amp;quot;) eq \&amp;quot;off\&amp;quot;){fhem(\&amp;quot;set Shelly_Plug_S_1 off\&amp;quot;)}}; sleep 5; set PwSw_Schalter on&amp;quot;);&lt;br /&gt;
	}else{&lt;br /&gt;
	Log3 (&amp;quot;Pool&amp;quot;, 4, qq{Notify Pool Kurz - parameter is not on or off});&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterung&lt;br /&gt;
&lt;br /&gt;
* Da hier eine Pumpe durch einen 3-poligen Umschalter zwischen zwei Hausanspeisungen umgeschaltet wird, ist es wichtig, dass die Pumpe dazwischen &#039;&#039;&#039;gesichert&#039;&#039;&#039; zum Stehen gebracht wird! Sonst führt die rotierende Pumpe als Generator zu einem gewaltigen Kurzschluss mit der &amp;quot;fremden&amp;quot; Phase. War nicht schön ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sonderprogramme für den Poolbetrieb&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hier ist das Aus- und Einschalten der Solarforcast-Automatik zu sehen. Es werden alle Stati gespeichert. Danach kann von beliebigen &amp;quot;Sonderfunktionen&amp;quot; (Reinigung des Filters, Massagefunktion, usw.) auf die Hardware zugegriffen werden. Wenn wieder in den Automatikmodus zurückgewechselt wird, wird hardwaremäßig wieder der Zustand der Automatik von vorher hergestellt, die Stati wieder zurück geschrieben und die Automatik wieder aktiviert.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
##############################################&lt;br /&gt;
# Status speichern und Automatik ausschalten #&lt;br /&gt;
##############################################&lt;br /&gt;
sub PoolAutoOff{&lt;br /&gt;
	my $pump_low_id			= sprintf &amp;quot;%02d&amp;quot;, 1;&lt;br /&gt;
	my $pump_high_id		= sprintf &amp;quot;%02d&amp;quot;, 3;&lt;br /&gt;
	my $heatpump_id			= sprintf &amp;quot;%02d&amp;quot;, 5;&lt;br /&gt;
	my $pool_kurz_id		= sprintf &amp;quot;%02d&amp;quot;, 7;&lt;br /&gt;
	my $sf				= &#039;energy_mgmt&#039;;&lt;br /&gt;
&lt;br /&gt;
		&lt;br /&gt;
#	my $pump_low_state = ReadingsVal($valve_dummy,&#039;pump_low&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pump_low_auto	= FHEM::SolarForecast::ConsumerVal ($sf, $pump_low_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Pumpe&lt;br /&gt;
#	my $pump_high_state = ReadingsVal($valve_dummy,&#039;pump_high&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pump_high_auto	= FHEM::SolarForecast::ConsumerVal ($sf, $pump_high_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Pumpe&lt;br /&gt;
#	my $heatpump_state = ReadingsVal($valve_dummy,&#039;heatpump&#039;,&#039;on&#039;);&lt;br /&gt;
	my $heatpump_auto	= FHEM::SolarForecast::ConsumerVal ($sf, $heatpump_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Wärmepumpe&lt;br /&gt;
#	my $pool_kurz_state = ReadingsVal($valve_dummy,&#039;pool_kurz&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pool_kurz_auto	= FHEM::SolarForecast::ConsumerVal ($sf, $pool_kurz_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus des Pools&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pump_low_auto 0&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pump_high_auto 0&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy heatpump_auto 0&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pool_kurz_auto 0&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy sf_automatic 0&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pump_low $pump_low_auto&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pump_high $pump_high_auto&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_heatpump $heatpump_auto&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pool_kurz $pool_kurz_auto&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	my $last_pump_level_1 = ReadingsVal($valve_dummy,&amp;quot;pump_low&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_2 = ReadingsVal($valve_dummy,&amp;quot;pump_high&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_3 = ReadingsVal($pump_level_3,&amp;quot;value&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_4 = ReadingsVal($pump_level_4,&amp;quot;value&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_heatpump = ReadingsVal($valve_dummy,&amp;quot;heatpump&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_1 $last_pump_level_1&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_2 $last_pump_level_2&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_3 $last_pump_level_3&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_4 $last_pump_level_4&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_heatpump $last_heatpump&amp;quot;); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
##########################################&lt;br /&gt;
# Status laden und Automatik einschalten #&lt;br /&gt;
##########################################&lt;br /&gt;
sub PoolAutoOn{&lt;br /&gt;
	my $last_pump_level_4 = ReadingsVal($valve_dummy,&amp;quot;last_pump_level_4&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_3 = ReadingsVal($valve_dummy,&amp;quot;last_pump_level_3&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_2 = ReadingsVal($valve_dummy,&amp;quot;last_pump_level_2&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_1 = ReadingsVal($valve_dummy,&amp;quot;last_pump_level_1&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_heatpump = ReadingsVal($valve_dummy,&amp;quot;last_heatpump&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $pump_level_4 $last_pump_level_4&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;set $pump_level_3 $last_pump_level_3&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $pump_level_2 $last_pump_level_2&amp;quot;);&lt;br /&gt;
	if($last_pump_level_1 eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $last_pump_level_2 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_3 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_4 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set $pump_level_2 on; sleep 1; set $pump_level_1 $last_pump_level_1; sleep 28; set $pump_level_2 off; set $valve_dummy sf_automatic 1&amp;quot;);&lt;br /&gt;
	}elsif($last_pump_level_1 eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $last_pump_level_2 eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $last_pump_level_3 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_4 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set $pump_level_1 off; set $valve_dummy sf_automatic 1&amp;quot;); &lt;br /&gt;
	}elsif($last_pump_level_1 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_2 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_3 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_4 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set $pump_level_1 off; set $valve_dummy sf_automatic 1&amp;quot;); &lt;br /&gt;
	}&lt;br /&gt;
	fhem(&amp;quot;sleep 10; set $heatpump $last_heatpump&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_1 none&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_2 none&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_3 none&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_4 none&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_heatpump none&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy valve_position normal&amp;quot;);&lt;br /&gt;
	my $last_auto_pump_low = ReadingsVal($valve_dummy,&amp;quot;last_auto_pump_low&amp;quot;,0);&lt;br /&gt;
	my $last_auto_pump_high = ReadingsVal($valve_dummy,&amp;quot;last_auto_pump_high&amp;quot;,0);&lt;br /&gt;
	my $last_auto_heatpump = ReadingsVal($valve_dummy,&amp;quot;last_auto_heatpump&amp;quot;,0);&lt;br /&gt;
	my $last_auto_pool_kurz = ReadingsVal($valve_dummy,&amp;quot;last_auto_pool_kurz&amp;quot;,0);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pump_low_auto $last_auto_pump_low&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pump_high_auto $last_auto_pump_high&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy heatpump_auto $last_auto_heatpump&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pool_kurz_auto $last_auto_pool_kurz&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pump_low none&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pump_high none&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_heatpump none&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pool_kurz none&amp;quot;);&lt;br /&gt;
}		&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* pump_level_1 ist Pump Low, pump_level_2 ist Pump High, pump_level_3 und pump_level_4 sind Sonderfunktionen (Filterreinigung, Massage)&lt;br /&gt;
* Beim Wiedereinschalten von Pump Low ist es wieder nötig kurz Pump High zu aktivieren, um Luft auszuspülen.&lt;br /&gt;
* Es wird der Zustand von Solarforecast gespeichert und danach auf die Hardware geschrieben. -&amp;gt; Stellt sicher, dass nach dem Einschalten der Automatik der logical switchstate zum physical switchstate passt.&lt;br /&gt;
&lt;br /&gt;
== Tips &amp;amp; Tricks ==&lt;br /&gt;
* Interruptable verhält sich völlig anders, wenn der Perlcode 1 oder 0 liefert, als wenn man 1 oder 0 in der Config hinterlegt. -&amp;gt; siehe commandref&lt;br /&gt;
* Rückgabewert bei swoncond und swoffcond wird mit dem Readingswert verglichen und nicht dirket verwendet. Bsp. wenn das Reading 100 enthält muss auch der Rückgabewert des Perlcodes 100 liefern, um true zu ergeben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== weiterführende Links ==&lt;br /&gt;
* Forenthema &amp;quot;{{Link2Forum|Topic=137058|LinkText=76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support}}&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;
* Photovoltaik Ingenieurbüro Junge: https://www.ing-büro-junge.de/html/photovoltaik.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung&amp;diff=40366</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=40366"/>
		<updated>2025-09-08T14:20:03Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Hinweis|Die vorliegende Wiki-Seite befindet sich im Aufbau.}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Solarprognose und Verbrauchersteuerung&lt;br /&gt;
|ModType=d&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 Prognosewerte können die SolCast API, OpenMeteo API, Forecast.Solar API, Victron VRM Portal API oder alternativ DWD Stahlungswerte-Stationen verwendet werden&lt;br /&gt;
&lt;br /&gt;
::* optionale KI Unterstützung der PV-Prognose bei Verwendung von geeigneten Solar-API&#039;s&lt;br /&gt;
&lt;br /&gt;
::* es wird sowohl die Erzeugungsprognose als auch eine Verbrauchsprognose sowie SoC Prognose (bei Batterie-Integration) erstellt&lt;br /&gt;
&lt;br /&gt;
::* Wetterdaten werden über DWD Wetter-Stationen oder verschiedene API integriert. Es können verschiedene API zur Gewinnung von Solar- und Wetterdaten kombiniert werden. &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 FHEM-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 Integration von bis zu 4 Inverter und Smartloader (DC-DC Batterieladegeräte) ist möglich&lt;br /&gt;
&lt;br /&gt;
::* eine Integration von bis zu 3 nicht PV-Energieerzeugern wie BHKW, Windrädern oder Notstromaggregaten ist möglich&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;
::* Einbindung von bis zu drei Batteriespeichersystemen&lt;br /&gt;
&lt;br /&gt;
::* Bereitstellung von Leitwerten zur optimalen Einstellung/Steuerung von Batteriespeichersystemen&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 Benutzererlebnis 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;
Das Wiki gibt allgemeingültige und teilweise sehr spezifische bzw. tiefgehende Informationen und Handlungsempfehlungen zum SolarForecast Modul. Die dargestellten Informationen beziehen sich auf den zum Zeitpunkt der Wiki-Erstellung vorhandenen Entwicklungsstand des Moduls. Durch die stetige Weiterentwicklung können sich Abweichungen zum beschriebenen Inhalt ergeben oder zur Obsoleszenz dieser Inhalte führen. &lt;br /&gt;
&lt;br /&gt;
Vergleiche deshalb die Informationen immer mit der aktuellen Befehls-Referenz zum Modul!&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Ein SolarForecast Device wird mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 define &amp;lt;Name&amp;gt; SolarForecast &lt;br /&gt;
&lt;br /&gt;
angelegt. Nach der Definition wird der User durch einen Dialog geführt, der einige unerlässliche Einstellungen abfragt und in den entsprechenden Attributen und Readings persistiert. Alle Attribute und Readings die eine Einstellung der Anlage bewirken, sind mit dem Präfix &amp;quot;setup&amp;quot; versehen. &lt;br /&gt;
&lt;br /&gt;
Die Verwendung von setup-Readings gestattet es die Anlagenparameter dynamisch im Betrieb zu verändern. So kann mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringAzimuth   bzw.&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringDeclination &lt;br /&gt;
&lt;br /&gt;
die Ausrichtung und der Neigungswinkel der PV-Module ständig angepasst werden, was zum Beispiel bei einer dem Sonnenstand nachgeführten Anlage von Bedeutung ist.&lt;br /&gt;
&lt;br /&gt;
Die abgefragten Einstellungen während des Dialoges sind ausführlich in den entsprechenden Attributen bzw. Set-Kommandos erläutert. Die benötigten Informationen sind anhängig von der gewählten Prognose-API und können im Umfang variieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 213257.png|right|thumb|400px|Anlagenprüfung über Drucktaste in der Kopfgrafik]]&lt;br /&gt;
&lt;br /&gt;
Sobald alle verlangten Einstellungen vorgenommen sind, sollte eine Anlagenprüfung mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; plantConfiguration check&lt;br /&gt;
&lt;br /&gt;
oder über die angebotene Drucktaste in der Grafik durchgeführt werden. Es wird eine Plausibilitätsprüfung vorgenommen und das Ergebnis sowie eventuelle Hinweise bzw. Fehler ausgegeben.&lt;br /&gt;
Die Prüfung kann beliebig wiederholt werden und sollte sich bei jeder Einstellungsänderung der Anlage durchgeführt werden. Dadurch wird die Wahrscheinlichkeit von fehlerhaften Einstellungen minimiert.&lt;br /&gt;
&lt;br /&gt;
Neben den grundlegenden Einstellungen können im Device weitere sekundäre Anlagenkomponenten wie Batteriesystem(e) (Attribut setupBatteryDev1 - setupBatteryDev3), weitere Wetter-Devices (Attribut setupWeatherDev1 - setupWeatherDev3) oder sonstige Erzeuger (z.B. BHKW, Winderzeugung, Notstromaggregat) integriert werden (Attribut setupOtherProducer01 - setupOtherProducer03).&lt;br /&gt;
&lt;br /&gt;
Die verlangten Parameter der Anlage werden in der Online-Hilfe umfassend beschrieben und deren Funktion erschließt sich zum größten Teil selbst. Dennoch soll nachfolgend auf einige Punkte im Zusammenhang der Einrichtung eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Hinweise zur Struktur der Attribute ===&lt;br /&gt;
&lt;br /&gt;
Durch die umfangreichen Funktionen des Moduls würde bei Nutzung der im FHEM herkömmlich vorhandenen Attributstruktur die Anzahl der benötigten Attribute extrem stark steigen und nicht sinnvoll genutzt werden können. Deshalb gibt es neben den &#039;&#039;gewöhnlichen&#039;&#039; Attributen mit einfachen Werteauswahlmöglichkeiten oder Eingaben (z.B. ctrlDebug, ctrlSpecialReadings) sogenannte &#039;&#039;zusammengesetzte&#039;&#039; Attribute, deren Inhalt durch &#039;&#039;&#039;Schlüssel=Wert Paare&#039;&#039;&#039; gebildet wird und dadurch deutlich mehr Funktionen und Informationen transportieren als ein gewöhnliches Attribut.&lt;br /&gt;
&lt;br /&gt;
Für zusammengesetzte Attribute besteht die zusätzliche Möglichkeit, gewünschte Änderungen der Schlüssel=Wert Paare selektiv vornehmen zu können, ohne das gesamte Attribut aufrufen und ändern zu müssen. Die Vorgang, der vor allem für programmtechnische Manipulationen gedacht ist, kann durch eine Set-Funktion ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; attrKeyVal &amp;lt;Attribut&amp;gt; [&amp;lt;Gerät&amp;gt;] &amp;lt;Schlüssel=Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiele für zusammengesetzte Attribute sind:&lt;br /&gt;
&lt;br /&gt;
* aiControl&lt;br /&gt;
* plantControl&lt;br /&gt;
* setup* Attribute&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktionen der Attribute werden durch einen Präfix geclustert und so inhaltlich, aber vor allem auch in der Attribute Drop-Down Liste, strukturiert dargestellt.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der &#039;&#039;&#039;Präfixe&#039;&#039;&#039; sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ai&#039;&#039;&#039; - Steuerungsfunktionen für KI (z.B. aiControl)&lt;br /&gt;
* &#039;&#039;&#039;consumer&#039;&#039;&#039; - Registrierung und Einstellungen für Verbraucher (z.B. consumer02, consumerControl)&lt;br /&gt;
* &#039;&#039;&#039;ctrl&#039;&#039;&#039; - Steuerungsfunktion allgemeiner Art (z.B. ctrlDebug, ctrlSpecialReadings, ctrlUserExitFn)&lt;br /&gt;
* &#039;&#039;&#039;flowGraphic&#039;&#039;&#039; - Einstellungen für die Energieflußgrafik (z.B. flowGraphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphic&#039;&#039;&#039; - Einstellung für die Grafik allgemein (z.B. graphicSelect, graphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphicBeam&#039;&#039;&#039; -  Einstellungen bestimmte Balkeneigenschaften in der Balkengrafik (z.B. graphicBeamHeightLevel1)&lt;br /&gt;
* &#039;&#039;&#039;plant&#039;&#039;&#039; - übergreifende Einstellungen betreffend der gesamten PV-Anlage bzw. des SolarForecast-Devices (z.B. plantControl)&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039; - Registrierung von Geräten in der Gesamtanlage und Einstellung deren Eigenschaften (Inverter, Zähler, Batterien usw.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Einrichtung der Wechselrichter mit setupInverterDevXX ===&lt;br /&gt;
&lt;br /&gt;
Mit den Attributen setupInverterDev01 bis setupInverterDevXX werden die vorhandenen Wechselrichter der Anlage registriert.&lt;br /&gt;
Das Modul unterscheidet verschiedene Wechselrichter-Typen, die sich durch ihre Arbeitsweise innerhalb der Anlage unterscheiden. Die Schlüssel=Wert Paare in den Attributen können mehrzeilig organisiert werden. Das erleichtert die Übersicht wenn viele dieser Parameter eingegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;PV-Wechselrichter: Es ist der Standard Wechselrichter in einer PV-Anlage. An ihn sind die Solarzellen bzw. Strings angeschlossen. Die zugeordneten Strings können mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ohne diese Angabe werden diesem Gerät alle definierten Strings (siehe Attribut &#039;&#039;setupInverterStrings&#039;&#039;) zugeordnet. Der Wechselrichter liefert seine Energie in das Hausnetz. Alternativ kann mit der Angabe &#039;&#039;&#039;feed=grid&#039;&#039;&#039; die Funktion des Wechselrichters geändert werden. Diese Angabe sagt aus, dass dieser Wechselrichter ausschließlich in das öffentliche Netz einspeist.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel-Setup eines PV-Wechselrichters (SMA STP):&lt;br /&gt;
&lt;br /&gt;
 STP_5000 pvIn=string_1_pdc:kW pvOut=total_pac:kW etotal=etotal:kWh capacity=5000 strings=Süddach asynchron=1 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Solar-Ladegeräte: Solar-Ladegeräte sind DC-DC Wandler und liefern die Energie der angeschlossenen Solarzellen nicht in das Wechselstromnetz, sondern laden direkt eine Batterie bzw. versorgen einen Batteriewechselrichter auf der Gleichstromseite. Die Funktion als Solar-Ladegerät wird mit &#039;&#039;&#039;feed=bat&#039;&#039;&#039; aktiviert, die relevanten Strings können ebenfalls mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ein Beispiel eines Solar-Ladegerätes ist ein Victron SmartSolar MPPT. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel für das Setup eines Solar-Ladegeräts (SmartSolar Charger MPPT):&lt;br /&gt;
&lt;br /&gt;
 MQTT2_cerboGX_c0619ab34e08_solarcharger_Common pv=Yield_Power_value:W etotal=Yield_System_value:kWh capacity=2080 strings=Schleppdach feed=bat synchron=0 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Batterie-Wechselrichter: Dieses Gerät hat keine angeschlossenen Solarzellen und arbeitet als DC-AC bzw. AC-DC Wandler zwischen einer Batterie (=Gleichstromquelle) und dem Wechselstrom-Hausnetz. Die Funktion als Batterie-Wechselrichter wird mit der Angabe &#039;&#039;&#039;strings=none&#039;&#039;&#039; aktiviert. Die Schlüssel &#039;&#039;etotal&#039;&#039; und &#039;&#039;pv&#039;&#039; können bei einem Batterie-Wechselrichter ohne zugeordnete Solarzellen nicht gesetzt werden. Ein Beispiel eines Batterie-Wechselrichter ist der Victron MultiPlus II.&lt;br /&gt;
&lt;br /&gt;
Ein Setup-Beispiel für einen Batterie-Wechselrichter (Victron MultiPlus II):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dc2ac=DC_IN:W&lt;br /&gt;
ac2dc=DC_OUT:W&lt;br /&gt;
capacity=7200&lt;br /&gt;
strings=none&lt;br /&gt;
icon=inverter@darkorange:inverter@grey&lt;br /&gt;
asynchron=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Eigenschaften des Wechselrichters werden durch eine Reihe von &amp;lt;Schlüssel=Wert&amp;gt; Paaren festgelegt. Auf einige dieser Paramter soll hier eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Ausgewählte Schlüssel=Wert Paare ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;pvIn=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvIn&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell zugeführte PV-Leistung bereitstellt. Der Schlüssel ist optional und dient in erster Linie dazu den entsprechenden Input-Wert in der Flußgrafik anzuzeigen sofern man das Attribut flowGraphicControl-&amp;gt;showGenerators=1 setzt. Dadurch ist auch der Eigenverbrauch des Inverters bzw. dessen Wandlungsverlust visuell abschätzbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pvOut=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvOut&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell erzeugte Leistung als positiven Wert liefert. Für einen PV-Wechselrichter (DC-&amp;gt;AC) oder Solar-Ladegerät (DC-&amp;gt;DC) ist es die erzeugte PV-Leistung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ac2dc=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter vom Hausnetz in Richtung Batterie (AC-&amp;gt;DC) wandelt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;dc2ac=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter aus einer Gleichstromquelle, d.h. einer Batterie oder einem Solar-Ladegerät, in Richtung des Hausnetzes (AC) wandelt . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;capacity=&amp;lt;max. WR-Leistung&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In dem Schlüssel &#039;&#039;capacity&#039;&#039; wird die maximal mögliche Leistung in Watt (ohne Einheit) angegeben, die der Wechselrichter lt. seinem Datenblatt in der Lage ist zu leisten. &lt;br /&gt;
&lt;br /&gt;
Die Angabe &#039;&#039;capacity&#039;&#039; hat in erster Linie die Aufgabe, die max. mögliche PV-Leistung für die Prognose zu begrenzen. Oft sind die installierten Peak-Leistungen der PV-Module höher als die angeschlossene Wechselrichter-Leistung bzw. kommt es vor, dass die KI / (korrigierte) API-Prognose über der maximal möglichen Wechselrichter-Leistung liegt. In diesen Fällen wird die Prognose auf die angegebene &#039;&#039;capacity&#039;&#039; begrenzt.&lt;br /&gt;
&lt;br /&gt;
Der Wert in diesem Schlüssel kann, wie andere Schlüssel auch, dynamisch zur Laufzeit mit dem Set-Befehl &amp;quot;[[#Hinweise zur Struktur der Attribute|set &amp;lt;Name&amp;gt; attrKeyVal ...]]&amp;quot; geändert werden. Ein Beispiel zur Anwendung ergibt sich aus folgendem Szenario.&lt;br /&gt;
&lt;br /&gt;
Gegeben sei eine Anlage die aus Solarzellen (1300 W Peak) mit einem Solar-Ladegerät mit max. 1800 W Leistung, einer Batterie und einem Batterie-Wechselrichter besteht. Die Anlage versorgt nur das Hausnetz. Eine Netzeinspeisung ist nicht vorgesehen oder nicht erlaubt.  &lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, es ist ein Tag voller Sonnenschein prognostiziert und die Batterie ist zunächst entladen. Der Haushalt verbraucht 300 W. Dann würden die PV-Module Module ihre volle Leistung von 1300 W Peak leisten können, die sich auch in der Balken-Vorhersage niederschlägt. Die Leistung wird nicht begrenzt, weil:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* sie niedriger ist als die nominale und angegebene Wechselrichter Kapazität von &#039;&#039;capacity=1800&#039;&#039;&lt;br /&gt;
* die erzeugte Energie anteilig für die Verorgung des Hauses und die Aufladung der Batterie verwendet wird&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders verhält es sich wenn nach einer gewissen Zeit die Batterie voll ist und weiterhin volle PV Leistung zur Verfügung steht. In diesem Fall würde der Haushalt seine benötigte Leistung von 300 W abnehmen, aber das Solar-Ladegerät kann keine weitere Leistung mehr abgeben, da die Batterie bereits voll geladen ist, d.h. die Anlagensteuerung würde die PV-Anlage abregeln. In diesem Fall, wenn es einen längeren Zeitraum betrifft, muß auch die Prognose PV-Energie auf 300 Wh (bzw. den durchschnittlichen Energieverbrauch des Hauses pro Stunde) begrenzt werden, damit die PV-Prognose nach unten angepasst wird und so eine realitätsnahere Prognose ermöglicht wird. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;icon=&amp;lt;aktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;][:&amp;lt;inaktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Jeder Wechselrichter wird im Standard durch ein Icon getrennt nach Tag und Nacht, d.h. je nach Aktiv-Status und Inaktiv-Status, symbolisiert.&lt;br /&gt;
&lt;br /&gt;
;Tag bzw. Aktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Sonnensymbol im Standard verwendet. Batterie-Wechselrichter verwenden ein gefärbtes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
;Nacht bzw. Inaktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Symbol der aktuellen Mondphasen im Standard verwendet. Batterie-Wechselrichter verwenden ein ausgegrautes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie angegeben, kann man für Tag und Nacht jeweils ein Wunsch-Icon, wenn gewünscht mit einer alternativen Färbung, auswählen.&lt;br /&gt;
&lt;br /&gt;
 icon=inverter@darkorange:inverter@gray&lt;br /&gt;
&lt;br /&gt;
Soll nur das Icon für die Nacht bzw. Inaktivät geändert werden, kann dies in dieser Form angegeben werden:&lt;br /&gt;
&lt;br /&gt;
 icon=:inverter@gray  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(beachte den führenden &#039;:&#039;)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Der integrierte SolarForecast Grafikbereich ==&lt;br /&gt;
Das SolarForecast Modul beinhaltet eine Grafikdarstellung die sich in mehrere Bereiche gliedert. Diese Bereiche können über Attribute ein- bzw. ausgeblendet sowie die Inhalte festgelegt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 223545.png|right|thumb|400px|Bereiche der integrierten Grafik]]&lt;br /&gt;
&lt;br /&gt;
Der nebenstehende Screenshot gibt die Gliederung der Grafikbereiche wieder:&lt;br /&gt;
&lt;br /&gt;
 1 - der Kopfbereich (Graphic Header)&lt;br /&gt;
 2 - durch den Nutzer selbst definierbarer Inhalt (Graphic Header Own Specification) als Teil des Kopfbereiches&lt;br /&gt;
 3 - Bereich Verbraucherdarstellung (Consumer Legend)&lt;br /&gt;
 4 - Bereich Balkengrafik (Beam Graphic)&lt;br /&gt;
 5 - Energieflußgrafik (Flow Graphic)&lt;br /&gt;
&lt;br /&gt;
Jeder dieser Bereiche hat spezifische Steuerungsattribute zur Anpassung des Verhaltens und ggf. des Inhalts.&lt;br /&gt;
&lt;br /&gt;
=== 1 - Der Grafik Kopfbereich ===&lt;br /&gt;
Im Kopfbereich befinden sich fest verankerte Informationen zur verwendeten Vorhersage-API sowie deren Status, Informationen zum Sonnenaufgang und Sonnenuntergang, dem aktuellen Gesamtstatus des SolarForecast Devices, Abweichungskennzahlen der PV Vorhersage sowie weitere Kennzeichen zur Verfügung.&lt;br /&gt;
Über zwei Drucktasten kann eine Anlagenprüfung durchgeführt und in den Spportthread des Moduls im FHEM Forum abgesprungen werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;graphicHeaderShow&#039;&#039;&#039; kann der gesamte Kopfbereich 1 und 2 (nutzereigener Teilbereich) ausgeblendet werden. Wird der Kopbereich ausgeblendet, ist es hilfreich mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;showLink&#039;&#039;&#039; einen Link zur Detailgrafik einzufügen da der in der Kopfgrafik integrierte Link in diesem Fall nicht mehr zur Verfügung steht. &lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;graphicHeaderDetail&#039;&#039;&#039; definiert welche Bereiche des Grafikkopfes angezeigt werden sollen. Es kann die Anzeige des Energieverbrauches, der PV-Erzeugung und der vom Nutzer selbst definierte Inhalt miteinander frei kombiniert werden.&lt;br /&gt;
&lt;br /&gt;
=== 2 - Der Bereich mit selbst definierbarem Inhalt (Graphic Header Own Specification) ===&lt;br /&gt;
In diesem Bereich kann der User beliebige Readings, Set-Kommandos und Attribute des SolarForecast Devices oder anderer Devices, die sich im gleichen FHEM-System wie das SolarForecast Device befinden, anzeigen lassen.&lt;br /&gt;
&lt;br /&gt;
Dieser Bereich ist als Tabelle mit einer beliebigen Anzahl von Zeilen organisiert. Jede Zeile beinhaltet ein Kommentarfeld und vier Nutzfelder zur Darstellung ausgewähler Werte + Label. Der Bereich bzw. der Inhalt des Bereiches wird mit dem Attribut &#039;&#039;&#039;graphicHeaderOwnspec&#039;&#039;&#039; definiert.  &lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt ein real gesetztes graphicHeaderOwnspec Attribut. Die Leerzeilen sind nicht notwendig, erhöhen aber die Lesbarkeit der Struktur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
Autarkierate:Current_AutarkyRate&lt;br /&gt;
PV&amp;amp;nbsp;übermorgen:special_dayAfterTomorrowPVforecast&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;Sunset:special_todayConForecastTillSunset&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;nächsten&amp;amp;nbsp;Sunrise:special_conForecastTillNextSunrise&lt;br /&gt;
&lt;br /&gt;
#Batterie&lt;br /&gt;
BatteryLive&amp;amp;nbsp;Status:userFn_BatLive_State&lt;br /&gt;
SoC&amp;amp;nbsp;Limit:Settings_CGwacs_BatteryLife_MinimumSocLimit_value@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SoC&amp;amp;nbsp;Ist:SOC_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
SOC&amp;amp;nbsp;Optimum:Battery_OptimumTargetSoC&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
aktuelle&amp;amp;nbsp;Ladung:userFn_Bat_EnergyState&lt;br /&gt;
Verfügbar:userFn_BatLive_UsableEnergy&lt;br /&gt;
benötigte&amp;amp;nbsp;Ladeenergie:userFn_Bat_EnergyRemain&lt;br /&gt;
Ladefreigabe:Battery_ChargeRecommended&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
akt.&amp;amp;nbsp;DC&amp;amp;nbsp;Strom:DC_Current_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
Restladezeit&amp;amp;nbsp;Ziel:userFn_Bat_HoursUntilChargeFinish&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Soll:userFn_Bat_MaxChargeCurrent_set&lt;br /&gt;
:&lt;br /&gt;
&lt;br /&gt;
#Settings&lt;br /&gt;
Batterie&amp;amp;nbsp;Lademanagement:userFn_BatteryChargeManagement&lt;br /&gt;
SoC&amp;amp;nbsp;Management:userFn_BatterySoCManagement&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Ist:MaxChargeCurrent@MQTT2_cerboGX_c0619ab34e08_vebus&lt;br /&gt;
SmartSolar&amp;lt;br&amp;gt;Einspeisung:OvervoltageFeedIn@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
MPII&amp;amp;nbsp;Limit&amp;lt;br&amp;gt;Einspeisung&amp;amp;nbsp;(W):MaxFeedInPower@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SOC&amp;amp;nbsp;Limit&amp;amp;nbsp;Soll:MinimumSocLimit@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Verbr.&amp;amp;nbsp;Neuplanung:consumerNewPlanning&lt;br /&gt;
Wetteranzeige:graphicShowWeather &lt;br /&gt;
&lt;br /&gt;
Anzeige&amp;amp;nbsp;Nachtstunden:graphicShowNight&lt;br /&gt;
hist.&amp;amp;nbsp;Stunden:graphicHistoryHour&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto&lt;br /&gt;
Victron&amp;amp;nbsp;BatteryLife&amp;lt;br&amp;gt;(1=an,10=aus):BatteryLife@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Debug:ctrlDebu&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Kommentarfeld am Beginn einer Zeile wird durch ein &#039;&#039;&#039;#&#039;&#039;&#039; gekennzeichnet. Folgt dem # ein String, wird dieser String als Kommentarangabe gewertet und in der Grafik ausgegeben. Ein leeres Kommentarfeld wird lediglich durch ein # gefolgt von einem Leerzeichen oder NL beschrieben:&lt;br /&gt;
&lt;br /&gt;
 #:&amp;lt;Text&amp;gt;  (bzw nur # für einen &#039;leeren&#039; Titel)&lt;br /&gt;
&lt;br /&gt;
Ein Netzfeld bzw. ein Datensatz wird durch die Angabe von einem Label und dem darzustellenden Wert getrennt durch &#039;:&#039; definiert:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Label&amp;gt;:&amp;lt;Reading, Attribut oder Set-Kommando&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das System erkennt selbständig, ob es sich bei der Angabe um ein Reading, Attribut oder ein Set-Kommando handelt. Sollen Readings, Set-Kommandos und Attribute anderer Devices als dem SolarForecast-Device angezeigt werden, kann dies einfach durch Zusatz von&lt;br /&gt;
&lt;br /&gt;
 ....@&amp;lt;Device-Name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
an den Parameter erreicht werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-12-05 203916.png|right|thumb|400px|Darstellung eigener Grafikbereich]]&lt;br /&gt;
Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten &amp;quot;Wh&amp;quot; bzw. &amp;quot;kWh&amp;quot; werden entsprechend der Einstellung des Attributs &#039;&#039;&#039;graphicEnergyUnit&#039;&#039;&#039; umgerechnet. Im Label sind Leerzeichen durch &amp;quot;&amp;amp;amp;nbsp;&amp;quot; einzufügen, ein Zeilenumbruch durch &amp;quot;&amp;amp;lt;br&amp;amp;gt;&amp;quot;. Ein leeres Feld in einer Zeile wird durch &amp;quot;:&amp;quot; ohne eine weitere Angabe erzeugt.&lt;br /&gt;
&lt;br /&gt;
Die nebenstehende Abbildung zeigt die reale Darstellung der oben angegebenen Struktur im Attribut graphicHeaderOwnspec.&lt;br /&gt;
&lt;br /&gt;
==== Formatierung der Inhalte im Bereich &amp;quot;Graphic Header Own Specification&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
Die angezeigten Inhalte, wie z.B. Readingwerte, des User eigenen Bereiches (Attribut graphicHeaderOwnspec) können durch Spezifikationen im Attribut &#039;&#039;&#039;graphicHeaderOwnspecValForm&#039;&#039;&#039; manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
Die Online-Hilfe zum Attribut graphicHeaderOwnspecValForm erläutert die verfügbaren Möglichkeiten und Optionen.&lt;br /&gt;
Als Beispiel hier einige mögliche Notationen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &#039;userFn_Bat_HoursUntilChargeFinish&#039;                        =&amp;gt; &amp;quot;($VALUE).&#039; Stunden&#039;&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_battery.SOC_value&#039;             =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Settings_CGwacs_BatteryLife_MinimumSocLimit_value&#039;        =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Info_MaxChargeCurrent_value&#039;                              =&amp;gt; &amp;quot;($VALUE).&#039; A&#039;&amp;quot;,&lt;br /&gt;
  &#039;DC_Current_value&#039;                                         =&amp;gt; &amp;quot;%.0f A&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common.Regulated&#039; =&amp;gt; &amp;quot;($VALUE eq &#039;1&#039; ? &#039;Ja&#039; : &#039;Nein&#039;)&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine Besonderheit besteht bei darzustellenden Werten die die Einheiten &#039;Wh&#039; bzw. &#039;kWh&#039; besitzen. Diese Werte und Einheiten werden automatisch entsprechend des gesetzten Attributes graphicEnergyUnit umgerechnet und angezeigt.&lt;br /&gt;
&lt;br /&gt;
Soll in diesen Fällen eine automatische Formatierung umgangen werden, kann eine solche Notation verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &#039;Today_PVforecast&#039; =&amp;gt; &amp;quot;(sprintf &#039;%.1f &amp;amp;amp;nbsp;kWh&#039;, ($VALUE / 1000))&amp;quot;,&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Die Angabe von &amp;amp;amp;nbsp; vor &#039;kWh&#039; verhindert die Erkennung der Einheit und so auch die automatische Umsetzung durch das Modul. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 3 - Bereich Verbraucherdarstellung (Consumer Legend) ===&lt;br /&gt;
Dieser Grafikbereich zeigt die im Modul registrierten Verbraucher sowie deren Status und weitere Informationen an. Sind die Voraussetzungen gegeben, d.h. entsprechende Schlüssel in der ConsumerXX-Attributen gesetzt, können die Verbraucher über das Paneel manuell geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Zur Anpassung der Darstellung sind verschiedene Attribute verfügbar:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;consumerControl-&amp;gt;showLegend: Definiert die Lage bzw. Darstellungsweise der Verbraucherlegende sofern Verbraucher im SolarForecast Device registriert sind.&lt;br /&gt;
;consumerControl-&amp;gt;adviceIcon: Definiert die Art der Information über die geplanten Schaltzeiten eines Verbrauchers in der Verbraucherlegende. &lt;br /&gt;
;consumerControl-&amp;gt;detailLink: Wenn gesetzt, ist der jeweilige Verbraucher klickbar um direkt zur Detailansicht des jeweiligen Geräts auf einer neuen Browserseite zu gelangen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Standard wird das Verbraucherpaneel zwischen dem Kopfbereich und der ersten Balkengrafik Ebene dargestellt. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;showLegend&#039;&#039;&#039; und Argument &#039;&#039;&#039;icon_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_bottom&#039;&#039;&#039; kann das Verbraucherpaneel an das Ende des Grafikbereiches verschoben werden.&lt;br /&gt;
Die Verwendung von &#039;&#039;&#039;text_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_top&#039;&#039;&#039; blendet die Icon-Spalte im Verbraucherpaneel aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Screenshot 2025-02-08 093239.png|Darstellung mit consumerControl showLegend=icon_top (default)&lt;br /&gt;
File:Screenshot 2025-02-08 093646.png|Darstellung mit consumerControl showLegend=icon_bottom&lt;br /&gt;
File:Screenshot 2025-02-08 152018.png|Darstellung mit consumerControl showLegend=text_top bzw. text_bottom&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 213634.png|right|thumb|400px|]]&lt;br /&gt;
Ein Mouse-Over über das Uhrensymbol zeigt nähere Informationen zum Status, den Planungsdaten, Modus und weitere Daten des Verbrauchers. Der Schalter &amp;quot;Aus/Ein&amp;quot; visualisiert den Schaltzustand des Verbrauchers und können auch zum manuellen Schalten des Verbrauchers dienen. Voraussetzung ist, dass im consumer-Attribut die Schlüssel &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; mit den Set-Kommandos zum Schalten des Verbrauchers defininiert sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 222210.png|right|thumb|300px|]]&lt;br /&gt;
Der Auto-Schieberegler zeigt einerseits den Freigabestatus zum Schalten des Verbrauchers durch das SolarForecast Modul und kann andererseits manuell betätigt werden. Der Status des Reglers korrespondiert mit dem im zugehörigen Consumer Attribut vorhandenen Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; angegebenen Reading-Wert.&lt;br /&gt;
&lt;br /&gt;
Die Verbraucherbezeichnungen in dem Paneel können in der Standardkonfiguration angeklickt werden um direkt zur Detailansicht des Devices zu gelangen. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;detailLink&#039;&#039;&#039; kann der Link zur Detailansicht deaktiviert werden.&lt;br /&gt;
&lt;br /&gt;
Das Uhrensymbol kann mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;adviceIcon&#039;&#039;&#039; geändert und/oder dessen Farbe angepasst, sowie einen Informationstext statt eines Icons angezeigt werden. &lt;br /&gt;
&lt;br /&gt;
=== 4 - Bereich Balkengrafik (Beam Graphic) ===&lt;br /&gt;
&lt;br /&gt;
Die Balkengrafik des Moduls ist ein wesentliches Visualisierungshilfsmittel. Im Auslieferungszustand existiert eine Balkengrafikebene, die &#039;&#039;&#039;Ebene 1&#039;&#039;&#039;.&lt;br /&gt;
Jede Ebene kann zwei Balkendiagramme mit auswählbaren Inhalten, Farben und einstellbarem LayoutTyp darstellen. In Ebene 1 kann die Wettervorhersage eingebettet oder, bei Vorhandensein von Batteriegeräten, die zukünftigen Zeiten mit empfohlener Ladefreigabe und SoC-Prognose eingeblendet werden. &lt;br /&gt;
&lt;br /&gt;
Welche Daten in welchen Zeiträumen dargestellt werden sollen, die Bestimmung des Layouts, die Gestaltung der Balken und einiges mehr wird durch Attribute gesteuert. Ein Teil dieser Einstellungen wird über das zusammengesetzete Attribut &#039;&#039;&#039;graphicControl-&amp;gt;&#039;Schlüssel&#039;=&#039;Wert&#039;&#039;&#039;&#039; eingestellt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;grundsätzliche Layout Definitionen&#039;&#039;&#039;&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204342.png|right|thumb|400px|Standardanzeige mit Wetter-Icons, gesetzen Attributen graphicBeam1Color=D4C177, graphicHistoryHour=11]]&lt;br /&gt;
&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingTop:Legt den Platz in px im Balkendiagramm fest, der zwischen dem oberen Rand der jeweiligen Balkengrafik Ebene und der ersten Text- oder Iconreihe dieser Ebene eingefügt wird.&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingBottom:Legt den Platz in px im Balkendiagramm fest, der zwischen der letzten Text- oder Iconreihe der jeweiligen Balkengrafik Ebene und dem unteren Rand dieser Ebene eingefügt wird. &lt;br /&gt;
;graphicControl-&amp;gt;layoutType:Layout-Optionen zur grundlegenden Gestaltung der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourStyle:Format der Zeitangabe in der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourCount:Anzahl der darzustellenden Balken/Stunden in der Balkengrafk&lt;br /&gt;
[[Datei:Screenshot Screenshot 2025-05-21 153613.png|right|thumb|400px|Erweiterung des oberen und unteren Abstandes mit den Attributen graphicControl-&amp;gt;beamPaddingTop und graphicControl-&amp;gt;beamPaddingBottom]]&lt;br /&gt;
;graphicControl-&amp;gt;energyUnit:definiert die Einheit zur Anzeige der elektrischen Leistung in der Grafik&lt;br /&gt;
;graphicHistoryHour:Anzahl der vorangegangenen Stunden die in der Balkengrafik dargestellt werden&lt;br /&gt;
;graphicControl-&amp;gt;beamWidth:Vorgabe Breite der Balken der Balkengrafik in px (sonst automatische Bestimmung) &lt;br /&gt;
;graphicBeamHeightLevel1:Multiplikator zur Festlegung der maximalen Balkenhöhe der jeweiligen Ebene (hier Ebene 1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;Definition der Inhalte und Balkeneigenschaften&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204756.png|right|thumb|400px|Wie oben aber mit gesetzem Attribut graphicShowNight=1]]&lt;br /&gt;
;graphicBeam1Color:Farbauswahl des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2Color:Farbauswahl des sekundären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam1Content:Legt den darzustellenden Inhalt des primären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam2Content:Legt den darzustellenden Inhalt des sekundären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam1FontColor:Auswahl der Schriftfarbe des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2FontColor:Auswahl der Schriftfarbe des sekundären Balkens (Ebene 1)&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 205024.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=0 (ohne Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;zusätzliche Optionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;graphicShowNight:Anzeigen oder Verbergen der Nachtstunden in der Balkengrafik&lt;br /&gt;
;graphicShowWeather:Wettericons in der Balkengrafik anzeigen/verbergen (nur Ebene 1)&lt;br /&gt;
;graphicWeatherColor:Farbe der Wetter-Icons für die Tagesstunden&lt;br /&gt;
;graphicWeatherColorNight:Farbe der Wetter-Icons für die Nachtstunden&lt;br /&gt;
;graphicShowDiff:Zusätzliche Anzeige der Differenz &amp;quot;&amp;lt;primärer Balkeninhalt&amp;gt; - &amp;lt;sekundärer Balkeninhalt&amp;gt;&amp;quot; im Kopf- oder Fußbereich der Balkengrafik&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die genaue Beschreibung und deren Optionen sind der aktuellen Online-Hilfe zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Für alle Ebenen gilt:&#039;&#039;&#039; Ein Attribut mit einer ungeraden Balkennummer (z.B. graphicBeam1Content) bezieht sich immer auf den primären Balken, ein Attribut mit einer geraden Balkennummer (z.B. graphicBeam2Content) bezieht sich immer auf den sekundären Balken.&lt;br /&gt;
&lt;br /&gt;
Die Balken haben, wie die meisten Elemente in der Balkengrafik, eine Mouse-Over Eigenschaft welche relevante Informationen zu den dargestellten Werten anzeigt. &lt;br /&gt;
&lt;br /&gt;
Sind die Nachtunden mit &#039;&#039;&#039;graphicShowNight&#039;&#039;&#039; ausgeblendet, werden keine Balken angezeigt sofern es keine Werte anzuzeigen gibt. Sollten dennoch Werte ungleich 0 anzuzeigen sein, werden diese Werte auch trotz ausgeblendeter Nachstunden angezeigt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 2 ====&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 211741.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=01 (mit Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 2&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam3Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam4Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 4 für Balken 4) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wetter-Icons können nur in Ebene 1 integriert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 2 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 2 gibt, eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgende Ebene.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 3 ====&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 3&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam5Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam6Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 5 für Balken 5) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 3 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 3 gibt, ist eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgenden Ebenen, d.h. auch auf die Ebene 3.&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 5 - Die Energieflußgrafik (Flow Graphic) ===&lt;br /&gt;
[[Datei:Screenshot 2025-02-13 213424.png|right|thumb|400px|Energieflußgrafik mit Verbrauchern in der Nachtdarstellung (Mondphasen) nach Sonnenuntergang]]&lt;br /&gt;
&lt;br /&gt;
Die Energieflußgrafik stellt die registrierten Erzeuger, Batterien, Netzzugänge und Verbraucher strukturiert in mehreren Ebenen dar:&lt;br /&gt;
&lt;br /&gt;
;Ebene 1: In der oberen Ebene befinden sich die PV-Generatoren, Smart-Loader sowie sonstigen Erzeuger &lt;br /&gt;
;Ebene 2: Die mittlere Ebene organisiert den Zugang zum öffentlichen Netz, dem Hausknoten, dem Batterieknoten sowie einem Dummy-Verbraucher (Lampensymbol) für den Energieverbrauch des Hauses der keinem der registrierten Verbraucher zugeordnet werden kann.&lt;br /&gt;
;Ebene 3: In der unteren Ebene werden die registrierten Verbraucher dargestellt. Unterhalb der Verbrauchersymbole werden der aktuelle Verbrauch (bzw. der On/Off-Zustand) sowie darunter die Restlaufzeit (Minuten) des Verbrauchers, sofern er durch das Modul geplant und gestartet wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Position und Gestaltung der Grafikelemente ist umfangreich über das Attribut &#039;&#039;&#039;flowGraphicControl&#039;&#039;&#039; und den darin verfügbaren Schlüsseln einstellbar.&lt;br /&gt;
Die Bedeutung der Schlüssel ist in der Online-Hilfe zum Attribut mit einem Beispiel beschrieben. &lt;br /&gt;
&lt;br /&gt;
Darüber hinaus enthalten die Setup-Attribute &#039;&#039;&#039;setupInverterDevXX&#039;&#039;&#039;, &#039;&#039;&#039;setupOtherProducerXX&#039;&#039;&#039; und &#039;&#039;&#039;consumerXX&#039;&#039;&#039; weitere Einstellungsmöglichkeiten um deren Icons und Färbungen in der Flußgrafik individuell einstellen zu können. So sind zum Beispiel die Icons der PV-Inverter und deren Färbung mit dem Schlüssel &#039;&#039;&#039;icon&#039;&#039;&#039; der setupInverterDevXX-Attribute in Abhängigkeit von Tag und Nacht separat definierbar.&lt;br /&gt;
&lt;br /&gt;
In den Verbraucher-Attributen ist mit dem Schlüssel &#039;&#039;&#039;noshow&#039;&#039;&#039; die Sichtbarkeit in der Flußgrafik definierbar.&lt;br /&gt;
&lt;br /&gt;
Generell steuert das Attribut &#039;&#039;&#039;graphicSelect&#039;&#039;&#039; die Ein- bzw. Ausblendung der gesamten Flußgrafik.&lt;br /&gt;
&lt;br /&gt;
== Die Verbrauchsprognose ==&lt;br /&gt;
Im Gegensatz zu der PV Prognose gibt es keine API oder andere externen Datenquellen die für die Verbrauchsprognose herangezogen werden könnten.&lt;br /&gt;
&lt;br /&gt;
Zum Zweck der Verbrauchsermittlung verwendet das Modul die Meterdaten aus dem Attribut &#039;&#039;setupMeterDev&#039;&#039; sowie den weiteren setup-Attributen &#039;&#039;setupInverterDevXX&#039;&#039;. &lt;br /&gt;
Sind auch andere Erzeuger (BHKW, Windanlagen, etc.) bzw. eine Batterie vorhanden, sind ebenfalls die Attribute &#039;&#039;setupOtherProducerXX&#039;&#039; bzw. &#039;&#039;setupBatteryDev&#039;&#039; für die Berechnung des Hausverbrauchs relevant. In diesen Attributen gibt es die Schlüssel &#039;&#039;*total&#039;&#039; die teilweise optional sind. Für die Verbrauchsprognose bilden sie jedoch die Berechnungsgrundlage und sind deswegen für diese Funktionalität wichtig anzugeben.&lt;br /&gt;
&lt;br /&gt;
Die Verbrauchswerte werden stundengenau erfasst und im Datenspeicher &#039;&#039;pvHistory&#039;&#039; für 31 Tage, sowie im Datenspeicher &#039;&#039;pvCircular&#039;&#039; 210 Tage gespeichert. Die beiden Datenspeicher übernehmen unterschiedliche Aufgaben im Rahmen der Prognoseerstellung. Auf Grundlage der gespeicherten und somit historischen Verbrauchswerte erstellt das Modul eine Prognose für die kommende Zeit.&lt;br /&gt;
&lt;br /&gt;
Mit dem Kommando &lt;br /&gt;
&lt;br /&gt;
   &amp;quot;get ... pvHistory [Tag]&amp;quot; &lt;br /&gt;
&lt;br /&gt;
wird der Inhalt aufgelistet. Die Schlüssel &#039;&#039;confc&#039;&#039;, &#039;&#039;con&#039;&#039; und &#039;&#039;gcon&#039;&#039; zeigen die Verbrauchsprognose, den Verbrauch und den Netzbezug der jeweiligen Stunde des gewählten Tages.&lt;br /&gt;
Die Stunde &amp;quot;99&amp;quot; zeigt die Summen dieser Schlüsssel für den Tag:&lt;br /&gt;
&lt;br /&gt;
      99 =&amp;gt; etotal: , pvfc: 782, pvrl: 0, rad1h: -&lt;br /&gt;
            confc: 14540, con: 13873, gcon: 13873, gfeedin: 0&lt;br /&gt;
            batintotal: , batin: 0, batouttotal: , batout: 0&lt;br /&gt;
            batmaxsoc: -, batsetsoc: -&lt;br /&gt;
            wid: , wcc: , wrp: , pvcorrf: , dayname: So&lt;br /&gt;
            cyclescsm01: 0&lt;br /&gt;
            cyclescsm02: 0&lt;br /&gt;
            cyclescsm03: 0&lt;br /&gt;
            cyclescsm04: 1, hourscsme04: 0.00&lt;br /&gt;
            cyclescsm05: 0&lt;br /&gt;
            cyclescsm06: 0&lt;br /&gt;
            cyclescsm07: 1, hourscsme07: 0.00&lt;br /&gt;
            cyclescsm08: 1, hourscsme08: 0.00&lt;br /&gt;
            cyclescsm09: 1, hourscsme09: 0.03 &lt;br /&gt;
&lt;br /&gt;
In dem Beispiel wurden für den Tag 14540 Wh Verbrauch prognostiziert, 13873 Wh tatsächlich verbraucht und davon 13873 Wh aus dem Netz bezogen. Leider war an diesem Tag keinerlei PV Ertrag vorhanden, was man auch an dem Schlüssel &#039;&#039;pvrl&#039;&#039; erkennen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Inhalt des pvCircular-Speichers kann mit dem Befehl  &lt;br /&gt;
&lt;br /&gt;
     &amp;quot;get ... pvCircular [Tag]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Das nachfolgende Beispiel zeigt die Ausgabe für die Tagesstunde 23:&lt;br /&gt;
&lt;br /&gt;
 23 =&amp;gt; pvapifc: 0, pvaifc: -, pvfc: 0, aihit: 0, pvrl: 0&lt;br /&gt;
       batin01: 0, batin02: -, batin03: -&lt;br /&gt;
       batout01: 619, batout02: -, batout03: -&lt;br /&gt;
       confc: 650, gcon: 23, gfeedin: 0, wcc: 40, rr1c: 0.00&lt;br /&gt;
       temp: -6.00, wid: 100, wtxt: Bewölkungsentwicklung nicht beobachtet&lt;br /&gt;
       pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
       ... &lt;br /&gt;
       con_all =&amp;gt; Sa  @ 617 762&lt;br /&gt;
                  Di  @ 693 645&lt;br /&gt;
                  Mo  @ 620 679&lt;br /&gt;
                  So  @ 669 666 636&lt;br /&gt;
                  Mi  @ 701 626&lt;br /&gt;
                  Do  @ 612 642&lt;br /&gt;
                  Fr  @ 615 606&lt;br /&gt;
&lt;br /&gt;
Der Schüssel &#039;&#039;con_all&#039;&#039; enthält einen Hash aus Arrays die für jeden Wochentag (Mo..So) bis zu 30 Verbrauchswerte (in Wh) für die angezeigte Stunde speichern. Wie hier erkennbar ist, wurden an den drei vergangenen Sonntagen jweils 669 Wh, 666 Wh bzw. 636 Wh in der Stunde 23 (22:00-22:59) verbraucht.&lt;br /&gt;
Der Median aus diesen Werten geht in die Verbrauchsprognose ein. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wochentagsnamen Mo..So sind von den installierten Locales auf Betriebsystemebene abhängig. Ist keine deutsche locale installiert, werden die englischen Wochentagsnamen Mon..Sun verwendet. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Wie wird der Verbrauch des Hauses ermittelt und gespeichert? ===&lt;br /&gt;
Die Verbrauchsdaten des Hauses werden auf Stundenbasis ermittelt und gespeichert. Das &amp;quot;Haus&amp;quot; steht als Synonym aller im Kontext des Solarforecast Devices zusammengeführten Inverter (setupInverterDevXX), sonstigen Erzeuger (setupOtherProducerXX), Netzanschlüsse (setupMeterDev), Verbraucher (consumerXX) und Batterien (setupBatteryDev).&lt;br /&gt;
&lt;br /&gt;
Alle diese Daten werden durch das Modul mit jedem ausgeführten Zyklus (Attribut plantControl-&amp;gt;cycleInterval) und, wenn ein Event eines als &#039;asynchron&#039; definierten Devices auftritt, gesammelt und daraus permanent ein aktualisierter Verbrauch berechnet. Die Berechnung beschreibt folgende Formel:&lt;br /&gt;
&lt;br /&gt;
 PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung - Verbrauch = 0&lt;br /&gt;
&lt;br /&gt;
bzw.&lt;br /&gt;
 &lt;br /&gt;
 Verbrauch (Wh) = PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung&lt;br /&gt;
            con = PV           + PP                 - GridIn          + GridCon   - BatIn          + BatOut&lt;br /&gt;
&lt;br /&gt;
Die PV-Erzeugung beinhaltet die Summe aller durch die angegebnen Inverter (setupInverterDev01 .. setupInverterDevXX) erzeugten Energien. Die &amp;quot;sonstige Erzeugung&amp;quot; summiert sich aus den Werten aller angegebenen Producer (setupOtherProducer01 .. setupOtherProducerXX). Der Verbrauch wird durch die registrierten Geräte consumerXX teilweise direkt erfasst, ist aber grundsätzlich unvollständig da nicht alle Verbrauchswerte im &amp;quot;Haus&amp;quot; gemessen und durch das Modul erfasst werden können.&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel zeigt das Ergebnis bei 300 Wh PV-Erzeugung und gleichzeitige 500 Wh Netzbezug:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 300 + 0 - 0 + 500 - 0 + 0 = 800 Wh&lt;br /&gt;
&lt;br /&gt;
Bei 1300Wh PV-Erzeugung, 100 Wh Netzeinspeisung sowie 200 Wh Batterieladung ergibt sich der Verbrauch zu:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 1300 + 0 - 100 + 0 - 200 + 0 = 1000 Wh&lt;br /&gt;
&lt;br /&gt;
Ohne Erzeugung, aber mit der Energielieferung von 500 Wh aus der Batterie, 800 Wh Netzbezug (mit einem Anteil Batterienachladung aus dem Netz von 200 Wh) sieht die Verbrauchsrechnung wie folgt aus: &lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 0 + 0 - 0 + 800 - 200 + 500 = 1100 Wh&lt;br /&gt;
&lt;br /&gt;
Der so ermittelte Verbrauchsert wird mit jedem Zyklus in der pvHistory im Schlüssel &amp;quot;con&amp;quot; gespeichert. Man kann sich die gespeicherten Werte mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;name&amp;gt; pvHistory [&amp;lt;Tag&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Nachfolgendes Beispiel zeigt einen Datensatz für die Stunde 8 eines Tages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      08 =&amp;gt; pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotali01: 62940734, etotali02: 2928860, etotali03: -&lt;br /&gt;
            pvrl01: 0, pvrl02: 0, pvrl03: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 630, con: 962, gcons: 962, conprice: 0.2958&lt;br /&gt;
            gfeedin: 0, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 120, sunalt: -3&lt;br /&gt;
            batintotal: 3713815.07742543, batouttotal: 3604468.26993988, batin: 0, batout: 0&lt;br /&gt;
            wid: 161, wcc: 89, rr1c: 0.00, pvcorrf: 0.27/0.00 temp: 7.40, &lt;br /&gt;
            csmt01: 110996.12, csme01: 32.1399999999994, minutescsm01: 30&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 2513.67, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1581293.6, csme04: 136.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 1662.17, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 90.53, csme06: 0, minutescsm06: 0&lt;br /&gt;
            csmt07: 39.75, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 38050, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 131627, csme09: 33.2000000000116, minutescsm09: 39&lt;br /&gt;
            minutescsm10: 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Schlüssel &amp;quot;con&amp;quot; ist der gespeicherte Verbrauch von 962 Wh ersichtlich.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit bekommt man mit dem Attribut &#039;&#039;ctrlDebug=collectData&#039;&#039; einen Einblick in die Verbrauchsermittlung bei jedem Zyklus und kann so die Eingangswerte und das daraus resultierende Ergebnis im FHEM Log nachverfolgen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
2024.11.28 11:38:20.080 1: SolCast DEBUG&amp;gt; EnergyConsumption input -&amp;gt; PV: 96, PP: 0, GridIn: 0, GridCon: 582, BatIn: 5, BatOut: 0&lt;br /&gt;
2024.11.28 11:38:20.081 1: SolCast DEBUG&amp;gt; EnergyConsumption result -&amp;gt; 673 Wh&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie wird die Verbrauchsprognose erstellt? ===&lt;br /&gt;
&lt;br /&gt;
Aus den gespeicherten con-Werten (Verbrauchsdaten) der pvCircular (Schlüssel con_all) sowie Einträgen der pvHistory wird der Median der historischen Tage ermittelt und für den kommenden Tag bzw. die kommen Stunden zur Prognose angewendet. Dabei geht per default jeder verfügbare historische Tag gleichberechtigt in die Prognose ein. Mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039; kann festgelegt werden, dass nur gleiche Wochentage (Mo..So) für die Prognose verwendet werden. Hierbei spielt die Vermutung, dass das Verbrauchsverhalten eine gewisse Korrelation zum Wochentag hat, eine Rolle. &lt;br /&gt;
&lt;br /&gt;
Verwendet man die Einstellung consForecastIdentWeekdays=1, hat es sich als vorteilhaft erwiesen, das Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays&#039;&#039;&#039; auf einen niedrigeren Wert als den Default zu setzen. Eine Einstellung auf &#039;8&#039; zum Beispiel verwendet den Median der gleichen Wochentage der vergangenenen 8 Wochen. Dadurch wird nicht zu weit in die Vergangenheit verzweigt und so eine langsame Veränderung des Verbrauchsmedian, zum Beispiel hervorgerufen durch den Übergang vom Winter in das Frühjahr hinein, abgebildet.&lt;br /&gt;
&lt;br /&gt;
Weiteren Einfluß auf die Verbrauchsprognose kann mit dem Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; im Consumerattribut genommen werden. Insbesondere bei der unregelmäßigen Nutzung von Verbrauchern mit hoher Leistung kann die Projektion der aufgezeichneten historischen Werte in die Prognose zu unverhältnismäßig hohen Verbrauchswerwartunden führen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Möglicherweise führt in Fällen die Verwendung eine der nachfolgenden Optionen zu einem besseren Ergebnis:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;1 -&#039;&#039;&#039; die allgemeine Verbrauchsprognose wird um die gespeicherten Energieverbrauchsanteile reduziert.&lt;br /&gt;
* &#039;&#039;&#039;2 -&#039;&#039;&#039; wie bei &#039;1&#039;, jedoch gehen die Planungsdaten des Verbrauchers bei der Prognose der kommenden Stunden wieder mit ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;&#039;exconfc&#039;&#039;&#039; in einem der Consumer verwendet, sollte&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays=4&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
eingestellt werden. Hintergrund ist, dass die Verbrauchsanteile der jeweiligen Verbraucher nur maximal 31 Tage in der pvHistory verfügbar sind. Für längere Zeiträume stehen nur Gesamtsummen des Verbrauchs in der pvCircular zu Verfügung.  &lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=1&#039;&#039;&#039; werden die in der Historie aufgezeichneten Verbrauchsbestandteile aus einer Prognose herausgerechnet. Konkret werden die in der pvHistory aufgezeichneten Verbrauchsbestandteile für die relevante Stunde ermittelt und daraus ein Durchschnitt gebildet der vom Prognosewert subtrahiert wird. Mit dem Attributwert plantControl-&amp;gt;consForecastIdentWeekdays=1 werden wiederum nur identische Wochentage (Mo .. So) zusammengefasst.&lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=2&#039;&#039;&#039; erfolgt ebenso die Eliminierung des Verbrauchsanteils, es wird jedoch auf die Planungsdaten für diesen Verbraucher zugegriffen und die geplanten Energieanteile wiederum der Verbrauchsprognose für die kommenden Stunden hinzugerechnet.&lt;br /&gt;
&lt;br /&gt;
In beiden Anwendungsfällen ist es notwendig, dass dem Modul durch die Angabe entsprechender Readings der Energieverbrauch im Setup des Consumers bekannt gemacht wird damit diese Energieanteile registriert werden können. Allgemein funktioniert die Verbrauchsprognose gut wenn Verbrauchsprozesse regelmäßig in einem wiederkehrenden Zeitraster ablaufen, der Verbrauch durch persönliche Rituale bestimmt ist. So zum Beispiel könnte am Dienstag und Samstag gewöhnlich die Waschmaschine laufen, das E-Auto täglich aufgeladen werden und gebügelt wird oft am Sonntag Nachmittag.&lt;br /&gt;
&lt;br /&gt;
Unregelmäßige Nutzung, vor allem vom Großverbrauchern, lässt sich nur sehr schwer und ungenügend auf zukünftige Verbrauchsprognosen projizieren.&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis der Prognose wird im Kopf der Grafik in der Zeile &#039;&#039;Verbrauch&#039;&#039; sowie in diversen Readings wie &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RestOfDayConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den Rest des Tages)&lt;br /&gt;
* &#039;&#039;&#039;NextHours_Sum04_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für die nächsten 4 Stunden)&lt;br /&gt;
* &#039;&#039;&#039;Tomorrow_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den kommenden Tag)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
angezeigt.&lt;br /&gt;
&lt;br /&gt;
Weitere Aggregationen kann man sich über das Attribut &#039;&#039;&#039;ctrlStatisticReadings&#039;&#039;&#039; bei Bedarf zuschalten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;conForecastTillNextSunrise&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
* &#039;&#039;&#039;todayConForecastTillSunset&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
* &#039;&#039;&#039;todayConsumptionForecast&#039;&#039;&#039; - Verbrauchsprognose aufgesplittet pro Stunde des aktuellen Tages (01-24) &lt;br /&gt;
 &lt;br /&gt;
==== Debugging der Verbrauchsprognose ====&lt;br /&gt;
Um sich einen Einblick über die Erstellung der Verbrauchsprognose zu verschaffen, bietet sich die Einschaltung von:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
an. Mit diesem gesetzten Attribut wird die Erstellung der Prognose im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; ################### Start Consumption forecast ###################&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; Basics - installed locale: de_DE.UTF-8, used scheme: DE&lt;br /&gt;
2025.02.27 19:52:00.064 1: SolCast DEBUG&amp;gt; process Today dayname: Do, Tomorrow dayname: Fr&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 01 - 74.43 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 10 - 290.77 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 24 - 660.70 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 20, hod: 07 - 459.93 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;07&#039; register for exclude day 20, hod: 02 - 0.33 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 30, hod: 08 - 264.78 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next Hours (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; excl. hist 74 Wh for Hour 01, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; estimated cons of Hour 01: 436 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; excl. hist 0 Wh for Hour 02, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 02: 428 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 03: 458 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 04: 503 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 05: 489 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 06: 482 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; excl. hist 460 Wh for Hour 07, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 07: 274 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 265 Wh for Hour 08, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 08: 441 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 09: 558 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 291 Wh for Hour 10, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 10: 443 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 11: 881 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 12: 794 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 13: 840 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 14: 660 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 15: 812 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 16: 752 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 17: 597 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 18: 652 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 19: 634 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 20: 628 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 21: 713 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 22: 596 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 23: 629 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; excl. hist 661 Wh for Hour 24, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons of Hour 24: 660 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons Tomorrow: 16848 Wh, Individual hourly values considered: 72, exclude: 0 Wh (avg of 0 entities)&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Store Consumption forecast values (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour00&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;20&#039; confc: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour01&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;21&#039; confc: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour02&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;22&#039; confc: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour03&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;23&#039; confc: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store &#039;NextHour04&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;24&#039; confc: 660&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour05&#039; hod &#039;01&#039; confc: 436, confcEx: 436&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour06&#039; hod &#039;02&#039; confc: 428, confcEx: 428&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour07&#039; hod &#039;03&#039; confc: 458, confcEx: 458&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour08&#039; hod &#039;04&#039; confc: 503, confcEx: 503&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour09&#039; hod &#039;05&#039; confc: 489, confcEx: 489&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour10&#039; hod &#039;06&#039; confc: 482, confcEx: 482&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour11&#039; hod &#039;07&#039; confc: 274, confcEx: 274&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour12&#039; hod &#039;08&#039; confc: 441, confcEx: 441&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour13&#039; hod &#039;09&#039; confc: 558, confcEx: 558&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour14&#039; hod &#039;10&#039; confc: 443, confcEx: 443&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour15&#039; hod &#039;11&#039; confc: 881, confcEx: 881&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour16&#039; hod &#039;12&#039; confc: 794, confcEx: 794&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour17&#039; hod &#039;13&#039; confc: 840, confcEx: 840&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour18&#039; hod &#039;14&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour19&#039; hod &#039;15&#039; confc: 812, confcEx: 812&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour20&#039; hod &#039;16&#039; confc: 752, confcEx: 752&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour21&#039; hod &#039;17&#039; confc: 597, confcEx: 597&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour22&#039; hod &#039;18&#039; confc: 652, confcEx: 652&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour23&#039; hod &#039;19&#039; confc: 634, confcEx: 634&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour24&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour25&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour26&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour27&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour28&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; consumption calculated - day: 27, hod: 20, con: 574 Wh&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; write pvCircular consumption - hod: 99, todayConsumption: 11210 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe startet mit &#039;&#039;&amp;quot;Start Consumption forecast&#039;&#039;&amp;quot;, es werden die zu exkludierenden historischen Daten für jeden Consumer bzgl. jedem Tag (day) und Stunde des Tages (hod) getrennt registriert. Diese Werte werden durch die gespeicherte Einträge in der pvHistory (max. 31 historische Tage) geliefert. &lt;br /&gt;
&lt;br /&gt;
Im nächsten Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next Hours (new median)&amp;quot;&#039;&#039; werden die Prognosen für die nächsten Stunden kalkuliert und die zuvor registrierten Excludes angewendet. Die Prognose für den kommenden Tag ist im Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next day (new median)&amp;quot;&#039;&#039; protokolliert. Die Prognose für den kommenden Tag ist nicht einfach die Summe der Prognose der nächsten Stunden, denn in den kommenden Stunden werden auch die verfügbaren Planungen der Consumer einbezogen. Für den kommenden Tag können diese Werte unter Umständen nicht einbezogen werden da sie zum Zeitpunkt X noch nicht verfügbar sind.&lt;br /&gt;
&lt;br /&gt;
Im Abschnitt &#039;&#039;&amp;quot;Store Consumption forecast values (new median)&amp;quot;&#039;&#039; erscheinen die effektiv gespeicherten Werte. Diese sind die Grandlage für die grafische Darstellung sowie weiteren Kalkulationen.&lt;br /&gt;
&lt;br /&gt;
=== Wie kann eine fehlerhafte Verbrauchsprognose korrigiert werden? ===&lt;br /&gt;
Wie im vorherigen Abschnitt beschrieben, wird die Prognose aus den gespeicherten &amp;quot;con&amp;quot;-Werten der vergangenen Tage (bzw. Stunden) abgeleitet. &lt;br /&gt;
Grundsätzlich muß zunächst sichergestellt werden, dass die auszulesenden Readings der angegebenen Energiezähler sowie deren Einheiten! korrekt eingestellt sind. Das gilt ebenfalls für die registrierten Verbraucher im Modul.&lt;br /&gt;
&lt;br /&gt;
Für einen ersten Überblick bietet sich das Debug Attribut an zu setzen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
Beispielausgabe des Debug:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2024.09.21 13:28:27.041 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day ###################&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;01&amp;lt; considering possible exclusions: 14082&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;08&amp;lt; considering possible exclusions: 16446&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;15&amp;lt; considering possible exclusions: 14568&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;25&amp;lt; considering possible exclusions: 15522&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; estimated Consumption for tomorrow: 15154, days for avg: 4&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next hours ###################&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 14 -&amp;gt; 850 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 14 -&amp;gt; 643 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 14 -&amp;gt; 590 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 14 -&amp;gt; 522 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 13:00:00, confc: 651, days for avg: 4, hist. consumption registered consumers: 560.97&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 15 -&amp;gt; 720 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 15 -&amp;gt; 743 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 15 -&amp;gt; 897 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 15 -&amp;gt; 557 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 14:00:00, confc: 729, days for avg: 4, hist. consumption registered consumers: 620.97&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 16 -&amp;gt; 676 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 16 -&amp;gt; 790 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 16 -&amp;gt; 785 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 16 -&amp;gt; 581 Wh&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 15:00:00, confc: 708, days for avg: 4, hist. consumption registered consumers: 647.29&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 17 -&amp;gt; 622 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 17 -&amp;gt; 639 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 17 -&amp;gt; 646 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 17 -&amp;gt; 572 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 16:00:00, confc: 619, days for avg: 4, hist. consumption registered consumers: 618.30&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 18 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 18 -&amp;gt; 614 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 18 -&amp;gt; 580 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 18 -&amp;gt; 480 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 17:00:00, confc: 567, days for avg: 4, hist. consumption registered consumers: 583.41&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 19 -&amp;gt; 615 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 19 -&amp;gt; 1659 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 19 -&amp;gt; 597 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 19 -&amp;gt; 618 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 18:00:00, confc: 872, days for avg: 4, hist. consumption registered consumers: 636.97&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 20 -&amp;gt; 611 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 20 -&amp;gt; 1124 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 20 -&amp;gt; 546 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 20 -&amp;gt; 479 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 19:00:00, confc: 690, days for avg: 4, hist. consumption registered consumers: 578.87&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 21 -&amp;gt; 1474 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 21 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 21 -&amp;gt; 619 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 21 -&amp;gt; 433 Wh&lt;br /&gt;
2024.09.21 13:28:27.058 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Im ersten Teil wird die erwartete Consumption für den nächsten Tag unter Berücksichtigung möglicher Ausschlüsse von Verbrauchern ausgegeben. Ausschlüsse von Verbrauchern ergeben sich wenn in dem Verbraucherattribut der Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; gesetzt ist. Er besagt, dass die Verbrauchswerte des Verbrauchers in eine zukünftige Prognose nicht eingehen sollen. Zum Beispiel wenn ein Verbraucher mit sehr hohen Verbrauchswerten nur sporadisch eingesetzt wird und dadurch die Prognose stark verfälschen würde. Es ist auch zu sehen, dass bedingt durch das Attribut &#039;&#039;&#039;affectConsForecastIdentWeekdays = 1&#039;&#039;&#039; nur die historischen Tage 01, 08, 15 und 25 berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Teil wird die berechnete Erwartung für die nächsten Stunden ausgegeben. &lt;br /&gt;
Zur Beschreibung der Fehlersuche gehen wir davon aus, dass die Prognose von 780 Wh am 2024-09-21 20:00:00 zu hoch erscheint weil am Tag &amp;quot;07&amp;quot; ein Wert von 1474 Wh gespeichert ist:&lt;br /&gt;
&lt;br /&gt;
 SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt geben wir die historischen Werte für den Tag 07 aus:&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;Name&amp;gt; pvHistory 07&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz interessiert die Stunde 21. Sie resultiert aus der obigen Angabe &amp;quot;starttime: xxxx-xx-xx 20:00:00&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      21 =&amp;gt; etotal: 64354660, pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 496, con: 1474, gcons: 23, conprice: 0.2958&lt;br /&gt;
            gfeedin: 5, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 289, sunalt: -8&lt;br /&gt;
            batintotal: 3064096.92456668, batouttotal: 2958021.37946804, batin: 0, batout: 1460&lt;br /&gt;
            wid: 101, wcc: 20, rr1c: 0.00, pvcorrf: 1.00/-temp: 26.00, &lt;br /&gt;
            csmt01: 64262.43, csme01: 28.8099999999977, minutescsm01: 25&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 0, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1389417.4, csme04: 94.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 0, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 290.15, csme06: 6.66999999999996, minutescsm06: 54&lt;br /&gt;
            csmt07: 0, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 32800, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 103987.8, csme09: 38, minutescsm09: 43&lt;br /&gt;
            csmt10: 9151.24999999783, csme10: 3.99999999997999, minutescsm10: 60&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz sind die Energieverbrauchsanteile der im Device registrierten Verbraucher mit dem Schlüssel &amp;quot;csmeXX&amp;quot; gespeichert. Dabei ist &amp;quot;XX&amp;quot; die Verbrauchernummer. In dem Beispiel existieren die Anteile csme01 und csme03 - csme10. Keiner dieser Verbraucher hat einen auffälligen Verbrauchswert gespeichert, d.h. die Messung der Verbraucher scheidet als Problemquelle aus. Wäre ein unverhältmismäßig hoher Verbrauch bei einem der Verbraucher feststellbar, müssten die Schlüssel &#039;&#039;&#039;pcurr&#039;&#039;&#039; und &#039;&#039;&#039;etotal&#039;&#039;&#039; im consumerXX-Attribut geprüft, sowie die Datenlieferung des Consumerdevices selbst geprüft werden.  &lt;br /&gt;
&lt;br /&gt;
Es wurde offensichtlich ein hoher Verbrauch von einem nicht registrierten Verbraucher verursacht oder durch die Übertragung eines Meßfehlers des Devices, angegeben im Attribut &#039;&#039;&#039;setupMeterDev&#039;&#039;&#039;, in das SolarForecast Device übertragen. Eine weitere Analyse ist an dieser Stelle nicht möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Behebung des falschen Wertes kann ein Reset der gespeicherten Consumption der relevanten Stunde durchgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; reset consumptionHistory 07 21&lt;br /&gt;
&lt;br /&gt;
== Modulinterne Datenstrukturen ==&lt;br /&gt;
Das Modul speichert die verschiedenen historischen und aktuellen Daten wie PV-Prognose, Witterungsdaten (Regen, Bewölkung), Strahlungsdaten, Einspeisung, Bezug, reale Erzeugungsdaten und vieles mehr zur Laufzeit im Arbeitsspeicher. Dadurch ist die Verarbeitung dieser Daten im Vergleich zu Lesevorgängen aus dem Filesystem bzw. einer Datenbank sehr performant. Allerdings würden diese Daten bei einem FHEM Absturz bzw. bei einem regulären Shutdown verlorengehen.&lt;br /&gt;
&lt;br /&gt;
Deswegen werden die relevanten Daten regelmäßig in Dateien gesichert und bei Bedarf wiederhergestellt. Diese Dateien befinden sich im Verzeichnis &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; und heißen &#039;&#039;&#039;.*_SolarForecast_.*&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Die Daten werden in jedem Zyklus der Zentralschleife (CentralTask) gesammelt bzw. berechnet. Der Zyklus wird mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;cycleInterval&#039;&#039;&#039; eingestellt.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit können diese Daten über get-Kommandos abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvHistory [Tag]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der pvHistory Datenspeicher enthält die vergangenen Kennwerte der letzten 31 Tage mit einer Genauigkeit von einer Stunde. Es werden die Prognosewerte für Erzeugung und Verbrauch, die realen Werte für Erzeugung und Verbrauch sowie ebenso die Laufzeiten jedes einzelnen Verbrauchers (Consumer) festgehalten. Für jeden Tag gibt es die Stunde &amp;quot;99&amp;quot; die eine Summierung der Stundenwerte des Tages bzw. Sonderschlüssel enthält.&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf lässt sich mit dem Befehl &amp;quot;set ... reset pvHistory&amp;quot; der gesamte Inhalt des Speichers löschen (nicht empfohlen). Selektiver funktioniert die Datenlöschung mit &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt;&amp;quot; (Daten eines bestimmten Tages löschen) bzw. &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt; &amp;lt;Stunde&amp;gt;&amp;quot; (Daten der Stunde  eines bestimmten Tages löschen). Die letzten beiden Kommandos müssen über die Kommandozeile im Browser ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvCircular &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Ringspeicher enthält Daten der letzten 24 Stunden sowie fortwährend berechnete Werte wie Korrekturfaktoren der PV-Erzeugung und Prognosequalität.&lt;br /&gt;
Neue Stundenwerte des Tages überschreiben die gespeicherten Schüssel des vorangegangenen Tages sofern es sich nicht um fortwährend berechnete Werte handelt. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... nextHours&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Speicher enthält sämtliche Prognosewerte der kommenden Stunden beginnend mit der aktuellen Stunde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... radiationApiData&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Abhängig von der ausgewählten Strahlungsdaten API enthält dieser Speicher die von der API gelieferten Rohdaten sowie evtl. weitere für die Funktion benötigte Daten wie API-Keys, Response Messages, Anzahl der API Abruf und weitere.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valCurrent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Struktur wird nicht regelmäßig im Filesystem gespeichert und enthält immer aktuell gesammelte oder berechnete/gelieferte Daten wie z.B. die Autarkierate, letze Laufzeit der Zentralschleife (CentralTask), Zeit des Sonnenauf- und untergangs sowie weitere Betriebsdaten. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valConsumerMaster [XX]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zeigt die Daten der aktuell im SolarForecast Device registrierten Verbraucher. Mit der Nummer &#039;&#039;&#039;XX&#039;&#039;&#039; kann ein bestimmter Verbraucher angesprungen werden. Die Nummer korrespondiert mit dem entsprechenden &#039;&#039;&#039;consumerXX&#039;&#039;&#039; Attribut.&lt;br /&gt;
Neben anderen Betriebs- und Energiedaten werden insbesondere folgende Daten ermittelt, die für die zukünftige Planung der Verbraucherschaltzeiten relevant sind:&lt;br /&gt;
&lt;br /&gt;
* epieces - prognostizierte Energiescheiben pro Betriebsstunde &lt;br /&gt;
&lt;br /&gt;
Ausgehend von gespeicherten historischen Verbrauchsdaten des Verbrauchers wird der Energieverbrauch des Verbrauchers in seiner ersten Betriebsstunde prognostiziert, was insbesondere für die Planung der optimalen Startzeit des Verbrauchers in Bezug zu der prognostizierten PV Energie und den Verbrauchswerten weiterer vorhandener bzw. zu planender Verbraucher Berücksichtigung findet. Weitere Informationen zur Verbrauchersteuerung in diesem  [[#Verbrauchersteuerung_-_Registrieren_und_visualisieren_von_Verbrauchern|Abschnitt]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Schnittstelle für Modulautoren bzw. eigenen Code ===&lt;br /&gt;
&lt;br /&gt;
Die im vorherigen Artikel beschriebenen internen Datenstrukturen können durch externen Code abgefragt und ausgewertet werden.&lt;br /&gt;
Dazu stehen die folgenden Funktionen zur Verfügung. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]BatteryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Bn&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valBattery&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CurrentVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valCurrent&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]InverterVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valInverter&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ProducerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valProducer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]HistoryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Day&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvHistory&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CircularVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvCircular&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]NexthoursVal (&#039;&amp;lt;Name&amp;gt;&#039;, &amp;lt;nhr&amp;gt;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... nextHours&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ConsumerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valConsumerMaster&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]RadiationAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;DateTime&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... radiationApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]WeatherAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;TimeCode&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... weatherApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StatusAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;QTag&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... statusApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StringVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valStrings&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Angabe des Packages (FHEM::SolarForecast::) ist nur notwendig wenn die Funktionen von außerhalb des SolarForecast-Devices aufgerufen werden. Innerhalb des Devices (Code-Ausführung im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039;) kann darauf verzichtet werden.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der Platzhalter sind:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     &amp;lt;Name&amp;gt;     - Name des SolarForecast Devices&lt;br /&gt;
     &amp;lt;Day&amp;gt;      - abzufragender Tag (01 - 31)&lt;br /&gt;
     &amp;lt;Bn&amp;gt;       - Batterie Nummer (01, 02, ...)&lt;br /&gt;
     &amp;lt;DateTime&amp;gt; - Startzeit der Form YYYY-MM-DD hh:00:00&lt;br /&gt;
     &amp;lt;TimeCode&amp;gt; - Zeitwert der Form fcX_XX (z.B. fc1_19)&lt;br /&gt;
     &amp;lt;APIname&amp;gt;  - Hauptname der API gemäß setupWeatherDev1 (z.B. OpenMeteo)&lt;br /&gt;
     &amp;lt;String&amp;gt;   - Name des PV-Modulstrings wie im Attribut &#039;setupInverterStrings&#039;&lt;br /&gt;
     &amp;lt;QTag&amp;gt;     - Question Tag, z.B. &#039;?All&#039;&lt;br /&gt;
     &amp;lt;Nr&amp;gt;       - laufende Nummer des Verbrauchers / Gerätes (01, 02, 03, 04,...)&lt;br /&gt;
     &amp;lt;HoD&amp;gt;      - abzufragende Stunde (01 - 24, 99)&lt;br /&gt;
     &amp;lt;nhr&amp;gt;      - nächste Stunde (NextHour00, NextHour01,...)&lt;br /&gt;
     &amp;lt;Key&amp;gt;      - der abzufragende Schlüssel &lt;br /&gt;
     &amp;lt;default&amp;gt;  - def default-Rückgabewert&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Auswerten von internen Arrays ===&lt;br /&gt;
&lt;br /&gt;
Die meisten der internen Datenstrukturen liefern bei der Abfrage einen einfachen String oder numerischen Wert der ausgewertet werden kann. Es gibt allerdings auch intern gespeicherte Wertelisten. Werden die Listenstrukturen mit den oben beschriebenen Befehlen abgefragt, wird eine Referenz auf die Liste geliefert sofern sie vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
Um auf die Werte einer solchen Liste zuzugreifen, ist am Beispiel des Arrays &#039;&#039;surplusslidereg&#039;&#039; aus dem Current-Speicher (get ... valCurrent) dargestellt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
my $splref = CurrentVal ($name, &#039;surplusslidereg&#039;, &#039;.&#039;);&lt;br /&gt;
my $spser  = ref $splref eq &#039;ARRAY&#039; ? join &#039; &#039;, @{$splref} : undef;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Variable $spser enthält bei Vorhandensein der Liste einen String, der die Listenelemente von &#039;surplusslidereg&#039; durch Leerzeichen getrennt enthält.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backup und Wiederherstellung der Moduldaten ==&lt;br /&gt;
Neben der Datenhaltung in den Attributen und Readings des SolarForecast Devices, erzeugt jedes SolarForecast Device Dateien im Verzeichnis  &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; mit folgenden Inhalten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PVH_SolarForecast_&amp;lt;name&amp;gt;        - PV History&lt;br /&gt;
PVC_SolarForecast_&amp;lt;name&amp;gt;        - PV Circular&lt;br /&gt;
PVCfg_SolarForecast_&amp;lt;name&amp;gt;      - PV Anlagenkonfiguration&lt;br /&gt;
PVCsm_SolarForecast_&amp;lt;name&amp;gt;      - Consumer Status&lt;br /&gt;
ScApi_SolarForecast_&amp;lt;name&amp;gt;      - Strahlungswerte aus verwendeter API&lt;br /&gt;
StatApi_SolarForecast_&amp;lt;name&amp;gt;    - Statusdaten der verwendeten API&#039;s&lt;br /&gt;
WeatherApi_SolarForecast_&amp;lt;name&amp;gt; - Wetterdaten der gewählten Wetter-API (außer DWD-Device)&lt;br /&gt;
AItra_SolarForecast_&amp;lt;name&amp;gt;      - KI Entscheidungsquelle (trainierte Daten)&lt;br /&gt;
AIraw_SolarForecast_&amp;lt;name&amp;gt;      - KI Input Daten = Raw Trainigsdaten&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nach Ausprägung und eingesetzten Features des SolarForecast Devices sind alle oder nur ein Teil dieser Dateien vorhanden. Dabei ist &#039;&#039;&#039;&amp;lt;name&amp;gt;&#039;&#039;&#039; der Name des SolarForecast Devices.&lt;br /&gt;
&lt;br /&gt;
Bei einem Filebackup des FHEM-Servers ist darauf zu achten, dass diese Dateien in dem Backup enthalten sind. Der Inhalt der Dateien ist nicht statisch, sondern kann sich dynamisch aktualisieren. Um im Bedarfsfall einen aktuellen Datenstand zu haben, ist mindestens ein tägliches Backup dieser Dateien empfehlenswert. Eventuell auch öfter mit Hilfe einer Versionierung welche z.B. immer die letzten 3 Versionen aufbewahrt.&lt;br /&gt;
&lt;br /&gt;
Beim Start von FHEM werden bestimmte Dateien automatisch gelesen und in das SolarForecast Device importiert. &lt;br /&gt;
Der Vorgang ist mit verbose=3 im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2023.10.02 09:57:07.967 3: SolCast6 - cached data &amp;quot;pvHistory&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.969 3: SolCast6 - cached data &amp;quot;pvCircular&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;consumerMaster&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;radiationApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;statusApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;weatherApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.974 3: SolCast6 - cached data &amp;quot;aiTrainedData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.976 3: SolCast6 - cached data &amp;quot;aiRawData&amp;quot; restored&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bestimmte Betriebsdaten, wie z.B. die witterungsabhängigen Korrekturfaktoren (circular) oder die KI-Daten (aitrained/airaw), bauen sich über die Zeit immer granularer auf und stellen einen wertvollen Datenbestand dar.&lt;br /&gt;
&lt;br /&gt;
Wird das SolarForecast Device gelöscht und anschließend wieder neu mit dem gleichen Namen definiert, können die bisher verfügbaren Daten sehr einfach wiederhergestellt werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. starten von FHEM (bestimmte Daten werden automatisch importiert)&lt;br /&gt;
* 5. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Soll das neue SolarForecast Device mit einem anderen Namen oder weitere SolarForecast Devices erstellt werden, welche die Betriebsdaten des primären Devices verwenden sollen, ist wie folgt vorzugehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. umbenenen der Dateien, wobei &amp;lt;name&amp;gt; durch den Namen des neuen SolarForecast Devices ersetzt wird&lt;br /&gt;
* 5. starten von FHEM (die Daten werden automatisch importiert)&lt;br /&gt;
* 6. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn sich die SolarForecast Devices hinsichtlich ihres Models oder der integrierten Consumer unterscheiden, sind die Dateien &amp;quot;PVCsm_SolarForecast_&amp;lt;name&amp;gt; &amp;quot; , &amp;quot;ScApi_SolarForecast_&amp;lt;name&amp;gt;&amp;quot; von dem Verfahren auszuschließen.&lt;br /&gt;
&lt;br /&gt;
== Batterieintegration und -steuerung ==&lt;br /&gt;
&lt;br /&gt;
=== Wie eine Batterie eingebunden wird ===&lt;br /&gt;
Wie immer muß die Batterieanlage zunächst mit einem für die Batterie spezifischen FHEM-Device in FHEM definiert sein.&lt;br /&gt;
In diesem Device werden Readings erwartet die folgende Werte bereitstellen:&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieentladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die installierte Batteriekapazität liefert (&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; dieser Schlüssel ist für die Aktivierung des Batterie SOC-Managements und die grafische Anzeige des SOC wesentlich!)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Lade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Entlade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* Reading welches den aktuellen Ladezustand (SOC in Prozent) liefert (optional)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Batterie, bzw. das Batteriedevice wird mit dem Attribut &#039;&#039;&#039;setupBatteryDev&#039;&#039;&#039; im SolarForecast Device registriert. Die Syntax des Attributes ist in  der Online-Hilfe zum Attribut umfassend erläutert. &lt;br /&gt;
Auch wenn manche Readings optional sind, wird empfohlen alle Werte bereitzustellen um alle Batterie-Funktionen im Modul nutzen zu können. Durch die Weiterentwicklung des Moduls können optionale Readings später auch obligatorisch werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Visualisierung der Batterie in der Balkengrafik ====&lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;setupBatteryDevXX&#039;&#039;&#039; verfügt über den Schlüssel &#039;&#039;&#039;show&#039;&#039;&#039;, mit dem die Einblendung des bzw. der Batteriesymbole in den Ebenen der Balkengrafik gesteuert werden kann:&lt;br /&gt;
[[Datei:Screenshot 2025-02-23 192002.png|right|thumb|400px|Einblendung der Batterieleiste und Darstellung des Batterie-SoC als Balkencontent in der zweiten Ebene]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 0 - keine Anzeige des Gerätes (default)&lt;br /&gt;
* 1 - Anzeige des Gerätes in der Balkengrafik Ebene 1&lt;br /&gt;
* 2 - Anzeige des Gerätes in der Balkengrafik Ebene 2 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Symbole und die Farbgebung der Batterie(n) können mittels des Schlüssels &#039;&#039;&#039;icon&#039;&#039;&#039; verändert werden. Die Online-Hilfe gibt weitere Informationen zur Ausgestaltung. &lt;br /&gt;
&lt;br /&gt;
In der Batteriedarstellung wird das Symbol der aktuellen Stunde hervorgehoben. Ein Mouse-Over zeigt wesentliche Betriebszustände der Batterie. Die Batteriesymbole vergangener Stunden zeigen mit einem Mouse-Over die erreichten SoC (State of Charge) Stände. Die kommenden Stunden visualisieren die folgenden Prognosen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der prognostizierte SoC unter Berücksichtigung der PV-Prognose und der [[#Aktivierung_des_Batterie_SOC-Managements|Batteriesteuerung]] sofern sie im Modul aktiviert ist.&lt;br /&gt;
* eine Freigabe bzw. Empfehlung der Batterieladung zur [[#Unterstützung_eines_netzdienlichen_Verhaltens|Unterstützung eines netzdienlichen Verhaltens]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Neben der Einblendung der Batterieleiste über der Balkengrafik selbst können bestimmte Batteriekennwerte als Balkeninhalt dargestellt werden. Die Auswahl erfolgt über das Attribut &#039;&#039;&#039;graphicBeamXContent&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Aktivierung des Batterie SOC- und Lade-Managements ===&lt;br /&gt;
Das integrierte SOC- und Lade-Management verfolgt insbesondere zwei Ziele: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* den Ladezustand der Batterie(n) zu optmimieren, was besonders in den Monaten mit geringerer PV-Erzeugung einen wertvollen Beitrag zur Erhöhung der Autarkierate und Batteriepflege leisten kann&lt;br /&gt;
 &lt;br /&gt;
* eine PV-Prognose und Verbrauch optimierte Beladungssteuerung, die in den Monaten mit hoher PV-Erzeugung hilft eine evtl. Abregelung der Anlage zu verhindern, die Batterie ausgewogen über den Tag zu laden und ein netzdienliches Verhalten zu unterstützen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese beiden Aspekte der Batteriesteuerung werden in den folgenden Abschnitten beschrieben. Sind mehrere Batterien installiert, kann die Steuerung getrennt für jede einzelne Batterie aktiviert und eingestellt werden. Dabei ist zu beachten, dass vom Modul nur Signale und Readings bereitgestellt werden, die durch eine entsprechende Routine ausgewertet werden können um spezifische Befehle zur Umsetzung der Steuerung an das Batteriesystem zu senden. &lt;br /&gt;
 &lt;br /&gt;
Für eine Aktivierung des Managements muß zunächst das Batterie-Device wie im vorigen Abschnitt im SolarForecast Device registriert werden.&lt;br /&gt;
Das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; aktiviert die im Modul integrierte SOC- und Lade-Management Routine: &lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; ctrlBatSocManagement01 lowSoc=&amp;lt;Wert&amp;gt; upSoC=&amp;lt;Wert&amp;gt; [maxSoC=&amp;lt;Wert&amp;gt;] [careCycle=&amp;lt;Wert&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
Die einzelnen Schlüssel werden der Kalkulationsroutine als Steuerungsparameter übergeben und bedeuten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;lowSoc:unterer Mindest-SoC, die Batterie wird nicht tiefer als dieser Wert entladen (muß &amp;gt; 0 sein). Dieser Wert kann zum Beispiel dazu dienen, stets eine Mindestenergiemenge für den Fall eines Stromausfalls im öffentlichen Netz in den Batterien vorzuhalten.&lt;br /&gt;
&lt;br /&gt;
;upSoC:oberer Mindest-SoC, Der übliche Wert des optimalen SoC bewegt sich in Perioden mit hohen PV-Überschuß tendenziell zwischen &#039;lowSoC&#039; und &#039;upSoC&#039;, in Perioden mit geringer PV-Ausbeute bzw. geringem PV Energieüberschuß bewegt sich der optimale SoC tendenziell zwischen &#039;upSoC&#039; und &#039;maxSoC&#039;. Die Einstellung von upSoC=50 für ein ausgewogenes Verhalten kann als guter Startwert dienen.&lt;br /&gt;
&lt;br /&gt;
;maxSoC:maximaler Mindest-SoC, d.h. der SoC Wert der mindestens im Abstand von &#039;careCycle&#039; Tagen erreicht werden muß um den Ladungsausgleich im Speicherverbund auszuführen. Die Angabe ist optional (muß &amp;lt;= 100 sein, default: 95)&lt;br /&gt;
&lt;br /&gt;
;careCycle:maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens &#039;maxSoC&#039; auftreten darf. Die Angabe ist optional. (default: 20)&lt;br /&gt;
&lt;br /&gt;
;loadAbort: definiert eine vom Anwender gewünnschte Bedingung für einen generellen Ladeabbruch und Wiederfreigabe der Lademöglichkeit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle Werte sind ganze Zahlen in %. Dabei gilt: &lt;br /&gt;
&lt;br /&gt;
 lowSoc &amp;lt; upSoC &amp;lt; maxSoC&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====  Erläuterung der Batterie-Steuerungsreadings ==== &lt;br /&gt;
&lt;br /&gt;
Für die Steuerung des Batteriesystems gibt es im SolarForecast einen Satz an Readings, die unterschiedliche Zustände signalisieren und für entsprechende Steuerungsaufgaben bezüglich der Batteriesysteme eingesetzt werden können. In den nachfolgenden Abschnitten werden diese Zusammenhänge noch dataillierter beschrieben.&lt;br /&gt;
&lt;br /&gt;
;Hinweis: SolarForecast stellt lediglich Steuerungsinformationen zur Verfügung. Die Umsetzung des Eingriffs in das Batteriesystem erfolgt durch den Anwender selbst über entsprechende Skripte. In den thematischen Abschnitten werden Beispiele für solche Steuerungsskripte vorgestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle erstellten Readings gelten für ein Batteriesystem, es können mehrere Batteriesysteme in SolarForecast integriert sein. Die Endung &#039;&#039;XX&#039;&#039; der Readings beschreibt die Nummer des Batteriesystems und korrespondiert mit der Endung des entsprechenden Attributes &#039;&#039;ctrlBatSocManagementXX&#039;&#039; bzw. &#039;&#039;setupBatteryDevXX&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Battery_OptimumTargetSoC_XX: Mit den im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; hinterlegten Parametern unter Berücksichtigung von PV- und Verbrauchsprognosen wird ein optimaler SOC-Wert errechnet. Dieser Wert dient zur Einstellung des unteren SOC des Batteriesystems.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeRequest_XX: Dieses Reading signalisiert mit 1 eine Anforderung zur Zwangsladung der Batterie um die Batterie vor Schäden zu schützen (wenn der SOC unter ctrlBatSocManagementXX-&amp;gt;lowSoc gefallen ist) oder wenn der aktuelle SOC unter den berechneten Mindest-SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeUnrestricted_XX: Dieses Reading kann den Wert &#039;&#039;&#039;0&#039;&#039;&#039; oder &#039;&#039;&#039;1&#039;&#039;&#039; einnehmen. Ist der Wert 0, sollte die Batterie nur geladen werden, wenn der im Attribut &#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039; definierte Wert überschritten wird. Ist der Wert 1, sollte die Batterie mit der vollen zur Verfügung stehenden Ladeleistung angesteuert werden, um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten. Der Fokus der Steuerung mit diesem Reading ist es, die Speicherkapazität der Batterie optimal zur Verhinderung der Überschreitung von Einspeiselimits einzusetzen und dennoch einen maximal möglichen SoC am Tagesende zu erreichen. (siehe das beschriebene [[SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#PV-Prognose_und_Verbrauch_optimierte_Beladungssteuerung_unter_Berücksichtigung_einer_Wirkleistungsbegrenzung|Nutzungsbeispiel]])&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeOptTargetPower_XX: Dieses Reading enthält einen Richtwert für die optimierte Ladeleistung für jede Batterie. Die Aufladung wird prognosegeführt über den gesamten Tag verteilt, wobei der Fokus auf eine kontinuierliche, aber möglichst niederige Ladeleistung gelegt wird. (siehe diesen [[SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#leistungsoptimierte_Beladungssteuerung_mit_dem_Fokus_geringe_Verlustleistung_und_Verschleiß|Abschnitt]])  &lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeAbort_XX: Im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; kann mit dem Schlüssel &#039;&#039;loadAbort&#039;&#039; eine Bedingung definiert werden, bei deren Eintritt die Ladung der Batterie abgebrochen werden soll. In diesem Fall wird &#039;&#039;Battery_ChargeAbort_XX=1&#039;&#039; gesetzt. Mit einem entsprechenden Befehl kann der Anwender das Batteriesystem anweisen den Ladevorgang abzubrechen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Nutzung des Batterie SOC-Management ====&lt;br /&gt;
&lt;br /&gt;
Oftmals wird durch die Anlagenhersteller ein hoher statischer SOC eingestellt bzw. empfohlen, der eine längere Verharrungszeit auf einem tiefen SOC-Wert verhindern soll. Allerdings wechseln sich in auch in den Herbst-, Frühlings- und Wintermonaten Zeiten mit wenig PV-Erzeugung mit Phasen stärkerer Solarstrahlung bei klarem Himmel und Sonnenschein ab.&lt;br /&gt;
&lt;br /&gt;
Ein statischer SOC würde dazu führen, dass in den erwähnten Phasen zuviel Energie in das öffentliche Netz eingespeist wird. Dies soll verhindert werden da die wertvolle Energie besser im eigenen Netz gespeichert und in Dunkelphasen verwendet werden kann. Andererseits soll die Batterie nicht zu lange auf einem tiefen SOC verbleiben und außerdem in gewissen Abständen auf einen so hohen SOC geladen werden der den internen Zellausgleich ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Die SOC Kalkulationsroutine des Moduls errechnet unter Berücksichtigung des prognostizierten PV-Ertrages der kommenden Tage, des aktuellen SOC und der im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; (nachfolgend beschrieben) angegebenen Steuerparameter den Vorschlag für eine optimale SOC-Einstellung. Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert.&lt;br /&gt;
&lt;br /&gt;
Durch das Modul selbst findet keine Steuerung der Batterie statt. Es stellt entsprechende Readings zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen SoC.&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SoC unter den optimalen SoC gefallen ist. In diesem Fall sollte die Batterie, unter Umständen mit Netzstrom, zwangsgeladen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Readings können zur Steuerung des SoC (State of Charge) sowie zur Steuerung des verwendeten Ladestroms der Batterie verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ermittlung des optimalen SOC erfolgt nach folgender Logik:&lt;br /&gt;
&lt;br /&gt;
# 	Ausgehend von &#039;lowSoc&#039; wird der Mindest-SoC kurz vor Sonnenuntergang um 5% inkrementiert sofern am laufenden Tag &#039;maxSoC&#039; nicht erreicht wurde und die PV-Prognose keinen hinreichenden Ertrag des kommenden Tages vorhersagt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Wird &#039;maxSoC&#039; (wieder) erreicht, wird Mindest-SoC um 5%, aber nicht tiefer als &#039;lowSoc&#039;, verringert. Ist der berechnete Mindest-SoC größer als &#039;upSoc&#039;, wird der Mindest-SoC auf &#039;upSoc&#039; gesetzt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#   Mindest-SoC wird soweit verringert, dass die prognostizierte PV Energie des aktuellen bzw. des folgenden Tages von der Batterie aufgenommen werden kann. Mindest-SoC wird typisch auf &#039;upSoc&#039; und nicht tiefer als &#039;lowSoc&#039; verringert.  &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Das Modul erfasst den letzten Zeitpunkt am &#039;maxSoC&#039;-Level, um eine Ladung auf &#039;maxSoC&#039; mindestens alle &#039;careCycle&#039; Tage zu realisieren. Zu diesem Zweck wird der optimierte SoC in Abhängigkeit der Resttage bis zum nächsten &#039;careCycle&#039; Zeitpunkt derart verändert, dass durch eine tägliche 5% SoC-Steigerung &#039;maxSoC&#039; am &#039;careCycle&#039; Zeitpunkt rechnerisch erreicht wird. Wird zwischenzeitlich &#039;maxSoC&#039; erreicht, beginnt der &#039;careCycle&#039; Zeitraum erneut. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im fünften Schritt werden die Grenzen &#039;lowSoc&#039; und &#039;upSoc&#039; berücksichtigt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im letzten Schritt erfolgt Generierung des Readings &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; zur Signalisierung einer eventuell empfohlenen Zwangsladung auf den berechneten Min-SoC. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei sehr wenig Erzeugungungsprognose, d.h. wenn sich der berechnete Min-SoC oberhalb von &#039;upSoC&#039; bewegt, wird &#039;upSoC&#039; eingestellt. Liegt der berechnete Min-SoC unterhalb von &#039;upSoC&#039;, ist jedoch größer als &#039;lowSoC&#039;, wird der berechnete SOC im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; eingestellt. Somit eignet sich die Angabe im Schlüssel &#039;upSoC&#039; um in Zeiten geringer Solarenergieerzeugung die Batterie für eine Notstromerzeugung auf mindestens diesem Wert zu halten. Sollte die PV-Prognose kurzfristig einen größeren Ertrag vorhersagen als die Batterie durch die Einhaltung von &#039;upSoC&#039; aufnehmen kann, wird der Min-SoC unter &#039;upSoC&#039; abgesenkt um möglichst allen PV-Überschuß in der Batterie zu speichern und somit dem Eigenverbrauch zuzuführen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der berechnete Mindest-SoC ist immer nur ein unterer Grenzwert. Die Batterie kann durch Ladevorgänge natürlich jederzeit einen höheren als den im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; dargestellten optimalen SoC haben. Der optimale SoC sollte nicht unterschritten werden um die oben genannten Zusammenhänge abbilden zu können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Die dynamische SOC Steuerung mit Umsetzungsbeispiel =====&lt;br /&gt;
Das Modul bietet eine Unterstützung zur automatisierten Einstellung eines optimalen SoC Wertes.&lt;br /&gt;
&lt;br /&gt;
Ziel ist es, den Minimum SoC in Abhängigkeit der zu erwartenden Solarerträge des aktuellen und des folgenden Tages so einzustellen, dass der prognostizierte Solarertrag von der Batterie aufgenommen werden kann. Die Einspeisung in das öffentliche Netz soll minimiert werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin soll ein unterer SoC nicht unterschritten, sowie ein oberer Minimum SoC im Normalfall nicht überschritten werden. Der obere Grenzwert stellt sicher, dass die Batterie mindestens bis zu diesem Wert wieder entladen werden kann. Dadurch bleibt innerhalb der Batterie immer genügend Kapazität verfügbar um unvorhergesehene PV Energie aufnehmen zu können.&lt;br /&gt;
&lt;br /&gt;
Aktiviert wird die Unterstützung der Batteriesteuerung durch das Setzen des Attributes &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; z.B. mit diesen Angaben:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagementXX lowSoc=x upSoC=x maxSoC=x careCycle=x &lt;br /&gt;
&lt;br /&gt;
so zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=98 careCycle=20&lt;br /&gt;
&lt;br /&gt;
Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert. &lt;br /&gt;
Ist dieses Attribut gesetzt, werden Steuerungs-Readings erstellt, die der Nutzer auswerten und seine Batterieanlage z.B. via notify oder DOIF steuern kann. &amp;lt;bR&amp;gt;&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen Mindest-SoC.&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SOC unter den optimalen SOC bzw. minimalen SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
Die Schlüssel &#039;&#039;&#039;lowSoc&#039;&#039;&#039; und &#039;&#039;&#039;upSoC&#039;&#039;&#039; sind die unteren und oberen Grenzen, zwischen denen sich der Minimum SoC im normalen Betrieb bewegen soll.&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;maxSoC&#039;&#039;&#039; stellt eine Ladungsgrenze dar, die mindestens alle X (careCycle) Tage erreicht werden soll. Zu diesem Zweck errechnet das Modul die Anzahl der nötigen Erhöhungen der Minimum Batterieladung von 5% pro Tag um ausgehend vom aktuellen SoC-Level. Der resultierende Minimum SoC Wert wird entsprechend angepasst. Wurde der einstellte maxSoC Level erreicht, startet der Wartungszyklus (careCycle) erneut. &amp;lt;br&amp;gt;&lt;br /&gt;
Der maxSoC in Verbindung mit dem durch &#039;&#039;&#039;careCycle&#039;&#039;&#039; definierten Zyklus soll sicherstellen, dass der Batterieverbund in regelmäßigen Abständen einen Ladungsausgleich vollziehen kann. &lt;br /&gt;
&lt;br /&gt;
Durch die Modullogik erfolgt eine 5 protentige Anhebung des Minimum SoC wenn am Vortag maxSoC nicht erreicht wurde. Die Anhebung erfolgt aber nicht über upSoC. upSoC ist die obere Grenze des Minimum SoC. Wird am Vortag mindestens die maxSoC Ladung erreicht, verringert sich der Minimum SoC wieder schrittweise um 5%, aber nicht tiefer als lowSoc.&lt;br /&gt;
&lt;br /&gt;
Ergänzt wird die Logik noch um die PV Vorhersage. Dabei wird die obige Minimum SoC Berechnung um die Erwartung der PV Erwartung am aktuellen und folgenden Tag korrigiert. Das bedeutet, dass der Minimum SoC z.B. von heute 50% auf 10% abgesenkt und dadurch die gespeicherte Energie dem Haushalt zugeführt wird, wenn am heutigen oder kommenden Tag eine entsprechende PV Energie zu erwarten ist um die Batterie wieder vollständig zu zuladen.&lt;br /&gt;
Dadurch ist immer genügend &amp;quot;Freiplatz&amp;quot; in der Batterie und andererseits hat die Batterie in langen Dunkelphasen eine Reserve für einen eventuellen Stromausfall (falls der abgesichert werden soll) und wird vor einem dauerhaften tiefen SoC geschützt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Umsetzungsbeispiel =====&lt;br /&gt;
&lt;br /&gt;
Wie das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; genutzt werden kann, wird am Beispiel einer Victron Batterieanlage gezeigt. Die Anlage wird durch Cerbo GX Gerät gesteuert. Der Cerbo GX ist per MQTT2 in FHEM eingebunden. Umgesetzt ist die Steuerung der Batterie &#039;01&#039;, d.h. die Angabe &#039;XX&#039; ist durch &#039;01&#039; ersetzt.&lt;br /&gt;
&lt;br /&gt;
Die folgende kleine Logik ist in einem &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; File eingebaut und wird regelmäßig mit&lt;br /&gt;
&lt;br /&gt;
 batSocChargeMgmnt (&#039;&amp;lt;Name SolarForecast Device&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
aufgerufen. Der Aufruf erfolgt durch Angabe der Routine im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; des SolarForecast Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
  # Hinweis: die Zeichen &#039;::&#039; vor der Routine sind durch das SolarForecast Package bedingt&lt;br /&gt;
  ::batSocChargeMgmnt ($name);&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Routine wird dadurch automatisch am Ende jedes Zyklus (siehe Attribut plantControl-&amp;gt;cycleInterval) ausgeführt.&lt;br /&gt;
Um die SOC Managementfunktion nach Bedarf ein- bzw. ausschalten zu können wird zunächst im SolarForecast Device ein userattr zur Steuerung der SOC-Logik angelegt:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; userattr userFn_BatterySoCManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
Die Perl Routine &#039;&#039;&#039;batSocChargeMgmnt&#039;&#039;&#039; ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#  Batterie SOC und Max. Ladestrom Management&lt;br /&gt;
############################################################################&lt;br /&gt;
sub batSocChargeMgmnt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vebus   = &#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;;                            # Victron Vebus Device&lt;br /&gt;
  my $vicsets = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                         # Victron Einstellungen&lt;br /&gt;
&lt;br /&gt;
  my $maxcspc = 105;                                                           # max. Ladestrom (A) Victron MPII Verbund&lt;br /&gt;
  my $actmcc  = ReadingsNum ($vebus, &#039;MaxChargeCurrent&#039;, undef);               # akt. Ladestromeinstellung&lt;br /&gt;
  my $load    = $actmcc // $maxcspc;                                           # Soll-Ladestrom (A)&lt;br /&gt;
&lt;br /&gt;
  ## Battery SoC Management&lt;br /&gt;
  ###########################&lt;br /&gt;
  my $ubsm = AttrVal ($name, &#039;userFn_BatterySoCManagement&#039;, &#039;aus&#039;); &lt;br /&gt;
  &lt;br /&gt;
  if ($ubsm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name,    &#039;Battery_ChargeRequest_01&#039;,     0);&lt;br /&gt;
    my $csoc = ReadingsNum ($vicsets, &#039;MinimumSocLimit&#039;,             10);      # akt. SoC&lt;br /&gt;
    my $osoc = ReadingsNum ($name,    &#039;Battery_OptimumTargetSoC_01&#039;, 10);      # Soll-SoC&lt;br /&gt;
    my $surp = ReadingsNum ($name,    &#039;Current_Surplus&#039;,              0);      # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if ($csoc != $osoc) {&lt;br /&gt;
      CommandSet (undef, &amp;quot;$vicsets MinimumSocLimit $osoc&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn SoCMgmnt -&amp;gt; MinimumSocLimit in $vicsets set to $osoc %});&lt;br /&gt;
    }&lt;br /&gt;
	                                           &lt;br /&gt;
    if ($bcrq &amp;amp;&amp;amp; $surp &amp;lt; 1000) {                                              # max. Strom b. Battery_ChargeRequest &lt;br /&gt;
      $load = 21;&lt;br /&gt;
    }&lt;br /&gt;
	else {&lt;br /&gt;
	  $load = $maxcspc;&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Batterie Einstellung MaxChargeCurrent&lt;br /&gt;
  ##########################################&lt;br /&gt;
  if ($load != $actmcc) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$vebus MaxChargeCurrent $load&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
    Log3 ($name, 3, qq{$name - userFn ChargeMgmnt -&amp;gt; MaxChargeCurrent in $vebus set }.&lt;br /&gt;
                    qq{from old $actmcc A to $load A});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent_set&#039;, $load, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist im SolarForecast Device das Reading  &#039;&#039;&#039;Battery_ChargeRequest_01&#039;&#039;&#039; gesetzt, ist der aktuelle SOC kleiner als der optimale SOC und die Batterie wird (eventuell aus dem öffentlichen Netz) geladen. Das kann automatisch durch den Cerbo GX bzw. in anderen Anlagen durch einen entsprechenden Befehl erfolgen.&lt;br /&gt;
Damit die Netzbeladung nicht mit der vollen Ladestromstärke geschieht, wird der Ladestrom auf den gewünschten Wert (hier 21 A -&amp;gt; ca. 1000 W bei einem 48V System) reduziert sofern kein oder zu wenig PV-Überschuß vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== weitere mögliche Aspekte der SOC- und Batterieladesteuerung ====&lt;br /&gt;
&lt;br /&gt;
SolarForecast liefert durch seine internen Logiken bereits sehr hilfreiche Signale zur Steuerung von Batteriesystemen in Form von Readings an. Abhängig von den individuellen Möglichkeiten der vorhandenen Anlage käme zum Beispiel zusätzlich zu einer Steurung des optimalen SOC oder der Zeitfenster für die Batterieaufladung auch eine Steuerung des Ladestroms bzw. der verwendeten Ladeleistung in Betracht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hintergründe:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Das Laden eines Akkus mit möglichst gleichbleibender und geringer Leistung wirkt sich positiv auf dessen Langlebigkeit aus, was u.a. auch daran liegt, dass der Temperaturstreß im Akku bei langsamer Energiezuführung nur gering ist.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom führt zu einem geringen Absacken der Akkuspannung beim (ggf, temporären) Abschalten des Ladestroms, was sich positiv auf die SOC-Schätzung auswirkt.&lt;br /&gt;
    &lt;br /&gt;
* Ein geringer Ladestrom führt, insb. bei Nutzung passiver Balancer (sind in den Akku-Systemen üblicherweise verbaut), zu einer geringen Differenz zwischen den einzelnen Zellspannungen und damit zu einer besseren Kapazitätsausnutzung eins Akkus.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom kann zu einem zeitlich punktgenauen Zielfüllstand (im Winter 100%, ansonsten natürlich weniger) am Ende des Tages führen.&lt;br /&gt;
    &lt;br /&gt;
* Eine geringer Ladestrom führt auch zu geringen Leitungsverlusten, da der Strom quadratisch zu den Leitungsverlusten beiträgt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann auch die Verweildauer oder die Begrenzung des SOC, auf den die Batterie maximal geladen werden soll, Gegenstand von Optimierungen sein.&lt;br /&gt;
&lt;br /&gt;
Die häufig zu findende Empfehlung, Akkus nicht zu lange bei einem SOC von 100% verweilen zu lassen, liegt weniger an dem SOC als solchem, sondern daran, dass &#039;&#039;SOC=100%&#039;&#039; üblicherweise dadurch ermittelt wird, dass eine Zelle im Akku einen Spannungsschwellenwert überschreitet, der – würde dieser Schwellenwert zeitlich länger überschritten sein – zu einer Schädigung des Akkus führen könnte. Schädlich sind insbesondere häufige Nachladevorgänge bei Werten um die 100% SOC, da Zellen dann ja häufiger und damit - integral gesehen - auch länger den o.g. Schwellenwert überschreiten.&lt;br /&gt;
&lt;br /&gt;
Einige Akku-Hersteller, z.B. BYD, haben auf o.g, Grund in der (neueren) Firmware Ihrer Systeme einen SOC-Threshold (bei BYD liegt dieser bei 95%) eingebaut. Dieser Wert muss nach einem erreichten SOC von 100% unterschritten  werden, bevor überhaupt eine weitere Ladung erfolgt. Insbesondere in der dunklen Jahreszeit kann es daher sinnvoll sein, den Akku unter Verwendung von PV-Leistung so zu füllen, dass dieser möglichst nur einmal vor Einbruch der Dunkelheit auf &#039;&#039;SOC=100%&#039;&#039; geladen wird. Hierbei sollte darauf geachtet werden, dass der Ladeschlussstrom des jeweiligen Systems nicht unterschritten wird. &lt;br /&gt;
&lt;br /&gt;
SolarForecast unterstützt die oben betrachtete Batteriesteuerung durch die optionale Angabe von &#039;&#039;&#039;loadAbort&#039;&#039;&#039; im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039;. Das in diesem Kontext erstellte Reading &#039;&#039;&#039;Battery_ChargeAbort_XX&#039;&#039;&#039; stellt die auswertbaren Steuerungsinformationen zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== PV-Prognose und Verbrauch optimierte Beladungssteuerung unter Berücksichtigung einer Wirkleistungsbegrenzung ====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-04-25 143910.png|right|thumb|400px|Batterie Popup &amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Batterie geladen. sobald PV-Überschuß vorhanden ist ohne eine Prognose zu berücksichtigen. Dadurch sind die Batterien im Sommer unter Umständen schon um 10-12 Uhr voll geladen und die Anlage liefert ihre mehr oder weniger volle Energie (je nach Ausrichtung) in das öffentliche Netz. Dann könnte es zu einer Begrenzung der PV-Leistung durch einen Schwellenwert (z.B. 70%-Regelung) oder eventuell Zwangsabregelung durch den Netzbetreiber kommen.&lt;br /&gt;
&lt;br /&gt;
Hintergrund dieser Erweiterung ist das Bestreben, eine optimale Unterstützung bei der Maximierung des Eigenverbrauchs zu geben und einen Beitrag zur Netzstabilität zu leisten.&lt;br /&gt;
Das Ziel der Beladungssteuerung der Batterie ist es, die Ladung der Batterie über den Tag verteilt so zu steuern, dass die Batterie erst dann geladen wird, wenn durch den PV-Überschuß eine Netzeinspeisung erfolgen würde bzw. ein Grenzwert erreicht werden würde, der zu einer Abregelung der PV-Anlage führen könnte.&lt;br /&gt;
Es kann auch zu einer Zwangsabregelung durch den Netzbetreiber führen, was vermieden werden soll.&lt;br /&gt;
 &lt;br /&gt;
Die interne Kalkulationslogik erstellt zu diesem Zweck ein Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039;.&lt;br /&gt;
Dieses Reading gibt dem User ein Signal, ob zu der aktuellen Stunde der Ladevorgang der Batterie freigegeben (1) oder nicht freigegeben werden sollte (0). Die Freigabe zur Ladung bedeutet dass:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; die Batterie mit ihrer vollen Ladeleistung angesteuert werden sollte um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=0&#039;&#039;&#039; die Batterie nur geladen werden sollte wenn der im Attribut plantControl-&amp;gt;feedinPowerLimit definierte Wert überschritten wird&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ist keine Freigabe zur Ladung vorhanden, kann bzw. sollte dennoch eine Ladung der Batterie vorgenommen werden, sofern eine über dem im &amp;lt;br&amp;gt;&lt;br /&gt;
Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limit liegende Einspeiseleistung vorhanden ist. In diesem Status sollte die Batterie nur mit der Differenzleistung von vorhandener Einspeiseleistung und dem gesetzen Einspeiselimit geladen werden und damit das gesetzte Einspeiselimit einhalten ohne die Anlage abzuregeln. Ist die Batterie in einer Balkengrafikebene dargestellt, wird im Mouse-Over Popup die Battrie mit &#039;&#039;&amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;&#039;&#039; gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Möglichkeiten der Batteriesteuerung sind stark von der individuellen Anlage abhängig und können hier nicht beschrieben werden. Ein Umsetzungsbeispiel mit einer Victron-Anlage mit Pylontech Batterie ist weiter unten dargestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Aktivierung und Arbeitsweise =====&lt;br /&gt;
&lt;br /&gt;
Die implementierte Logik zur optimierten Batterie Beladungssteuerung wird aktiviert, wenn folgende Kriterien erfüllt sind: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;capacity&#039;&#039;&#039; in den setupInverterDevXX Atributen ist gesetzt&lt;br /&gt;
* das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; für die jeweilige Batterie ist gesetzt&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;cap&#039;&#039;&#039; im Attribut setupBatteryDevXX der jeweiligen Batterie ist gesetzt&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Die Logik arbeitet wie folgt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Der resultierende Schwellenwert der Wirkleistungsbegrenzung: der Gesamtanlage wird durch die Auswertung der in den Inverter-Attributen setupInverterDevXX  gesetzen Schlüssel limit (optional) und capacity ermittelt. Inverter mit gesetztem Schlüssel feed = grid (deren Energie wird ausschließlich in das öffentlich Netz eingespeist) werden von der Betrachtung in diesem Kontext ausgeschlossen.&lt;br /&gt;
&lt;br /&gt;
;Die benötigte Beladung bis zu maxSoC (im Attribut setupBatteryDevXX) : wird ermittelt und mit der zu erwartenden PV Tagesprognose in Beziehung gesetzt. Sofern die PV-Erzeugung abzgl. Verbrauch noch nicht das Wirkleistungbegrenzungs-Limit erreicht UND noch genügend PV-Überschuß für eine Ladung auf &#039;&#039;maxSoC&#039;&#039; im Laufe der kommenden Stunden des Tages zu erwarten ist, bleibt das Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 0&#039;&#039;&#039;. Die erreichte Qualität der Steuerungslogik ist stark von der Prognosequaliät abhängig. Um die Steuerung resilienter zu gestalten, wird per default ein Sicherheitsaufschlag von 50% auf die prognostizierte benötigte Ladeenenergie auf Stundenbasis einkalkuliert. Dieser Wert kann mit dem Attribut &#039;&#039;&#039;ctrlBatSocManagementXX-&amp;gt;safetyMargin&#039;&#039;&#039; individuell angepasst werden.&lt;br /&gt;
&lt;br /&gt;
;Wird das Wirkleistungbegrenzungs-Limit erreicht/überschritten und/oder die PV-Überschußprognose: zzgl. eines Sicherheitspuffers unterschritten, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 1&#039;&#039;&#039; gesetzt. Der User kann darauf reagieren und den Batterie Ladevorgang aktivieren. Die Möglichkeiten der Aktivierung sind natürlich von der installierten Anlage abhängig. Das SolarForecast Device greift nicht in die Batteriesteuerung direkt ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders ausgedrückt erfolgt immer dann eine Ladefreigabe, wenn einer der nachfolgenden Sachverhalte &#039;&#039;wahr&#039;&#039; ist:&lt;br /&gt;
&lt;br /&gt;
- die benötigte Ladeenergie (aller installierten Batterien) &amp;gt;= PV-Restüberschuß des Tages (Reading RestOfDayPVforecast) zzgl. Sicherheitsaufschlag&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- der Zeitpunkt des PV-Erzeugungszenit des laufenden Tages überschritten ist (Reading Today_MaxPVforecastTime)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn die aktuelle PV Leistung &amp;gt;= einer eventuellen Wechselrichter-Leistungsbegrenzung ist (Summe aller WR-Begrenzungen)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn das BatSoc-Management _nicht_ aktiviert ist (nicht alle oben genannten Aktivierungskriterien erfüllt sind)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind mehrere Batterien installiert und durch das Management einer Batterie die Einhaltung der genannten Kriterien bzw. Sachverhalte erwirkt wird, bleiben die weiteren Batterien im Modus Ladefreigabe (Battery_ChargeUnrestricted_XX=1).  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Umsetzungsbeispiel Batterie Ladesteuerung mit Victron GX Venus über den Grid Setpoint =====&lt;br /&gt;
&lt;br /&gt;
Ziel der Steuerung ist es abhängig vom Wert des Readings Battery_ChargeUnrestricted_XX (z.B. Battery_ChargeUnrestricted_01) die Ladung des angeschlossenen Batteriesystems zu aktivieren bzw. zu deaktivieren.&lt;br /&gt;
Das vorliegende Beispiel soll umzusetzen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 0 -&amp;gt; Batterie nicht aufladen bzw. nur laden wenn Einspeiselimit überschritten (Attribut plantControl-&amp;gt;feedinPowerLimit)&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 1 -&amp;gt; Batterie aufladen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Grid Setpoint ist ein Parameter in den Victron Systemeinstellungen. Das Victron System wird den eingestellten Grid Setpoint versuchen einzuhalten und bei einem positiven Wert Energie aus dem Netz beziehen bzw. bei einem negativen Grid Setpoint Energie in das Netz einspeisen.&lt;br /&gt;
&lt;br /&gt;
Normalerweise wird das Victron System die erzeugte PV Energie zunächst zur Deckung des Hausverbrauchs verwenden, ist dann noch ein PV Überschuß vorhanden, die Batterien aufladen und bei weiter vohandenen PV Überschuß diese Energie in das öffentliche Netz einspeisen sofern dem System eine Einspeisung erlaubt ist. Anderenfalls werden die Wechselrichter oder MPPT Smartloader heruntergeregelt bzw. limitiert. &lt;br /&gt;
&lt;br /&gt;
In der Standardeinstellung ist beim Victron System ein Grid Setpoint von ca. 20 bis 50 Watt, d.h. das System strebt danach diese Vorgabe zu erfüllen zieht ständig Energie in diesem Bereich aus dem öffentlich Netz von einem gelegentlichen Überschwingen der Regelung abgesehen. Damit ein eventueller PV Überschuß nicht zum Laden der Batterie verwendet, sondern statt dessen in das öffentliche Netz eingespeist wird, muß der Grid Setpoint um diesen Betrag abgesenkt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-24 114403.png|right|thumb|400px|Integration des Grid Setpoint-Managements in den Own_Spec-Bereich]]&lt;br /&gt;
&lt;br /&gt;
Damit man später per Attribut bzw. über den [[#Formatierung_der_Inhalte_im_Bereich_&amp;quot;Graphic_Header_Own_Specification&amp;quot;|Own_Spec-Bereich]] die automatische Ladesteuerung über den Grid Setpoint ein- bzw. ausschalten kann, legen wir ein userattr an:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 userattr &amp;lt;Name&amp;gt; userFn_GridSetpointManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin sind einige Vorbereitungen im Device MQTT2_cerboGX_c0619ab34e08_settings vorzunehmen. Dieses Device ist im vorliegenden Beispiel ein in FHEM vorhandenes MQTT2_DEVICE, über das die Victron CerboGX Einstellungen zugreifbar sowie einstellbar sind. Die Vorgehensweise zur Erstellung des MQTT2_DEVICE ist hier nicht beschrieben und wird vorausgesetzt.&lt;br /&gt;
&lt;br /&gt;
Damit ein entsprechender Set-Befehl zur Einstellung des Grid Setpoints vorhanden ist, werden folgende Attribute gesetzt:&lt;br /&gt;
&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings jsonMap Settings_CGwacs_AcPowerSetPoint_value:GridSetpoint&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings setList GridSetpoint W/c0619ab34e08/settings/0/Settings/CGwacs/AcPowerSetPoint {&amp;quot;value&amp;quot;:$EVTPART1}&lt;br /&gt;
&lt;br /&gt;
Nach dieser Attributierung kann mit einem &amp;quot;&#039;&#039;set MQTT2_cerboGX_c0619ab34e08_settings GridSetpoint &amp;lt;Wert&amp;gt;&#039;&#039;&amp;quot; der Grid Setpoint eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Das Attribut userFn_GridSetpointManagement kann nun im Perl Code ausgewertet werden um das Grid Setpoint-Management ein- bzw. auszuschalten.&lt;br /&gt;
Der nachfolgende Code wird in die Datei &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; eingefügt. Ist diese Datei nicht vorhanden, legen wir sie vorab als Kopie der ausgelieferten 99_myUtils.pm an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Steuerung Start/Stop der Batterieladung über den Victron Grid Setpoint&lt;br /&gt;
############################################################################&lt;br /&gt;
sub gridSetpointMgmt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vicsets   = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                               # Device Victron Einstellungen&lt;br /&gt;
  my $gspdef    = 20;                                                                  # Default Einstellung des Grid Setpoint&lt;br /&gt;
  my $targetgsp = $gspdef;                                                             # Voreinstellung Grid Setpoint&lt;br /&gt;
  my $neggspmax = FHEM::SolarForecast::CurrentVal ($name, &#039;feedinPowerLimit&#039;, 5000);   # max. gewünschte Einspeiseleistung in Watt&lt;br /&gt;
  $neggspmax    = $neggspmax * -1;&lt;br /&gt;
  my $gspm      = AttrVal ($name, &#039;userFn_GridSetpointManagement&#039;, &#039;aus&#039;);             # Freischaltung des Grid Setpoint-Managements&lt;br /&gt;
  my $curgsp    = ReadingsNum ($vicsets, &#039;GridSetpoint&#039;,         $gspdef);             # aktuelle Einstellung Grid Setpoint&lt;br /&gt;
  &lt;br /&gt;
  if ($gspm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name, &#039;Battery_ChargeUnrestricted_01&#039;, 0);         # Ladefreigabe (1 -&amp;gt; Bat Ladefreigabe)&lt;br /&gt;
    my $surp = ReadingsNum ($name, &#039;Current_Surplus&#039;,               0);         # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if (!$bcrq) {                                                               # Grid Setpoint absenken wenn keine .. &lt;br /&gt;
        $targetgsp = $gspdef - $surp;                                           # ..Batterie Ladefreigabe&lt;br /&gt;
        $targetgsp = $neggspmax if($targetgsp &amp;lt; $neggspmax);                    # Begrenzung der Einspeiseleistung&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($curgsp != $targetgsp) {&lt;br /&gt;
	  fhem (&amp;quot;set $vicsets GridSetpoint $targetgsp&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn gridSetpointMgmt -&amp;gt; GridSetpoint in $vicsets set to $targetgsp});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Victron_GridSetpoint_set&#039;, $targetgsp, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Vergleich des Setpoints mit der Vorgabe von &#039;&#039;$neggspmax&#039;&#039; dient dazu die maximale Einspeiseleistung in das öffentliche Netz zu begrenzen. Ist diese Grenze erreicht, wird der noch verbleibende Überschuß in die Batterie geladen. Dadurch wird eine Abregelung der Anlage vermieden wenn der Schwellenwert &#039;&#039;$neggspmax&#039;&#039;erreicht ist sofern die Batterie aufnahmefähig ist und nicht voll geladen ist. &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::gridSetpointMgmt  ($name);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zum Management des automatischen Grid Setpoint und der Anzeige des eingestellten Wertes wird das Attribut und die Readinganzeige in den Own_Spec-Bereich eingebunden, z.B.:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; graphicHeaderOwnspec  #Settings&lt;br /&gt;
                                   SetPoint&amp;amp;nbsp;Management:userFn_GridSetpointManagement&lt;br /&gt;
                                   Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== leistungsoptimierte Beladungssteuerung mit dem Fokus geringe Verlustleistung und Verschleiß ====&lt;br /&gt;
&lt;br /&gt;
Das SF-Modul bietet ein weiteres Reading &#039;&#039;&#039;Battery_ChargeOptTargetPower_XX&#039;&#039;&#039; zur Batteriesteuerung an. Dieses Reading liefert eine kalkulierte optimale Ladeleistung in Watt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ladeleistung wird kontinuierlich neu kalkuliert und berücksichtigt dabei:&lt;br /&gt;
&lt;br /&gt;
* die Prognose der PV-Erzeugung der nächsten Stunden und des (Rest-)Tages&lt;br /&gt;
* den prognostizierten Verbrauch auf Stunden- bzw. Tagesbasis&lt;br /&gt;
* eine eventuell mögliche Überschreitung des gesetzten Einspeiselimits (plantControl-&amp;gt;feedinPowerLimit)&lt;br /&gt;
* die gesetzten Leistungsparameter der Batterie &lt;br /&gt;
* das Ziel, am Tagesende einen möglichst maximalen SoC der Batterie erreicht zu haben&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Fokus der implementierten Logik liegt dabei auf einer kontinuierlichen Ladeleistung, die aber unter den oben genannten Gesichtspunkten möglichst (relativ) gering sein soll um den Batterieverschleiß und die Verlustleistung zu minimieren. Die im Reading angezeigte Ladeleistung kann mit geeigneten Mitteln direkt in die Leistungssteuerung der Batterie eingebracht werden. Natürlich kann die Leistung auch vorab in einen optimalen Ladestrom umgerechnet werden.&lt;br /&gt;
&lt;br /&gt;
Da das Ergebnis der Kalkulation stark von den Prognosen abhängt, ist zur Erhöhung der Resilienz per Default ein Sicherheitszuschlag von 20% eingebaut. Dieser Wert kann mit dem Attribut &#039;&#039;&#039;ctrlBatSocManagementXX-&amp;gt;safetyMargin&#039;&#039;&#039; individuell angepasst werden. &lt;br /&gt;
&lt;br /&gt;
Ist kein PV-Überschuß (mehr) vorhanden oder das Ladeziel erreicht, erfolgt ein Rückfall der Ladeleistung im Reading auf den Wert angegeben im Attribut &#039;&#039;&#039;setupBatteryDevXX-&amp;gt;pinreduced&#039;&#039;&#039;. Ist setupBatteryDevXX-&amp;gt;pinreduced nicht gesetzt, erfolgt ein weiterer Rückfall auf den Attributwert &#039;&#039;&#039;setupBatteryDevXX-&amp;gt;pinmax&#039;&#039;&#039;. Ist dieser Wert ebenfalls nicht gesetzt, erfolgt der Rückfall auf &amp;quot;Unendlich&amp;quot; (9223372036854775807).&lt;br /&gt;
&lt;br /&gt;
Es ist demzufolge ratsam den optionalen Paramter &#039;&#039;&#039;setupBatteryDevXX-&amp;gt;pinreduced&#039;&#039;&#039; zu setzen. Da dieser Wert im Reading gesetzt wird wenn ohnehin kein PV-Überschuß vorliegt und somit keine LAdung durch PV erfolgt, ist er gleichzeitig die Ladeleistung bei einer eventuellen Notladung aus dem Netz bei Unterschreitung von lowSoC. Dadurch wird sichergestellt, die Batterie mit nur wenig Leistung aus dem Grid zu laden falls es nötig sein sollte.&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Unterstützung eines netzdienlichen Verhaltens ====&lt;br /&gt;
&lt;br /&gt;
Der Steuerungsprozess der Batterieanlage leistet insgesamt einen kleinen Beitrag zur Netzstabilität, indem die Speicherladung in den Zeitraum der meisten prognostizierten Überschußeinspeisung gelegt wird. Im Sommer kann sich dieser Zeitraum in die Zeit nach dem Maxmimum des prognostizierten PV-Überschusses verlagern, wenn auch danach noch genügend Überschußenergie zu Volladung der Batterie prognostiziert wird. In dem Zusammenhang sollte im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; ein Einspeiselimit gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zur Verdeutlichung soll das Beispiel dienen:&lt;br /&gt;
&lt;br /&gt;
* die Batterie ist zu 60% geladen &lt;br /&gt;
* der User hat upSoC=40 eingestellt&lt;br /&gt;
* der User hat maxSoC=90 eingestellt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Am Vormittag ist genügend Sonne vohanden, das Maximumum der Energie über die Zeit wird aber noch erwartet. &lt;br /&gt;
Zu diesem Zeitpunkt wird das Reading  &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039; auf den Wert &amp;quot;0&amp;quot; gesetzt. Durch den Nutzer erfolgt daraufhin, zum Beipiel über ein Notify, ein anlagenspezifischer Befehl &amp;quot;Ladestop&amp;quot; an die Batterieanlage. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ab diesem Moment wird:&lt;br /&gt;
&lt;br /&gt;
# die Batterie nicht geladen&lt;br /&gt;
# die erzeugte PV-Energie dem Haushalt zur Verfügung gestellt bzw. der verbleibende Überschuß eingespeist, sofern der Überschuß unterhalb des im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limits liegt.&lt;br /&gt;
# ein eventuell über dem Limit &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; vorhandener Überschuß in die Batterie geladen und so die Netzlast verringert sowie die Batterie schonend geladen. (dieser Punkt trifft in den Monaten mit wenig PV-Erzeugung eher nicht zu)  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig liefert die Batterie Energie an das Hausnetz und wird von 60% bis maximal einem SoC-Wert entladen, der durch die [[#Die_dynamische_SOC_Steuerung_mit_Umsetzungsbeispiel|dynamische SOC Steuerung]] bestimmt wird. Dazu muß diese Steuerung natürlich implementiert sein. Sofern der berechnete SoC größer als upSoC ist, wird der maximale Entladungs-SoC auf upSoC gesetzt. &lt;br /&gt;
&lt;br /&gt;
Zusätzlich überprüft das Modul permanent bei jedem Zyklus die Differenz des aktuell vorhandenen SoC zum eingestellten maxSoC.&lt;br /&gt;
Sie soll nicht größer sein um mit dem (noch) zu erwartenden PV-überschuß des Tages der eingestellte maxSoC bzw. dessen Nähe wahrscheinlich erreicht werden kann. &lt;br /&gt;
Sollte der Differenz-Grenzwert erreicht sein, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; gesetzt und der Nutzer sollte dann über einen geeigneten Befehl seine Anlage in den Modus &amp;quot;Laden&amp;quot; umschalten.&lt;br /&gt;
Dieser Vorgang kann beliebig oft während des Tages alternieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Nutzung von batteryTrigger ===&lt;br /&gt;
Ergänzt werden die Möglichkeiten durch das set-Kommando: &lt;br /&gt;
&lt;br /&gt;
 batteryTrigger &amp;lt;1on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;1off&amp;gt;=&amp;lt;Wert&amp;gt; [&amp;lt;2on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;2off&amp;gt;=&amp;lt;Wert&amp;gt; ...] &lt;br /&gt;
&lt;br /&gt;
Das Kommando setzt Triggerpunkte bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %).&lt;br /&gt;
&lt;br /&gt;
Der verwendete SoC wird als resultierender SoC als Summe der aktuellen Ladung aller registrierten Batterie-Geräte im Verhältnis zur installierten Gesamtkapazität gebildet. Das bedeutet, dass alle einzelnen Batterie-Geräte als ein gemeinsamer Cluster betrachtet werden. &lt;br /&gt;
&lt;br /&gt;
Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise definiert werden.&lt;br /&gt;
Überschreiten die letzten drei SoC-Messungen eine definierte Xon-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = on&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
Unterschreiten die letzten drei SoC-Messungen eine definierte Xoff-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = off&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
&lt;br /&gt;
Der Inhalt der Readings kann durch ein User-Programm oder, bei Erzeugung von entsprechenden Events, mittels notify-Device ausgewertet werden um bei Eintreten eines definierten Ereignisses entsprechende Reaktionen auszulösen. Das kann zum Beispiel die Freigabe eines Heizstabes oberhalb eines bestimmten SOC sein oder ein Entladeverbot der Batterie unterhalb eines SOC-Wertes um Reserven für einen eventuellen Stromausfall zu behalten.&lt;br /&gt;
&lt;br /&gt;
Damit die Batterietrigger dynamisch geändert werden können, ist die Einstellung als Set-Kommando und nicht als Attribut ausgeführt.   &lt;br /&gt;
&lt;br /&gt;
Alle Triggerpunkte können mit dem set-Befehl:&lt;br /&gt;
&lt;br /&gt;
 reset batteryTriggerSet&lt;br /&gt;
&lt;br /&gt;
wieder gelöscht werden.&lt;br /&gt;
&lt;br /&gt;
== Verbrauchersteuerung - Registrieren und visualisieren 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;
Die Eigenschaften und das Schaltverhalten wird durch die Angabe der verfügbaren Schlüssel gesteuert. Die Möglichkeiten sind sehr umfangreich. Die nachfolgenden Abschnitte beschreiben die Verwendung am Beispiel oft vorkommender bzw. nachgefragter Sachverhalte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die Phasen der Verbrauchersteuerung ===&lt;br /&gt;
&lt;br /&gt;
Jeder Zyklus eines Verbrauchers durchläuft im Modul die folgenden Phasen:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Planung&#039;&#039;&#039; der Aktivzeiten des Verbrauchers, d.h. wann der Verbraucher geplant eingeschaltet sowie geplant ausgeschaltet wird und damit der Zyklus beendet wird.&lt;br /&gt;
# &#039;&#039;&#039;Start&#039;&#039;&#039; des Zyklus, d.h. Einschalten des Verbrauchers entsprechend der Planungsdaten sofern weitere, in den Consumer-Schlüsseln definierbare Rahmenbedingungen das Einschalten nicht verhindern (z.B. kein oder zu wenig PV-Energieerzeugung / PV-Überschuss)&lt;br /&gt;
# &#039;&#039;&#039;Permanente Überprüfung von&#039;&#039;&#039; eventuell vorhandenen &#039;&#039;&#039;Interruptbedingungen&#039;&#039;&#039; die den Verbraucher temporär ausschalten und, sofern die Interruptbedingung nicht mehr vorliegt, den Verbraucher wieder einschalten und so den gestarteten Zyklus fortsetzen.&lt;br /&gt;
#  &#039;&#039;&#039;Beendigung&#039;&#039;&#039; der Zyklus. Die Beendigung erfolgt entweder (normalerweise) wenn die geplante Endezeit der Zyklus erreicht ist oder eine optionale Endebedingung erfüllt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Steuerung der Phasen ====&lt;br /&gt;
Der Ablauf der Phasen kann durch verschiedene Schlüssel-Wert Paare beeinflusst und gesteuert werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; kann eine &#039;&#039;&#039;zusätzliche externe Bedingung&#039;&#039;&#039; definiert werden um den Einschaltvorgang des Consumers freizugeben. Ist die Bedingung (Regex) nicht erfüllt, erfolgt kein Einschalten des Verbrauchers auch wenn die sonstigen Voraussetzungen wie Zeitplanung, on-Schlüssel, auto-Mode und aktuelle PV-Leistung gegeben sind. Es erfolgt somit eine &#039;&#039;&#039;UND-Verknüpfung&#039;&#039;&#039; des Schlüssels swoncond mit den Planungsdaten und weiteren Einschaltbedingungen.&lt;br /&gt;
&lt;br /&gt;
Der optionale Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; definiert eine &#039;&#039;&#039;vorrangige Ausschaltbedingung&#039;&#039;&#039; (Regex). Sobald diese Bedingung erfüllt ist, wird der Consumer ausgeschaltet auch wenn die geplante Endezeit (consumerXX_planned_stop) noch nicht erreicht ist (&#039;&#039;&#039;ODER-Verknüpfung&#039;&#039;&#039;). Weitere Bedingungen wie off-Schlüssel und auto-Mode müssen zum automatischen Ausschalten erfüllt sein.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; kann während der geplanten Einschaltzeit eine automatische Unterbrechung sowie Wiedereinschaltung des Verbrauchers vorgenommen werden. Der Verbraucher wird temporär ausgeschaltet (interrupted) und wieder eingeschaltet (continued) wenn die Interrupt-Bedingung nicht mehr vorliegt. Die verbleibende Laufzeit wird durch einen Interrupt nicht beeinflusst! &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;power&#039;&#039;&#039; gibt die nominale Leistungsaufnahme des Verbrauchers gemäß seines Datenblattes an. Dieser Wert wird verwendet um die Schaltzeiten des Verbrauchers zu planen und das Schalten in Abhängigkeit des tatsächlichen PV-Überschusses zum Einplanungszeitpunkt zu steuern. Ist &#039;&#039;&#039;power=0&#039;&#039;&#039; gesetzt, wird der Verbraucher unabhängig von einem zum Zeitpunkt des Zyklus-Start eventuell nicht ausreichend vorhandenem PV-Überschuss wie geplant eingeschaltet und somit der Zyklus gestartet.&lt;br /&gt;
&lt;br /&gt;
Durch die Schlüssel &#039;&#039;&#039;notbefore&#039;&#039;&#039; und &#039;&#039;&#039;notafter&#039;&#039;&#039; kann der Startzeitpunkt des Verbrauchers so gesteuert werden, dass der Start des Zyklus nicht vor bzw. nach der angegebenen Zeit eingeplant wird. Diese Steuerung bezieht sich auf die &#039;&#039;Planung&#039;&#039;, d.h. der eigentliche Start des Verbrauchers kann sich unter Umständen durch vorhandene Rahmenbedingungen verzögern. &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; legt die geplanten Einschaltzeit, d.h. die Laufzeit des Zyklus fest. Der Name &#039;&#039;&#039;mintime&#039;&#039;&#039; ist nicht als MInimum-Zeit zu deuten, sondern beschreibt die angegebene Zeit in Minuten die der Zyklus dauern soll.&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist optional, da sich die Standard-Laufzeit des Verbrauchers von dessen Typ abgeleitet wird. Diese Standard Laufzeiten sind:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|dryer&lt;br /&gt;
|90 Minten&lt;br /&gt;
|-&lt;br /&gt;
|dishwasher&lt;br /&gt;
|180 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|washingmachine&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|heater&lt;br /&gt;
|240 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|charger&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|other&lt;br /&gt;
|60 Minuten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Der Verbraucher wurde nicht gestartet obwohl die Startzeit der Einplanung erreicht wurde ===&lt;br /&gt;
&lt;br /&gt;
Wenn die Startzeit des Consumers entsprechend der Einplanung erreicht oder überschritten ist, wird der Consumer eingeschaltet wenn die weiteren Voraussetzungen wahr sind:&lt;br /&gt;
&lt;br /&gt;
* es ist aktuell ein PV-Überschuss vorhanden und der PV-Überschuss deckt die kalkulierten Leistungsaufnahme des Verbrauchers ab. Mit den Schlüsseln &#039;&#039;&#039;power&#039;&#039;&#039; und &#039;&#039;&#039;spignorecond&#039;&#039;&#039; kann die Einschaltung trotz fehlendem PV-Überschuss ermöglicht werden. &lt;br /&gt;
&lt;br /&gt;
* die Angabe im Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; ist wahr (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* das Schalten ist über den Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; freigegeben (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* im Schlüssel &#039;&#039;&#039;on&#039;&#039;&#039; ist ein valides Einschaltkommando hinterlegt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind diese zusätzlichen Bedingungen nicht erfüllt, erfolgt kein Start des eingeplanten Zyklus. Der Verbraucher verbleibt in diesem Fall weiterhin im Status &#039;&#039;planned&#039;&#039; oder &#039;&#039;suspended&#039;&#039;. Die Startbedingungen werden regelmäßig reviewed und der Consumer gestartet sobald alle Startbedingungen wahr sind bzw. Start verhindernde Bedingungen entfallen sind. &lt;br /&gt;
&lt;br /&gt;
Dieser Vorgang erfolgt bis das geplante Ende des Verbaucherzyklus erreicht ist oder die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; zutrifft. Sobald die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; wahr ist, wird der gesamte Planungszyklus des Consumers beendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Kann manuell / automatisiert in den Planungszyklus eines Verbrauchers eingegriffen werden? ===&lt;br /&gt;
&lt;br /&gt;
Die Einplanung und die darauf aufbauenden Schaltprozesse laufen gemäß den hinterlegten Schlüsseloptionen im Modul automatatisch ab ohne dass ein Eingriff durch den Anwender erfolgen muß.&lt;br /&gt;
&lt;br /&gt;
Dennoch kann es gewünscht sein eine Neuplanung oder eine Sofortplanung eines Consumers vorzunehmen weil der Bedarf dazu besteht. Zu diesem Zweck stehen die Set-Kommandos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* consumerNewPlanning &lt;br /&gt;
&lt;br /&gt;
* consumerImmediatePlanning &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
zur Verfügung. &lt;br /&gt;
Beide Befehle initiieren die Consumer-Neuplanung, wobei mit dem Befehl &#039;&#039;consumerImmediatePlanning&#039;&#039; die eventuell im consumerXX Attribut gesetzten Schlüssel notbefore, notafter bzw. mode werden nicht beachtet werden. Dagenen beachtet der Befehl &#039;&#039;consumerNewPlanning&#039;&#039; alle definierten Schlüsseloptionen und dient gewöhnlich dazu einen abgeschlossenen Verbraucherzyklus wiederholt ausführen zu lassen weil die aktuelle Witterungslage dazu geeignet ist. &lt;br /&gt;
&lt;br /&gt;
Ein Anwendungsbeispiel dafür ist zum Beispiel die Ausführung von mehreren Waschmaschinen-Zyklen an einem langen, sonnigen Sommertag.&lt;br /&gt;
Diese beiden Set-Befehle können zum Beispiel über ein auf einen Schalter/Taster reagierendes Notify oder DOIF Device ausgeführt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung eines Verbrauchers mit getrennten Geräten für Messung und Schalten ===&lt;br /&gt;
&lt;br /&gt;
Es existieren in FHEM Geräte, die über verschiedene Kanäle für unterschiedliche Aufgaben verfügen. Diese Kanäle werden jeweils in einem gesonderten Device abgebildet. HomeMatic oder readingsProxy sind Beispiele für solche Varianten.&lt;br /&gt;
&lt;br /&gt;
Um solche Verbraucher einzubinden gibt es im consumerXX Attribut den Schlüssel &#039;&#039;&#039;switchdev&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Bei der Registrierung gibt man als Consumerdevice das Gerät für die Messung an und im Schüssel switchdev das entsprechende FHEM-Device, welches für die Schaltvorgänge benutzt wird. &lt;br /&gt;
Ist switchdev angegeben, beziehen sich die weiteren Schlüssel on, off, swstate, auto und asynchron auf dieses Gerät.&lt;br /&gt;
&lt;br /&gt;
In dem nachfolgenden Beispiel (Homematic) ist &#039;&#039;eg.az.fridge_Pwr&#039;&#039; FHEM Device für die Energiemessung. Die Schlüssel &#039;&#039;pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; geben Readings in diesem Device an damit SolarForecast den Verbrauch und die Energiemengen auslesen kann. Demgegenüber ist im Schlüssel &#039;&#039;switchdev&#039;&#039; das zugehörige Schalter-Device der Kombination angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eg.az.fridge_Pwr&lt;br /&gt;
type=noSchedule switchdev=eg.az.fridge_Sw power=0 icon=fridge pcurr=power:W:5 etotal=energyCalc:Wh &lt;br /&gt;
swstate=state:on:off auto=automatic&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung von Verbrauchern ohne Zeitplanung und aktivem Schalten ===&lt;br /&gt;
Manchmal besteht der Wunsch, Verbraucher in SolarForecast zu integrieren um lediglich folgende Sachverhalte abzubilden:&lt;br /&gt;
&lt;br /&gt;
* Visualisierung des Schaltstatus in der Consumer Legende und/oder der Energieflußgrafik&lt;br /&gt;
* Darstellung des aktuellen Energieverbrauchs in der Energieflußgrafik&lt;br /&gt;
* Erfassung der (externen) Schaltzeiten, d.h. der Zeiten der Gerätenutzung sowie der Verbrauchsdaten um deren Einfluß bei den Planungszeiten anderer Geräte durch SolarForecast berücksichtigen zu lassen&lt;br /&gt;
&lt;br /&gt;
In solchen Fällen werden bei der Registrierung die Schlüssel &#039;&#039;swstate, pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; zur Erfassung der Schaltzustände und der Energieverbrauchs angegeben, jedoch zur Verhinderung der Zeitplanung durch SolarForecast der Schlüssel &#039;&#039;&#039;type=noSchedule&#039;&#039;&#039; gesetzt sowie die Schlüssel &#039;&#039;on&#039;&#039; und &#039;&#039;off&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt eine mögliche Registrierung eines Zwischensteckers (Shelly) zur Erfassung der Daten eines Gefrierschrankes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Shelly.shellyplug4&lt;br /&gt;
type=noSchedule power=65 asynchron=1&lt;br /&gt;
icon=gefrierschrank &lt;br /&gt;
swstate=state:.*on.*:.*off.* &lt;br /&gt;
pcurr=relay_0_power:W:5 etotal=relay_0_energy_Wh:Wh&lt;br /&gt;
&amp;lt;/pre&amp;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;
&lt;br /&gt;
 Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off&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;
&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;
&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. Alternativ kann die Berücksichtigung des zwangsweisen PV Überschuss mit dem Schlüssel &amp;quot;spignorecond&amp;quot; im Consumer-Attribut ausgesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== zusätzliche Readings bzw. Erzeugung von statistischen Readings ==&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den zahlreichen im Modul per Standard erzeugten Readings kann der Anwender weitere Readings generieren lassen.&lt;br /&gt;
Diese zusätzlichen Readings geben entweder einen bestimmten Sachverhalt (Laufzeit, Status der API-Abfragen, etc.) oder einen statistischen Wert, z.B. die Batterieentladung des aktuellen Tages, wieder.&lt;br /&gt;
&lt;br /&gt;
Die zusätzlich erstellten Readings sind durch den Präfix &#039;&#039;&#039;special_&#039;&#039;&#039; im Device gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Diese zusätzlichen Informationen können durch das Setzen einer oder mehrerer Kennzeichen im Attribut &#039;&#039;&#039;ctrlSpecialReadings&#039;&#039;&#039; erzeugt werden. Die mögliche Auswahl wird je nach Bedarf ausgebaut und umfasst zum aktuellen Zeitpunkt (07.02.2025) diese Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;BatPowerIn_Sum: 	die Summe der momentanen Batterieladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;BatPowerOut_Sum: 	die Summe der momentanen Batterieentladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;allStringsFullfilled: 	Erfüllungsstatus der fehlerfreien Generierung aller Strings&lt;br /&gt;
;conForecastTillNextSunrise: 	Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
;currentAPIinterval: 	das aktuelle Abrufintervall der gewählten Strahlungsdaten-API in Sekunden&lt;br /&gt;
;currentRunMtsConsumer_XX: 	die Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; seit dem letzten Einschalten. (letzter Laufzyklus)&lt;br /&gt;
;dayAfterTomorrowPVforecast: 	liefert die Vorhersage der PV Erzeugung für Übermorgen (sofern verfügbar) ohne Autokorrektur (Rohdaten).&lt;br /&gt;
;daysUntilBatteryCare_XX: 	Tage bis zur nächsten Batterie XX Pflege (Erreichen der Ladung &#039;maxSoC&#039; aus Attribut ctrlBatSocManagementXX)&lt;br /&gt;
;lastretrieval_time: 	der letzte Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;lastretrieval_timestamp: 	der Timestamp der letzen Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;response_message: 	die letzte Statusmeldung der gewählten Strahlungsdaten-API&lt;br /&gt;
;runTimeAvgDayConsumer_XX: 	die durchschnittliche Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; an einem Tag&lt;br /&gt;
;runTimeCentralTask: 	die Laufzeit des letzten SolarForecast Intervalls (Gesamtprozess) in Sekunden&lt;br /&gt;
;runTimeTrainAI: 	die Laufzeit des letzten KI Trainingszyklus in Sekunden&lt;br /&gt;
;runTimeLastAPIAnswer: 	die letzte Antwortzeit des Strahlungsdaten-API Abrufs auf einen Request in Sekunden&lt;br /&gt;
;runTimeLastAPIProc: 	die letzte Prozesszeit zur Verarbeitung der empfangenen Strahlungsdaten-API Daten&lt;br /&gt;
;SunMinutes_Remain: 	die verbleibenden Minuten bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;SunHours_Remain: 	die verbleibenden Stunden bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;todayConsumptionForecast: 	Verbrauchsprognose pro Stunde des aktuellen Tages (01-24)&lt;br /&gt;
;todayConForecastTillSunset: 	Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
;todayDoneAPIcalls: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Calls&lt;br /&gt;
;todayDoneAPIrequests: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Requests&lt;br /&gt;
;todayConsumption: 	der gesamte Energieverbrauch (Wh) des Hauses am aktuellen Tag&lt;br /&gt;
;todayGridConsumption: 	die aus dem öffentlichen Netz bezogene Energie am aktuellen Tag&lt;br /&gt;
;todayGridFeedIn: 	die in das öffentliche Netz eingespeiste PV Energie am aktuellen Tag&lt;br /&gt;
;todayMaxAPIcalls: 	die maximal mögliche Anzahl Strahlungsdaten-API Calls. Ein Call kann mehrere API Requests enthalten.&lt;br /&gt;
;todayRemainingAPIcalls: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Calls&lt;br /&gt;
;todayRemainingAPIrequests: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Requests&lt;br /&gt;
;todayBatIn_XX: 	die am aktuellen Tag in die Batterie XX geladene Energie&lt;br /&gt;
;todayBatInSum: 	Summe der am aktuellen Tag in alle Batterien geladene Energie&lt;br /&gt;
;todayBatOut_XX: 	die am aktuellen Tag aus der Batterie XX entnommene Energie&lt;br /&gt;
;todayBatOutSum: 	Summe der am aktuellen Tag aus allen Batterien entnommene Energie&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Manche Angaben sind im Setup des Moduls optional, d.h. sie müssen nicht zwingend beim Setup angegeben werden. Allerdings sind diese Angaben für die Erstellung eines zusätzlichen Readings unter Umständen Voraussetzung. Es empfiehlt sich deshalb bei Setup so viele Informationen wie möglich zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
So ist zum Beispiel für die sinnvolle Erstellung der Informationen &#039;&#039;&#039;todayBatInSum&#039;&#039;&#039; und &#039;&#039;&#039;todayBatOutSum&#039;&#039;&#039; (Readings special_todayBatInSum und special_todayBatOutSum) das Vorhandensein der Schlüssel &#039;&#039;intotal&#039;&#039; und &#039;&#039;outtotal&#039;&#039; im Attribut setupBatteryDevXX notwendig (Beispiel):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupBatteryDev01 MQTT2_cerboGX_c0619ab34e08_battery &lt;br /&gt;
                              pin=BatIn:W pout=BatOut:W charge=SOC_value intotal=BatInTotal:Wh outtotal=BatOutTotal:Wh &lt;br /&gt;
                              cap=InstalledCapacity_Wh:Wh asynchron=1 show=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Fehlersuche ==&lt;br /&gt;
Das Modul SolarForecast ist sehr komplex und es die verschiedensten Datenquellen ausgewertet, zusammengeführt und daraus Ergebnisse berechnet und/oder visualisiert. Wird etwas nicht wie erwartet durch das Modul geliefert, können die Ursachen vielfältig sein. Natürlich kann ein Fehler im Modulcode vorliegen, oftmals gibt es aber andere Ursachen.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgenden Hinweise sollen Hilfe zur Selbsthilfe geben und sind eine Zusammenfassung von realen Fällen die mit dem beschriebenen Wegen und Verfahren gelöst wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die erwartete erzeugte PV-Energie ist im Modul zu gering und wird im Balkendiagramm nicht angezeigt === &lt;br /&gt;
&lt;br /&gt;
Die erzeugte PV-Energie wird nicht richtig angezeigt: Am Vormittag sind keine Werte vorhanden und, wenn dann etwas kommt, ist die Anzeige zu gering. Für 13 und 14 Uhr wurden ca. 5.000Wh erwartet (im Vergleich mit den Daten aus einer anderen Auswertungsquelle). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lösungsweg:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Aus dem List des Devices wurden die für den Fall wesentlichen Readings herausgezogen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVforecast 152 Wh&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVforecast 1400 Wh&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVforecast 2500 Wh&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVforecast 4392 Wh&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVforecast 4000 Wh&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVreal 300 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVforecast 6415 Wh&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVreal 3200 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVforecast 5629 Wh&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVreal 2700 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVforecast 3958 Wh&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVreal 900 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVforecast 945 Wh&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVreal 500 Wh&lt;br /&gt;
   &lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour18_PVforecast 59 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man sieht dass bis 12:00 keine erzeugte Energie vom WR gemeldet wird. Deswegen wird in der Balkengrafik nichts dargestellt. Auch danach bleibt die registrierte PV-Energie hinter den Erwartungen zurück. Zuständig für die Lieferung der PV-Energie an das Modul ist das Reading im Schlüssel:&lt;br /&gt;
&lt;br /&gt;
 setupInverterDev01 SH10rt pv=Total_DC_Power:W &amp;lt;mark&amp;gt;etotal=Total_Export_Energy_from_PV:kWh&amp;lt;/mark&amp;gt; capacity=10000 strings=Hauptdach,Flachdach&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Welche Änderungen es zwischen den Stunden gab, sieht man mit einem &amp;quot;get ... pvHistory XX&amp;quot; (&amp;quot;XX&amp;quot; steht für das Datum, d.h. den Tag, z.B. 02). &amp;lt;br&amp;gt;&lt;br /&gt;
Hier ein Beispiel für die Stunden 10 (9:00 - 9:59) und 11 (10:00 - 10:59). &amp;lt;br&amp;gt;&lt;br /&gt;
Wichtig ist hier der Key etotali01 für den ersten Inverter. Die Differenz zwischen den Werten beider Stunden ist die in der Stunde erzeugte Energie (hier 380 Wh). Diese 380 Wh findest du auch im Key pvrl01 als PVReal für diese Stunde. Das Modul rechnet intern immer mit Wh, kWh werden vorher in Wh umgerechnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
10 =&amp;gt; pvfc: 365, pvrl: 530, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63364714&amp;lt;/mark&amp;gt;, etotali02: 3044110, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;pvrl01: 380&amp;lt;/mark&amp;gt;, pvrl02: 150, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 574, con: 518, gcons: 22, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 1, feedprice: 0.1269&lt;br /&gt;
&lt;br /&gt;
            DoN: 1, sunaz: 137, sunalt: 12&lt;br /&gt;
&lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
      11 =&amp;gt; pvfc: 2966, pvrl: 1862, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63365094&amp;lt;/mark&amp;gt;, etotali02: 3044260, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            pvrl01: 1392, pvrl02: 470, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 774, con: 609, gcons: 25, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 4, feedprice: 0.1269&lt;br /&gt;
           &lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
D.h. wenn zwischen den beiden Stunden keine Differenzen zu finden sind, liegt es sehr wahrscheinlich am Input des Readings:&lt;br /&gt;
&lt;br /&gt;
 etotal=Total_Export_Energy_from_PV:kWh&lt;br /&gt;
&lt;br /&gt;
welches sich in den ersten Stunden nicht ändert und danach auch nur wenig.&lt;br /&gt;
&lt;br /&gt;
Man kann mit dem Attribut:&lt;br /&gt;
&lt;br /&gt;
 ctrlDebug=collectData&lt;br /&gt;
&lt;br /&gt;
die Datensammlung verfolgen (leider entstehen viele Daten im Log). Man sieht welche Werte von dem Inverter/Reading geliefert werden:&lt;br /&gt;
 &lt;br /&gt;
 ....&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; collect Inverter 01 data - device: STP_5000, delivery: default =&amp;gt;&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; pv: 0 W, &amp;lt;mark&amp;gt;etotal: 63378810 Wh&amp;lt;/mark&amp;gt;&lt;br /&gt;
 ....&lt;br /&gt;
&lt;br /&gt;
Dieser Wert muß bei PV Erzeugung kontinuierlich hochzählen. Wenn nicht, muss das angegebene Reading, d.h. die Quelle überprüft werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ergebnis der Prüfung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tatsächlich wurde ein Reading benutzt, das ungeeignet war: Statt &amp;quot;Total_PV_Generation&amp;quot; wurde &amp;quot;Total_export_energy_from_PV&amp;quot; genutzt. In diesem Reading wurde immer die in die Batterie gespeicherte Energie von der gesamten erzeugten Energie abgezogen. Daher war auch vormittags alles 0, da in dieser Periode alle PV-Energie in die Batterie geladen wurde bzw. in weiteren Stunden ein Anteil der dann bei dem PV-Erzeugungswert fehlte.&lt;br /&gt;
&lt;br /&gt;
Nachdem die Ursache beseitigt war, zeigt SolarForecast wieder die erwarteten PV-Erzeugungswerte an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Konfigurationsbeispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Visualisierung solare Vorhersage und reale Erzeugung ===&lt;br /&gt;
&lt;br /&gt;
Zu Beginn jedes neuen Tages gegen 00:00 Uhr werden durch das SolarForecast Device Events für die initiale PV Prognose des kommenden Tages erstellt.&lt;br /&gt;
Der Readingteil dieser Events heißt&lt;br /&gt;
&lt;br /&gt;
 AllPVforecastsToEvent&lt;br /&gt;
&lt;br /&gt;
Die Uhrzeiten der Events sind so aufbereitet und können direkt geloggt werden um sie in einen SVG Plot zu integrieren.&lt;br /&gt;
Im SolarForecast Device ist dieses Reading nicht sichtbar, nur die Events werden erstellt.&lt;br /&gt;
&lt;br /&gt;
Die meteorologischen Bedingungen verändern sich über den Tag permanent. Je nach gewählter Strahlungsdatenquelle (eine API oder DWD Device) erfolgt eine mehr oder weniger dynamische Anpassung der Prognose an die sich verändernde Umwelt.&lt;br /&gt;
&lt;br /&gt;
Aktuelle Prognosedaten sowie die reale PV Erzeugung der vergangenen Stunde können über die Readings&lt;br /&gt;
&lt;br /&gt;
 LastHourPVforecast&lt;br /&gt;
 LastHourPVreal&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-10-20 134050.png|right|thumb|400px|Übersicht solare Vorhersage]]&lt;br /&gt;
geloggt werden. &lt;br /&gt;
&lt;br /&gt;
Werden alle drei Werte in einem SVG kombiniert, kann die Entwicklung der Prognose über den Tag und die Beziehung von Prognose zu realer PV Erzeugnung pro Stunde visualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Für das rechts abgebildete Beispiel des Plots aus einer Datenbank &amp;quot;LogDBShort&amp;quot; sieht das gplot-File wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Created by FHEM/98_SVG.pm, 2024-03-08 15:05:31&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;TL&amp;gt;&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid&lt;br /&gt;
set ylabel &amp;quot;Wh&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Wh&amp;quot;&lt;br /&gt;
set yrange [0:7500]&lt;br /&gt;
set y2range [0:7500]&lt;br /&gt;
&lt;br /&gt;
#LogDBShort SolCast:LastHourPVforecast:::&lt;br /&gt;
#LogDBShort SolCast:LastHourPVreal:::&lt;br /&gt;
#LogDBShort SolCast:AllPVforecastsToEvent:::&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;aktuelle PV Vorhersage&#039; ls l6fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;reale PV Erzeugung&#039; ls l2fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;initiale PV Vorhersage&#039; ls l4 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; In manchen Fällen werden die Vorhersagewerte im SVG-Plot nicht angezeigt wenn FileLog verwendet wird. Ein Setzen des Attribute &amp;quot;fixedrange=3days +1&amp;quot; im SVG löst das Problem. Die Definition des SVG-Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_LogDBShort_SolCast SVG LogDBShort:SVG_LogDBShort_SolCast:HISTORY&lt;br /&gt;
attr SVG_LogDBShort_SolCast fixedrange 3days +1&lt;br /&gt;
attr SVG_LogDBShort_SolCast room Energie-&amp;gt;SolarPrognose&lt;br /&gt;
attr SVG_LogDBShort_SolCast sortby 2&lt;br /&gt;
attr SVG_LogDBShort_SolCast title &amp;quot;Übersicht solare Vorhersage&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Technisch bedingt werden an einem Tag X kurz nach 00:00 Uhr die am Vortag für den Tag X erzeugten Events aktualisiert. Diese Daten erzeugen in der Datenbank einen zweiten Satz an Daten mit dem gleichen Timestamp was für die Anzeige unvorteilhaft ist. &lt;br /&gt;
Um nur die aktualisierten Events von &#039;&#039;&#039;AllPVforecastsToEvent&#039;&#039;&#039; in der Datenbank zu erhalten, bietet sich ein DbRep-Device an. Die nachfolgende Vorschlagsdefinition kann per at-Device jeden Tag kurz vor Mitternacht (z.B. 23:57:10) ausgeführt werden. Es werden immer die in der Vergangenheit geschriebenen (veralteten) Daten aus der Datenbank gelöscht, doppelte Datesätze vermieden und immer die aktuellste initiale Prognose gespeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.Del.AllPVforecastsToEvent DbRep LogDBShort&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent alias Löschen Readings AllPVforecastsToEvent des Folgetages&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent comment ermöglicht dass die Readings AllPVforecastsToEvent am Folgetag wieder neu und aktuell geschrieben werden können&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent devStateIcon initialized:control_3dot_hor_s connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent disable 0&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent event-on-update-reading state&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent icon edit_delete&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent showproctime 1&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent device TYPE=SolarForecast&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_begin next_day_begin&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_end next_day_end&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das angegebene DbLog-Device &#039;&#039;&#039;LogDBShort&#039;&#039;&#039; ist natürlich anzupassen.&lt;br /&gt;
&lt;br /&gt;
Das at-Device zum Starten der Datenbankbereinigung sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define At.Del.AllPVforecastsToEvent at *23:58:10 set Rep.Del.AllPVforecastsToEvent delEntries&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent alias Start Löschen Readings AllPVforecastsToEventn LogDBShort&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent icon clock&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich sind auch hier die eigenen Devicenamen entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
Ab SolarForecast Version 1.51.7 kann die Eventerzeugung für bestimmte SVG Plot-Typen optimiert werden. &amp;lt;br&amp;gt; &lt;br /&gt;
Die Aktivierung dieser Optimierungen ist in der Online Hilfe zum Attribut &#039;&#039;&#039;plantControl-&amp;gt;genPVforecastsToEvent&#039;&#039;&#039; beschrieben. Bei Nutzung des Attributes plantControl-&amp;gt;genPVforecastsToEvent ist ebenfalls das Attribut &#039;&#039;&#039;event-on-update-reading=AllPVforecastsToEvent&#039;&#039;&#039; zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispielkonfiguration 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;
Bitte dabei diese DWD-Version aus dem [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter Contrib] von DS_Starter dazu nutzen&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|55_DWD_OpenData.pm&lt;br /&gt;
|136.2 KB ​&lt;br /&gt;
|29260  &lt;br /&gt;
|DS_Starter&lt;br /&gt;
|55_DWD_OpenData: contrib 1.17.7&lt;br /&gt;
|}&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 downloadTimeout 120&lt;br /&gt;
attr DWD comment Im DWD Wetterdevice verwendet Solarforecast : \&lt;br /&gt;
TTT,Neff,RR1c,ww,SunUp,SunRise,SunSet \&lt;br /&gt;
zusätzlich ist jedoch auch noch Rad1h notwendig \&lt;br /&gt;
wenn dieses DWD-Device als Strahlungsdevice genutzt wird.\&lt;br /&gt;
Die Station 10418 (Lüdenscheid) überträgt aktuell am 09.03.2025 (noch) Rad1h.\&lt;br /&gt;
attr DWD downloadTimeout 120&lt;br /&gt;
attr DWD forecastDays 7&lt;br /&gt;
attr DWD forecastProperties SunUp, SunRise, SunSet, Rad1h, R101, RR1c, TTT, Tx, Tn, Tg, DD, FX1, RR6c, R600, RRhc, Rh00, ww, wwd, Neff&lt;br /&gt;
attr DWD forecastRefresh 1&lt;br /&gt;
attr DWD forecastResolution 1&lt;br /&gt;
attr DWD forecastStation 10418&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 fc_description  -(state fc_time)&lt;br /&gt;
attr DWD verbose 2&lt;br /&gt;
&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;
defmod InverterDummy dummy&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;
defmod 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 feedinPrice 0.08&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 powerCost 0.25&lt;br /&gt;
attr SMA_Energymeter room 015_Zaehler,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;
defmod 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;
attr BatteryDummy userReadings total_pac, power_out, power_in, chargestatus, bat_rated_capacity, bat_loadtotal, bat_unloadtotal&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;
defmod N.PV.TotalConsumption.Dum.Energy notify SMA_Energymeter:Saldo_Wirkleistung:.* {\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung_2 Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&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;MB_USRW610_004&amp;quot;,&amp;quot;Power_Sum__W&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;
fhem &amp;quot;setreading InverterDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(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;
#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;
 # Batterie-total_pac  InverterDummy\&lt;br /&gt;
my $wert7 = sprintf(&amp;quot;%.3f&amp;quot;,((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy bat_rated_capacity &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert7));;\&lt;br /&gt;
 # möglicher Aufruf einer Batterie-Bebladung-Routine....SMABatteryChargewithTibber();;\&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;
defmod Forecast SolarForecast&lt;br /&gt;
attr Forecast DbLogExclude .*&lt;br /&gt;
attr Forecast DbLogInclude Current_BatCharge999&lt;br /&gt;
attr Forecast affectBatteryPreferredCharge 30&lt;br /&gt;
attr Forecast affectConsForecastLastDays 31&lt;br /&gt;
attr Forecast affect70percentRule 0&lt;br /&gt;
attr Forecast comment &amp;quot;wget -qO ./FHEM/76_SolarForecast.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/76_SolarForecast.pm&amp;quot;\&lt;br /&gt;
&amp;quot;wget -qO ./FHEM/55_DWD_OpenData.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/55_DWD_OpenData.pm&amp;quot;\&lt;br /&gt;
&amp;quot;13.01.2025 mit der Version 76_SolarForecast.pm:v1.43.2-s29518/2025-01-12&amp;quot;&lt;br /&gt;
attr Forecast graphicHeaderOwnspec PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal Verbrauch&amp;amp;nbsp;;bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast  Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest FCU-Erzeugung&amp;amp;nbsp;;:Current_PP01\&lt;br /&gt;
attr Forecast consumer01 FBDECT_fbahahttp_11657_0127183 icon=scene_washing_machine@orange type=washingmachine power=10 swstate:state notbefore=09 notafter=20 pcurr=power:W:3 etotal=energy:Wh interruptable=1 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer02 FBDECT_fbahahttp_E8_DF_70_07_3E_57 icon=light_floor_lamp@orange type=other power=15 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer03 FBDECT_fbahahttp_E8_DF_70_07_42_0B icon=raspberrypi@orange type=other power=8 swstate:state pcurr=power:W:1 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer04 FBDECT_fbahahttp_11657_0067275 icon=springbrunnen_icon@orange type=other power=50 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer05 FBDECT_fbahahttp_34_31_C4_D4_31_37 icon=sani_domestic_waterworks@orange type=other power=10 swstate:state pcurr=power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer06 tuya_local_bf5037060f450bdbd4rl0q icon=scene_clothes_dryer@orange type=dryer power=10 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer07 tuya_local_bfac44fb487476efd1vhdu icon=weather_sunset@orange type=noSchedule power=5 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumerControl adviceIcon=light_light_dim_100@gold&lt;br /&gt;
attr Forecast consumerControl showLegend=icon_top&lt;br /&gt;
attr Forecast consumerControl detailLink=1&lt;br /&gt;
attr Forecast ctrlAIdataStorageDuration 1825&lt;br /&gt;
attr Forecast ctrlAIshiftTrainStart 2&lt;br /&gt;
attr Forecast ctrlBatSocManagement01 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlBatSocManagement02 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlDebug none&lt;br /&gt;
attr Forecast plantControl genPVdeviation=continuously&lt;br /&gt;
attr Forecast plantControl cycleInterval=15&lt;br /&gt;
attr Forecast ctrlNextDayForecastReadings 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24&lt;br /&gt;
attr Forecast ctrlNextHoursSoCForecastReadings 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23&lt;br /&gt;
attr Forecast ctrlSpecialReadings BatPowerIn_Sum,BatPowerOut_Sum,SunHours_Remain,SunMinutes_Remain,allStringsFullfilled,conForecastTillNextSunrise,currentAPIinterval,currentRunMtsConsumer_01,currentRunMtsConsumer_02,currentRunMtsConsumer_03,currentRunMtsConsumer_04,currentRunMtsConsumer_05,currentRunMtsConsumer_06,currentRunMtsConsumer_07,dayAfterTomorrowPVforecast,daysUntilBatteryCare_01,daysUntilBatteryCare_02,lastretrieval_time,lastretrieval_timestamp,response_message,runTimeAvgDayConsumer_01,runTimeAvgDayConsumer_02,runTimeAvgDayConsumer_03,runTimeAvgDayConsumer_04,runTimeAvgDayConsumer_05,runTimeAvgDayConsumer_06,runTimeAvgDayConsumer_07,runTimeCentralTask,runTimeLastAPIAnswer,runTimeLastAPIProc,runTimeTrainAI,todayBatIn_01,todayBatIn_02,todayBatOut_01,todayBatOut_02,todayConForecastTillSunset,todayConsumptionForecast,todayDoneAPIcalls,todayDoneAPIrequests,todayGridConsumption,todayGridFeedIn,todayMaxAPIcalls,todayRemainingAPIcalls,todayRemainingAPIrequests&lt;br /&gt;
attr Forecast disable 0&lt;br /&gt;
attr Forecast event-min-interval .*:1800&lt;br /&gt;
attr Forecast event-on-change-reading .*&lt;br /&gt;
attr Forecast flowGraphicControl animate=1 consumerdist=80 h2consumerdist=50 shiftx=0  shifty=0 showconsumer=1 showconsumerdummy=1 showconsumerpower=1 showconsumerremaintime=0 size=400 strokewidth=12&lt;br /&gt;
attr Forecast graphicBeam1Color 3C14FF&lt;br /&gt;
attr Forecast graphicBeam1Content pvReal&lt;br /&gt;
attr Forecast graphicBeam2Color 19FF29&lt;br /&gt;
attr Forecast graphicBeam2Content pvForecast&lt;br /&gt;
attr Forecast graphicBeam3Color D60924&lt;br /&gt;
attr Forecast graphicBeam3Content batsocforecast_02&lt;br /&gt;
attr Forecast graphicBeam3FontColor FFFF0D&lt;br /&gt;
attr Forecast graphicBeam4Color FFFF1F&lt;br /&gt;
attr Forecast graphicBeam4Content batsocforecast_01&lt;br /&gt;
attr Forecast graphicBeam4FontColor 000000&lt;br /&gt;
attr Forecast graphicBeamHeightLevel1 200&lt;br /&gt;
attr Forecast graphicBeamHeightLevel2 200&lt;br /&gt;
attr Forecast graphicHeaderDetail all&lt;br /&gt;
attr Forecast graphicHeaderOwnspec #PV\&lt;br /&gt;
PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal\&lt;br /&gt;
PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast\&lt;br /&gt;
PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast\&lt;br /&gt;
:\&lt;br /&gt;
#\&lt;br /&gt;
AutarkyRate:Current_AutarkyRate\&lt;br /&gt;
Überschuss:Current_Surplus\&lt;br /&gt;
aktueller&amp;amp;nbsp;;Netzbezug:Current_GridConsumption\&lt;br /&gt;
:\&lt;br /&gt;
#Verbrauch\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenuntergang:special_todayConForecastTillSunset\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie01\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_01\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_01\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_01\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_01\&lt;br /&gt;
#Batterie01_tmp\&lt;br /&gt;
Current_PowerBatIn_01:Current_PowerBatIn_01\&lt;br /&gt;
Current_PowerBatOut_01:Current_PowerBatOut_01\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie02\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_02\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_02\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_02\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_02\&lt;br /&gt;
#Batterie02_tmp\&lt;br /&gt;
Current_PowerBatIn_02:Current_PowerBatIn_02\&lt;br /&gt;
Current_PowerBatOut_02:Current_PowerBatOut_02\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Settings\&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto \&lt;br /&gt;
Wetter:graphicShowWeather\&lt;br /&gt;
History:graphicHistoryHour\&lt;br /&gt;
ShowNight:graphicShowNight\&lt;br /&gt;
Debug:ctrlDebug\&lt;br /&gt;
FCU-Modus:FCU-Betriebsmodus@FCU&lt;br /&gt;
attr Forecast graphicHistoryHour 4&lt;br /&gt;
attr Forecast graphicHourCount 24&lt;br /&gt;
attr Forecast graphicLayoutType double&lt;br /&gt;
attr Forecast graphicShowDiff top&lt;br /&gt;
attr Forecast graphicShowNight 1&lt;br /&gt;
attr Forecast graphicShowWeather 1&lt;br /&gt;
attr Forecast group Energy Meter&lt;br /&gt;
attr Forecast room 020_PV,Energie&lt;br /&gt;
attr Forecast setupBatteryDev01 SBS25 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupBatteryDev02 SBS25_2 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupInverterDev01 SB25 pv=total_pac:kW etotal=etotal:kWh capacity=2500 strings=GarageSE limit=70&lt;br /&gt;
attr Forecast setupInverterDev02 SB30 pv=total_pac:kW etotal=etotal:kWh capacity=3000 strings=GarageNW,HausNW limit=70&lt;br /&gt;
attr Forecast setupInverterDev03 SB40 pv=total_pac:kW etotal=etotal:kWh capacity=4000 strings=HausSE1,HausSE2,HausSW limit=70&lt;br /&gt;
attr Forecast setupInverterStrings GarageSE,GarageNW,HausNW,HausSW,HausSE1,HausSE2&lt;br /&gt;
attr Forecast setupMeterDev SMA_Energymeter gcon=Bezug_Wirkleistung:W contotal=Bezug_Wirkleistung_Zaehler:kWh gfeedin=Einspeisung_Wirkleistung:W feedtotal=Einspeisung_Wirkleistung_Zaehler:kWh conprice=0.25:€ feedprice=0.08123:€&lt;br /&gt;
attr Forecast setupOtherProducer01 icon=Heizung_FCU_green@red MB_USRW610_004 pcurr=Power_L1__W:W etotal=Energy_L1_import__kWh:kWh&lt;br /&gt;
attr Forecast setupRadiationAPI DWD&lt;br /&gt;
attr Forecast setupStringPeak GarageSE=2.75 GarageNW=3.200 HausNW=2.230 HausSW=2.230 HausSE1=2.200 HausSE2=2.200&lt;br /&gt;
attr Forecast setupWeatherDev1 DWD&lt;br /&gt;
attr Forecast stateFormat Current_PV&lt;br /&gt;
attr Forecast userReadings Current_BatCharge999 {((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))) / ( (ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0) * 1000)  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0)*1000))*100}&lt;br /&gt;
attr Forecast verbose 2&lt;br /&gt;
&lt;br /&gt;
setstate Forecast 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .FCU_FCU-Betriebsmodus 2&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_ctrlDebug none&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicHistoryHour 4&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowNight 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowWeather 1&lt;br /&gt;
setstate Forecast 2025-01-13 08:24:25 .associatedWith SMA_Energymeter FBDECT_fbahahttp_11657_0127183 FBDECT_fbahahttp_E8_DF_70_07_3E_57 FBDECT_fbahahttp_E8_DF_70_07_42_0B FBDECT_fbahahttp_11657_0067275 FBDECT_fbahahttp_34_31_C4_D4_31_37 tuya_local_bf5037060f450bdbd4rl0q tuya_local_bfac44fb487476efd1vhdu SBS25 SBS25_2 SB25 SB30 SB40 DWD MB_USRW610_004&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .lastupdateForecastValues 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .pvCorrectionFactor_Auto_Soll on_complex_ai&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .signaldone_01 done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .signaldone_02 done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .signaldone_03 done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .signaldone_04 done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .signaldone_05 done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .signaldone_06 done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .signaldone_07 done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .signaldone_08 done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .signaldone_09 done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .signaldone_10 done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .signaldone_11 done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .signaldone_12 done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .signaldone_13 done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .signaldone_14 done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .signaldone_15 done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .signaldone_16 done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .signaldone_17 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .signaldone_18 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_01 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_02 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_01 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_02 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_AutarkyRate 83 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 Current_BatCharge999 10&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_01 12 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_02 8 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Consumption 626 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridConsumption 2 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridFeedIn 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PP_01 746.0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PV 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_01 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_02 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_01 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_02 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumption 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumptionRate 0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Surplus 120 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourGridconsumptionReal 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_ConsumptionForecast 2944 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayConsumptionForecast 3609 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_01 272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PPreal_01 748 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PPreal_01 787 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_01 271 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PPreal_01 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PPreal_01 745 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_01 267 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PPreal_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_01 255 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PPreal_01 752 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_01 226 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_01 50 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PPreal_01 681 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_02 233 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_01 845 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridConsumption 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_01 37 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_02 90 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_01 351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_02 188 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridConsumption 447 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVforecast 127 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridConsumption 1650 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVforecast 478 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVreal 26 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridConsumption 513 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVforecast 868 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVreal 97 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridConsumption 576 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVforecast 1157 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVreal 320 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_01 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_02 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridConsumption 1272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridFeedIn 7 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVforecast 1238 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVreal 945 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_01 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_02 53 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridConsumption 955 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridFeedIn 31 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PPreal_01 562 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVforecast 1168 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVreal 1410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_01 703 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_02 500 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_01 22 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_02 18 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridConsumption 32 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridFeedIn 71 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PPreal_01 777 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVreal 1416 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_01 296 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_02 70 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_01 74 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_02 258 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridConsumption 13 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridFeedIn 17 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PPreal_01 732 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVforecast 880 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVreal 1051 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_01 47 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_02 126 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_01 102 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_02 75 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridConsumption 15 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridFeedIn 23 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PPreal_01 771 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVforecast 117 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVreal 86 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_02 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_02 67 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridConsumption 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridFeedIn 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PPreal_01 723 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_01 349 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_02 124 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_01 73 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_02 450 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridConsumption 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridFeedIn 6 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PPreal_01 671 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecastTime 2025-01-13 14:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVdeviation 30.17 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVforecast 7663 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVreal 5351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunRise 08:28&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunSet 16:46&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_ConsumptionForecast 17043 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour05_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour06_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour07_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour08_PVforecast 10 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour09_PVforecast 161 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour10_PVforecast 275 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour11_PVforecast 532 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour12_PVforecast 730 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour13_PVforecast 1252 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour14_PVforecast 818 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour15_PVforecast 1465 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour16_PVforecast 303 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour17_PVforecast 20 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour18_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour19_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour20_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour21_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour22_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour23_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour24_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_PVforecast 5566 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunRise 08:27&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunSet 16:47&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01 name=&#039;_Waschmaschine&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_start 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_stop 14.01.2025 11:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02 name=&#039;_Esszimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_currentPower 15.3 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03 name=&#039;_FCU&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_currentPower 7.15 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04 name=&#039;_Brunnen&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05 name=&#039;_Zisterne&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06 name=&#039;SW Trockner&#039; state=&#039;unknown&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_stop 14.01.2025 08:30:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07 name=&#039;SW Urlaubslicht-Wohnzimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;noSchedule&#039; info=&#039;von extern umgeschaltet&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 nextCycletime 18:54:09&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 pvCorrectionFactor_10 0.53 (automatic - old factor: 1.00, Sun Alt range: 5, Cloud range: 75, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 pvCorrectionFactor_11 0.56 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 70, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 pvCorrectionFactor_12 0.64 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 pvCorrectionFactor_13 0.88 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 pvCorrectionFactor_14 1.10 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 50, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 pvCorrectionFactor_15 1.01 (automatic - old factor: 1.06, Sun Alt range: 15, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 pvCorrectionFactor_16 1.09 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 45, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 pvCorrectionFactor_17 0.28 (automatic - old factor: 0.52, Sun Alt range: 0, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 pvCorrectionFactor_Auto on_complex_ai&lt;br /&gt;
setstate Forecast 2024-10-30 19:42:19 setupStringAzimuth GarageSE=-55 GarageNW=125 HausNW=125 HausSW=35 HausSE1=-55 HausSE2=-55&lt;br /&gt;
setstate Forecast 2024-10-30 19:37:38 setupStringDeclination GarageSE=40 GarageNW=40 HausNW=50 HausSW=50 HausSE1=50 HausSE2=50&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerIn_Sum 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerOut_Sum 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunHours_Remain 0.00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunMinutes_Remain 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_allStringsFullfilled 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_conForecastTillNextSunrise 9467 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentAPIinterval 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_01 132 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_02 184 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_03 329512 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_04 200 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_05 27 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_06 193 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_07 106 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_dayAfterTomorrowPVforecast 7344 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_01 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_02 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_time 2025-01-13 18:53:54&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_timestamp 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_response_message success&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_01 545.94 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_02 382.10 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_03 1430.13 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_04 262.05 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_05 28.80 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_06 622.63 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_07 276.51 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeCentralTask 0.3744&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIAnswer -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIProc -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeTrainAI 1.2529&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_01 3683.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_02 1617.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_01 2287.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_02 1057.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConForecastTillSunset 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 special_todayConsumptionForecast_01 509 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 special_todayConsumptionForecast_02 499 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 special_todayConsumptionForecast_03 501 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 special_todayConsumptionForecast_04 511 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 special_todayConsumptionForecast_05 503 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 special_todayConsumptionForecast_06 495 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 special_todayConsumptionForecast_07 504 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 special_todayConsumptionForecast_08 561 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 special_todayConsumptionForecast_09 768 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 special_todayConsumptionForecast_10 783 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 special_todayConsumptionForecast_11 692 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 special_todayConsumptionForecast_12 791 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 special_todayConsumptionForecast_13 910 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 special_todayConsumptionForecast_14 1022 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 special_todayConsumptionForecast_15 965 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 special_todayConsumptionForecast_16 812 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 special_todayConsumptionForecast_17 884 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 special_todayConsumptionForecast_18 928 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_19 874 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_20 763 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_21 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_22 765 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_23 643 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_24 601 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIcalls 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIrequests 4532&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridConsumption 5500.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridFeedIn 178.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayMaxAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIrequests n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 state updated&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So sollte es dann als Ergebnis aussehen:&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13.png|zentriert|mini|Ergebnis nach kompletter Einrichtung]]&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13 Teil II.png|alternativtext=Unterer Teil der Anzeige|zentriert|mini]]&lt;br /&gt;
&lt;br /&gt;
== Praxisbeispiele und Lösungsansätze für Steuerungen ==&lt;br /&gt;
=== Fallstudie: Trockner darf pausiert werden, wenn nicht genug PV-Überschuss vorhanden ist, soll aber nach spätestens X Stunden fertig sein ===&lt;br /&gt;
Für diese Aufgabenstellung sind mehrere Schlüssel essentiell wichtig, &#039;&#039;&#039;power&#039;&#039;&#039;, &#039;&#039;&#039;mintime&#039;&#039;&#039;, &#039;&#039;&#039;mode&#039;&#039;&#039; und &#039;&#039;&#039;interruptable&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Die Bedingung, dass der Trockner nach spätestens X Stunden fertig sein soll, steht in einem Widerspruch zu der Möglichkeit den Trockner bei zu wenig PV-Überschuss unterbrechen zu können. Im Extremfall könnte nach dem Start die gesamte Planungszeit ungenügender Überschuss vorliegen und der Trockner nicht arbeiten. Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; (in Minuten) wird nun wie folgt angesetzt:&lt;br /&gt;
&lt;br /&gt;
 mintime = 2,5 x &amp;lt;gewöhnliche Betriebszeit für einen Trockengang (mneed, z.B. 120)&amp;gt; = 300 Minuten&lt;br /&gt;
&lt;br /&gt;
Das bedeutet, der Trockner wird nach 300 Minuten Laufzeit abgeschaltet werden bzw. vom Netz getrennt. Der Trockenvorgang wird natürlich bereits nach 120 Minuten beendet sein, sofern nach Start keine Unterbrechnung des Vorganges erfolgte. Wurde der Vorgang unterbrochen, soll der Trockner innerhalb &lt;br /&gt;
&lt;br /&gt;
 X+120 bis X+300 &lt;br /&gt;
&lt;br /&gt;
fertig sein. &lt;br /&gt;
&lt;br /&gt;
Demnach ist die ausgeführte Laufzeit des Trockners permanent zu überwachen, zu summieren (rtsum) und die notwendige Restzeit (mneed - rtsum) mit der noch verbleibenden Restzeit (mrest) bis zur geplanten Abschaltung des Consumers zu vergleichen. Ist der Consumer gestartet, wird die Laufzeit in der pvHistory für jede Stunde des Tages im Schlüssel &#039;&#039;minutescsmXX&#039;&#039; (XX = Consumernummer) aufgezeichnet und kann darüber ausgewertet werden. Somit ist:&lt;br /&gt;
&lt;br /&gt;
 msum = for (01 .. 24) {Summe von minutescsmXX} des aktuellen Tages&lt;br /&gt;
&lt;br /&gt;
Solange die Bedingung &lt;br /&gt;
&lt;br /&gt;
 mrest &amp;gt;= (mneed - msum)&lt;br /&gt;
&lt;br /&gt;
zutrifft, darf der Trockner unterbrochen werden, anderenfalls darf er nicht mehr unterbrochen werden da die Restzeit evtl. nicht ausreichen könnte um den Vorgang abzuschließen. Für die Planung des Trockners wird der Consumer wie gewöhnlich nach dem Bedarf im Modul registriert. Für die Steuerung der Unterbrechbarkeit wird noch ein Code erstellt, welcher im Trockner-Device &#039;&#039;Dryerdev&#039;&#039; das Reading &#039;&#039;SF_Int&#039;&#039; zur Unterbrechnungssteuerung verwaltet. Dieses Reading wird dem Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; übergeben. Für das Beispiel wird der Consumer &#039;07&#039; verwendet, es kann natürlich jede andere freie Nummer verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Dryerdev:Trockner&lt;br /&gt;
                        icon=scene_cloves_dryer type=dryer power=2000 mode=must mintime=300 &lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic asynchron=1&lt;br /&gt;
                        interruptable=Dryerdev:SF_Int:1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Kombination &#039;&#039;&#039;auto=automatic&#039;&#039;&#039; eröffnet die Möglickeit, in der Consumer-Legende den Trockner-Start zusätzlich manuell freizugeben oder zu verbieten. &lt;br /&gt;
&lt;br /&gt;
Im nachfolgenden Code werden modulinterne Subroutinen verwendet. Diese sind inklusive dem Paket &#039;&#039;FHEM::SolarForecast::&#039;&#039; anzugeben. Die erstellte Subroutine wird in die 99_mySolarForecastUtils.pm eingefügt. Die Datei 99_mySolarForecastUtils.pm wird vorher von 99_myUtils.pm kopiert und enthält für die Übersichtlichkeit nur Routinen für SolarForecast.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Trocknersteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub dryControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # gewöhlich benötigte Zeit für &lt;br /&gt;
                                                                                  # einen Trockengang, z.B. 120 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $dryer     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename des Trockners&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Trockner-Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit des Trockners&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      my $dhash = $defs{$dryer};&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 1, 0);                        # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 0, 0);                        # keine Interrupt-Freigabe&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die gewöhnliche Laufzeit des Trockners für einen Trockenvorgang (120 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::dryControl ($name, &#039;07&#039;, 120);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Fallstudie: Umwälzpumpe Pool soll X Stunden am Tag laufen. Ist kein PV-Überschuß vorhanden, müssen die X Stunden/Tag trotzdem erreicht werden ===&lt;br /&gt;
&lt;br /&gt;
Die Vorgehensweise ähnelt der Fallstudie zuvor. Verändernd kommt hinzu, dass der Planungszeitraum bewusst sehr lang angesetzt wird mit der Option, den Zyklus des Consumers vorfristig zu beenden sobald die Laufzeit von X Stunden am Tag erreicht ist. &lt;br /&gt;
Im folgenden Beispiel soll die Pumpe 5 Stunden am Tag (300 Minuten) laufen und dabei mögliche PV-Überschüsse ausnutzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Pump:Zirkulationspumpe&lt;br /&gt;
                        icon=sani_pump type=other power=50 mode=must mintime=780 notafter=09&lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic &lt;br /&gt;
                        interruptable=1 swoffcond=Pump:SF_Abort:1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit dieser Registrierung wird die Pumpe ca. 09 Uhr täglich starten. Wenn kein bzw. ungenügender PV-Überschuß vorhanden ist, erfolgt eine Unterbrechung nach dem Start. Ist genügender PV-Überschuß (wieder) vorhanden, erfolgt keine Unterbrechnung (mehr). Zusätzlich wird über den Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; eine vorfristige Beendigung veranlasst, sobald die gewünschte Tageslaufzeit erreicht ist.&lt;br /&gt;
&lt;br /&gt;
Zur Verwaltung des Schlüssels &#039;&#039;interruptable&#039;&#039; und des Readings &#039;&#039;SF_Abort&#039;&#039; verwenden wir eine leicht veränderte Subroutine aus dem vorhergehenden Fallbeispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Pumpensteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub pumpControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # Soll-Pumpenzeit, z.B. 300 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $pump      = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename der Pumpe&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;);&lt;br /&gt;
  my $intbl     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;interruptable&#039;, 1); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
  my $dhash     = $defs{$pump};&lt;br /&gt;
&lt;br /&gt;
  readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 0, 0);                                # default keine Zyklusbeendigung&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Pumpen Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit der Pumpe&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
     &lt;br /&gt;
      if ($msum &amp;gt;= $mneed) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 1, 0);                       # vorfristige Zyklusbeendigung&lt;br /&gt;
          return;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=1&amp;quot;) if(!$intbl);  # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=0&amp;quot;) if($intbl);   # keine Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Befehl &#039;&#039;attrKeyVal&#039;&#039; setzt den Schlüssel &#039;&#039;interruptable&#039;&#039; im Attribut &#039;&#039;consumer07&#039;&#039; dynamisch. Diese Strukturänderung wird automatisch im System gespeichert, sofern &#039;&#039;global-&amp;gt;autosave=1&#039;&#039; gesetzt ist. Diese Einstellung ist der FHEM default.  &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die Mindestlaufzeit der Umwälzpumpe (300 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::pumpControl ($name, &#039;07&#039;, 300);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamische Ladestromsteuerung eines Victron MultiPlus II Chargers mit Pylontech Batterie ===&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;
&lt;br /&gt;
 set &amp;lt;Device&amp;gt; MaxChargeCurrent &amp;lt;Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
eingestellt bzw. variiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Modul bietet dem Nutzer die Möglichkeit in dem Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltene Code wird am Ende jedes Zyklus (siehe Attribut &#039;&#039;plantControl-&amp;gt;cycleInterval&#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;
&lt;br /&gt;
&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 $mppt1   = &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common&#039;;              # SmartLoader Device&lt;br /&gt;
  my $maxcspc = 105;                        # max. Ladesollstrom (A) nominal&lt;br /&gt;
  my $spcorr  = 0.9;                        # Korrekturfaktor Überschuss 90%&lt;br /&gt;
  my $sch     = 0.25;                       # Verkürzungsfaktor Zeit bis Vollladung vor Sunset             &lt;br /&gt;
  &lt;br /&gt;
  my $cclvl0  = 15;                         # Ladestrom Level 0 max. 5  A (240 W) pro WR  (720  W)&lt;br /&gt;
  my $cclvl1  = 27;                         # Ladestrom Level 1 max. 9  A (432 W) pro WR  (1296 W)&lt;br /&gt;
  my $cclvl2  = 54;                         # Ladestrom Level 2 max. 18 A (864 W) pro WR  (2592 W)&lt;br /&gt;
  my $cclvl3  = 81;                         # Ladestrom Level 3 max. 27 A (1296 W) pro WR (3888 W)&lt;br /&gt;
  ###############&lt;br /&gt;
  &lt;br /&gt;
  my $cofc   = ReadingsNum ($name,  &#039;special_todayConForecastTillSunset&#039;, 0);&lt;br /&gt;
  my $pvfc   = ReadingsNum ($name,  &#039;RestOfDayPVforecast&#039;, 0);&lt;br /&gt;
  my $cpv    = ReadingsNum ($name,  &#039;Current_PV&#039;,          0);&lt;br /&gt;
  my $mppt1c = ReadingsNum ($mppt1, &#039;DC_0_Current_value&#039;,  0);             # Load I MPPT1 (max. 44 A)&lt;br /&gt;
  my $ssts   = CurrentVal  ($hash,  &#039;sunsetTodayTs&#039;,        0);&lt;br /&gt;
  my $srts   = CurrentVal  ($hash,  &#039;sunriseTodayTs&#039;,       0);&lt;br /&gt;
  my $sdiff  = ($ssts - $srts) / 3600;                                     # Sonnengang heute in h &lt;br /&gt;
  &lt;br /&gt;
  my $solh   = ReadingsNum ($name, &#039;special_SunHours_Remain&#039;, 0);          # h bis SunSet&lt;br /&gt;
  $solh      = $solh - ($sdiff * $sch);                                    # h bis SunSet - X&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;              # Ah Bat bis SOC&lt;br /&gt;
  $ahrem     = sprintf &amp;quot;%.0f&amp;quot;, $ahrem;&lt;br /&gt;
  &lt;br /&gt;
  my $fcdiff = ($pvfc - $cofc) * $spcorr;     # Korrektur d. noch prognostizierten Überschussenergie &lt;br /&gt;
  $fcdiff    = $fcdiff &amp;lt; 0 ? 0 : $fcdiff;     # Wh&lt;br /&gt;
  &lt;br /&gt;
  my $loadcur = $maxcspc;&lt;br /&gt;
  &lt;br /&gt;
  if ($cpv &amp;amp;&amp;amp; $solh &amp;amp;&amp;amp; $ahrem &amp;amp;&amp;amp; $fcdiff &amp;gt; $ahrem) {  # Ladeanforderung und Überschuss übersteigt &lt;br /&gt;
                                                      # Lademenge&lt;br /&gt;
      my $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($ahrem / $solh);    # A = Ah / h -&amp;gt; A Soll Schätzung&lt;br /&gt;
&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Battery charging process should be completed }.&lt;br /&gt;
                      qq{in &amp;gt;$solh&amp;lt; hours});&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; raw Target charging current: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($cspc - $mppt1c);      # SmartLoader IST berücksichtigen&lt;br /&gt;
	  &lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Charge Current minus MPPT load Current &amp;gt;$mppt1c&amp;lt;: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $loadcur = $cspc &amp;lt;= 0       ? 0       :     # nur MPPT Ladung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl0 ? $cclvl0 :     # Übergangsbereich&lt;br /&gt;
                 $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;
	  Log3 ($name, 3, qq{$name - userFn -&amp;gt; MaxChargeCurrent calculated: $loadcur});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent&#039;,       $loadcur.&#039; A&#039;,          1);&lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_HoursUntilChargeFinish&#039;, sprintf (&amp;quot;%.2f&amp;quot;,$solh), 1);&lt;br /&gt;
  CommandSet           (undef, &amp;quot;$vebus MaxChargeCurrent $loadcur&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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. 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;special_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;special_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;Verkürzungsfaktor Zeit bis Vollladung vor Sunset&#039;&#039;) reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche mindest Ladestromstärke ermittelt.&lt;br /&gt;
&lt;br /&gt;
&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 auch während der MQTT Intergration 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;
=== Poolheizung in Abhängigkeit von vorhandenem Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren) ===&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;consumer01&#039;&#039; wird beispielhaft wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr Forecast consumer01 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;&lt;br /&gt;
&lt;br /&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. &lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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, einen 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 Überschuss 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;. &lt;br /&gt;
&lt;br /&gt;
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;
=== PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) ===&lt;br /&gt;
[https://evcc.io evcc] ist ein Energie-Management-System, mit dem u.a. Überschussladen von Elektroautos möglich ist. Hier ist beschreiben, wie die SolarForecast-Vorhersagedaten per API von evcc abgerufen werden.&lt;br /&gt;
Lege im SolarForecast-Device ein User-Reading mit dem Namen forecast_json an. Es wandelt die Forecast-Werte in JSON und ins UTC-Zeitformat um, so dass evcc die Daten einlesen kann. Der Code wird nur ausgeführt, wenn das Reading nextCycletime ein Event erzeugt.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
forecast_json:nextCycletime.* {&lt;br /&gt;
&lt;br /&gt;
    use strict;&lt;br /&gt;
    use warnings;&lt;br /&gt;
    use JSON;&lt;br /&gt;
    use DateTime;&lt;br /&gt;
    use DateTime::Format::Strptime;&lt;br /&gt;
&lt;br /&gt;
    my $hour = 0;&lt;br /&gt;
    my $last_start_ts;    &lt;br /&gt;
    my @output;&lt;br /&gt;
    &lt;br /&gt;
    # Parser für Datum mit CET/CEST&lt;br /&gt;
    my $parser = DateTime::Format::Strptime-&amp;gt;new(&lt;br /&gt;
        pattern   =&amp;gt; &amp;quot;%Y-%m-%d %H:%M:%S&amp;quot;,&lt;br /&gt;
        time_zone =&amp;gt; &amp;quot;Europe/Berlin&amp;quot;,&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    # Alle NextHour-Daten durchsuchen (als Fallback zur Vermeidung einer Endlosschleife auf max. 100 Std. begrenzen)&lt;br /&gt;
    while ($hour &amp;lt; 100) {&lt;br /&gt;
        my $hour_str = sprintf(&amp;quot;NextHour%02d&amp;quot;, $hour);&lt;br /&gt;
        my $start_str = FHEM::SolarForecast::NexthoursVal(&amp;quot;$NAME&amp;quot;, $hour_str, &amp;quot;starttime&amp;quot;, &amp;quot;na&amp;quot;);&lt;br /&gt;
        my $pvfc = FHEM::SolarForecast::NexthoursVal(&amp;quot;$NAME&amp;quot;, $hour_str, &amp;quot;pvfc&amp;quot;, &amp;quot;na&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        # Schleife beenden, wenn keine Vorhersage-Werte mehr vorhanden sind&lt;br /&gt;
        last if $start_str eq &amp;quot;na&amp;quot; or $pvfc eq &amp;quot;na&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        my $start_ts = $parser-&amp;gt;parse_datetime($start_str);  # Zeitzone und Sommer/Winterzeit berücksichtigen&lt;br /&gt;
        $last_start_ts = $start_ts-&amp;gt;clone;  # merken für spätere Prüfung&lt;br /&gt;
&lt;br /&gt;
        # Zeit in UTC und ISO 8601 konvertieren und Vorhersagewert ergänzen&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $start_ts-&amp;gt;set_time_zone(&amp;quot;UTC&amp;quot;)-&amp;gt;iso8601() . &amp;quot;Z&amp;quot;,&lt;br /&gt;
            end   =&amp;gt; $start_ts-&amp;gt;add(hours =&amp;gt; 1)-&amp;gt;set_time_zone(&amp;quot;UTC&amp;quot;)-&amp;gt;iso8601() . &amp;quot;Z&amp;quot;,&lt;br /&gt;
            value =&amp;gt; 0 + $pvfc,&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        $hour++;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # Prüfen, ob der letzte Start-Wert 23 Uhr war -&amp;gt; zusätzliche Stunde anhängen, damit der Tag&lt;br /&gt;
    # bei evcc als vollständig angezeigt wird (siehe https://github.com/evcc-io/evcc/issues/22979)&lt;br /&gt;
    if (defined $last_start_ts &amp;amp;&amp;amp; $last_start_ts-&amp;gt;hour == 23) {&lt;br /&gt;
&lt;br /&gt;
        # Zeit in UTC und ISO 8601 konvertieren und Vorhersagewert ergänzen&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $last_start_ts-&amp;gt;add(hours =&amp;gt; 1)-&amp;gt;set_time_zone(&amp;quot;UTC&amp;quot;)-&amp;gt;iso8601() . &amp;quot;Z&amp;quot;,&lt;br /&gt;
            end   =&amp;gt; $last_start_ts-&amp;gt;add(hours =&amp;gt; 1)-&amp;gt;set_time_zone(&amp;quot;UTC&amp;quot;)-&amp;gt;iso8601() . &amp;quot;Z&amp;quot;,&lt;br /&gt;
            value =&amp;gt; 0,&lt;br /&gt;
        };       &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # Ausgabe als JSON&lt;br /&gt;
    my $json = JSON-&amp;gt;new-&amp;gt;utf8-&amp;gt;pretty-&amp;gt;encode(\@output);&lt;br /&gt;
    return $json;&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Datei:Screenshot 2025-08-04 104835.png|right|thumb|300px|Darstellung der PV-Vorhersage in evcc auf Basis der SolarForecast-Daten]]&lt;br /&gt;
Die Kommunikation läuft über den integrierten FHEM-Webserver, der die JSON-Daten aus dem Reading forecast_json veröffentlicht. Dazu wird in FHEM eine separate Webinstanz auf einem neuen Port erstellt, die ohne [[CsrfToken-HowTo|CSFR-Token]] (Achtung, Auswirkungen auf die Sicherheit beachten!) und nur von localhost aufrufbar ist (Voraussetzung: evcc läuft auf derselben Maschine wie FHEM):&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
define WEBapi FHEMWEB 8089&lt;br /&gt;
attr WEBapi csrfToken none&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;In der [https://docs.evcc.io/docs/tariffs#pv-vorhersage evcc-Konfig unter tariffs] steht die Quelle für die Solar-Vorhersage. Der FHEM-Befehl {ReadingsVal(&#039;solarforecast_dev&#039;,&#039;forecast_json&#039;,&#039;[]&#039;)} wird encoded und in die uri eingetragen. Trage statt solarforecast_dev den passenden Namen deines SolarForecast-Device ein. evcc holt die Daten aus dem Reading forecast_json dann regelmäßig ab.&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
solar:&lt;br /&gt;
  type: custom&lt;br /&gt;
  interval: 20m    &lt;br /&gt;
  forecast:&lt;br /&gt;
    source: http&lt;br /&gt;
    uri: http://localhost:8089/fhem?cmd=%7BReadingsVal%28%27solarforecast_dev%27%2C%27forecast_json%27%2C%27%5B%5D%27%29%7D&amp;amp;XHR=1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Zur Verbesserung der Sicherheit kann das neue WEBapi Device auch ein [[CsrfToken-HowTo#csrfToken festlegen|festes CSFR-Token]] verwenden. Dieses Token muss dann in der evcc-Konfiguration an die uri mittels &amp;amp;fwcsrf=&amp;lt;festes token&amp;gt; angehängt werden.&lt;br /&gt;
&lt;br /&gt;
=== Poolsteuerung inkl. Eigenverbrauchsoptimierung und zusätzlichem Verbraucher, um Einspeiselimit zu vermeiden + manuelle Steuerung durch Sonderprogramme ===&lt;br /&gt;
&#039;&#039;&#039;Vorhandene Hardware:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Poolpumpe, die über mehrere Stufen verfügt. Hier werden zwei verwendet.&lt;br /&gt;
** Pump Low: Energiesparprogramm um den Pool umzuwälzen, auch wenn nicht genug PV Leistung zur Verfügung steht. -&amp;gt; ca. 250W&lt;br /&gt;
** Pump High: Normalbetrieb wenn genug PV Überschuss zur Verfügung steht. -&amp;gt; ca. 800W zusätzlich&lt;br /&gt;
* Poolheizung: Wärmepumpe -&amp;gt; ca. 1,5kW elektrisch&lt;br /&gt;
* Nachbars Pool: Pumpe + Salzanlage +pH-Regler -&amp;gt; ca. 650W&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Anforderungen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Pool muss täglich mindestens 1x umgewälzt werden.&lt;br /&gt;
* Im Idealfall wird der Pool &amp;gt; 2x umgewälzt.&lt;br /&gt;
* Bei genügend Überschuss soll der Pool geheizt werden. Es soll nur Sonnenstrom für die Poolheizung verwendet werden.&lt;br /&gt;
* Um das Einspeiselimit zu vermeiden, soll auch geheizt werden, wenn der Pool schon warm genug ist. (&amp;gt;28,5 °C)&lt;br /&gt;
* Sollte trotzdem noch das Einspeiselimit erreicht werden, soll auch der Pool des Nachbarn versorgt werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Herausforderungen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Verbraucher dürfen nur in einer gewissen Reihenfolge geschaltet werden, auch wenn der Überschuss eine andere Reihenfolge ergeben würde.&lt;br /&gt;
* Pumpe mit mehreren Stufen muss als zwei Consumer abgebildet werden, um die Schaltlogik in SolarForecast abzubilden. Würde die Trennung außerhalb von Solarforecast realisiert, könnte Solarforecast den Verbraucher schlechter &amp;quot;lernen&amp;quot;, denn dann wäre es ein Consumer mit ständig wechselndem Verbrauch.&lt;br /&gt;
* Pool des Nachbarn darf nicht laut der benötigten Leistung geschaltet werden, sondern in Abhängigkeit der Einspeisebegrenzung.&lt;br /&gt;
&lt;br /&gt;
In diesem Solarforcast-Device sind 16 Verbraucher definiert. Im Weiteren werden jedoch nur die verwendeten betrachtet. Da diese Reglung mittlerweile recht komplex ist, werden auch viele Dinge, die nicht SolarForcast betreffen, aber trotzdem dazu gehören, gezeigt. Es trägt zum Verständnis bei und man kann sich hier sicher Ideen holen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ergebnis:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In den folgenden beiden Bildern sieht man das Regelverhalten recht gut.&lt;br /&gt;
[[Datei:Mustertag ohne Wolken.jpg|zentriert|mini|823x823px|Wolkenloser Tag]]&lt;br /&gt;
Hier erkennt man gut das Einschalten der jeweiligen Verbraucher (Pump Low, Pump High, Wärmepumpe und Nachbar Pool). Die Wärempumpe schaltet erst bei 5kW Überschuss ein, da der Pool eigentlich schon warm genug ist. Sie dient &amp;quot;nur&amp;quot; dazu, das EInspeiselimit zu verhindern.Auch das Auschalten ist wieder deutlich zu erkennen. Die Regleung folgt dem Überschuss recht gut. (Die Leistungsspitzen auf dem Plateau sind normale Großverbraucher im Haus.)&lt;br /&gt;
[[Datei:Wechselhaft.jpg|zentriert|mini|818x818px|Wechselhafter Tag.]]&lt;br /&gt;
In diesem Bild sieht man das &amp;quot;verzweifelte&amp;quot; Regeln um das wechselhafte Wetter auszugleichen. Hier gibt es keine korrekte Reaktion und es wird durch die Sperrzeiten und andere Delays versucht, ein zu häufiges hin- und herschalten möglichst zu vermeiden. In Summe aber auch bei so einem Wetter ein akzeptables Verhalten.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Definition der Consumer:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemeine Erklärungen zu den Definitionen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;asynchron=0&#039;&#039;&#039;: Da hier die Werte des Überschusses für das Timing der Schaltvorgänge verwendet werden, darf hier keine Eventsteuerung verwendet werden. Sonst kann man nicht mehr sagen, über welchen Zeitraum der Mittelwert oder der Median gebildet wurde. Dafür wurde die Zykluszeit des SolarForecast-Device auf 60 Sekunden geändert, um die Überlegungen zu vereinfachen. Bei Event-Steuerung könnte man nicht sagen ob die letzten 10 Events in den letzten 5 Sekunden oder in den letzten 10 Minuten aufgetreten sind.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;power=xxx&#039;&#039;&#039;: Wurde teilweise etwas höher als der tatsächliche Wert gewählt, um nach dem Einschalten sicherzustellen, dass nicht sofort der gesamte Überschuss &amp;quot;verbraucht&amp;quot; wird und somit gleich wieder abgeschaltet wird.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;auto=xxx&#039;&#039;&#039;: Jeder Verbraucher benötigt sein eigenes auto-Reading, da die Automatik für die Regelung in verschiedenen Stufen ein- und ausgeschaltet werden muss.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dum_valve&#039;&#039;&#039;: Dummy-Device in dem die Zustände der Regelung abgebildet werden. Notifys lesen bzw. befüllen diesen Dummy und steuern dann die Hardware bzw. wird der Dummy durch Werte aus der Hardware passend befüllt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;surpmeth=median_xx:&#039;&#039;&#039; Durch das asynchron=0 in allen Consumern und beim Generator wird von Solarforcast genau alle 60 Sekunden ein Zyklus ausgeführt. Das führt dazu, dass der Median genau über xx Minuten gebildet wird.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;locktime=xx:xx&#039;&#039;&#039;: Sicherheitsvorkehrung, dass nicht zu oft geschaltet werden kann. Schont die Hardware und verhindert ein Schwingen. Abhänging vom geschalteten Gerät. z.B. soll die Wärmepumpe möglichst wenig takten, um die Lebensdauer zu verlängern.&lt;br /&gt;
&lt;br /&gt;
Es gibt dann auch noch einige weitere Sicherheitsvorkehrungen, um diese Regelung möglichst stabil und hardwareschonend zu gestalten. Die Schwierigkeit sind nicht die Bilderbuchtage mit einem glatten Verlauf der PV-Leistung, sondern Tage mit ständig wechselndem Überschuss in der Nähe der Schaltgrenzen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;swoncond= dum_valve:sf_true:{main::xxx_On}:&#039;&#039;&#039; Hier werden verschiedene Zustände geprüft, um ein Gerät nur dann einzuschalten, wenn es sinnvoll und sicher ist.&lt;br /&gt;
&lt;br /&gt;
Details unter &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;swoffcond= dum_valve:sf_true:{main::xxx_Off}&#039;&#039;&#039;: Hier werden verschiedene Zustände geprüft, um ein Gerät nur dann auszuschalten, wenn es sinnvoll und sicher ist.&lt;br /&gt;
&lt;br /&gt;
Details unter &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pump Low: (consumer01)&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:Pool+Low&lt;br /&gt;
aliasshort=Low&lt;br /&gt;
asynchron=0&lt;br /&gt;
auto=pump_low_auto&lt;br /&gt;
icon=scene_pool&lt;br /&gt;
interruptable=0&lt;br /&gt;
mintime=SunPath:0:180&lt;br /&gt;
mode=must&lt;br /&gt;
noshow=0&lt;br /&gt;
notafter=08:00&lt;br /&gt;
off=&amp;quot;pump_low off&amp;quot;&lt;br /&gt;
on=&amp;quot;pump_low on&amp;quot;&lt;br /&gt;
pcurr=pump_low_power&lt;br /&gt;
power=250&lt;br /&gt;
surpmeth=median_13&lt;br /&gt;
switchdev=dum_valve&lt;br /&gt;
swoffcond=dum_valve:sf_true:{main::Check_Pump_Low_Off}&lt;br /&gt;
swoncond=dum_valve:sf_true:{main::Check_Pump_Low_On}&lt;br /&gt;
swstate=pump_low:on:off&lt;br /&gt;
type=other&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Die Pumpe soll ab Sonnenaufgang, bis 180 Minuten nach Sonnenuntergang (mintime=SunPath:0:180), bei mindestens 250W Überschuss (power=250) gestartet werden.&lt;br /&gt;
* Die Pumpe muss spätestens um 8:00 eingeplant werden (notafter=08:00), um das Umwälzen auch bei Schlechtwetter zu garantieren.&lt;br /&gt;
* Die Pumpe muss gestartet werden (mode=must) sobald sie eingeplant ist.&lt;br /&gt;
* swoncond sorgt dafür, dass sie vor 8:00 nur bei genügend Überschuss gestartet wird, oder es 8:00 ist. swondcond ist mit der eigentlichen Einschaltbedingung (eingeplant und mode=must) UND verknüpft. -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
* Überschuss wird auch in swoncond mit der gewählten Methode geprüft.&lt;br /&gt;
* Die Pumpe darf, wenn sie gestartet wurde, auch bei fehlendem Überschuss nicht mehr unterbrochen werden. (interruptable=0)&lt;br /&gt;
* Die Pumpe wird am Ende der Einplanung ausgeschaltet oder wenn swoffcond erfüllt ist. swoffcond wird true, wenn eine gewisse Wassermenge umgewälzt wurde oder die Sicherheitsbedingungen nicht (mehr) erfüllt sind. swoffcond ist mit der eigentlichen Ausschaltbedingung (Planung endet) ODER verknüpft. -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
* {&#039;&#039;&#039;main::&#039;&#039;&#039;xxx} dient dazu, um die Funktion xxx in der 99_mySolarForecastUtils.pm aus Solarforecast erreichbar zu machen.&lt;br /&gt;
* dum_valve:sf_true ist ein Reading, das fix 1 ist und als Vergleichswert für den in Klammern folgenden Perlcode dient. Wenn dieses Reading und der Perlcode gleich sind (1==1), ist die swoncond bzw swoffcond erfüllt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pump High: (consumer03)&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:Pool+High&lt;br /&gt;
aliasshort=High&lt;br /&gt;
type=other power=1000 asynchron=0&lt;br /&gt;
auto=pump_high_auto&lt;br /&gt;
icon=scene_pool&lt;br /&gt;
pcurr=pump_high_power&lt;br /&gt;
switchdev=dum_valve&lt;br /&gt;
swstate=pump_high:on:off&lt;br /&gt;
mode=can&lt;br /&gt;
mintime=SunPath&lt;br /&gt;
on=&amp;quot;pump_high on&amp;quot;&lt;br /&gt;
off=&amp;quot;pump_high off&amp;quot;&lt;br /&gt;
surpmeth=median_5&lt;br /&gt;
noshow=0&lt;br /&gt;
locktime=180:300&lt;br /&gt;
interruptable=1&lt;br /&gt;
swoncond=dum_valve:sf_true:{main::Check_Pump_High_On}&lt;br /&gt;
swoffcond=dum_valve:sf_true:{main::Check_Pump_High_Off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Pump HIgh ist die selbe Pumpe, aber eine höhere Durchflussmenge&lt;br /&gt;
* Der Mehrverbrauch beträgt eigentlich 800W wird hier aber mit 1000W angegeben, um eine Hysterese von ca. 200W zu erreichen und damit ein schnelles Abschalten nach dem Einschalten zu verhindern.&lt;br /&gt;
* Diese Stufe wird nur bei genügend Überschuss aktiviert. (mode=can)&lt;br /&gt;
* Diese Stufe wird bei fehlendem Überschuss unterbrochen. (interruptable=1)&lt;br /&gt;
* Diese Stufe wird nur während Sonnenschein eingeplant. (mintime=SunPath)&lt;br /&gt;
* locktime sorgt dafür, dass bei schnell wechselnden Bedingungen, nicht ständig umgeschaltet wird. -&amp;gt; Schonung der Pumpe.&lt;br /&gt;
* swoncond und swoffcond -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Heatpump: (consumer05)&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Pool_Strom_Heizung:Poolheizung&lt;br /&gt;
aliasshort=WP&lt;br /&gt;
type=other power=1800 asynchron=0&lt;br /&gt;
icon=sani_heating_heatpump&lt;br /&gt;
auto=heatpump_auto&lt;br /&gt;
pcurr=Pool_Pin32_monotonic_count_PowerCurrent:W&lt;br /&gt;
etotal=Pool_Pin32_monotonic_count_EnergyMeter:kWh&lt;br /&gt;
switchdev=dum_valve&lt;br /&gt;
swstate=heatpump:on:off&lt;br /&gt;
mode=can&lt;br /&gt;
locktime=600:600&lt;br /&gt;
mintime=SunPath&lt;br /&gt;
on=&amp;quot;heatpump on&amp;quot;&lt;br /&gt;
off=&amp;quot;heatpump off&amp;quot;&lt;br /&gt;
surpmeth=median_13&lt;br /&gt;
noshow=0&lt;br /&gt;
swoncond=dum_valve:sf_true:{main::CheckWPOn}&lt;br /&gt;
interruptable=1&lt;br /&gt;
swoffcond=dum_valve:sf_true:{main::CheckWPOff}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Der Verbrauch ist hier wieder etwas zu hoch angegeben (1800W statt realen 1500W), um eine Hysterese zu erreichen.&lt;br /&gt;
* Da es sich hier um eine Wärmepumpe handelt, die nicht getaktet werden sollte, ist die locktime in beide Schaltrichtungen mit 10 Minuten relativ hoch.&lt;br /&gt;
* Die Ermittlung des Medians ist mit 13 Minuten recht lang, um den Überschuss über lange Zeit zu glätten, damit möglichst selten geschaltet wird. Diese 13 Minuten in Kombination mit der Locktime und der Hysterese führten bei dieser Anlage bisher dazu, dass höchstens 5 Zyklen am Tag geschaltet wurden. -&amp;gt; Hier kann das individuelle Schaltverhalten optimiert werden. Besseres Verfolgen des Überschusses vs. weniger Taktungen der Wärmepumpe.&lt;br /&gt;
* swoncond und swoffcond -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nachbars Pool: (consumer07)&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Shelly_Plug_S_1:Kurz+Pool&lt;br /&gt;
aliasshort=Kurz&lt;br /&gt;
type=other power=650 asynchron=0&lt;br /&gt;
icon=scene_pool&lt;br /&gt;
auto=pool_kurz_auto&lt;br /&gt;
pcurr=power:W&lt;br /&gt;
switchdev=dum_valve&lt;br /&gt;
swstate=pool_kurz:on:off&lt;br /&gt;
mode=can&lt;br /&gt;
mintime=SunPath&lt;br /&gt;
on=&amp;quot;pool_kurz on&amp;quot;&lt;br /&gt;
off=&amp;quot;pool_kurz off&amp;quot;&lt;br /&gt;
surpmeth=median_13&lt;br /&gt;
noshow=0&lt;br /&gt;
interruptable=1&lt;br /&gt;
locktime=600:300&lt;br /&gt;
swoncond=dum_valve:sf_true:{main::Check_Pool_Kurz_On}&lt;br /&gt;
swoffcond=dum_valve:sf_true:{main::Check_Pool_Kurz_Off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Dieser Consumer dient als Einspeisebegrenzungsschutz und wird aktiviert, sobald sich der Überschuss der Einspeisegrenze nähert.  -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
* Verbraucher kann recht träge geschaltet werden. (surpmeth=median_13 und locktime=600:300)&lt;br /&gt;
* Consumer wird ausgeschaltet wenn ein gewisser Überschuss unterschritten wird und somit die Einspeisegrenze wieder weit genug weg ist. -&amp;gt; siehe &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; &lt;br /&gt;
&#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hier sind die Funktionen, die für diese Regelung verwendet werden, der Übersichtlichkeit halber in einzelnen Blöcken mit Erklärungen dargestellt.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
package main;&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
&lt;br /&gt;
my $pool_dummy = &#039;dum_valve&#039;;&lt;br /&gt;
my $pool_temperature = &#039;Pool_Temp&#039;;&lt;br /&gt;
my $flow_sensor = &#039;Pool_Pin_A0&#039;;&lt;br /&gt;
my $water_counter_l1 = &#039;pump_l1_hc&#039;;&lt;br /&gt;
my $water_counter_l2 = &#039;pump_l2_hc&#039;;&lt;br /&gt;
my $target_temp = 28.4; # maximum temperature for heating, without infeed limit&lt;br /&gt;
&lt;br /&gt;
my $pump_low_id			= sprintf &amp;quot;%02d&amp;quot;, 1;&lt;br /&gt;
my $pump_high_id		= sprintf &amp;quot;%02d&amp;quot;, 3;&lt;br /&gt;
my $heatpump_id			= sprintf &amp;quot;%02d&amp;quot;, 5;&lt;br /&gt;
my $pool_kurz_id		= sprintf &amp;quot;%02d&amp;quot;, 7;&lt;br /&gt;
&lt;br /&gt;
my $switch_delay = 160; # just under three minutes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
SolarForecastUtils_Initialize($$)&lt;br /&gt;
{&lt;br /&gt;
  my ($hash) = @_;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Hier werden die IDs der Geräte definiert, um über sprechende Namen darauf zugreifen zu können.&lt;br /&gt;
* Einige Devices und Parameter, die immer wieder gebraucht werden sind hier angegeben.&lt;br /&gt;
* sprintf wird verwendet um sicherzustellen, dass die IDs zweistellig sind. z.B. 3 -&amp;gt; 03&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pump Low&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
###################&lt;br /&gt;
### Pumpe - LOW ###&lt;br /&gt;
###################&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
Check_Pump_Low_On{&lt;br /&gt;
my $name = &#039;energy_mgmt&#039;;&lt;br /&gt;
my $surplus	= FHEM::SolarForecast::ConsumerVal ($name,$pump_low_id,&#039;surpmethResult&#039;,&#039;&#039;);&lt;br /&gt;
my $nom_power	= FHEM::SolarForecast::ConsumerVal ($name,$pump_low_id,&#039;power&#039;,&#039;&#039;);&lt;br /&gt;
my ($min, $hour) = (localtime())[1,2];&lt;br /&gt;
my $timer = 0;&lt;br /&gt;
if($hour &amp;gt; 8 || ($hour == 8 &amp;amp;&amp;amp; $min &amp;gt;= 0)){$timer=1;}&lt;br /&gt;
&lt;br /&gt;
if(ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;normal&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ($surplus &amp;gt; $nom_power&lt;br /&gt;
		|| $timer&lt;br /&gt;
	)&lt;br /&gt;
)&lt;br /&gt;
	{&lt;br /&gt;
	return 1;}&lt;br /&gt;
else&lt;br /&gt;
	{&lt;br /&gt;
	return 0;}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
Check_Pump_Low_Off{&lt;br /&gt;
my $bath_mode = ReadingsVal($pool_dummy,&amp;quot;bath_mode&amp;quot;,0);&lt;br /&gt;
my $m3_l1 = ReadingsVal($water_counter_l1,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $m3_l2 = ReadingsVal($water_counter_l2,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $water_volume = AttrVal($pool_dummy,&amp;quot;water_volume&amp;quot;,42); #42m³&lt;br /&gt;
my $desired_cf_l1 = AttrVal($pool_dummy,&amp;quot;desired_cf_l1&amp;quot;,0); #circulation_factor_level1&lt;br /&gt;
my $desired_cf_l2 = AttrVal($pool_dummy,&amp;quot;desired_cf_l2&amp;quot;,0); #circulation_factor_level2&lt;br /&gt;
my $bathmode_factor = AttrVal($pool_dummy,&amp;quot;bathmode_factor&amp;quot;,1);&lt;br /&gt;
my $desired_amount_l1;&lt;br /&gt;
my $desired_amount_l2;&lt;br /&gt;
my $amount = $m3_l1 + $m3_l2;&lt;br /&gt;
if($bath_mode == 1){&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume;&lt;br /&gt;
}else{&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume/$bathmode_factor;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume/$bathmode_factor;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if(($amount &amp;gt; $desired_amount_l1)&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;pump_high&amp;quot;,&amp;quot;on&amp;quot;) eq &amp;quot;off&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;pump_high&amp;quot;,0) &amp;gt;160)&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;normal&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
	{&lt;br /&gt;
		return 1;&lt;br /&gt;
	}else{&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Einschalten:&lt;br /&gt;
&lt;br /&gt;
* Es wird der errechnete Wert für den Überschuss von SolarForecast verwendet und auch der benötigte Überschuss aus dem Consumer ausgelesen.&lt;br /&gt;
* Das Einschalten wird erst durch erfolgreiche Prüfung der Hardwarevoraussetzungen erlaubt. -&amp;gt; Das Motorventil steht richtig und es ist kein Sonderbetrieb (Reinigung, Massage, Winter, o.ä.) aktiv.&lt;br /&gt;
* Es muss entweder genügend Überschuss vorhanden sein oder es ist 8:00.&lt;br /&gt;
&lt;br /&gt;
Ausschalten:&lt;br /&gt;
&lt;br /&gt;
* Wenn der Badebetrieb aktiv ist (bath_mode==1, [bei Außentemperatur &amp;gt; 24°C]) wird nach 90m³ Gesamtumwälzung ausgeschaltet.&lt;br /&gt;
* Wenn der Badebetrieb nicht aktiv ist (bath_mode==0, [bei Außentemperatur &amp;lt; 20°C]) wird bereits nach 42m³ Gesamtumwälzung ausgeschaltet.&lt;br /&gt;
* Prüfung, ob Pump High schon aus ist. Sollte durch die Logik gar nicht möglich sein, aber es könnte manuell oder durch einen (Logik-)Fehler trotzdem eingeschaltet sein.&lt;br /&gt;
* Prüfung, ob alle Hardware-Funktionen in einem für die Automatik geeigneten Zustand sind.&lt;br /&gt;
* Es wird auch geprüft, ob Pump High seit mindestens 3 Minuten aus ist, um zu verhindern, dass wegen fehlendem Überschuss gleich mehrere Geräte ausgeschaltet werden.&lt;br /&gt;
* Da die Zykluszeit 60 Sekunden ist, führen die 160 Sekunden dazu, dass nach drei Minuten(180 Sekunden) ein definierter Wert gilt. Mit 180 Sekunden könnte es manchaml eine Minute mehr sein.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pump High&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
####################&lt;br /&gt;
### Pumpe - HIGH ###&lt;br /&gt;
####################&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
Check_Pump_High_On{&lt;br /&gt;
my $bath_mode = ReadingsVal($pool_dummy,&amp;quot;bath_mode&amp;quot;,0);&lt;br /&gt;
my $m3_l1 = ReadingsVal($water_counter_l1,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $m3_l2 = ReadingsVal($water_counter_l2,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $water_volume = AttrVal($pool_dummy,&amp;quot;water_volume&amp;quot;,42); #42m³&lt;br /&gt;
my $desired_cf_l1 = AttrVal($pool_dummy,&amp;quot;desired_cf_l1&amp;quot;,0); #circulation_factor_level1&lt;br /&gt;
my $desired_cf_l2 = AttrVal($pool_dummy,&amp;quot;desired_cf_l2&amp;quot;,0); #circulation_factor_level2&lt;br /&gt;
my $bathmode_factor = AttrVal($pool_dummy,&amp;quot;bathmode_factor&amp;quot;,1);&lt;br /&gt;
my $desired_amount_l1;&lt;br /&gt;
my $desired_amount_l2;&lt;br /&gt;
my $amount = $m3_l1 + $m3_l2;&lt;br /&gt;
if($bath_mode == 1){&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume;&lt;br /&gt;
}else{&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume/$bathmode_factor;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume/$bathmode_factor;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if(($amount &amp;lt; $desired_amount_l2)&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;normal&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;pump_low&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;pump_low&amp;quot;,0) &amp;gt; $switch_delay)&lt;br /&gt;
)&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
Check_Pump_High_Off{&lt;br /&gt;
my $bath_mode = ReadingsVal($pool_dummy,&amp;quot;bath_mode&amp;quot;,0);&lt;br /&gt;
my $m3_l1 = ReadingsVal($water_counter_l1,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $m3_l2 = ReadingsVal($water_counter_l2,&amp;quot;waterAmount&amp;quot;,0);&lt;br /&gt;
my $water_volume = AttrVal($pool_dummy,&amp;quot;water_volume&amp;quot;,42); #42m³&lt;br /&gt;
my $desired_cf_l1 = AttrVal($pool_dummy,&amp;quot;desired_cf_l1&amp;quot;,0); #circulation_factor_level1&lt;br /&gt;
my $desired_cf_l2 = AttrVal($pool_dummy,&amp;quot;desired_cf_l2&amp;quot;,0); #circulation_factor_level2&lt;br /&gt;
my $bathmode_factor = AttrVal($pool_dummy,&amp;quot;bathmode_factor&amp;quot;,1);&lt;br /&gt;
my $desired_amount_l1;&lt;br /&gt;
my $desired_amount_l2;&lt;br /&gt;
my $amount = $m3_l1 + $m3_l2;&lt;br /&gt;
&lt;br /&gt;
if($bath_mode == 1){&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume;&lt;br /&gt;
}else{&lt;br /&gt;
	$desired_amount_l1 = $desired_cf_l1 * $water_volume/$bathmode_factor;&lt;br /&gt;
	$desired_amount_l2 = $desired_cf_l2 * $water_volume/$bathmode_factor;&lt;br /&gt;
}&lt;br /&gt;
if(($amount &amp;gt; $desired_amount_l2)&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;heatpump&amp;quot;,&amp;quot;on&amp;quot;) eq &amp;quot;off&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;heatpump&amp;quot;,0) &amp;gt;160)&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;normal&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Einschalten:&lt;br /&gt;
&lt;br /&gt;
* Prüfung, ob die gewünschte Umwälzung bezüglich des Badebetriebs noch nicht erreicht wurde.&lt;br /&gt;
* Prüfung der Hardwarevoraussetzungen.&lt;br /&gt;
* Prüfung, ob Pump Low schon seit mindestens 3 Minuten aktiv ist. (sollte eigentlich immer der Fall sein, wenn die Automatik für Pump High aktiv ist)&lt;br /&gt;
&lt;br /&gt;
Ausschalten:&lt;br /&gt;
&lt;br /&gt;
* Prüfung, ob die gewünschte Umwälzung bezüglich des Badebetriebs bereits erreicht wurde.&lt;br /&gt;
* Prüfung der Hardwarevoraussetzungen.&lt;br /&gt;
* Prüfung, ob die Wärmepumpe schon seit mindestens 3 Minuten aus ist. Ermöglicht drei Minuten lang, den Median für den Überschuss zu aktualisieren.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wärmepumpe&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
##################&lt;br /&gt;
### Wärempumpe ###&lt;br /&gt;
##################&lt;br /&gt;
sub&lt;br /&gt;
CheckWPOn(){&lt;br /&gt;
my $name = &#039;energy_mgmt&#039;;&lt;br /&gt;
my $surplus_on = 5000; # minimum surplus to avoid infeed limit with heatpump&lt;br /&gt;
my $surplus_restart = 3000; # minimum surplus to re-enable heatpump, when avoidung infeed limit and a big consumer turned the hp off&lt;br /&gt;
&lt;br /&gt;
my $planstate = FHEM::SolarForecast::ConsumerVal ($name,$heatpump_id,&#039;planstate&#039;,&#039;&#039;);&lt;br /&gt;
my $surplus	= FHEM::SolarForecast::ConsumerVal ($name,$heatpump_id,&#039;surpmethResult&#039;,&#039;&#039;);&lt;br /&gt;
if ($planstate =~ /^([^:]+)/) {&lt;br /&gt;
	$planstate = $1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if(ReadingsVal($flow_sensor,&amp;quot;reading&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;&lt;br /&gt;
		|| ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;party&amp;quot;&lt;br /&gt;
	)&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&#039;heat_protection&#039;,&#039;on&#039;) eq &amp;quot;off&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;normal&amp;quot;&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;pump_high&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;pump_high&amp;quot;,0) &amp;gt; $switch_delay)&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_temperature,&amp;quot;temperature&amp;quot;,30) &amp;lt; $target_temp &lt;br /&gt;
		|| (ReadingsVal($pool_temperature,&amp;quot;temperature&amp;quot;,15) &amp;gt;= $target_temp&lt;br /&gt;
			&amp;amp;&amp;amp; ( $surplus &amp;gt; $surplus_on&lt;br /&gt;
				|| (($planstate eq &amp;quot;replanned&amp;quot;) &amp;amp;&amp;amp; ($surplus &amp;gt; $surplus_restart))&lt;br /&gt;
			)&lt;br /&gt;
		)&lt;br /&gt;
	)&lt;br /&gt;
)&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
CheckWPOff{&lt;br /&gt;
my $name = &#039;energy_mgmt&#039;;&lt;br /&gt;
my $surplus_off = 1000; #minimum surplus to keep heatpump on, when avoiding infeed limit&lt;br /&gt;
&lt;br /&gt;
my $surplus	= FHEM::SolarForecast::ConsumerVal ($name,$heatpump_id,&#039;surpmethResult&#039;,&#039;&#039;);&lt;br /&gt;
if((ReadingsVal($flow_sensor,&amp;quot;reading&amp;quot;,&amp;quot;on&amp;quot;) eq &amp;quot;off&amp;quot;&lt;br /&gt;
	|| !((ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;none&amp;quot;) &lt;br /&gt;
		|| (ReadingsVal($pool_dummy,&amp;quot;special_function&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;party&amp;quot;)&lt;br /&gt;
	)&lt;br /&gt;
	|| ReadingsVal($pool_dummy,&#039;heat_protection&#039;,&#039;off&#039;) eq &amp;quot;on&amp;quot;&lt;br /&gt;
	|| ReadingsVal($pool_dummy,&amp;quot;valve_position&amp;quot;,&amp;quot;&amp;quot;) ne &amp;quot;normal&amp;quot;&lt;br /&gt;
	|| ((ReadingsVal($pool_temperature,&amp;quot;temperature&amp;quot;,15) &amp;gt; $target_temp)&lt;br /&gt;
		&amp;amp;&amp;amp; ($surplus &amp;lt; $surplus_off)&lt;br /&gt;
		)&lt;br /&gt;
	)&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;heatpump&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;heatpump&amp;quot;,0) &amp;gt; $switch_delay)&lt;br /&gt;
)&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Einschalten:&lt;br /&gt;
&lt;br /&gt;
* Prüfung, ob Flussensor ein. (Pool_pin_A0) -&amp;gt; Wasser fließt durch die Wärmepumpe.&lt;br /&gt;
* Prüfung, ob Pool in Normal- oder Partybetrieb ist und das Ventil in Normalposition ist. In beiden Fällen läuft Pump High.&lt;br /&gt;
* Einschalten wenn genug Überschuss da ist und die Temperatur &amp;lt;28.4°C ist oder wenn über 5000W Überschuss (Einspeisebegrenzung bei 5900W) da ist, egal wie warm der Pool ist.&lt;br /&gt;
* Sonderfall: Wenn die Wärmepumpe durch einen/mehrere Großverbrucher &amp;quot;kurz&amp;quot; ausgeschaltet wurde (swoffcond) wird sie ausgeplant. Ein Notify plant sie wieder ein. Wenn das passiert, soll die Wärmepumpe aber wieder bei 3000W Überschuss gestartet werden, um die Energie noch weiter zu nutzen bis der Überschuss unter 1000W fällt. (Hysterese von 500W, da die WP nur 1500W braucht)&lt;br /&gt;
&lt;br /&gt;
Ausschalten:&lt;br /&gt;
&lt;br /&gt;
* Ausschalten sobald hardwaremäßig irgendetwas faul ist. (Betriebsart, Ventilstellung, Durchfluss)&lt;br /&gt;
* Ausschalten wenn kein Überschuss. (interruptable=1)&lt;br /&gt;
* Wenn Wassertemperatur über 28,5°C und der Überschuss kleiner als 1000W ist.&lt;br /&gt;
* Nur schalten, wenn Wärmepumpe läuft und seit mindestens 3 Minuten läuft (Sicherheit). Das verhindert das erneute Triggern des Notifys, wenn die Pumpe schon aus ist. Sollte nicht passieren, aber sicher ist sicher.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nachbar Pool&#039;&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
###################&lt;br /&gt;
### Pool - KURZ ###&lt;br /&gt;
###################&lt;br /&gt;
sub&lt;br /&gt;
Check_Pool_Kurz_On{&lt;br /&gt;
my $name = &#039;energy_mgmt&#039;;&lt;br /&gt;
my $surplus	= FHEM::SolarForecast::ConsumerVal ($name,$pool_kurz_id,&#039;surpmethResult&#039;,&#039;&#039;);&lt;br /&gt;
if(($surplus &amp;gt; 3000)&lt;br /&gt;
	&amp;amp;&amp;amp; ((ReadingsVal($pool_dummy,&amp;quot;heatpump&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;heatpump&amp;quot;,0) &amp;gt;160) || ReadingsVal($pool_dummy,&#039;heat_protection&#039;,&#039;off&#039;) eq &#039;on&#039; ))&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
Check_Pool_Kurz_Off{&lt;br /&gt;
my $name = &#039;energy_mgmt&#039;;&lt;br /&gt;
my $surplus	= FHEM::SolarForecast::ConsumerVal ($name,$pool_kurz_id,&#039;surpmethResult&#039;,&#039;&#039;);&lt;br /&gt;
if(($surplus &amp;lt; 1000 )&lt;br /&gt;
	&amp;amp;&amp;amp; (ReadingsVal($pool_dummy,&amp;quot;pool_kurz&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;  &amp;amp;&amp;amp; ReadingsAge($pool_dummy,&amp;quot;pool_kurz&amp;quot;,0) &amp;gt;160))&lt;br /&gt;
	{return 1}&lt;br /&gt;
else&lt;br /&gt;
	{return 0}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Einschalten:&lt;br /&gt;
&lt;br /&gt;
* Überschuss ist nahe der Einspeisegrenze (5900W) und Wärmepumpe läuft seit mindestens 3 Minuten. Es wird schon bei 3000W eingeschaltet, um dem Nachbarn etwas Gutes zu tun ;-)&lt;br /&gt;
&lt;br /&gt;
Ausschalten:&lt;br /&gt;
&lt;br /&gt;
* Überschuss ist unter 1000W. -&amp;gt; Um noch Reserven für den eigenen Verbrauch zu haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hilfsfunktionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hier erfolgt nach jedem Zyklus die Festlegung der verschiedenen Automatikmodi.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#############################################################&lt;br /&gt;
##################### Exit Function #########################&lt;br /&gt;
#############################################################&lt;br /&gt;
sub&lt;br /&gt;
SF_UserExitFn{&lt;br /&gt;
	my $ctrl_dummy	= &amp;quot;dum_valve&amp;quot;;&lt;br /&gt;
	my $pump_low_delay = 220;&lt;br /&gt;
	my $pump_high_delay = 160;&lt;br /&gt;
	my $heatpump_delay = 290;&lt;br /&gt;
	my $pool_kurz_delay = 160;&lt;br /&gt;
	my $automatic	= ReadingsNum($ctrl_dummy,&amp;quot;sf_automatic&amp;quot;,1);&lt;br /&gt;
&lt;br /&gt;
if($automatic){&lt;br /&gt;
&lt;br /&gt;
	my $pump_low_state = ReadingsVal($ctrl_dummy,&#039;pump_low&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pump_low_auto	= FHEM::SolarForecast::ConsumerVal ($name, $pump_low_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Pumpe&lt;br /&gt;
&lt;br /&gt;
	my $pump_high_state = ReadingsVal($ctrl_dummy,&#039;pump_high&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pump_high_auto	= FHEM::SolarForecast::ConsumerVal ($name, $pump_high_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Pumpe&lt;br /&gt;
&lt;br /&gt;
	my $heatpump_state = ReadingsVal($ctrl_dummy,&#039;heatpump&#039;,&#039;on&#039;);&lt;br /&gt;
	my $heatpump_auto	= FHEM::SolarForecast::ConsumerVal ($name, $heatpump_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Wärmepumpe&lt;br /&gt;
	my $pool_heat_protection = ReadingsVal($ctrl_dummy,&#039;heat_protection&#039;,&#039;on&#039;);&lt;br /&gt;
&lt;br /&gt;
	my $pool_kurz_state = ReadingsVal($ctrl_dummy,&#039;pool_kurz&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pool_kurz_auto	= FHEM::SolarForecast::ConsumerVal ($name, $pool_kurz_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus des Pools&lt;br /&gt;
&lt;br /&gt;
############################&lt;br /&gt;
# Überhitzungsschutz aktiv #&lt;br /&gt;
############################&lt;br /&gt;
&lt;br /&gt;
if($pool_heat_protection eq &#039;on&#039;){&lt;br /&gt;
	if($heatpump_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy heatpump_auto 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	if($heatpump_state eq &amp;quot;on&amp;quot;){&lt;br /&gt;
			fhem(&amp;quot;set $ctrl_dummy heatpump off&amp;quot;)&lt;br /&gt;
	}&lt;br /&gt;
	#################&lt;br /&gt;
	#### on-chain ###&lt;br /&gt;
	#################&lt;br /&gt;
	if($pump_low_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pump_low&#039;,0) &amp;gt; $pump_low_delay &amp;amp;&amp;amp; $pump_high_auto == 0  &amp;amp;&amp;amp; $pool_kurz_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pump_high_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pump_high&#039;,0) &amp;gt; $pump_high_delay &amp;amp;&amp;amp; $pool_kurz_auto == 0 &amp;amp;&amp;amp; $pump_high_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pool_kurz_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pool_kurz_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $pool_kurz_auto == 1 &amp;amp;&amp;amp; $pump_high_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	#################&lt;br /&gt;
	### off-chain ###&lt;br /&gt;
	#################&lt;br /&gt;
	if($pool_kurz_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pool_kurz&#039;,0) &amp;gt; $pool_kurz_delay &amp;amp;&amp;amp; $pool_kurz_auto == 1 &amp;amp;&amp;amp; $pump_high_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pump_high_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pump_high&#039;,0) &amp;gt; $pump_high_delay &amp;amp;&amp;amp; $pump_high_auto == 1 &amp;amp;&amp;amp; $pool_kurz_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pool_kurz_auto 0&amp;quot;);&lt;br /&gt;
	}elsif($pump_low_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high_auto == 1 &amp;amp;&amp;amp; $pool_kurz_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
##################################&lt;br /&gt;
# Überhitzungsschutz nicht aktiv #&lt;br /&gt;
##################################&lt;br /&gt;
}else{&lt;br /&gt;
	if($heatpump_auto == 0 &amp;amp;&amp;amp; $heatpump_state eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		if($pool_kurz_state eq &amp;quot;on&amp;quot;){&lt;br /&gt;
			fhem(&amp;quot;set $ctrl_dummy pool_kurz off&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if($pool_kurz_auto == 1){&lt;br /&gt;
			fhem(&amp;quot;set $ctrl_dummy pool_kurz_auto 0&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	#################&lt;br /&gt;
	#### on-chain ###&lt;br /&gt;
	#################&lt;br /&gt;
	if($pump_low_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pump_low&#039;,0) &amp;gt; $pump_low_delay &amp;amp;&amp;amp; $pump_high_auto == 0 &amp;amp;&amp;amp; $heatpump_auto == 0 &amp;amp;&amp;amp; $pool_kurz_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pump_high_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pump_high&#039;,0) &amp;gt; $pump_high_delay &amp;amp;&amp;amp; $heatpump_auto == 0 &amp;amp;&amp;amp; $pool_kurz_auto == 0 &amp;amp;&amp;amp; $pump_high_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy heatpump_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($heatpump_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;heatpump&#039;,0) &amp;gt; $heatpump_delay &amp;amp;&amp;amp; $pool_kurz_auto == 0 &amp;amp;&amp;amp; $pump_high_auto == 1 &amp;amp;&amp;amp; $heatpump_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 0&amp;quot;);&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pool_kurz_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pool_kurz_state eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $pool_kurz_auto == 1 &amp;amp;&amp;amp; $heatpump_auto == 1 &amp;amp;&amp;amp; $pump_high_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy heatpump_auto 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	#################&lt;br /&gt;
	### off-chain ###&lt;br /&gt;
	#################&lt;br /&gt;
	if($pool_kurz_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pool_kurz&#039;,0) &amp;gt; $pool_kurz_delay &amp;amp;&amp;amp; $pool_kurz_auto == 1 &amp;amp;&amp;amp; $heatpump_auto == 0 &amp;amp;&amp;amp; $pump_high_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy heatpump_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($heatpump_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;heatpump&#039;,0) &amp;gt; $heatpump_delay &amp;amp;&amp;amp; $heatpump_auto == 1 &amp;amp;&amp;amp; $pump_high_auto == 0 &amp;amp;&amp;amp; $pool_kurz_auto == 1){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pool_kurz_auto 0&amp;quot;);&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 1&amp;quot;);&lt;br /&gt;
	}elsif($pump_high_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; ReadingsAge($ctrl_dummy,&#039;pump_high&#039;,0) &amp;gt; $pump_high_delay &amp;amp;&amp;amp; $pump_high_auto == 1 &amp;amp;&amp;amp; $heatpump_auto == 1 &amp;amp;&amp;amp; $pool_kurz_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy heatpump_auto 0&amp;quot;);&lt;br /&gt;
	}elsif($pump_low_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high_state eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high_auto == 1 &amp;amp;&amp;amp; $heatpump_auto == 0){&lt;br /&gt;
		fhem(&amp;quot;set $ctrl_dummy pump_high_auto 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Erläuterungen:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Überhitzungsschutz:&#039;&#039;&#039;&lt;br /&gt;
** Da durch die Wärmepumpe Überschuss &amp;quot;verheizt&amp;quot; wird, der durch das Einspeiselimit gar nicht produziert würde, kann es vorkommen, dass der Pool unangenehm warm wird.&lt;br /&gt;
** Um das zu vermeiden gibt es ein Reading, welches gesetzt wird, wenn der Pool eine gewisse Temperatur überschreitet. Dieses Setzen und Zurücksetzen erfolgt mit einer Hysterese von 0.2°C, um ein Takten der Wärmepumpe zu verhindern. Diese 0.4°C sind bei dieser Wassermenge einige Stunden.&lt;br /&gt;
** Wenn der Überhitzungsschutz aktiv ist, wird die Wärmepumpe in der Kette übersprungen.&lt;br /&gt;
** Wenn sich der Hitzeschutz während des Betriebs ändert, wird die Wärmepumpe bzw. der Pool vom Nachbarn passend ausgeschaltet und die Modi entsprechend gesetzt.&lt;br /&gt;
* &#039;&#039;&#039;On-chain:&#039;&#039;&#039;&lt;br /&gt;
** Wenn am Morgen Pump Low seit $pump_low_delay aktiv ist und alle folgenden Consumer noch nicht, dann wird die nächste Stufe freigegeben. -&amp;gt; Pump High&lt;br /&gt;
** Wenn Pump High seit $pump_high_delay aktiv ist und alle folgenden Consumer noch nicht, wird die Wärmepumpe freigegeben. -&amp;gt; Heatpump&lt;br /&gt;
** Wenn die Wärmepumpe seit $heatpump_delay aktiv ist und der letzte Consumer noch nicht, wird der letzte Verbraucher freigegeben. -&amp;gt; Pool Kurz Gleichzeitig wird die Automatik für Pump High ausgeschaltet, da dieser Verbraucher erst unterbrochen werden darf wenn die Wärmepumpe aus ist!&lt;br /&gt;
** Wenn der letzte Verbraucher aktiviert ist, wird die Automatik der Wärmepumpe deaktiviert, da ja zuerst der letzte Verbraucher (Pool Kurz) wieder ausgeschaltet werden muss, bevor der vorletzte (Wärmepumpe) wieder ausgeschaltet werden darf. Da es keinen nachfolgenden Verbraucher mehr gibt, kann hier auf ein delay verzichtet werden, da es nicht passieren kann, dass zwei Verbraucher wegen sehr hohem Überschuss unmittelbar hintereinander geschaltet werden können.&lt;br /&gt;
[[Datei:Poolsteuerung mit unterschiedlichen Automatikmodi.jpg|alternativtext=Poolsteuerung|mini|Consumer der Poolsteuerung|500x500px]]&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Es dürfen immer nur maximal zwei unterbrechbare Consumer im Automatikmodus sein. Der &amp;quot;aktuelle&amp;quot;, der ja aufgrund von fehlendem Überschuss jederzeit unterbrochen werden kann und der &amp;quot;folgende&amp;quot; Consumer, der auf das Einschalten wartet. Pump Low ist immer im Automatikmodus, da diese nie unterbrochen wird. (mode=must, interruptable=0)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Off-chain:&#039;&#039;&#039;&lt;br /&gt;
** Wenn der letzte Verbraucher seit mindestens der delay-Zeit aufgrund von fehlendem Überschuss inaktiv war, im Automatikmodus ist und der vorherige Verbraucher nicht im Automatikmodus ist, wird der vorherige Verbraucher in den Automatikmodus geschaltet und wartet jetzt auch auf das Ausschalten. Wenn der Überschuss steigt, springt man wieder in die on-chain und der letzte Verbraucher wird eingeschaltet und die Automatik des vorletzten Verbrauchers deaktiviert.&lt;br /&gt;
** Wenn die Wärmepumpe seit mindestens der delay-Zeit aus ist, sich im Automatikmodus befind und Pump High noch nicht im Automatikmodus ist, wird die Automatik für den Nachbarpool ausgeschaltet, da er ja jetzt nicht mehr einschalten darf, da zuerst die Wärmepumpe ein sein müsste. Die Automatik von Pump High wird wieder aktiviert, da diese jetzt auf das Ausschalten wartet. Steigt der Überschuss wieder, wird in den entsprechenden On-chain Zweig gesprungen.&lt;br /&gt;
** Wenn Pump High mindestens die delay-Zeit aus ist, wird die Automatik der Wärmepumpe deaktiviert, da diese ja erst einschalten darf, wenn Pump High wieder läuft. Steigender Überschuss führt wieder zum aktivieren von Pump High und zum Sprung in den entsprechenden On-chain Zweig.&lt;br /&gt;
** Wenn Pump Low ausgeschaltet wird, wird sofort die Automatik für Pump High ausgeschaltet, da durch das spätere Ausschalten von (der evtl. wieder eingeschalteten) Pump High, hardwaremäßig wieder Pump Low aktiviert wird, aber durch SolarForecast nie ausgeschaltet wird, da Pump Low vor ein paar Minuten ja schon logisch ausgeschaltet wurde.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Es dürfen immer nur maximal zwei unterbrechbare Consumer im Automatikmodus sein. Der &amp;quot;aktuelle&amp;quot;, der ja aufgrund von neuem Überschuss jederzeit wieder gestartet werden kann und der &amp;quot;vorherige&amp;quot; Consumer, der auf das Ausschalten wartet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hilfs-Notifys für die Automatik&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Da durch das Verwenden von swoffcond die Verbraucher beim Ausschalten auch ausgeplant werden, aber eigentlich &amp;quot;nur&amp;quot; unterbrochen werden sollen, müssen sie wieder neu eingeplant werden. Dazu sind notifys nötig. Wichtig: IDs müssen zweistellig angegeben werden!&lt;br /&gt;
&lt;br /&gt;
Wärmepumpe:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:heatpump:.off sleep 10; set energy_mgmt consumerNewPlanning 05&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Nachbar Pool:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:pool_kurz:.off sleep 10; set energy_mgmt consumerNewPlanning 07&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Eine Pumpe mit einem Energiezähler als zwei Consumer verwenden&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
Die verwendete Pumpe hat vier Betriebsarten mit unterschiedlichen Leistungen. Da sie als zwei Consumer abgebildet wird, führt das dazu, dass die Leistung fälschlicherweise von SolarForecast auch zweimal gezählt wird. Die Lösung sind Dummy-Readings, welche die Leistungsdaten passend auseinander rechnen.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Pool_Strom_Pumpe:Pool_Pin31_monotonic_count_PowerCurrent:.* {&lt;br /&gt;
my $power = $EVTPART1;&lt;br /&gt;
my $pump_low = ReadingsVal(&#039;dum_valve&#039;,&#039;pump_low&#039;,&#039;off&#039;);&lt;br /&gt;
my $pump_high = ReadingsVal(&#039;dum_valve&#039;,&#039;pump_high&#039;,&#039;off&#039;);&lt;br /&gt;
my $power_low_sim = 250;&lt;br /&gt;
&lt;br /&gt;
if($pump_low eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $pump_high eq &amp;quot;on&amp;quot;){	&lt;br /&gt;
	my $power_low = $power_low_sim; #fiktiver Verbrauch der niedrigen Stufe&lt;br /&gt;
	my $power_high = $power - $power_low_sim;&lt;br /&gt;
	fhem(&amp;quot;set dum_valve pump_low_power $power_low&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set dum_valve pump_high_power $power_high&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
elsif($pump_low eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $pump_high eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_low_power $power&amp;quot;);&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_high_power 0&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
elsif($pump_low eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_low_power 0&amp;quot;);&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_high_power 0&amp;quot;);&lt;br /&gt;
}elsif($pump_low eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $pump_high eq &amp;quot;on&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_low_power 0&amp;quot;);&lt;br /&gt;
		fhem(&amp;quot;set dum_valve pump_high_power $power&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Es sind alle vier Möglichkeiten der zwei Pumpenlevel abgebildet.&lt;br /&gt;
* Wenn die Automatik deaktiviert ist und die Level 1-4 von extern geschaltet werden, zählen sie dadurch korrekterweise nicht zu diesen beiden Consumern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notifys für das hardwaremäßige Schalten der Consumer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es werden einige Notifys verwendet, die die Umsetzung vom Dummy-Device auf die Hardware erledigen, da ein logisches Ein teilweise hardwaremäßig einige Dinge erfordert.&lt;br /&gt;
&lt;br /&gt;
Notify für Pump Low:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:pump_low:.* {&lt;br /&gt;
	if($EVTPART1 eq &amp;quot;on&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin26 on; sleep 60; set Pool_Pin25 on; sleep 1; set Pool_Pin26 off&amp;quot;);&lt;br /&gt;
	}elsif($EVTPART1 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin14 off; sleep 5; set Pool_Pin12 off; sleep 15; set Pool_Pin25 off&amp;quot;);&lt;br /&gt;
	}else{&lt;br /&gt;
	Log3 (&amp;quot;Pool&amp;quot;, 4, qq{Notify Level1 - parameter is not on or off});&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* Beim Einschalten ist es nötig für eine Minute Pump High zu aktivieren, um Luft aus der Elektrolysezelle zu spülen, bevor Pump Low aktiv sein darf. (Pin26 und Pin25 sind die Steuerpins auf der Interfacekarte der Pumpe für die beiden Level.)&lt;br /&gt;
* Beim Ausschalten werden zuerst die Salzanlage (Pin14) und die pH-Anlage (Pin12) deaktiviert, damit noch 15 Sekunden lang die Elektrolysezelle mit frischem Wasser gespült wird, um das verbleibende Chlor auszuspülen. Hier wird zusätzlich nochmal die Automatik für Pump High deaktiviert. (Um das finale Ausschalten zu sichern.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notify für Pump High:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:pump_high:.* {&lt;br /&gt;
	if($EVTPART1 eq &amp;quot;on&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin26 on; sleep 1; set Pool_Pin25 off&amp;quot;);&lt;br /&gt;
	}elsif($EVTPART1 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin25 on; sleep 1; set Pool_Pin26 off&amp;quot;);&lt;br /&gt;
	}else{&lt;br /&gt;
	Log3 (&amp;quot;Pool&amp;quot;, 4, qq{Notify Level 2- parameter is not on or off});&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterung:&lt;br /&gt;
&lt;br /&gt;
* Da die Interfacekarte immer auf den höchsten Level reagiert, wird beim Umschalten zuerst Pump High aktiviert und nach einer Sekunde Pump Low deaktiviert, um ein &amp;quot;stufenloses&amp;quot; (ohne Ausschalten) Umschalten zu ermöglichen. Beim Ausschalten genauso.&lt;br /&gt;
&lt;br /&gt;
Notify für die Wärmepumpe:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:heatpump:.* {&lt;br /&gt;
	if($EVTPART1 eq &amp;quot;on&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin6 on&amp;quot;);&lt;br /&gt;
	}elsif($EVTPART1 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set Pool_Pin6 off&amp;quot;);&lt;br /&gt;
	}else{&lt;br /&gt;
	Log3 (&amp;quot;Pool&amp;quot;, 4, qq{Notify heatpump - parameter is not on or off});&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterung:&lt;br /&gt;
&lt;br /&gt;
* Hier reicht ein dirketes Übernehmen aus dem Dummy.&lt;br /&gt;
&lt;br /&gt;
Notify für den Nachbar-Pool:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dum_valve:pool_kurz:.* {&lt;br /&gt;
	if($EVTPART1 eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; ReadingsVal(&amp;quot;Shelly_Plug_S_1&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;on&amp;quot;) eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set PwSw_Schalter off; sleep 3;{if(ReadingsAge(\&amp;quot;PwSw_Schalter\&amp;quot;,\&amp;quot;state\&amp;quot;,0)&amp;lt;4 &amp;amp;&amp;amp; ReadingsVal(\&amp;quot;PwSw_Schalter\&amp;quot;,\&amp;quot;state\&amp;quot;,\&amp;quot;on\&amp;quot;) eq \&amp;quot;off\&amp;quot;){fhem(\&amp;quot;set Shelly_Plug_S_1 on\&amp;quot;)}}; sleep 5; set PwSw_Schalter on&amp;quot;);&lt;br /&gt;
	}elsif($EVTPART1 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; ReadingsVal(&amp;quot;Shelly_Plug_S_1&amp;quot;,&amp;quot;state&amp;quot;,&amp;quot;off&amp;quot;) eq &amp;quot;on&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set PwSw_Schalter off; sleep 3;{if(ReadingsAge(\&amp;quot;PwSw_Schalter\&amp;quot;,\&amp;quot;state\&amp;quot;,0)&amp;lt;4 &amp;amp;&amp;amp; ReadingsVal(\&amp;quot;PwSw_Schalter\&amp;quot;,\&amp;quot;state\&amp;quot;,\&amp;quot;on\&amp;quot;) eq \&amp;quot;off\&amp;quot;){fhem(\&amp;quot;set Shelly_Plug_S_1 off\&amp;quot;)}}; sleep 5; set PwSw_Schalter on&amp;quot;);&lt;br /&gt;
	}else{&lt;br /&gt;
	Log3 (&amp;quot;Pool&amp;quot;, 4, qq{Notify Pool Kurz - parameter is not on or off});&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterung&lt;br /&gt;
&lt;br /&gt;
* Da hier eine Pumpe durch einen 3-poligen Umschalter zwischen zwei Hausanspeisungen umgeschaltet wird, ist es wichtig, dass die Pumpe dazwischen &#039;&#039;&#039;gesichert&#039;&#039;&#039; zum Stehen gebracht wird! Sonst führt die rotierende Pumpe als Generator zu einem gewaltigen Kurzschluss mit der &amp;quot;fremden&amp;quot; Phase. War nicht schön ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sonderprogramme für den Poolbetrieb&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hier ist das Aus- und Einschalten der Solarforcast-Automatik zu sehen. Es werden alle Stati gespeichert. Danach kann von beliebigen &amp;quot;Sonderfunktionen&amp;quot; (Reinigung des Filters, Massagefunktion, usw.) auf die Hardware zugegriffen werden. Wenn wieder in den Automatikmodus zurückgewechselt wird, wird hardwaremäßig wieder der Zustand der Automatik von vorher hergestellt, die Stati wieder zurück geschrieben und die Automatik wieder aktiviert.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
##############################################&lt;br /&gt;
# Status speichern und Automatik ausschalten #&lt;br /&gt;
##############################################&lt;br /&gt;
sub PoolAutoOff{&lt;br /&gt;
	my $pump_low_id			= sprintf &amp;quot;%02d&amp;quot;, 1;&lt;br /&gt;
	my $pump_high_id		= sprintf &amp;quot;%02d&amp;quot;, 3;&lt;br /&gt;
	my $heatpump_id			= sprintf &amp;quot;%02d&amp;quot;, 5;&lt;br /&gt;
	my $pool_kurz_id		= sprintf &amp;quot;%02d&amp;quot;, 7;&lt;br /&gt;
	my $sf				= &#039;energy_mgmt&#039;;&lt;br /&gt;
&lt;br /&gt;
		&lt;br /&gt;
#	my $pump_low_state = ReadingsVal($valve_dummy,&#039;pump_low&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pump_low_auto	= FHEM::SolarForecast::ConsumerVal ($sf, $pump_low_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Pumpe&lt;br /&gt;
#	my $pump_high_state = ReadingsVal($valve_dummy,&#039;pump_high&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pump_high_auto	= FHEM::SolarForecast::ConsumerVal ($sf, $pump_high_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Pumpe&lt;br /&gt;
#	my $heatpump_state = ReadingsVal($valve_dummy,&#039;heatpump&#039;,&#039;on&#039;);&lt;br /&gt;
	my $heatpump_auto	= FHEM::SolarForecast::ConsumerVal ($sf, $heatpump_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus der Wärmepumpe&lt;br /&gt;
#	my $pool_kurz_state = ReadingsVal($valve_dummy,&#039;pool_kurz&#039;,&#039;on&#039;);&lt;br /&gt;
	my $pool_kurz_auto	= FHEM::SolarForecast::ConsumerVal ($sf, $pool_kurz_id, &#039;auto&#039;, &#039;&#039;);	# Automatikmodus des Pools&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pump_low_auto 0&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pump_high_auto 0&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy heatpump_auto 0&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pool_kurz_auto 0&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy sf_automatic 0&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pump_low $pump_low_auto&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pump_high $pump_high_auto&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_heatpump $heatpump_auto&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pool_kurz $pool_kurz_auto&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	my $last_pump_level_1 = ReadingsVal($valve_dummy,&amp;quot;pump_low&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_2 = ReadingsVal($valve_dummy,&amp;quot;pump_high&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_3 = ReadingsVal($pump_level_3,&amp;quot;value&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_4 = ReadingsVal($pump_level_4,&amp;quot;value&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_heatpump = ReadingsVal($valve_dummy,&amp;quot;heatpump&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_1 $last_pump_level_1&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_2 $last_pump_level_2&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_3 $last_pump_level_3&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_4 $last_pump_level_4&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_heatpump $last_heatpump&amp;quot;); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
##########################################&lt;br /&gt;
# Status laden und Automatik einschalten #&lt;br /&gt;
##########################################&lt;br /&gt;
sub PoolAutoOn{&lt;br /&gt;
	my $last_pump_level_4 = ReadingsVal($valve_dummy,&amp;quot;last_pump_level_4&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_3 = ReadingsVal($valve_dummy,&amp;quot;last_pump_level_3&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_2 = ReadingsVal($valve_dummy,&amp;quot;last_pump_level_2&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_pump_level_1 = ReadingsVal($valve_dummy,&amp;quot;last_pump_level_1&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	my $last_heatpump = ReadingsVal($valve_dummy,&amp;quot;last_heatpump&amp;quot;,&amp;quot;off&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $pump_level_4 $last_pump_level_4&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;set $pump_level_3 $last_pump_level_3&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $pump_level_2 $last_pump_level_2&amp;quot;);&lt;br /&gt;
	if($last_pump_level_1 eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $last_pump_level_2 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_3 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_4 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set $pump_level_2 on; sleep 1; set $pump_level_1 $last_pump_level_1; sleep 28; set $pump_level_2 off; set $valve_dummy sf_automatic 1&amp;quot;);&lt;br /&gt;
	}elsif($last_pump_level_1 eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $last_pump_level_2 eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; $last_pump_level_3 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_4 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set $pump_level_1 off; set $valve_dummy sf_automatic 1&amp;quot;); &lt;br /&gt;
	}elsif($last_pump_level_1 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_2 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_3 eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; $last_pump_level_4 eq &amp;quot;off&amp;quot;){&lt;br /&gt;
		fhem(&amp;quot;set $pump_level_1 off; set $valve_dummy sf_automatic 1&amp;quot;); &lt;br /&gt;
	}&lt;br /&gt;
	fhem(&amp;quot;sleep 10; set $heatpump $last_heatpump&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_1 none&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_2 none&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_3 none&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_pump_level_4 none&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_heatpump none&amp;quot;); &lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy valve_position normal&amp;quot;);&lt;br /&gt;
	my $last_auto_pump_low = ReadingsVal($valve_dummy,&amp;quot;last_auto_pump_low&amp;quot;,0);&lt;br /&gt;
	my $last_auto_pump_high = ReadingsVal($valve_dummy,&amp;quot;last_auto_pump_high&amp;quot;,0);&lt;br /&gt;
	my $last_auto_heatpump = ReadingsVal($valve_dummy,&amp;quot;last_auto_heatpump&amp;quot;,0);&lt;br /&gt;
	my $last_auto_pool_kurz = ReadingsVal($valve_dummy,&amp;quot;last_auto_pool_kurz&amp;quot;,0);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pump_low_auto $last_auto_pump_low&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pump_high_auto $last_auto_pump_high&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy heatpump_auto $last_auto_heatpump&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;set $valve_dummy pool_kurz_auto $last_auto_pool_kurz&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pump_low none&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pump_high none&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_heatpump none&amp;quot;);&lt;br /&gt;
	fhem(&amp;quot;setreading $valve_dummy last_auto_pool_kurz none&amp;quot;);&lt;br /&gt;
}		&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Erläuterungen:&lt;br /&gt;
&lt;br /&gt;
* pump_level_1 ist Pump Low, pump_level_2 ist Pump High, pump_level_3 und pump_level_4 sind Sonderfunktionen (Filterreinigung, Massage)&lt;br /&gt;
* Beim Wiedereinschalten von Pump Low ist es wieder nötig kurz Pump High zu aktivieren, um Luft auszuspülen.&lt;br /&gt;
* Es wird der Zustand von Solarforecast gespeichert und danach auf die Hardware geschrieben. -&amp;gt; Stellt sicher, dass nach dem Einschalten der Automatik der logical switchstate zum physical switchstate passt.&lt;br /&gt;
&lt;br /&gt;
== Tips &amp;amp; Tricks ==&lt;br /&gt;
* Interruptable verhält sich völlig anders, wenn der Perlcode 1 oder 0 liefert, als wenn man 1 oder 0 in der Config hinterlegt. -&amp;gt; siehe commandref&lt;br /&gt;
* Rückgabewert bei swoncond und swoffcond wird mit dem Readingswert verglichen und nicht dirket verwendet. Bsp. wenn das Reading 100 enthält muss auch der Rückgabewert des Perlcodes 100 liefern, um true zu ergeben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== weiterführende Links ==&lt;br /&gt;
* Forenthema &amp;quot;{{Link2Forum|Topic=137058|LinkText=76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support}}&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;
* Photovoltaik Ingenieurbüro Junge: https://www.ing-büro-junge.de/html/photovoltaik.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung&amp;diff=40309</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=40309"/>
		<updated>2025-08-05T06:23:25Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Hinweis|Die vorliegende Wiki-Seite befindet sich im Aufbau.}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Solarprognose und Verbrauchersteuerung&lt;br /&gt;
|ModType=d&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 Prognosewerte können die SolCast API, OpenMeteo API, Forecast.Solar API, Victron VRM Portal API oder alternativ DWD Stahlungswerte-Stationen verwendet werden&lt;br /&gt;
&lt;br /&gt;
::* optionale KI Unterstützung der PV-Prognose bei Verwendung von geeigneten Solar-API&#039;s&lt;br /&gt;
&lt;br /&gt;
::* es wird sowohl die Erzeugungsprognose als auch eine Verbrauchsprognose sowie SoC Prognose (bei Batterie-Integration) erstellt&lt;br /&gt;
&lt;br /&gt;
::* Wetterdaten werden über DWD Wetter-Stationen oder verschiedene API integriert. Es können verschiedene API zur Gewinnung von Solar- und Wetterdaten kombiniert werden. &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 FHEM-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 Integration von bis zu 4 Inverter und Smartloader (DC-DC Batterieladegeräte) ist möglich&lt;br /&gt;
&lt;br /&gt;
::* eine Integration von bis zu 3 nicht PV-Energieerzeugern wie BHKW, Windrädern oder Notstromaggregaten ist möglich&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;
::* Einbindung von bis zu drei Batteriespeichersystemen&lt;br /&gt;
&lt;br /&gt;
::* Bereitstellung von Leitwerten zur optimalen Einstellung/Steuerung von Batteriespeichersystemen&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 Benutzererlebnis 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;
Das Wiki gibt allgemeingültige und teilweise sehr spezifische bzw. tiefgehende Informationen und Handlungsempfehlungen zum SolarForecast Modul. Die dargestellten Informationen beziehen sich auf den zum Zeitpunkt der Wiki-Erstellung vorhandenen Entwicklungsstand des Moduls. Durch die stetige Weiterentwicklung können sich Abweichungen zum beschriebenen Inhalt ergeben oder zur Obsoleszenz dieser Inhalte führen. &lt;br /&gt;
&lt;br /&gt;
Vergleiche deshalb die Informationen immer mit der aktuellen Befehls-Referenz zum Modul!&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Ein SolarForecast Device wird mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 define &amp;lt;Name&amp;gt; SolarForecast &lt;br /&gt;
&lt;br /&gt;
angelegt. Nach der Definition wird der User durch einen Dialog geführt, der einige unerlässliche Einstellungen abfragt und in den entsprechenden Attributen und Readings persistiert. Alle Attribute und Readings die eine Einstellung der Anlage bewirken, sind mit dem Präfix &amp;quot;setup&amp;quot; versehen. &lt;br /&gt;
&lt;br /&gt;
Die Verwendung von setup-Readings gestattet es die Anlagenparameter dynamisch im Betrieb zu verändern. So kann mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringAzimuth   bzw.&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringDeclination &lt;br /&gt;
&lt;br /&gt;
die Ausrichtung und der Neigungswinkel der PV-Module ständig angepasst werden, was zum Beispiel bei einer dem Sonnenstand nachgeführten Anlage von Bedeutung ist.&lt;br /&gt;
&lt;br /&gt;
Die abgefragten Einstellungen während des Dialoges sind ausführlich in den entsprechenden Attributen bzw. Set-Kommandos erläutert. Die benötigten Informationen sind anhängig von der gewählten Prognose-API und können im Umfang variieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 213257.png|right|thumb|400px|Anlagenprüfung über Drucktaste in der Kopfgrafik]]&lt;br /&gt;
&lt;br /&gt;
Sobald alle verlangten Einstellungen vorgenommen sind, sollte eine Anlagenprüfung mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; plantConfiguration check&lt;br /&gt;
&lt;br /&gt;
oder über die angebotene Drucktaste in der Grafik durchgeführt werden. Es wird eine Plausibilitätsprüfung vorgenommen und das Ergebnis sowie eventuelle Hinweise bzw. Fehler ausgegeben.&lt;br /&gt;
Die Prüfung kann beliebig wiederholt werden und sollte sich bei jeder Einstellungsänderung der Anlage durchgeführt werden. Dadurch wird die Wahrscheinlichkeit von fehlerhaften Einstellungen minimiert.&lt;br /&gt;
&lt;br /&gt;
Neben den grundlegenden Einstellungen können im Device weitere sekundäre Anlagenkomponenten wie Batteriesystem(e) (Attribut setupBatteryDev1 - setupBatteryDev3), weitere Wetter-Devices (Attribut setupWeatherDev1 - setupWeatherDev3) oder sonstige Erzeuger (z.B. BHKW, Winderzeugung, Notstromaggregat) integriert werden (Attribut setupOtherProducer01 - setupOtherProducer03).&lt;br /&gt;
&lt;br /&gt;
Die verlangten Parameter der Anlage werden in der Online-Hilfe umfassend beschrieben und deren Funktion erschließt sich zum größten Teil selbst. Dennoch soll nachfolgend auf einige Punkte im Zusammenhang der Einrichtung eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Hinweise zur Struktur der Attribute ===&lt;br /&gt;
&lt;br /&gt;
Durch die umfangreichen Funktionen des Moduls würde bei Nutzung der im FHEM herkömmlich vorhandenen Attributstruktur die Anzahl der benötigten Attribute extrem stark steigen und nicht sinnvoll genutzt werden können. Deshalb gibt es neben den &#039;&#039;gewöhnlichen&#039;&#039; Attributen mit einfachen Werteauswahlmöglichkeiten oder Eingaben (z.B. ctrlDebug, ctrlSpecialReadings) sogenannte &#039;&#039;zusammengesetzte&#039;&#039; Attribute, deren Inhalt durch &#039;&#039;&#039;Schlüssel=Wert Paare&#039;&#039;&#039; gebildet wird und dadurch deutlich mehr Funktionen und Informationen transportieren als ein gewöhnliches Attribut.&lt;br /&gt;
&lt;br /&gt;
Für zusammengesetzte Attribute besteht die zusätzliche Möglichkeit, gewünschte Änderungen der Schlüssel=Wert Paare selektiv vornehmen zu können, ohne das gesamte Attribut aufrufen und ändern zu müssen. Die Vorgang, der vor allem für programmtechnische Manipulationen gedacht ist, kann durch eine Set-Funktion ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; attrKeyVal &amp;lt;Attribut&amp;gt; [&amp;lt;Gerät&amp;gt;] &amp;lt;Schlüssel=Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiele für zusammengesetzte Attribute sind:&lt;br /&gt;
&lt;br /&gt;
* aiControl&lt;br /&gt;
* plantControl&lt;br /&gt;
* setup* Attribute&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktionen der Attribute werden durch einen Präfix geclustert und so inhaltlich, aber vor allem auch in der Attribute Drop-Down Liste, strukturiert dargestellt.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der &#039;&#039;&#039;Präfixe&#039;&#039;&#039; sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ai&#039;&#039;&#039; - Steuerungsfunktionen für KI (z.B. aiControl)&lt;br /&gt;
* &#039;&#039;&#039;consumer&#039;&#039;&#039; - Registrierung und Einstellungen für Verbraucher (z.B. consumer02, consumerControl)&lt;br /&gt;
* &#039;&#039;&#039;ctrl&#039;&#039;&#039; - Steuerungsfunktion allgemeiner Art (z.B. ctrlDebug, ctrlSpecialReadings, ctrlUserExitFn)&lt;br /&gt;
* &#039;&#039;&#039;flowGraphic&#039;&#039;&#039; - Einstellungen für die Energieflußgrafik (z.B. flowGraphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphic&#039;&#039;&#039; - Einstellung für die Grafik allgemein (z.B. graphicSelect, graphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphicBeam&#039;&#039;&#039; -  Einstellungen bestimmte Balkeneigenschaften in der Balkengrafik (z.B. graphicBeamHeightLevel1)&lt;br /&gt;
* &#039;&#039;&#039;plant&#039;&#039;&#039; - übergreifende Einstellungen betreffend der gesamten PV-Anlage bzw. des SolarForecast-Devices (z.B. plantControl)&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039; - Registrierung von Geräten in der Gesamtanlage und Einstellung deren Eigenschaften (Inverter, Zähler, Batterien usw.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Einrichtung der Wechselrichter mit setupInverterDevXX ===&lt;br /&gt;
&lt;br /&gt;
Mit den Attributen setupInverterDev01 bis setupInverterDevXX werden die vorhandenen Wechselrichter der Anlage registriert.&lt;br /&gt;
Das Modul unterscheidet verschiedene Wechselrichter-Typen, die sich durch ihre Arbeitsweise innerhalb der Anlage unterscheiden. Die Schlüssel=Wert Paare in den Attributen können mehrzeilig organisiert werden. Das erleichtert die Übersicht wenn viele dieser Parameter eingegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;PV-Wechselrichter: Es ist der Standard Wechselrichter in einer PV-Anlage. An ihn sind die Solarzellen bzw. Strings angeschlossen. Die zugeordneten Strings können mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ohne diese Angabe werden diesem Gerät alle definierten Strings (siehe Attribut &#039;&#039;setupInverterStrings&#039;&#039;) zugeordnet. Der Wechselrichter liefert seine Energie in das Hausnetz. Alternativ kann mit der Angabe &#039;&#039;&#039;feed=grid&#039;&#039;&#039; die Funktion des Wechselrichters geändert werden. Diese Angabe sagt aus, dass dieser Wechselrichter ausschließlich in das öffentliche Netz einspeist.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel-Setup eines PV-Wechselrichters (SMA STP):&lt;br /&gt;
&lt;br /&gt;
 STP_5000 pvIn=string_1_pdc:kW pvOut=total_pac:kW etotal=etotal:kWh capacity=5000 strings=Süddach asynchron=1 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Solar-Ladegeräte: Solar-Ladegeräte sind DC-DC Wandler und liefern die Energie der angeschlossenen Solarzellen nicht in das Wechselstromnetz, sondern laden direkt eine Batterie bzw. versorgen einen Batteriewechselrichter auf der Gleichstromseite. Die Funktion als Solar-Ladegerät wird mit &#039;&#039;&#039;feed=bat&#039;&#039;&#039; aktiviert, die relevanten Strings können ebenfalls mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ein Beispiel eines Solar-Ladegerätes ist ein Victron SmartSolar MPPT. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel für das Setup eines Solar-Ladegeräts (SmartSolar Charger MPPT):&lt;br /&gt;
&lt;br /&gt;
 MQTT2_cerboGX_c0619ab34e08_solarcharger_Common pv=Yield_Power_value:W etotal=Yield_System_value:kWh capacity=2080 strings=Schleppdach feed=bat synchron=0 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Batterie-Wechselrichter: Dieses Gerät hat keine angeschlossenen Solarzellen und arbeitet als DC-AC bzw. AC-DC Wandler zwischen einer Batterie (=Gleichstromquelle) und dem Wechselstrom-Hausnetz. Die Funktion als Batterie-Wechselrichter wird mit der Angabe &#039;&#039;&#039;strings=none&#039;&#039;&#039; aktiviert. Die Schlüssel &#039;&#039;etotal&#039;&#039; und &#039;&#039;pv&#039;&#039; können bei einem Batterie-Wechselrichter ohne zugeordnete Solarzellen nicht gesetzt werden. Ein Beispiel eines Batterie-Wechselrichter ist der Victron MultiPlus II.&lt;br /&gt;
&lt;br /&gt;
Ein Setup-Beispiel für einen Batterie-Wechselrichter (Victron MultiPlus II):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dc2ac=DC_IN:W&lt;br /&gt;
ac2dc=DC_OUT:W&lt;br /&gt;
capacity=7200&lt;br /&gt;
strings=none&lt;br /&gt;
icon=inverter@darkorange:inverter@grey&lt;br /&gt;
asynchron=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Eigenschaften des Wechselrichters werden durch eine Reihe von &amp;lt;Schlüssel=Wert&amp;gt; Paaren festgelegt. Auf einige dieser Paramter soll hier eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Ausgewählte Schlüssel=Wert Paare ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;pvIn=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvIn&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell zugeführte PV-Leistung bereitstellt. Der Schlüssel ist optional und dient in erster Linie dazu den entsprechenden Input-Wert in der Flußgrafik anzuzeigen sofern man das Attribut flowGraphicControl-&amp;gt;showGenerators=1 setzt. Dadurch ist auch der Eigenverbrauch des Inverters bzw. dessen Wandlungsverlust visuell abschätzbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pvOut=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvOut&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell erzeugte Leistung als positiven Wert liefert. Für einen PV-Wechselrichter (DC-&amp;gt;AC) oder Solar-Ladegerät (DC-&amp;gt;DC) ist es die erzeugte PV-Leistung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ac2dc=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter vom Hausnetz in Richtung Batterie (AC-&amp;gt;DC) wandelt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;dc2ac=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter aus einer Gleichstromquelle, d.h. einer Batterie oder einem Solar-Ladegerät, in Richtung des Hausnetzes (AC) wandelt . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;capacity=&amp;lt;max. WR-Leistung&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In dem Schlüssel &#039;&#039;capacity&#039;&#039; wird die maximal mögliche Leistung in Watt (ohne Einheit) angegeben, die der Wechselrichter lt. seinem Datenblatt in der Lage ist zu leisten. &lt;br /&gt;
&lt;br /&gt;
Die Angabe &#039;&#039;capacity&#039;&#039; hat in erster Linie die Aufgabe, die max. mögliche PV-Leistung für die Prognose zu begrenzen. Oft sind die installierten Peak-Leistungen der PV-Module höher als die angeschlossene Wechselrichter-Leistung bzw. kommt es vor, dass die KI / (korrigierte) API-Prognose über der maximal möglichen Wechselrichter-Leistung liegt. In diesen Fällen wird die Prognose auf die angegebene &#039;&#039;capacity&#039;&#039; begrenzt.&lt;br /&gt;
&lt;br /&gt;
Der Wert in diesem Schlüssel kann, wie andere Schlüssel auch, dynamisch zur Laufzeit mit dem Set-Befehl &amp;quot;[[#Hinweise zur Struktur der Attribute|set &amp;lt;Name&amp;gt; attrKeyVal ...]]&amp;quot; geändert werden. Ein Beispiel zur Anwendung ergibt sich aus folgendem Szenario.&lt;br /&gt;
&lt;br /&gt;
Gegeben sei eine Anlage die aus Solarzellen (1300 W Peak) mit einem Solar-Ladegerät mit max. 1800 W Leistung, einer Batterie und einem Batterie-Wechselrichter besteht. Die Anlage versorgt nur das Hausnetz. Eine Netzeinspeisung ist nicht vorgesehen oder nicht erlaubt.  &lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, es ist ein Tag voller Sonnenschein prognostiziert und die Batterie ist zunächst entladen. Der Haushalt verbraucht 300 W. Dann würden die PV-Module Module ihre volle Leistung von 1300 W Peak leisten können, die sich auch in der Balken-Vorhersage niederschlägt. Die Leistung wird nicht begrenzt, weil:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* sie niedriger ist als die nominale und angegebene Wechselrichter Kapazität von &#039;&#039;capacity=1800&#039;&#039;&lt;br /&gt;
* die erzeugte Energie anteilig für die Verorgung des Hauses und die Aufladung der Batterie verwendet wird&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders verhält es sich wenn nach einer gewissen Zeit die Batterie voll ist und weiterhin volle PV Leistung zur Verfügung steht. In diesem Fall würde der Haushalt seine benötigte Leistung von 300 W abnehmen, aber das Solar-Ladegerät kann keine weitere Leistung mehr abgeben, da die Batterie bereits voll geladen ist, d.h. die Anlagensteuerung würde die PV-Anlage abregeln. In diesem Fall, wenn es einen längeren Zeitraum betrifft, muß auch die Prognose PV-Energie auf 300 Wh (bzw. den durchschnittlichen Energieverbrauch des Hauses pro Stunde) begrenzt werden, damit die PV-Prognose nach unten angepasst wird und so eine realitätsnahere Prognose ermöglicht wird. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;icon=&amp;lt;aktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;][:&amp;lt;inaktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Jeder Wechselrichter wird im Standard durch ein Icon getrennt nach Tag und Nacht, d.h. je nach Aktiv-Status und Inaktiv-Status, symbolisiert.&lt;br /&gt;
&lt;br /&gt;
;Tag bzw. Aktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Sonnensymbol im Standard verwendet. Batterie-Wechselrichter verwenden ein gefärbtes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
;Nacht bzw. Inaktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Symbol der aktuellen Mondphasen im Standard verwendet. Batterie-Wechselrichter verwenden ein ausgegrautes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie angegeben, kann man für Tag und Nacht jeweils ein Wunsch-Icon, wenn gewünscht mit einer alternativen Färbung, auswählen.&lt;br /&gt;
&lt;br /&gt;
 icon=inverter@darkorange:inverter@gray&lt;br /&gt;
&lt;br /&gt;
Soll nur das Icon für die Nacht bzw. Inaktivät geändert werden, kann dies in dieser Form angegeben werden:&lt;br /&gt;
&lt;br /&gt;
 icon=:inverter@gray  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(beachte den führenden &#039;:&#039;)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Der integrierte SolarForecast Grafikbereich ==&lt;br /&gt;
Das SolarForecast Modul beinhaltet eine Grafikdarstellung die sich in mehrere Bereiche gliedert. Diese Bereiche können über Attribute ein- bzw. ausgeblendet sowie die Inhalte festgelegt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 223545.png|right|thumb|400px|Bereiche der integrierten Grafik]]&lt;br /&gt;
&lt;br /&gt;
Der nebenstehende Screenshot gibt die Gliederung der Grafikbereiche wieder:&lt;br /&gt;
&lt;br /&gt;
 1 - der Kopfbereich (Graphic Header)&lt;br /&gt;
 2 - durch den Nutzer selbst definierbarer Inhalt (Graphic Header Own Specification) als Teil des Kopfbereiches&lt;br /&gt;
 3 - Bereich Verbraucherdarstellung (Consumer Legend)&lt;br /&gt;
 4 - Bereich Balkengrafik (Beam Graphic)&lt;br /&gt;
 5 - Energieflußgrafik (Flow Graphic)&lt;br /&gt;
&lt;br /&gt;
Jeder dieser Bereiche hat spezifische Steuerungsattribute zur Anpassung des Verhaltens und ggf. des Inhalts.&lt;br /&gt;
&lt;br /&gt;
=== 1 - Der Grafik Kopfbereich ===&lt;br /&gt;
Im Kopfbereich befinden sich fest verankerte Informationen zur verwendeten Vorhersage-API sowie deren Status, Informationen zum Sonnenaufgang und Sonnenuntergang, dem aktuellen Gesamtstatus des SolarForecast Devices, Abweichungskennzahlen der PV Vorhersage sowie weitere Kennzeichen zur Verfügung.&lt;br /&gt;
Über zwei Drucktasten kann eine Anlagenprüfung durchgeführt und in den Spportthread des Moduls im FHEM Forum abgesprungen werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;graphicHeaderShow&#039;&#039;&#039; kann der gesamte Kopfbereich 1 und 2 (nutzereigener Teilbereich) ausgeblendet werden. Wird der Kopbereich ausgeblendet, ist es hilfreich mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;showLink&#039;&#039;&#039; einen Link zur Detailgrafik einzufügen da der in der Kopfgrafik integrierte Link in diesem Fall nicht mehr zur Verfügung steht. &lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;graphicHeaderDetail&#039;&#039;&#039; definiert welche Bereiche des Grafikkopfes angezeigt werden sollen. Es kann die Anzeige des Energieverbrauches, der PV-Erzeugung und der vom Nutzer selbst definierte Inhalt miteinander frei kombiniert werden.&lt;br /&gt;
&lt;br /&gt;
=== 2 - Der Bereich mit selbst definierbarem Inhalt (Graphic Header Own Specification) ===&lt;br /&gt;
In diesem Bereich kann der User beliebige Readings, Set-Kommandos und Attribute des SolarForecast Devices oder anderer Devices, die sich im gleichen FHEM-System wie das SolarForecast Device befinden, anzeigen lassen.&lt;br /&gt;
&lt;br /&gt;
Dieser Bereich ist als Tabelle mit einer beliebigen Anzahl von Zeilen organisiert. Jede Zeile beinhaltet ein Kommentarfeld und vier Nutzfelder zur Darstellung ausgewähler Werte + Label. Der Bereich bzw. der Inhalt des Bereiches wird mit dem Attribut &#039;&#039;&#039;graphicHeaderOwnspec&#039;&#039;&#039; definiert.  &lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt ein real gesetztes graphicHeaderOwnspec Attribut. Die Leerzeilen sind nicht notwendig, erhöhen aber die Lesbarkeit der Struktur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
Autarkierate:Current_AutarkyRate&lt;br /&gt;
PV&amp;amp;nbsp;übermorgen:special_dayAfterTomorrowPVforecast&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;Sunset:special_todayConForecastTillSunset&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;nächsten&amp;amp;nbsp;Sunrise:special_conForecastTillNextSunrise&lt;br /&gt;
&lt;br /&gt;
#Batterie&lt;br /&gt;
BatteryLive&amp;amp;nbsp;Status:userFn_BatLive_State&lt;br /&gt;
SoC&amp;amp;nbsp;Limit:Settings_CGwacs_BatteryLife_MinimumSocLimit_value@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SoC&amp;amp;nbsp;Ist:SOC_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
SOC&amp;amp;nbsp;Optimum:Battery_OptimumTargetSoC&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
aktuelle&amp;amp;nbsp;Ladung:userFn_Bat_EnergyState&lt;br /&gt;
Verfügbar:userFn_BatLive_UsableEnergy&lt;br /&gt;
benötigte&amp;amp;nbsp;Ladeenergie:userFn_Bat_EnergyRemain&lt;br /&gt;
Ladefreigabe:Battery_ChargeRecommended&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
akt.&amp;amp;nbsp;DC&amp;amp;nbsp;Strom:DC_Current_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
Restladezeit&amp;amp;nbsp;Ziel:userFn_Bat_HoursUntilChargeFinish&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Soll:userFn_Bat_MaxChargeCurrent_set&lt;br /&gt;
:&lt;br /&gt;
&lt;br /&gt;
#Settings&lt;br /&gt;
Batterie&amp;amp;nbsp;Lademanagement:userFn_BatteryChargeManagement&lt;br /&gt;
SoC&amp;amp;nbsp;Management:userFn_BatterySoCManagement&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Ist:MaxChargeCurrent@MQTT2_cerboGX_c0619ab34e08_vebus&lt;br /&gt;
SmartSolar&amp;lt;br&amp;gt;Einspeisung:OvervoltageFeedIn@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
MPII&amp;amp;nbsp;Limit&amp;lt;br&amp;gt;Einspeisung&amp;amp;nbsp;(W):MaxFeedInPower@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SOC&amp;amp;nbsp;Limit&amp;amp;nbsp;Soll:MinimumSocLimit@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Verbr.&amp;amp;nbsp;Neuplanung:consumerNewPlanning&lt;br /&gt;
Wetteranzeige:graphicShowWeather &lt;br /&gt;
&lt;br /&gt;
Anzeige&amp;amp;nbsp;Nachtstunden:graphicShowNight&lt;br /&gt;
hist.&amp;amp;nbsp;Stunden:graphicHistoryHour&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto&lt;br /&gt;
Victron&amp;amp;nbsp;BatteryLife&amp;lt;br&amp;gt;(1=an,10=aus):BatteryLife@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Debug:ctrlDebu&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Kommentarfeld am Beginn einer Zeile wird durch ein &#039;&#039;&#039;#&#039;&#039;&#039; gekennzeichnet. Folgt dem # ein String, wird dieser String als Kommentarangabe gewertet und in der Grafik ausgegeben. Ein leeres Kommentarfeld wird lediglich durch ein # gefolgt von einem Leerzeichen oder NL beschrieben:&lt;br /&gt;
&lt;br /&gt;
 #:&amp;lt;Text&amp;gt;  (bzw nur # für einen &#039;leeren&#039; Titel)&lt;br /&gt;
&lt;br /&gt;
Ein Netzfeld bzw. ein Datensatz wird durch die Angabe von einem Label und dem darzustellenden Wert getrennt durch &#039;:&#039; definiert:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Label&amp;gt;:&amp;lt;Reading, Attribut oder Set-Kommando&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das System erkennt selbständig, ob es sich bei der Angabe um ein Reading, Attribut oder ein Set-Kommando handelt. Sollen Readings, Set-Kommandos und Attribute anderer Devices als dem SolarForecast-Device angezeigt werden, kann dies einfach durch Zusatz von&lt;br /&gt;
&lt;br /&gt;
 ....@&amp;lt;Device-Name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
an den Parameter erreicht werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-12-05 203916.png|right|thumb|400px|Darstellung eigener Grafikbereich]]&lt;br /&gt;
Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten &amp;quot;Wh&amp;quot; bzw. &amp;quot;kWh&amp;quot; werden entsprechend der Einstellung des Attributs &#039;&#039;&#039;graphicEnergyUnit&#039;&#039;&#039; umgerechnet. Im Label sind Leerzeichen durch &amp;quot;&amp;amp;amp;nbsp;&amp;quot; einzufügen, ein Zeilenumbruch durch &amp;quot;&amp;amp;lt;br&amp;amp;gt;&amp;quot;. Ein leeres Feld in einer Zeile wird durch &amp;quot;:&amp;quot; ohne eine weitere Angabe erzeugt.&lt;br /&gt;
&lt;br /&gt;
Die nebenstehende Abbildung zeigt die reale Darstellung der oben angegebenen Struktur im Attribut graphicHeaderOwnspec.&lt;br /&gt;
&lt;br /&gt;
==== Formatierung der Inhalte im Bereich &amp;quot;Graphic Header Own Specification&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
Die angezeigten Inhalte, wie z.B. Readingwerte, des User eigenen Bereiches (Attribut graphicHeaderOwnspec) können durch Spezifikationen im Attribut &#039;&#039;&#039;graphicHeaderOwnspecValForm&#039;&#039;&#039; manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
Die Online-Hilfe zum Attribut graphicHeaderOwnspecValForm erläutert die verfügbaren Möglichkeiten und Optionen.&lt;br /&gt;
Als Beispiel hier einige mögliche Notationen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &#039;userFn_Bat_HoursUntilChargeFinish&#039;                        =&amp;gt; &amp;quot;($VALUE).&#039; Stunden&#039;&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_battery.SOC_value&#039;             =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Settings_CGwacs_BatteryLife_MinimumSocLimit_value&#039;        =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Info_MaxChargeCurrent_value&#039;                              =&amp;gt; &amp;quot;($VALUE).&#039; A&#039;&amp;quot;,&lt;br /&gt;
  &#039;DC_Current_value&#039;                                         =&amp;gt; &amp;quot;%.0f A&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common.Regulated&#039; =&amp;gt; &amp;quot;($VALUE eq &#039;1&#039; ? &#039;Ja&#039; : &#039;Nein&#039;)&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine Besonderheit besteht bei darzustellenden Werten die die Einheiten &#039;Wh&#039; bzw. &#039;kWh&#039; besitzen. Diese Werte und Einheiten werden automatisch entsprechend des gesetzten Attributes graphicEnergyUnit umgerechnet und angezeigt.&lt;br /&gt;
&lt;br /&gt;
Soll in diesen Fällen eine automatische Formatierung umgangen werden, kann eine solche Notation verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &#039;Today_PVforecast&#039; =&amp;gt; &amp;quot;(sprintf &#039;%.1f &amp;amp;amp;nbsp;kWh&#039;, ($VALUE / 1000))&amp;quot;,&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Die Angabe von &amp;amp;amp;nbsp; vor &#039;kWh&#039; verhindert die Erkennung der Einheit und so auch die automatische Umsetzung durch das Modul. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 3 - Bereich Verbraucherdarstellung (Consumer Legend) ===&lt;br /&gt;
Dieser Grafikbereich zeigt die im Modul registrierten Verbraucher sowie deren Status und weitere Informationen an. Sind die Voraussetzungen gegeben, d.h. entsprechende Schlüssel in der ConsumerXX-Attributen gesetzt, können die Verbraucher über das Paneel manuell geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Zur Anpassung der Darstellung sind verschiedene Attribute verfügbar:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;consumerControl-&amp;gt;showLegend: Definiert die Lage bzw. Darstellungsweise der Verbraucherlegende sofern Verbraucher im SolarForecast Device registriert sind.&lt;br /&gt;
;consumerControl-&amp;gt;adviceIcon: Definiert die Art der Information über die geplanten Schaltzeiten eines Verbrauchers in der Verbraucherlegende. &lt;br /&gt;
;consumerControl-&amp;gt;detailLink: Wenn gesetzt, ist der jeweilige Verbraucher klickbar um direkt zur Detailansicht des jeweiligen Geräts auf einer neuen Browserseite zu gelangen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Standard wird das Verbraucherpaneel zwischen dem Kopfbereich und der ersten Balkengrafik Ebene dargestellt. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;showLegend&#039;&#039;&#039; und Argument &#039;&#039;&#039;icon_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_bottom&#039;&#039;&#039; kann das Verbraucherpaneel an das Ende des Grafikbereiches verschoben werden.&lt;br /&gt;
Die Verwendung von &#039;&#039;&#039;text_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_top&#039;&#039;&#039; blendet die Icon-Spalte im Verbraucherpaneel aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Screenshot 2025-02-08 093239.png|Darstellung mit consumerControl showLegend=icon_top (default)&lt;br /&gt;
File:Screenshot 2025-02-08 093646.png|Darstellung mit consumerControl showLegend=icon_bottom&lt;br /&gt;
File:Screenshot 2025-02-08 152018.png|Darstellung mit consumerControl showLegend=text_top bzw. text_bottom&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 213634.png|right|thumb|400px|]]&lt;br /&gt;
Ein Mouse-Over über das Uhrensymbol zeigt nähere Informationen zum Status, den Planungsdaten, Modus und weitere Daten des Verbrauchers. Der Schalter &amp;quot;Aus/Ein&amp;quot; visualisiert den Schaltzustand des Verbrauchers und können auch zum manuellen Schalten des Verbrauchers dienen. Voraussetzung ist, dass im consumer-Attribut die Schlüssel &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; mit den Set-Kommandos zum Schalten des Verbrauchers defininiert sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 222210.png|right|thumb|300px|]]&lt;br /&gt;
Der Auto-Schieberegler zeigt einerseits den Freigabestatus zum Schalten des Verbrauchers durch das SolarForecast Modul und kann andererseits manuell betätigt werden. Der Status des Reglers korrespondiert mit dem im zugehörigen Consumer Attribut vorhandenen Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; angegebenen Reading-Wert.&lt;br /&gt;
&lt;br /&gt;
Die Verbraucherbezeichnungen in dem Paneel können in der Standardkonfiguration angeklickt werden um direkt zur Detailansicht des Devices zu gelangen. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;detailLink&#039;&#039;&#039; kann der Link zur Detailansicht deaktiviert werden.&lt;br /&gt;
&lt;br /&gt;
Das Uhrensymbol kann mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;adviceIcon&#039;&#039;&#039; geändert und/oder dessen Farbe angepasst, sowie einen Informationstext statt eines Icons angezeigt werden. &lt;br /&gt;
&lt;br /&gt;
=== 4 - Bereich Balkengrafik (Beam Graphic) ===&lt;br /&gt;
&lt;br /&gt;
Die Balkengrafik des Moduls ist ein wesentliches Visualisierungshilfsmittel. Im Auslieferungszustand existiert eine Balkengrafikebene, die &#039;&#039;&#039;Ebene 1&#039;&#039;&#039;.&lt;br /&gt;
Jede Ebene kann zwei Balkendiagramme mit auswählbaren Inhalten, Farben und einstellbarem LayoutTyp darstellen. In Ebene 1 kann die Wettervorhersage eingebettet oder, bei Vorhandensein von Batteriegeräten, die zukünftigen Zeiten mit empfohlener Ladefreigabe und SoC-Prognose eingeblendet werden. &lt;br /&gt;
&lt;br /&gt;
Welche Daten in welchen Zeiträumen dargestellt werden sollen, die Bestimmung des Layouts, die Gestaltung der Balken und einiges mehr wird durch Attribute gesteuert. Ein Teil dieser Einstellungen wird über das zusammengesetzete Attribut &#039;&#039;&#039;graphicControl-&amp;gt;&#039;Schlüssel&#039;=&#039;Wert&#039;&#039;&#039;&#039; eingestellt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;grundsätzliche Layout Definitionen&#039;&#039;&#039;&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204342.png|right|thumb|400px|Standardanzeige mit Wetter-Icons, gesetzen Attributen graphicBeam1Color=D4C177, graphicHistoryHour=11]]&lt;br /&gt;
&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingTop:Legt den Platz in px im Balkendiagramm fest, der zwischen dem oberen Rand der jeweiligen Balkengrafik Ebene und der ersten Text- oder Iconreihe dieser Ebene eingefügt wird.&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingBottom:Legt den Platz in px im Balkendiagramm fest, der zwischen der letzten Text- oder Iconreihe der jeweiligen Balkengrafik Ebene und dem unteren Rand dieser Ebene eingefügt wird. &lt;br /&gt;
;graphicControl-&amp;gt;layoutType:Layout-Optionen zur grundlegenden Gestaltung der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourStyle:Format der Zeitangabe in der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourCount:Anzahl der darzustellenden Balken/Stunden in der Balkengrafk&lt;br /&gt;
[[Datei:Screenshot Screenshot 2025-05-21 153613.png|right|thumb|400px|Erweiterung des oberen und unteren Abstandes mit den Attributen graphicControl-&amp;gt;beamPaddingTop und graphicControl-&amp;gt;beamPaddingBottom]]&lt;br /&gt;
;graphicControl-&amp;gt;energyUnit:definiert die Einheit zur Anzeige der elektrischen Leistung in der Grafik&lt;br /&gt;
;graphicHistoryHour:Anzahl der vorangegangenen Stunden die in der Balkengrafik dargestellt werden&lt;br /&gt;
;graphicControl-&amp;gt;beamWidth:Vorgabe Breite der Balken der Balkengrafik in px (sonst automatische Bestimmung) &lt;br /&gt;
;graphicBeamHeightLevel1:Multiplikator zur Festlegung der maximalen Balkenhöhe der jeweiligen Ebene (hier Ebene 1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;Definition der Inhalte und Balkeneigenschaften&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204756.png|right|thumb|400px|Wie oben aber mit gesetzem Attribut graphicShowNight=1]]&lt;br /&gt;
;graphicBeam1Color:Farbauswahl des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2Color:Farbauswahl des sekundären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam1Content:Legt den darzustellenden Inhalt des primären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam2Content:Legt den darzustellenden Inhalt des sekundären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam1FontColor:Auswahl der Schriftfarbe des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2FontColor:Auswahl der Schriftfarbe des sekundären Balkens (Ebene 1)&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 205024.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=0 (ohne Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;zusätzliche Optionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;graphicShowNight:Anzeigen oder Verbergen der Nachtstunden in der Balkengrafik&lt;br /&gt;
;graphicShowWeather:Wettericons in der Balkengrafik anzeigen/verbergen (nur Ebene 1)&lt;br /&gt;
;graphicWeatherColor:Farbe der Wetter-Icons für die Tagesstunden&lt;br /&gt;
;graphicWeatherColorNight:Farbe der Wetter-Icons für die Nachtstunden&lt;br /&gt;
;graphicShowDiff:Zusätzliche Anzeige der Differenz &amp;quot;&amp;lt;primärer Balkeninhalt&amp;gt; - &amp;lt;sekundärer Balkeninhalt&amp;gt;&amp;quot; im Kopf- oder Fußbereich der Balkengrafik&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die genaue Beschreibung und deren Optionen sind der aktuellen Online-Hilfe zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Für alle Ebenen gilt:&#039;&#039;&#039; Ein Attribut mit einer ungeraden Balkennummer (z.B. graphicBeam1Content) bezieht sich immer auf den primären Balken, ein Attribut mit einer geraden Balkennummer (z.B. graphicBeam2Content) bezieht sich immer auf den sekundären Balken.&lt;br /&gt;
&lt;br /&gt;
Die Balken haben, wie die meisten Elemente in der Balkengrafik, eine Mouse-Over Eigenschaft welche relevante Informationen zu den dargestellten Werten anzeigt. &lt;br /&gt;
&lt;br /&gt;
Sind die Nachtunden mit &#039;&#039;&#039;graphicShowNight&#039;&#039;&#039; ausgeblendet, werden keine Balken angezeigt sofern es keine Werte anzuzeigen gibt. Sollten dennoch Werte ungleich 0 anzuzeigen sein, werden diese Werte auch trotz ausgeblendeter Nachstunden angezeigt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 2 ====&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 211741.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=01 (mit Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 2&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam3Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam4Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 4 für Balken 4) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wetter-Icons können nur in Ebene 1 integriert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 2 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 2 gibt, eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgende Ebene.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 3 ====&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 3&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam5Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam6Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 5 für Balken 5) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 3 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 3 gibt, ist eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgenden Ebenen, d.h. auch auf die Ebene 3.&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 5 - Die Energieflußgrafik (Flow Graphic) ===&lt;br /&gt;
[[Datei:Screenshot 2025-02-13 213424.png|right|thumb|400px|Energieflußgrafik mit Verbrauchern in der Nachtdarstellung (Mondphasen) nach Sonnenuntergang]]&lt;br /&gt;
&lt;br /&gt;
Die Energieflußgrafik stellt die registrierten Erzeuger, Batterien, Netzzugänge und Verbraucher strukturiert in mehreren Ebenen dar:&lt;br /&gt;
&lt;br /&gt;
;Ebene 1: In der oberen Ebene befinden sich die PV-Generatoren, Smart-Loader sowie sonstigen Erzeuger &lt;br /&gt;
;Ebene 2: Die mittlere Ebene organisiert den Zugang zum öffentlichen Netz, dem Hausknoten, dem Batterieknoten sowie einem Dummy-Verbraucher (Lampensymbol) für den Energieverbrauch des Hauses der keinem der registrierten Verbraucher zugeordnet werden kann.&lt;br /&gt;
;Ebene 3: In der unteren Ebene werden die registrierten Verbraucher dargestellt. Unterhalb der Verbrauchersymbole werden der aktuelle Verbrauch (bzw. der On/Off-Zustand) sowie darunter die Restlaufzeit (Minuten) des Verbrauchers, sofern er durch das Modul geplant und gestartet wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Position und Gestaltung der Grafikelemente ist umfangreich über das Attribut &#039;&#039;&#039;flowGraphicControl&#039;&#039;&#039; und den darin verfügbaren Schlüsseln einstellbar.&lt;br /&gt;
Die Bedeutung der Schlüssel ist in der Online-Hilfe zum Attribut mit einem Beispiel beschrieben. &lt;br /&gt;
&lt;br /&gt;
Darüber hinaus enthalten die Setup-Attribute &#039;&#039;&#039;setupInverterDevXX&#039;&#039;&#039;, &#039;&#039;&#039;setupOtherProducerXX&#039;&#039;&#039; und &#039;&#039;&#039;consumerXX&#039;&#039;&#039; weitere Einstellungsmöglichkeiten um deren Icons und Färbungen in der Flußgrafik individuell einstellen zu können. So sind zum Beispiel die Icons der PV-Inverter und deren Färbung mit dem Schlüssel &#039;&#039;&#039;icon&#039;&#039;&#039; der setupInverterDevXX-Attribute in Abhängigkeit von Tag und Nacht separat definierbar.&lt;br /&gt;
&lt;br /&gt;
In den Verbraucher-Attributen ist mit dem Schlüssel &#039;&#039;&#039;noshow&#039;&#039;&#039; die Sichtbarkeit in der Flußgrafik definierbar.&lt;br /&gt;
&lt;br /&gt;
Generell steuert das Attribut &#039;&#039;&#039;graphicSelect&#039;&#039;&#039; die Ein- bzw. Ausblendung der gesamten Flußgrafik.&lt;br /&gt;
&lt;br /&gt;
== Die Verbrauchsprognose ==&lt;br /&gt;
Im Gegensatz zu der PV Prognose gibt es keine API oder andere externen Datenquellen die für die Verbrauchsprognose herangezogen werden könnten.&lt;br /&gt;
&lt;br /&gt;
Zum Zweck der Verbrauchsermittlung verwendet das Modul die Meterdaten aus dem Attribut &#039;&#039;setupMeterDev&#039;&#039; sowie den weiteren setup-Attributen &#039;&#039;setupInverterDevXX&#039;&#039;. &lt;br /&gt;
Sind auch andere Erzeuger (BHKW, Windanlagen, etc.) bzw. eine Batterie vorhanden, sind ebenfalls die Attribute &#039;&#039;setupOtherProducerXX&#039;&#039; bzw. &#039;&#039;setupBatteryDev&#039;&#039; für die Berechnung des Hausverbrauchs relevant. In diesen Attributen gibt es die Schlüssel &#039;&#039;*total&#039;&#039; die teilweise optional sind. Für die Verbrauchsprognose bilden sie jedoch die Berechnungsgrundlage und sind deswegen für diese Funktionalität wichtig anzugeben.&lt;br /&gt;
&lt;br /&gt;
Die Verbrauchswerte werden stundengenau erfasst und im Datenspeicher &#039;&#039;pvHistory&#039;&#039; für 31 Tage, sowie im Datenspeicher &#039;&#039;pvCircular&#039;&#039; 210 Tage gespeichert. Die beiden Datenspeicher übernehmen unterschiedliche Aufgaben im Rahmen der Prognoseerstellung. Auf Grundlage der gespeicherten und somit historischen Verbrauchswerte erstellt das Modul eine Prognose für die kommende Zeit.&lt;br /&gt;
&lt;br /&gt;
Mit dem Kommando &lt;br /&gt;
&lt;br /&gt;
   &amp;quot;get ... pvHistory [Tag]&amp;quot; &lt;br /&gt;
&lt;br /&gt;
wird der Inhalt aufgelistet. Die Schlüssel &#039;&#039;confc&#039;&#039;, &#039;&#039;con&#039;&#039; und &#039;&#039;gcon&#039;&#039; zeigen die Verbrauchsprognose, den Verbrauch und den Netzbezug der jeweiligen Stunde des gewählten Tages.&lt;br /&gt;
Die Stunde &amp;quot;99&amp;quot; zeigt die Summen dieser Schlüsssel für den Tag:&lt;br /&gt;
&lt;br /&gt;
      99 =&amp;gt; etotal: , pvfc: 782, pvrl: 0, rad1h: -&lt;br /&gt;
            confc: 14540, con: 13873, gcon: 13873, gfeedin: 0&lt;br /&gt;
            batintotal: , batin: 0, batouttotal: , batout: 0&lt;br /&gt;
            batmaxsoc: -, batsetsoc: -&lt;br /&gt;
            wid: , wcc: , wrp: , pvcorrf: , dayname: So&lt;br /&gt;
            cyclescsm01: 0&lt;br /&gt;
            cyclescsm02: 0&lt;br /&gt;
            cyclescsm03: 0&lt;br /&gt;
            cyclescsm04: 1, hourscsme04: 0.00&lt;br /&gt;
            cyclescsm05: 0&lt;br /&gt;
            cyclescsm06: 0&lt;br /&gt;
            cyclescsm07: 1, hourscsme07: 0.00&lt;br /&gt;
            cyclescsm08: 1, hourscsme08: 0.00&lt;br /&gt;
            cyclescsm09: 1, hourscsme09: 0.03 &lt;br /&gt;
&lt;br /&gt;
In dem Beispiel wurden für den Tag 14540 Wh Verbrauch prognostiziert, 13873 Wh tatsächlich verbraucht und davon 13873 Wh aus dem Netz bezogen. Leider war an diesem Tag keinerlei PV Ertrag vorhanden, was man auch an dem Schlüssel &#039;&#039;pvrl&#039;&#039; erkennen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Inhalt des pvCircular-Speichers kann mit dem Befehl  &lt;br /&gt;
&lt;br /&gt;
     &amp;quot;get ... pvCircular [Tag]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Das nachfolgende Beispiel zeigt die Ausgabe für die Tagesstunde 23:&lt;br /&gt;
&lt;br /&gt;
 23 =&amp;gt; pvapifc: 0, pvaifc: -, pvfc: 0, aihit: 0, pvrl: 0&lt;br /&gt;
       batin01: 0, batin02: -, batin03: -&lt;br /&gt;
       batout01: 619, batout02: -, batout03: -&lt;br /&gt;
       confc: 650, gcon: 23, gfeedin: 0, wcc: 40, rr1c: 0.00&lt;br /&gt;
       temp: -6.00, wid: 100, wtxt: Bewölkungsentwicklung nicht beobachtet&lt;br /&gt;
       pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
       ... &lt;br /&gt;
       con_all =&amp;gt; Sa  @ 617 762&lt;br /&gt;
                  Di  @ 693 645&lt;br /&gt;
                  Mo  @ 620 679&lt;br /&gt;
                  So  @ 669 666 636&lt;br /&gt;
                  Mi  @ 701 626&lt;br /&gt;
                  Do  @ 612 642&lt;br /&gt;
                  Fr  @ 615 606&lt;br /&gt;
&lt;br /&gt;
Der Schüssel &#039;&#039;con_all&#039;&#039; enthält einen Hash aus Arrays die für jeden Wochentag (Mo..So) bis zu 30 Verbrauchswerte (in Wh) für die angezeigte Stunde speichern. Wie hier erkennbar ist, wurden an den drei vergangenen Sonntagen jweils 669 Wh, 666 Wh bzw. 636 Wh in der Stunde 23 (22:00-22:59) verbraucht.&lt;br /&gt;
Der Median aus diesen Werten geht in die Verbrauchsprognose ein. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wochentagsnamen Mo..So sind von den installierten Locales auf Betriebsystemebene abhängig. Ist keine deutsche locale installiert, werden die englischen Wochentagsnamen Mon..Sun verwendet. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Wie wird der Verbrauch des Hauses ermittelt und gespeichert? ===&lt;br /&gt;
Die Verbrauchsdaten des Hauses werden auf Stundenbasis ermittelt und gespeichert. Das &amp;quot;Haus&amp;quot; steht als Synonym aller im Kontext des Solarforecast Devices zusammengeführten Inverter (setupInverterDevXX), sonstigen Erzeuger (setupOtherProducerXX), Netzanschlüsse (setupMeterDev), Verbraucher (consumerXX) und Batterien (setupBatteryDev).&lt;br /&gt;
&lt;br /&gt;
Alle diese Daten werden durch das Modul mit jedem ausgeführten Zyklus (Attribut plantControl-&amp;gt;cycleInterval) und, wenn ein Event eines als &#039;asynchron&#039; definierten Devices auftritt, gesammelt und daraus permanent ein aktualisierter Verbrauch berechnet. Die Berechnung beschreibt folgende Formel:&lt;br /&gt;
&lt;br /&gt;
 PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung - Verbrauch = 0&lt;br /&gt;
&lt;br /&gt;
bzw.&lt;br /&gt;
 &lt;br /&gt;
 Verbrauch (Wh) = PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung&lt;br /&gt;
            con = PV           + PP                 - GridIn          + GridCon   - BatIn          + BatOut&lt;br /&gt;
&lt;br /&gt;
Die PV-Erzeugung beinhaltet die Summe aller durch die angegebnen Inverter (setupInverterDev01 .. setupInverterDevXX) erzeugten Energien. Die &amp;quot;sonstige Erzeugung&amp;quot; summiert sich aus den Werten aller angegebenen Producer (setupOtherProducer01 .. setupOtherProducerXX). Der Verbrauch wird durch die registrierten Geräte consumerXX teilweise direkt erfasst, ist aber grundsätzlich unvollständig da nicht alle Verbrauchswerte im &amp;quot;Haus&amp;quot; gemessen und durch das Modul erfasst werden können.&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel zeigt das Ergebnis bei 300 Wh PV-Erzeugung und gleichzeitige 500 Wh Netzbezug:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 300 + 0 - 0 + 500 - 0 + 0 = 800 Wh&lt;br /&gt;
&lt;br /&gt;
Bei 1300Wh PV-Erzeugung, 100 Wh Netzeinspeisung sowie 200 Wh Batterieladung ergibt sich der Verbrauch zu:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 1300 + 0 - 100 + 0 - 200 + 0 = 1000 Wh&lt;br /&gt;
&lt;br /&gt;
Ohne Erzeugung, aber mit der Energielieferung von 500 Wh aus der Batterie, 800 Wh Netzbezug (mit einem Anteil Batterienachladung aus dem Netz von 200 Wh) sieht die Verbrauchsrechnung wie folgt aus: &lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 0 + 0 - 0 + 800 - 200 + 500 = 1100 Wh&lt;br /&gt;
&lt;br /&gt;
Der so ermittelte Verbrauchsert wird mit jedem Zyklus in der pvHistory im Schlüssel &amp;quot;con&amp;quot; gespeichert. Man kann sich die gespeicherten Werte mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;name&amp;gt; pvHistory [&amp;lt;Tag&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Nachfolgendes Beispiel zeigt einen Datensatz für die Stunde 8 eines Tages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      08 =&amp;gt; pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotali01: 62940734, etotali02: 2928860, etotali03: -&lt;br /&gt;
            pvrl01: 0, pvrl02: 0, pvrl03: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 630, con: 962, gcons: 962, conprice: 0.2958&lt;br /&gt;
            gfeedin: 0, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 120, sunalt: -3&lt;br /&gt;
            batintotal: 3713815.07742543, batouttotal: 3604468.26993988, batin: 0, batout: 0&lt;br /&gt;
            wid: 161, wcc: 89, rr1c: 0.00, pvcorrf: 0.27/0.00 temp: 7.40, &lt;br /&gt;
            csmt01: 110996.12, csme01: 32.1399999999994, minutescsm01: 30&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 2513.67, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1581293.6, csme04: 136.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 1662.17, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 90.53, csme06: 0, minutescsm06: 0&lt;br /&gt;
            csmt07: 39.75, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 38050, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 131627, csme09: 33.2000000000116, minutescsm09: 39&lt;br /&gt;
            minutescsm10: 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Schlüssel &amp;quot;con&amp;quot; ist der gespeicherte Verbrauch von 962 Wh ersichtlich.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit bekommt man mit dem Attribut &#039;&#039;ctrlDebug=collectData&#039;&#039; einen Einblick in die Verbrauchsermittlung bei jedem Zyklus und kann so die Eingangswerte und das daraus resultierende Ergebnis im FHEM Log nachverfolgen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
2024.11.28 11:38:20.080 1: SolCast DEBUG&amp;gt; EnergyConsumption input -&amp;gt; PV: 96, PP: 0, GridIn: 0, GridCon: 582, BatIn: 5, BatOut: 0&lt;br /&gt;
2024.11.28 11:38:20.081 1: SolCast DEBUG&amp;gt; EnergyConsumption result -&amp;gt; 673 Wh&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie wird die Verbrauchsprognose erstellt? ===&lt;br /&gt;
&lt;br /&gt;
Aus den gespeicherten con-Werten (Verbrauchsdaten) der pvCircular (Schlüssel con_all) sowie Einträgen der pvHistory wird der Median der historischen Tage ermittelt und für den kommenden Tag bzw. die kommen Stunden zur Prognose angewendet. Dabei geht per default jeder verfügbare historische Tag gleichberechtigt in die Prognose ein. Mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039; kann festgelegt werden, dass nur gleiche Wochentage (Mo..So) für die Prognose verwendet werden. Hierbei spielt die Vermutung, dass das Verbrauchsverhalten eine gewisse Korrelation zum Wochentag hat, eine Rolle. &lt;br /&gt;
&lt;br /&gt;
Verwendet man die Einstellung consForecastIdentWeekdays=1, hat es sich als vorteilhaft erwiesen, das Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays&#039;&#039;&#039; auf einen niedrigeren Wert als den Default zu setzen. Eine Einstellung auf &#039;8&#039; zum Beispiel verwendet den Median der gleichen Wochentage der vergangenenen 8 Wochen. Dadurch wird nicht zu weit in die Vergangenheit verzweigt und so eine langsame Veränderung des Verbrauchsmedian, zum Beispiel hervorgerufen durch den Übergang vom Winter in das Frühjahr hinein, abgebildet.&lt;br /&gt;
&lt;br /&gt;
Weiteren Einfluß auf die Verbrauchsprognose kann mit dem Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; im Consumerattribut genommen werden. Insbesondere bei der unregelmäßigen Nutzung von Verbrauchern mit hoher Leistung kann die Projektion der aufgezeichneten historischen Werte in die Prognose zu unverhältnismäßig hohen Verbrauchswerwartunden führen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Möglicherweise führt in Fällen die Verwendung eine der nachfolgenden Optionen zu einem besseren Ergebnis:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;1 -&#039;&#039;&#039; die allgemeine Verbrauchsprognose wird um die gespeicherten Energieverbrauchsanteile reduziert.&lt;br /&gt;
* &#039;&#039;&#039;2 -&#039;&#039;&#039; wie bei &#039;1&#039;, jedoch gehen die Planungsdaten des Verbrauchers bei der Prognose der kommenden Stunden wieder mit ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;&#039;exconfc&#039;&#039;&#039; in einem der Consumer verwendet, sollte&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays=4&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
eingestellt werden. Hintergrund ist, dass die Verbrauchsanteile der jeweiligen Verbraucher nur maximal 31 Tage in der pvHistory verfügbar sind. Für längere Zeiträume stehen nur Gesamtsummen des Verbrauchs in der pvCircular zu Verfügung.  &lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=1&#039;&#039;&#039; werden die in der Historie aufgezeichneten Verbrauchsbestandteile aus einer Prognose herausgerechnet. Konkret werden die in der pvHistory aufgezeichneten Verbrauchsbestandteile für die relevante Stunde ermittelt und daraus ein Durchschnitt gebildet der vom Prognosewert subtrahiert wird. Mit dem Attributwert plantControl-&amp;gt;consForecastIdentWeekdays=1 werden wiederum nur identische Wochentage (Mo .. So) zusammengefasst.&lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=2&#039;&#039;&#039; erfolgt ebenso die Eliminierung des Verbrauchsanteils, es wird jedoch auf die Planungsdaten für diesen Verbraucher zugegriffen und die geplanten Energieanteile wiederum der Verbrauchsprognose für die kommenden Stunden hinzugerechnet.&lt;br /&gt;
&lt;br /&gt;
In beiden Anwendungsfällen ist es notwendig, dass dem Modul durch die Angabe entsprechender Readings der Energieverbrauch im Setup des Consumers bekannt gemacht wird damit diese Energieanteile registriert werden können. Allgemein funktioniert die Verbrauchsprognose gut wenn Verbrauchsprozesse regelmäßig in einem wiederkehrenden Zeitraster ablaufen, der Verbrauch durch persönliche Rituale bestimmt ist. So zum Beispiel könnte am Dienstag und Samstag gewöhnlich die Waschmaschine laufen, das E-Auto täglich aufgeladen werden und gebügelt wird oft am Sonntag Nachmittag.&lt;br /&gt;
&lt;br /&gt;
Unregelmäßige Nutzung, vor allem vom Großverbrauchern, lässt sich nur sehr schwer und ungenügend auf zukünftige Verbrauchsprognosen projizieren.&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis der Prognose wird im Kopf der Grafik in der Zeile &#039;&#039;Verbrauch&#039;&#039; sowie in diversen Readings wie &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RestOfDayConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den Rest des Tages)&lt;br /&gt;
* &#039;&#039;&#039;NextHours_Sum04_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für die nächsten 4 Stunden)&lt;br /&gt;
* &#039;&#039;&#039;Tomorrow_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den kommenden Tag)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
angezeigt.&lt;br /&gt;
&lt;br /&gt;
Weitere Aggregationen kann man sich über das Attribut &#039;&#039;&#039;ctrlStatisticReadings&#039;&#039;&#039; bei Bedarf zuschalten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;conForecastTillNextSunrise&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
* &#039;&#039;&#039;todayConForecastTillSunset&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
* &#039;&#039;&#039;todayConsumptionForecast&#039;&#039;&#039; - Verbrauchsprognose aufgesplittet pro Stunde des aktuellen Tages (01-24) &lt;br /&gt;
 &lt;br /&gt;
==== Debugging der Verbrauchsprognose ====&lt;br /&gt;
Um sich einen Einblick über die Erstellung der Verbrauchsprognose zu verschaffen, bietet sich die Einschaltung von:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
an. Mit diesem gesetzten Attribut wird die Erstellung der Prognose im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; ################### Start Consumption forecast ###################&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; Basics - installed locale: de_DE.UTF-8, used scheme: DE&lt;br /&gt;
2025.02.27 19:52:00.064 1: SolCast DEBUG&amp;gt; process Today dayname: Do, Tomorrow dayname: Fr&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 01 - 74.43 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 10 - 290.77 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 24 - 660.70 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 20, hod: 07 - 459.93 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;07&#039; register for exclude day 20, hod: 02 - 0.33 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 30, hod: 08 - 264.78 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next Hours (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; excl. hist 74 Wh for Hour 01, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; estimated cons of Hour 01: 436 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; excl. hist 0 Wh for Hour 02, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 02: 428 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 03: 458 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 04: 503 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 05: 489 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 06: 482 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; excl. hist 460 Wh for Hour 07, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 07: 274 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 265 Wh for Hour 08, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 08: 441 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 09: 558 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 291 Wh for Hour 10, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 10: 443 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 11: 881 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 12: 794 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 13: 840 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 14: 660 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 15: 812 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 16: 752 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 17: 597 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 18: 652 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 19: 634 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 20: 628 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 21: 713 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 22: 596 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 23: 629 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; excl. hist 661 Wh for Hour 24, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons of Hour 24: 660 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons Tomorrow: 16848 Wh, Individual hourly values considered: 72, exclude: 0 Wh (avg of 0 entities)&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Store Consumption forecast values (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour00&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;20&#039; confc: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour01&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;21&#039; confc: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour02&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;22&#039; confc: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour03&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;23&#039; confc: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store &#039;NextHour04&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;24&#039; confc: 660&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour05&#039; hod &#039;01&#039; confc: 436, confcEx: 436&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour06&#039; hod &#039;02&#039; confc: 428, confcEx: 428&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour07&#039; hod &#039;03&#039; confc: 458, confcEx: 458&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour08&#039; hod &#039;04&#039; confc: 503, confcEx: 503&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour09&#039; hod &#039;05&#039; confc: 489, confcEx: 489&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour10&#039; hod &#039;06&#039; confc: 482, confcEx: 482&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour11&#039; hod &#039;07&#039; confc: 274, confcEx: 274&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour12&#039; hod &#039;08&#039; confc: 441, confcEx: 441&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour13&#039; hod &#039;09&#039; confc: 558, confcEx: 558&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour14&#039; hod &#039;10&#039; confc: 443, confcEx: 443&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour15&#039; hod &#039;11&#039; confc: 881, confcEx: 881&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour16&#039; hod &#039;12&#039; confc: 794, confcEx: 794&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour17&#039; hod &#039;13&#039; confc: 840, confcEx: 840&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour18&#039; hod &#039;14&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour19&#039; hod &#039;15&#039; confc: 812, confcEx: 812&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour20&#039; hod &#039;16&#039; confc: 752, confcEx: 752&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour21&#039; hod &#039;17&#039; confc: 597, confcEx: 597&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour22&#039; hod &#039;18&#039; confc: 652, confcEx: 652&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour23&#039; hod &#039;19&#039; confc: 634, confcEx: 634&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour24&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour25&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour26&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour27&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour28&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; consumption calculated - day: 27, hod: 20, con: 574 Wh&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; write pvCircular consumption - hod: 99, todayConsumption: 11210 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe startet mit &#039;&#039;&amp;quot;Start Consumption forecast&#039;&#039;&amp;quot;, es werden die zu exkludierenden historischen Daten für jeden Consumer bzgl. jedem Tag (day) und Stunde des Tages (hod) getrennt registriert. Diese Werte werden durch die gespeicherte Einträge in der pvHistory (max. 31 historische Tage) geliefert. &lt;br /&gt;
&lt;br /&gt;
Im nächsten Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next Hours (new median)&amp;quot;&#039;&#039; werden die Prognosen für die nächsten Stunden kalkuliert und die zuvor registrierten Excludes angewendet. Die Prognose für den kommenden Tag ist im Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next day (new median)&amp;quot;&#039;&#039; protokolliert. Die Prognose für den kommenden Tag ist nicht einfach die Summe der Prognose der nächsten Stunden, denn in den kommenden Stunden werden auch die verfügbaren Planungen der Consumer einbezogen. Für den kommenden Tag können diese Werte unter Umständen nicht einbezogen werden da sie zum Zeitpunkt X noch nicht verfügbar sind.&lt;br /&gt;
&lt;br /&gt;
Im Abschnitt &#039;&#039;&amp;quot;Store Consumption forecast values (new median)&amp;quot;&#039;&#039; erscheinen die effektiv gespeicherten Werte. Diese sind die Grandlage für die grafische Darstellung sowie weiteren Kalkulationen.&lt;br /&gt;
&lt;br /&gt;
=== Wie kann eine fehlerhafte Verbrauchsprognose korrigiert werden? ===&lt;br /&gt;
Wie im vorherigen Abschnitt beschrieben, wird die Prognose aus den gespeicherten &amp;quot;con&amp;quot;-Werten der vergangenen Tage (bzw. Stunden) abgeleitet. &lt;br /&gt;
Grundsätzlich muß zunächst sichergestellt werden, dass die auszulesenden Readings der angegebenen Energiezähler sowie deren Einheiten! korrekt eingestellt sind. Das gilt ebenfalls für die registrierten Verbraucher im Modul.&lt;br /&gt;
&lt;br /&gt;
Für einen ersten Überblick bietet sich das Debug Attribut an zu setzen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
Beispielausgabe des Debug:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2024.09.21 13:28:27.041 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day ###################&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;01&amp;lt; considering possible exclusions: 14082&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;08&amp;lt; considering possible exclusions: 16446&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;15&amp;lt; considering possible exclusions: 14568&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;25&amp;lt; considering possible exclusions: 15522&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; estimated Consumption for tomorrow: 15154, days for avg: 4&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next hours ###################&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 14 -&amp;gt; 850 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 14 -&amp;gt; 643 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 14 -&amp;gt; 590 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 14 -&amp;gt; 522 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 13:00:00, confc: 651, days for avg: 4, hist. consumption registered consumers: 560.97&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 15 -&amp;gt; 720 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 15 -&amp;gt; 743 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 15 -&amp;gt; 897 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 15 -&amp;gt; 557 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 14:00:00, confc: 729, days for avg: 4, hist. consumption registered consumers: 620.97&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 16 -&amp;gt; 676 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 16 -&amp;gt; 790 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 16 -&amp;gt; 785 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 16 -&amp;gt; 581 Wh&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 15:00:00, confc: 708, days for avg: 4, hist. consumption registered consumers: 647.29&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 17 -&amp;gt; 622 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 17 -&amp;gt; 639 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 17 -&amp;gt; 646 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 17 -&amp;gt; 572 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 16:00:00, confc: 619, days for avg: 4, hist. consumption registered consumers: 618.30&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 18 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 18 -&amp;gt; 614 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 18 -&amp;gt; 580 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 18 -&amp;gt; 480 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 17:00:00, confc: 567, days for avg: 4, hist. consumption registered consumers: 583.41&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 19 -&amp;gt; 615 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 19 -&amp;gt; 1659 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 19 -&amp;gt; 597 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 19 -&amp;gt; 618 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 18:00:00, confc: 872, days for avg: 4, hist. consumption registered consumers: 636.97&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 20 -&amp;gt; 611 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 20 -&amp;gt; 1124 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 20 -&amp;gt; 546 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 20 -&amp;gt; 479 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 19:00:00, confc: 690, days for avg: 4, hist. consumption registered consumers: 578.87&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 21 -&amp;gt; 1474 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 21 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 21 -&amp;gt; 619 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 21 -&amp;gt; 433 Wh&lt;br /&gt;
2024.09.21 13:28:27.058 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Im ersten Teil wird die erwartete Consumption für den nächsten Tag unter Berücksichtigung möglicher Ausschlüsse von Verbrauchern ausgegeben. Ausschlüsse von Verbrauchern ergeben sich wenn in dem Verbraucherattribut der Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; gesetzt ist. Er besagt, dass die Verbrauchswerte des Verbrauchers in eine zukünftige Prognose nicht eingehen sollen. Zum Beispiel wenn ein Verbraucher mit sehr hohen Verbrauchswerten nur sporadisch eingesetzt wird und dadurch die Prognose stark verfälschen würde. Es ist auch zu sehen, dass bedingt durch das Attribut &#039;&#039;&#039;affectConsForecastIdentWeekdays = 1&#039;&#039;&#039; nur die historischen Tage 01, 08, 15 und 25 berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Teil wird die berechnete Erwartung für die nächsten Stunden ausgegeben. &lt;br /&gt;
Zur Beschreibung der Fehlersuche gehen wir davon aus, dass die Prognose von 780 Wh am 2024-09-21 20:00:00 zu hoch erscheint weil am Tag &amp;quot;07&amp;quot; ein Wert von 1474 Wh gespeichert ist:&lt;br /&gt;
&lt;br /&gt;
 SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt geben wir die historischen Werte für den Tag 07 aus:&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;Name&amp;gt; pvHistory 07&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz interessiert die Stunde 21. Sie resultiert aus der obigen Angabe &amp;quot;starttime: xxxx-xx-xx 20:00:00&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      21 =&amp;gt; etotal: 64354660, pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 496, con: 1474, gcons: 23, conprice: 0.2958&lt;br /&gt;
            gfeedin: 5, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 289, sunalt: -8&lt;br /&gt;
            batintotal: 3064096.92456668, batouttotal: 2958021.37946804, batin: 0, batout: 1460&lt;br /&gt;
            wid: 101, wcc: 20, rr1c: 0.00, pvcorrf: 1.00/-temp: 26.00, &lt;br /&gt;
            csmt01: 64262.43, csme01: 28.8099999999977, minutescsm01: 25&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 0, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1389417.4, csme04: 94.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 0, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 290.15, csme06: 6.66999999999996, minutescsm06: 54&lt;br /&gt;
            csmt07: 0, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 32800, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 103987.8, csme09: 38, minutescsm09: 43&lt;br /&gt;
            csmt10: 9151.24999999783, csme10: 3.99999999997999, minutescsm10: 60&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz sind die Energieverbrauchsanteile der im Device registrierten Verbraucher mit dem Schlüssel &amp;quot;csmeXX&amp;quot; gespeichert. Dabei ist &amp;quot;XX&amp;quot; die Verbrauchernummer. In dem Beispiel existieren die Anteile csme01 und csme03 - csme10. Keiner dieser Verbraucher hat einen auffälligen Verbrauchswert gespeichert, d.h. die Messung der Verbraucher scheidet als Problemquelle aus. Wäre ein unverhältmismäßig hoher Verbrauch bei einem der Verbraucher feststellbar, müssten die Schlüssel &#039;&#039;&#039;pcurr&#039;&#039;&#039; und &#039;&#039;&#039;etotal&#039;&#039;&#039; im consumerXX-Attribut geprüft, sowie die Datenlieferung des Consumerdevices selbst geprüft werden.  &lt;br /&gt;
&lt;br /&gt;
Es wurde offensichtlich ein hoher Verbrauch von einem nicht registrierten Verbraucher verursacht oder durch die Übertragung eines Meßfehlers des Devices, angegeben im Attribut &#039;&#039;&#039;setupMeterDev&#039;&#039;&#039;, in das SolarForecast Device übertragen. Eine weitere Analyse ist an dieser Stelle nicht möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Behebung des falschen Wertes kann ein Reset der gespeicherten Consumption der relevanten Stunde durchgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; reset consumptionHistory 07 21&lt;br /&gt;
&lt;br /&gt;
== Modulinterne Datenstrukturen ==&lt;br /&gt;
Das Modul speichert die verschiedenen historischen und aktuellen Daten wie PV-Prognose, Witterungsdaten (Regen, Bewölkung), Strahlungsdaten, Einspeisung, Bezug, reale Erzeugungsdaten und vieles mehr zur Laufzeit im Arbeitsspeicher. Dadurch ist die Verarbeitung dieser Daten im Vergleich zu Lesevorgängen aus dem Filesystem bzw. einer Datenbank sehr performant. Allerdings würden diese Daten bei einem FHEM Absturz bzw. bei einem regulären Shutdown verlorengehen.&lt;br /&gt;
&lt;br /&gt;
Deswegen werden die relevanten Daten regelmäßig in Dateien gesichert und bei Bedarf wiederhergestellt. Diese Dateien befinden sich im Verzeichnis &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; und heißen &#039;&#039;&#039;.*_SolarForecast_.*&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Die Daten werden in jedem Zyklus der Zentralschleife (CentralTask) gesammelt bzw. berechnet. Der Zyklus wird mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;cycleInterval&#039;&#039;&#039; eingestellt.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit können diese Daten über get-Kommandos abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvHistory [Tag]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der pvHistory Datenspeicher enthält die vergangenen Kennwerte der letzten 31 Tage mit einer Genauigkeit von einer Stunde. Es werden die Prognosewerte für Erzeugung und Verbrauch, die realen Werte für Erzeugung und Verbrauch sowie ebenso die Laufzeiten jedes einzelnen Verbrauchers (Consumer) festgehalten. Für jeden Tag gibt es die Stunde &amp;quot;99&amp;quot; die eine Summierung der Stundenwerte des Tages bzw. Sonderschlüssel enthält.&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf lässt sich mit dem Befehl &amp;quot;set ... reset pvHistory&amp;quot; der gesamte Inhalt des Speichers löschen (nicht empfohlen). Selektiver funktioniert die Datenlöschung mit &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt;&amp;quot; (Daten eines bestimmten Tages löschen) bzw. &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt; &amp;lt;Stunde&amp;gt;&amp;quot; (Daten der Stunde  eines bestimmten Tages löschen). Die letzten beiden Kommandos müssen über die Kommandozeile im Browser ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvCircular &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Ringspeicher enthält Daten der letzten 24 Stunden sowie fortwährend berechnete Werte wie Korrekturfaktoren der PV-Erzeugung und Prognosequalität.&lt;br /&gt;
Neue Stundenwerte des Tages überschreiben die gespeicherten Schüssel des vorangegangenen Tages sofern es sich nicht um fortwährend berechnete Werte handelt. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... nextHours&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Speicher enthält sämtliche Prognosewerte der kommenden Stunden beginnend mit der aktuellen Stunde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... radiationApiData&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Abhängig von der ausgewählten Strahlungsdaten API enthält dieser Speicher die von der API gelieferten Rohdaten sowie evtl. weitere für die Funktion benötigte Daten wie API-Keys, Response Messages, Anzahl der API Abruf und weitere.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valCurrent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Struktur wird nicht regelmäßig im Filesystem gespeichert und enthält immer aktuell gesammelte oder berechnete/gelieferte Daten wie z.B. die Autarkierate, letze Laufzeit der Zentralschleife (CentralTask), Zeit des Sonnenauf- und untergangs sowie weitere Betriebsdaten. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valConsumerMaster [XX]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zeigt die Daten der aktuell im SolarForecast Device registrierten Verbraucher. Mit der Nummer &#039;&#039;&#039;XX&#039;&#039;&#039; kann ein bestimmter Verbraucher angesprungen werden. Die Nummer korrespondiert mit dem entsprechenden &#039;&#039;&#039;consumerXX&#039;&#039;&#039; Attribut.&lt;br /&gt;
Neben anderen Betriebs- und Energiedaten werden insbesondere folgende Daten ermittelt, die für die zukünftige Planung der Verbraucherschaltzeiten relevant sind:&lt;br /&gt;
&lt;br /&gt;
* epieces - prognostizierte Energiescheiben pro Betriebsstunde &lt;br /&gt;
&lt;br /&gt;
Ausgehend von gespeicherten historischen Verbrauchsdaten des Verbrauchers wird der Energieverbrauch des Verbrauchers in seiner ersten Betriebsstunde prognostiziert, was insbesondere für die Planung der optimalen Startzeit des Verbrauchers in Bezug zu der prognostizierten PV Energie und den Verbrauchswerten weiterer vorhandener bzw. zu planender Verbraucher Berücksichtigung findet. Weitere Informationen zur Verbrauchersteuerung in diesem  [[#Verbrauchersteuerung_-_Registrieren_und_visualisieren_von_Verbrauchern|Abschnitt]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Schnittstelle für Modulautoren bzw. eigenen Code ===&lt;br /&gt;
&lt;br /&gt;
Die im vorherigen Artikel beschriebenen internen Datenstrukturen können durch externen Code abgefragt und ausgewertet werden.&lt;br /&gt;
Dazu stehen die folgenden Funktionen zur Verfügung. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]BatteryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Bn&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valBattery&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CurrentVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valCurrent&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]InverterVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valInverter&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ProducerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valProducer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]HistoryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Day&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvHistory&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CircularVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvCircular&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]NexthoursVal (&#039;&amp;lt;Name&amp;gt;&#039;, &amp;lt;nhr&amp;gt;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... nextHours&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ConsumerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valConsumerMaster&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]RadiationAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;DateTime&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... radiationApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]WeatherAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;TimeCode&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... weatherApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StatusAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;QTag&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... statusApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StringVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valStrings&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Angabe des Packages (FHEM::SolarForecast::) ist nur notwendig wenn die Funktionen von außerhalb des SolarForecast-Devices aufgerufen werden. Innerhalb des Devices (Code-Ausführung im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039;) kann darauf verzichtet werden.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der Platzhalter sind:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     &amp;lt;Name&amp;gt;     - Name des SolarForecast Devices&lt;br /&gt;
     &amp;lt;Day&amp;gt;      - abzufragender Tag (01 - 31)&lt;br /&gt;
     &amp;lt;Bn&amp;gt;       - Batterie Nummer (01, 02, ...)&lt;br /&gt;
     &amp;lt;DateTime&amp;gt; - Startzeit der Form YYYY-MM-DD hh:00:00&lt;br /&gt;
     &amp;lt;TimeCode&amp;gt; - Zeitwert der Form fcX_XX (z.B. fc1_19)&lt;br /&gt;
     &amp;lt;APIname&amp;gt;  - Hauptname der API gemäß setupWeatherDev1 (z.B. OpenMeteo)&lt;br /&gt;
     &amp;lt;String&amp;gt;   - Name des PV-Modulstrings wie im Attribut &#039;setupInverterStrings&#039;&lt;br /&gt;
     &amp;lt;QTag&amp;gt;     - Question Tag, z.B. &#039;?All&#039;&lt;br /&gt;
     &amp;lt;Nr&amp;gt;       - laufende Nummer des Verbrauchers / Gerätes (01, 02, 03, 04,...)&lt;br /&gt;
     &amp;lt;HoD&amp;gt;      - abzufragende Stunde (01 - 24, 99)&lt;br /&gt;
     &amp;lt;nhr&amp;gt;      - nächste Stunde (NextHour00, NextHour01,...)&lt;br /&gt;
     &amp;lt;Key&amp;gt;      - der abzufragende Schlüssel &lt;br /&gt;
     &amp;lt;default&amp;gt;  - def default-Rückgabewert&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Auswerten von internen Arrays ===&lt;br /&gt;
&lt;br /&gt;
Die meisten der internen Datenstrukturen liefern bei der Abfrage einen einfachen String oder numerischen Wert der ausgewertet werden kann. Es gibt allerdings auch intern gespeicherte Wertelisten. Werden die Listenstrukturen mit den oben beschriebenen Befehlen abgefragt, wird eine Referenz auf die Liste geliefert sofern sie vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
Um auf die Werte einer solchen Liste zuzugreifen, ist am Beispiel des Arrays &#039;&#039;surplusslidereg&#039;&#039; aus dem Current-Speicher (get ... valCurrent) dargestellt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
my $splref = CurrentVal ($name, &#039;surplusslidereg&#039;, &#039;.&#039;);&lt;br /&gt;
my $spser  = ref $splref eq &#039;ARRAY&#039; ? join &#039; &#039;, @{$splref} : undef;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Variable $spser enthält bei Vorhandensein der Liste einen String, der die Listenelemente von &#039;surplusslidereg&#039; durch Leerzeichen getrennt enthält.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backup und Wiederherstellung der Moduldaten ==&lt;br /&gt;
Neben der Datenhaltung in den Attributen und Readings des SolarForecast Devices, erzeugt jedes SolarForecast Device Dateien im Verzeichnis  &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; mit folgenden Inhalten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PVH_SolarForecast_&amp;lt;name&amp;gt;        - PV History&lt;br /&gt;
PVC_SolarForecast_&amp;lt;name&amp;gt;        - PV Circular&lt;br /&gt;
PVCfg_SolarForecast_&amp;lt;name&amp;gt;      - PV Anlagenkonfiguration&lt;br /&gt;
PVCsm_SolarForecast_&amp;lt;name&amp;gt;      - Consumer Status&lt;br /&gt;
ScApi_SolarForecast_&amp;lt;name&amp;gt;      - Strahlungswerte aus verwendeter API&lt;br /&gt;
StatApi_SolarForecast_&amp;lt;name&amp;gt;    - Statusdaten der verwendeten API&#039;s&lt;br /&gt;
WeatherApi_SolarForecast_&amp;lt;name&amp;gt; - Wetterdaten der gewählten Wetter-API (außer DWD-Device)&lt;br /&gt;
AItra_SolarForecast_&amp;lt;name&amp;gt;      - KI Entscheidungsquelle (trainierte Daten)&lt;br /&gt;
AIraw_SolarForecast_&amp;lt;name&amp;gt;      - KI Input Daten = Raw Trainigsdaten&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nach Ausprägung und eingesetzten Features des SolarForecast Devices sind alle oder nur ein Teil dieser Dateien vorhanden. Dabei ist &#039;&#039;&#039;&amp;lt;name&amp;gt;&#039;&#039;&#039; der Name des SolarForecast Devices.&lt;br /&gt;
&lt;br /&gt;
Bei einem Filebackup des FHEM-Servers ist darauf zu achten, dass diese Dateien in dem Backup enthalten sind. Der Inhalt der Dateien ist nicht statisch, sondern kann sich dynamisch aktualisieren. Um im Bedarfsfall einen aktuellen Datenstand zu haben, ist mindestens ein tägliches Backup dieser Dateien empfehlenswert. Eventuell auch öfter mit Hilfe einer Versionierung welche z.B. immer die letzten 3 Versionen aufbewahrt.&lt;br /&gt;
&lt;br /&gt;
Beim Start von FHEM werden bestimmte Dateien automatisch gelesen und in das SolarForecast Device importiert. &lt;br /&gt;
Der Vorgang ist mit verbose=3 im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2023.10.02 09:57:07.967 3: SolCast6 - cached data &amp;quot;pvHistory&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.969 3: SolCast6 - cached data &amp;quot;pvCircular&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;consumerMaster&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;radiationApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;statusApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;weatherApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.974 3: SolCast6 - cached data &amp;quot;aiTrainedData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.976 3: SolCast6 - cached data &amp;quot;aiRawData&amp;quot; restored&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bestimmte Betriebsdaten, wie z.B. die witterungsabhängigen Korrekturfaktoren (circular) oder die KI-Daten (aitrained/airaw), bauen sich über die Zeit immer granularer auf und stellen einen wertvollen Datenbestand dar.&lt;br /&gt;
&lt;br /&gt;
Wird das SolarForecast Device gelöscht und anschließend wieder neu mit dem gleichen Namen definiert, können die bisher verfügbaren Daten sehr einfach wiederhergestellt werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. starten von FHEM (bestimmte Daten werden automatisch importiert)&lt;br /&gt;
* 5. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Soll das neue SolarForecast Device mit einem anderen Namen oder weitere SolarForecast Devices erstellt werden, welche die Betriebsdaten des primären Devices verwenden sollen, ist wie folgt vorzugehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. umbenenen der Dateien, wobei &amp;lt;name&amp;gt; durch den Namen des neuen SolarForecast Devices ersetzt wird&lt;br /&gt;
* 5. starten von FHEM (die Daten werden automatisch importiert)&lt;br /&gt;
* 6. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn sich die SolarForecast Devices hinsichtlich ihres Models oder der integrierten Consumer unterscheiden, sind die Dateien &amp;quot;PVCsm_SolarForecast_&amp;lt;name&amp;gt; &amp;quot; , &amp;quot;ScApi_SolarForecast_&amp;lt;name&amp;gt;&amp;quot; von dem Verfahren auszuschließen.&lt;br /&gt;
&lt;br /&gt;
== Batterieintegration und -steuerung ==&lt;br /&gt;
&lt;br /&gt;
=== Wie eine Batterie eingebunden wird ===&lt;br /&gt;
Wie immer muß die Batterieanlage zunächst mit einem für die Batterie spezifischen FHEM-Device in FHEM definiert sein.&lt;br /&gt;
In diesem Device werden Readings erwartet die folgende Werte bereitstellen:&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieentladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die installierte Batteriekapazität liefert (&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; dieser Schlüssel ist für die Aktivierung des Batterie SOC-Managements und die grafische Anzeige des SOC wesentlich!)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Lade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Entlade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* Reading welches den aktuellen Ladezustand (SOC in Prozent) liefert (optional)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Batterie, bzw. das Batteriedevice wird mit dem Attribut &#039;&#039;&#039;setupBatteryDev&#039;&#039;&#039; im SolarForecast Device registriert. Die Syntax des Attributes ist in  der Online-Hilfe zum Attribut umfassend erläutert. &lt;br /&gt;
Auch wenn manche Readings optional sind, wird empfohlen alle Werte bereitzustellen um alle Batterie-Funktionen im Modul nutzen zu können. Durch die Weiterentwicklung des Moduls können optionale Readings später auch obligatorisch werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Visualisierung der Batterie in der Balkengrafik ====&lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;setupBatteryDevXX&#039;&#039;&#039; verfügt über den Schlüssel &#039;&#039;&#039;show&#039;&#039;&#039;, mit dem die Einblendung des bzw. der Batteriesymbole in den Ebenen der Balkengrafik gesteuert werden kann:&lt;br /&gt;
[[Datei:Screenshot 2025-02-23 192002.png|right|thumb|400px|Einblendung der Batterieleiste und Darstellung des Batterie-SoC als Balkencontent in der zweiten Ebene]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 0 - keine Anzeige des Gerätes (default)&lt;br /&gt;
* 1 - Anzeige des Gerätes in der Balkengrafik Ebene 1&lt;br /&gt;
* 2 - Anzeige des Gerätes in der Balkengrafik Ebene 2 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Symbole und die Farbgebung der Batterie(n) können mittels des Schlüssels &#039;&#039;&#039;icon&#039;&#039;&#039; verändert werden. Die Online-Hilfe gibt weitere Informationen zur Ausgestaltung. &lt;br /&gt;
&lt;br /&gt;
In der Batteriedarstellung wird das Symbol der aktuellen Stunde hervorgehoben. Ein Mouse-Over zeigt wesentliche Betriebszustände der Batterie. Die Batteriesymbole vergangener Stunden zeigen mit einem Mouse-Over die erreichten SoC (State of Charge) Stände. Die kommenden Stunden visualisieren die folgenden Prognosen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der prognostizierte SoC unter Berücksichtigung der PV-Prognose und der [[#Aktivierung_des_Batterie_SOC-Managements|Batteriesteuerung]] sofern sie im Modul aktiviert ist.&lt;br /&gt;
* eine Freigabe bzw. Empfehlung der Batterieladung zur [[#Unterstützung_eines_netzdienlichen_Verhaltens|Unterstützung eines netzdienlichen Verhaltens]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Neben der Einblendung der Batterieleiste über der Balkengrafik selbst können bestimmte Batteriekennwerte als Balkeninhalt dargestellt werden. Die Auswahl erfolgt über das Attribut &#039;&#039;&#039;graphicBeamXContent&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Aktivierung des Batterie SOC- und Lade-Managements ===&lt;br /&gt;
Das integrierte SOC- und Lade-Management verfolgt insbesondere zwei Ziele: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* den Ladezustand der Batterie(n) zu optmimieren, was besonders in den Monaten mit geringerer PV-Erzeugung einen wertvollen Beitrag zur Erhöhung der Autarkierate und Batteriepflege leisten kann&lt;br /&gt;
 &lt;br /&gt;
* eine PV-Prognose und Verbrauch optimierte Beladungssteuerung, die in den Monaten mit hoher PV-Erzeugung hilft eine evtl. Abregelung der Anlage zu verhindern, die Batterie ausgewogen über den Tag zu laden und ein netzdienliches Verhalten zu unterstützen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese beiden Aspekte der Batteriesteuerung werden in den folgenden Abschnitten beschrieben. Sind mehrere Batterien installiert, kann die Steuerung getrennt für jede einzelne Batterie aktiviert und eingestellt werden. Dabei ist zu beachten, dass vom Modul nur Signale und Readings bereitgestellt werden, die durch eine entsprechende Routine ausgewertet werden können um spezifische Befehle zur Umsetzung der Steuerung an das Batteriesystem zu senden. &lt;br /&gt;
 &lt;br /&gt;
Für eine Aktivierung des Managements muß zunächst das Batterie-Device wie im vorigen Abschnitt im SolarForecast Device registriert werden.&lt;br /&gt;
Das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; aktiviert die im Modul integrierte SOC- und Lade-Management Routine: &lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; ctrlBatSocManagement01 lowSoc=&amp;lt;Wert&amp;gt; upSoC=&amp;lt;Wert&amp;gt; [maxSoC=&amp;lt;Wert&amp;gt;] [careCycle=&amp;lt;Wert&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
Die einzelnen Schlüssel werden der Kalkulationsroutine als Steuerungsparameter übergeben und bedeuten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;lowSoc:unterer Mindest-SoC, die Batterie wird nicht tiefer als dieser Wert entladen (muß &amp;gt; 0 sein). Dieser Wert kann zum Beispiel dazu dienen, stets eine Mindestenergiemenge für den Fall eines Stromausfalls im öffentlichen Netz in den Batterien vorzuhalten.&lt;br /&gt;
&lt;br /&gt;
;upSoC:oberer Mindest-SoC, Der übliche Wert des optimalen SoC bewegt sich in Perioden mit hohen PV-Überschuß tendenziell zwischen &#039;lowSoC&#039; und &#039;upSoC&#039;, in Perioden mit geringer PV-Ausbeute bzw. geringem PV Energieüberschuß bewegt sich der optimale SoC tendenziell zwischen &#039;upSoC&#039; und &#039;maxSoC&#039;. Die Einstellung von upSoC=50 für ein ausgewogenes Verhalten kann als guter Startwert dienen.&lt;br /&gt;
&lt;br /&gt;
;maxSoC:maximaler Mindest-SoC, d.h. der SoC Wert der mindestens im Abstand von &#039;careCycle&#039; Tagen erreicht werden muß um den Ladungsausgleich im Speicherverbund auszuführen. Die Angabe ist optional (muß &amp;lt;= 100 sein, default: 95)&lt;br /&gt;
&lt;br /&gt;
;careCycle:maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens &#039;maxSoC&#039; auftreten darf. Die Angabe ist optional. (default: 20)&lt;br /&gt;
&lt;br /&gt;
;loadAbort: definiert eine vom Anwender gewünnschte Bedingung für einen generellen Ladeabbruch und Wiederfreigabe der Lademöglichkeit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle Werte sind ganze Zahlen in %. Dabei gilt: &lt;br /&gt;
&lt;br /&gt;
 lowSoc &amp;lt; upSoC &amp;lt; maxSoC&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====  Erläuterung der Batterie-Steuerungsreadings ==== &lt;br /&gt;
&lt;br /&gt;
Für die Steuerung des Batteriesystems gibt es im SolarForecast einen Satz an Readings, die unterschiedliche Zustände signalisieren und für entsprechende Steuerungsaufgaben bezüglich der Batteriesysteme eingesetzt werden können. In den nachfolgenden Abschnitten werden diese Zusammenhänge noch dataillierter beschrieben.&lt;br /&gt;
&lt;br /&gt;
;Hinweis: SolarForecast stellt lediglich Steuerungsinformationen zur Verfügung. Die Umsetzung des Eingriffs in das Batteriesystem erfolgt durch den Anwender selbst über entsprechende Skripte. In den thematischen Abschnitten werden Beispiele für solche Steuerungsskripte vorgestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle erstellten Readings gelten für ein Batteriesystem, es können mehrere Batteriesysteme in SolarForecast integriert sein. Die Endung &#039;&#039;XX&#039;&#039; der Readings beschreibt die Nummer des Batteriesystems und korrespondiert mit der Endung des entsprechenden Attributes &#039;&#039;ctrlBatSocManagementXX&#039;&#039; bzw. &#039;&#039;setupBatteryDevXX&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Battery_OptimumTargetSoC_XX: Mit den im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; hinterlegten Parametern unter Berücksichtigung von PV- und Verbrauchsprognosen wird ein optimaler SOC-Wert errechnet. Dieser Wert dient zur Einstellung des unteren SOC des Batteriesystems.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeRequest_XX: Dieses Reading signalisiert mit 1 eine Anforderung zur Zwangsladung der Batterie um die Batterie vor Schäden zu schützen (wenn der SOC unter ctrlBatSocManagementXX-&amp;gt;lowSoc gefallen ist) oder wenn der aktuelle SOC unter den berechneten Mindest-SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeUnrestricted_XX: Dieses Reading kann den Wert &#039;&#039;&#039;0&#039;&#039;&#039; oder &#039;&#039;&#039;1&#039;&#039;&#039; einnehmen. Ist der Inhalt 0, sollte die Batterie nur geladen werden, wenn der im Attribut &#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039; definierte Wert überschritten wird. Ist der Inhalt 1, sollte die Batterie mit der vollen zur Verfügung stehenden Ladeleistung angesteuert werden, um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeAbort_XX: Im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; kann mit dem Schlüssel &#039;&#039;loadAbort&#039;&#039; eine Bedingung definiert werden, bei deren Eintritt die Ladung der Batterie abgebrochen werden soll. In diesem Fall wird &#039;&#039;Battery_ChargeAbort_XX=1&#039;&#039; gesetzt. Mit einem entsprechenden Befehl kann der Anwender das Batteriesystem anweisen den Ladevorgang abzubrechen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Nutzung des Batterie SOC-Management ====&lt;br /&gt;
&lt;br /&gt;
Oftmals wird durch die Anlagenhersteller ein hoher statischer SOC eingestellt bzw. empfohlen, der eine längere Verharrungszeit auf einem tiefen SOC-Wert verhindern soll. Allerdings wechseln sich in auch in den Herbst-, Frühlings- und Wintermonaten Zeiten mit wenig PV-Erzeugung mit Phasen stärkerer Solarstrahlung bei klarem Himmel und Sonnenschein ab.&lt;br /&gt;
&lt;br /&gt;
Ein statischer SOC würde dazu führen, dass in den erwähnten Phasen zuviel Energie in das öffentliche Netz eingespeist wird. Dies soll verhindert werden da die wertvolle Energie besser im eigenen Netz gespeichert und in Dunkelphasen verwendet werden kann. Andererseits soll die Batterie nicht zu lange auf einem tiefen SOC verbleiben und außerdem in gewissen Abständen auf einen so hohen SOC geladen werden der den internen Zellausgleich ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Die SOC Kalkulationsroutine des Moduls errechnet unter Berücksichtigung des prognostizierten PV-Ertrages der kommenden Tage, des aktuellen SOC und der im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; (nachfolgend beschrieben) angegebenen Steuerparameter den Vorschlag für eine optimale SOC-Einstellung. Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert.&lt;br /&gt;
&lt;br /&gt;
Durch das Modul selbst findet keine Steuerung der Batterie statt. Es stellt entsprechende Readings zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen SoC.&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SoC unter den optimalen SoC gefallen ist. In diesem Fall sollte die Batterie, unter Umständen mit Netzstrom, zwangsgeladen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Readings können zur Steuerung des SoC (State of Charge) sowie zur Steuerung des verwendeten Ladestroms der Batterie verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ermittlung des optimalen SOC erfolgt nach folgender Logik:&lt;br /&gt;
&lt;br /&gt;
# 	Ausgehend von &#039;lowSoc&#039; wird der Mindest-SoC kurz vor Sonnenuntergang um 5% inkrementiert sofern am laufenden Tag &#039;maxSoC&#039; nicht erreicht wurde und die PV-Prognose keinen hinreichenden Ertrag des kommenden Tages vorhersagt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Wird &#039;maxSoC&#039; (wieder) erreicht, wird Mindest-SoC um 5%, aber nicht tiefer als &#039;lowSoc&#039;, verringert. Ist der berechnete Mindest-SoC größer als &#039;upSoc&#039;, wird der Mindest-SoC auf &#039;upSoc&#039; gesetzt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#   Mindest-SoC wird soweit verringert, dass die prognostizierte PV Energie des aktuellen bzw. des folgenden Tages von der Batterie aufgenommen werden kann. Mindest-SoC wird typisch auf &#039;upSoc&#039; und nicht tiefer als &#039;lowSoc&#039; verringert.  &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Das Modul erfasst den letzten Zeitpunkt am &#039;maxSoC&#039;-Level, um eine Ladung auf &#039;maxSoC&#039; mindestens alle &#039;careCycle&#039; Tage zu realisieren. Zu diesem Zweck wird der optimierte SoC in Abhängigkeit der Resttage bis zum nächsten &#039;careCycle&#039; Zeitpunkt derart verändert, dass durch eine tägliche 5% SoC-Steigerung &#039;maxSoC&#039; am &#039;careCycle&#039; Zeitpunkt rechnerisch erreicht wird. Wird zwischenzeitlich &#039;maxSoC&#039; erreicht, beginnt der &#039;careCycle&#039; Zeitraum erneut. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im fünften Schritt werden die Grenzen &#039;lowSoc&#039; und &#039;upSoc&#039; berücksichtigt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im letzten Schritt erfolgt Generierung des Readings &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; zur Signalisierung einer eventuell empfohlenen Zwangsladung auf den berechneten Min-SoC. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei sehr wenig Erzeugungungsprognose, d.h. wenn sich der berechnete Min-SoC oberhalb von &#039;upSoC&#039; bewegt, wird &#039;upSoC&#039; eingestellt. Liegt der berechnete Min-SoC unterhalb von &#039;upSoC&#039;, ist jedoch größer als &#039;lowSoC&#039;, wird der berechnete SOC im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; eingestellt. Somit eignet sich die Angabe im Schlüssel &#039;upSoC&#039; um in Zeiten geringer Solarenergieerzeugung die Batterie für eine Notstromerzeugung auf mindestens diesem Wert zu halten. Sollte die PV-Prognose kurzfristig einen größeren Ertrag vorhersagen als die Batterie durch die Einhaltung von &#039;upSoC&#039; aufnehmen kann, wird der Min-SoC unter &#039;upSoC&#039; abgesenkt um möglichst allen PV-Überschuß in der Batterie zu speichern und somit dem Eigenverbrauch zuzuführen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der berechnete Mindest-SoC ist immer nur ein unterer Grenzwert. Die Batterie kann durch Ladevorgänge natürlich jederzeit einen höheren als den im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; dargestellten optimalen SoC haben. Der optimale SoC sollte nicht unterschritten werden um die oben genannten Zusammenhänge abbilden zu können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Die dynamische SOC Steuerung mit Umsetzungsbeispiel =====&lt;br /&gt;
Das Modul bietet eine Unterstützung zur automatisierten Einstellung eines optimalen SoC Wertes.&lt;br /&gt;
&lt;br /&gt;
Ziel ist es, den Minimum SoC in Abhängigkeit der zu erwartenden Solarerträge des aktuellen und des folgenden Tages so einzustellen, dass der prognostizierte Solarertrag von der Batterie aufgenommen werden kann. Die Einspeisung in das öffentliche Netz soll minimiert werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin soll ein unterer SoC nicht unterschritten, sowie ein oberer Minimum SoC im Normalfall nicht überschritten werden. Der obere Grenzwert stellt sicher, dass die Batterie mindestens bis zu diesem Wert wieder entladen werden kann. Dadurch bleibt innerhalb der Batterie immer genügend Kapazität verfügbar um unvorhergesehene PV Energie aufnehmen zu können.&lt;br /&gt;
&lt;br /&gt;
Aktiviert wird die Unterstützung der Batteriesteuerung durch das Setzen des Attributes &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; z.B. mit diesen Angaben:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagementXX lowSoc=x upSoC=x maxSoC=x careCycle=x &lt;br /&gt;
&lt;br /&gt;
so zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=98 careCycle=20&lt;br /&gt;
&lt;br /&gt;
Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert. &lt;br /&gt;
Ist dieses Attribut gesetzt, werden Steuerungs-Readings erstellt, die der Nutzer auswerten und seine Batterieanlage z.B. via notify oder DOIF steuern kann. &amp;lt;bR&amp;gt;&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen Mindest-SoC.&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SOC unter den optimalen SOC bzw. minimalen SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
Die Schlüssel &#039;&#039;&#039;lowSoc&#039;&#039;&#039; und &#039;&#039;&#039;upSoC&#039;&#039;&#039; sind die unteren und oberen Grenzen, zwischen denen sich der Minimum SoC im normalen Betrieb bewegen soll.&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;maxSoC&#039;&#039;&#039; stellt eine Ladungsgrenze dar, die mindestens alle X (careCycle) Tage erreicht werden soll. Zu diesem Zweck errechnet das Modul die Anzahl der nötigen Erhöhungen der Minimum Batterieladung von 5% pro Tag um ausgehend vom aktuellen SoC-Level. Der resultierende Minimum SoC Wert wird entsprechend angepasst. Wurde der einstellte maxSoC Level erreicht, startet der Wartungszyklus (careCycle) erneut. &amp;lt;br&amp;gt;&lt;br /&gt;
Der maxSoC in Verbindung mit dem durch &#039;&#039;&#039;careCycle&#039;&#039;&#039; definierten Zyklus soll sicherstellen, dass der Batterieverbund in regelmäßigen Abständen einen Ladungsausgleich vollziehen kann. &lt;br /&gt;
&lt;br /&gt;
Durch die Modullogik erfolgt eine 5 protentige Anhebung des Minimum SoC wenn am Vortag maxSoC nicht erreicht wurde. Die Anhebung erfolgt aber nicht über upSoC. upSoC ist die obere Grenze des Minimum SoC. Wird am Vortag mindestens die maxSoC Ladung erreicht, verringert sich der Minimum SoC wieder schrittweise um 5%, aber nicht tiefer als lowSoc.&lt;br /&gt;
&lt;br /&gt;
Ergänzt wird die Logik noch um die PV Vorhersage. Dabei wird die obige Minimum SoC Berechnung um die Erwartung der PV Erwartung am aktuellen und folgenden Tag korrigiert. Das bedeutet, dass der Minimum SoC z.B. von heute 50% auf 10% abgesenkt und dadurch die gespeicherte Energie dem Haushalt zugeführt wird, wenn am heutigen oder kommenden Tag eine entsprechende PV Energie zu erwarten ist um die Batterie wieder vollständig zu zuladen.&lt;br /&gt;
Dadurch ist immer genügend &amp;quot;Freiplatz&amp;quot; in der Batterie und andererseits hat die Batterie in langen Dunkelphasen eine Reserve für einen eventuellen Stromausfall (falls der abgesichert werden soll) und wird vor einem dauerhaften tiefen SoC geschützt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Umsetzungsbeispiel =====&lt;br /&gt;
&lt;br /&gt;
Wie das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; genutzt werden kann, wird am Beispiel einer Victron Batterieanlage gezeigt. Die Anlage wird durch Cerbo GX Gerät gesteuert. Der Cerbo GX ist per MQTT2 in FHEM eingebunden. Umgesetzt ist die Steuerung der Batterie &#039;01&#039;, d.h. die Angabe &#039;XX&#039; ist durch &#039;01&#039; ersetzt.&lt;br /&gt;
&lt;br /&gt;
Die folgende kleine Logik ist in einem &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; File eingebaut und wird regelmäßig mit&lt;br /&gt;
&lt;br /&gt;
 batSocChargeMgmnt (&#039;&amp;lt;Name SolarForecast Device&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
aufgerufen. Der Aufruf erfolgt durch Angabe der Routine im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; des SolarForecast Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
  # Hinweis: die Zeichen &#039;::&#039; vor der Routine sind durch das SolarForecast Package bedingt&lt;br /&gt;
  ::batSocChargeMgmnt ($name);&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Routine wird dadurch automatisch am Ende jedes Zyklus (siehe Attribut plantControl-&amp;gt;cycleInterval) ausgeführt.&lt;br /&gt;
Um die SOC Managementfunktion nach Bedarf ein- bzw. ausschalten zu können wird zunächst im SolarForecast Device ein userattr zur Steuerung der SOC-Logik angelegt:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; userattr userFn_BatterySoCManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
Die Perl Routine &#039;&#039;&#039;batSocChargeMgmnt&#039;&#039;&#039; ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#  Batterie SOC und Max. Ladestrom Management&lt;br /&gt;
############################################################################&lt;br /&gt;
sub batSocChargeMgmnt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vebus   = &#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;;                            # Victron Vebus Device&lt;br /&gt;
  my $vicsets = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                         # Victron Einstellungen&lt;br /&gt;
&lt;br /&gt;
  my $maxcspc = 105;                                                           # max. Ladestrom (A) Victron MPII Verbund&lt;br /&gt;
  my $actmcc  = ReadingsNum ($vebus, &#039;MaxChargeCurrent&#039;, undef);               # akt. Ladestromeinstellung&lt;br /&gt;
  my $load    = $actmcc // $maxcspc;                                           # Soll-Ladestrom (A)&lt;br /&gt;
&lt;br /&gt;
  ## Battery SoC Management&lt;br /&gt;
  ###########################&lt;br /&gt;
  my $ubsm = AttrVal ($name, &#039;userFn_BatterySoCManagement&#039;, &#039;aus&#039;); &lt;br /&gt;
  &lt;br /&gt;
  if ($ubsm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name,    &#039;Battery_ChargeRequest_01&#039;,     0);&lt;br /&gt;
    my $csoc = ReadingsNum ($vicsets, &#039;MinimumSocLimit&#039;,             10);      # akt. SoC&lt;br /&gt;
    my $osoc = ReadingsNum ($name,    &#039;Battery_OptimumTargetSoC_01&#039;, 10);      # Soll-SoC&lt;br /&gt;
    my $surp = ReadingsNum ($name,    &#039;Current_Surplus&#039;,              0);      # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if ($csoc != $osoc) {&lt;br /&gt;
      CommandSet (undef, &amp;quot;$vicsets MinimumSocLimit $osoc&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn SoCMgmnt -&amp;gt; MinimumSocLimit in $vicsets set to $osoc %});&lt;br /&gt;
    }&lt;br /&gt;
	                                           &lt;br /&gt;
    if ($bcrq &amp;amp;&amp;amp; $surp &amp;lt; 1000) {                                              # max. Strom b. Battery_ChargeRequest &lt;br /&gt;
      $load = 21;&lt;br /&gt;
    }&lt;br /&gt;
	else {&lt;br /&gt;
	  $load = $maxcspc;&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Batterie Einstellung MaxChargeCurrent&lt;br /&gt;
  ##########################################&lt;br /&gt;
  if ($load != $actmcc) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$vebus MaxChargeCurrent $load&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
    Log3 ($name, 3, qq{$name - userFn ChargeMgmnt -&amp;gt; MaxChargeCurrent in $vebus set }.&lt;br /&gt;
                    qq{from old $actmcc A to $load A});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent_set&#039;, $load, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist im SolarForecast Device das Reading  &#039;&#039;&#039;Battery_ChargeRequest_01&#039;&#039;&#039; gesetzt, ist der aktuelle SOC kleiner als der optimale SOC und die Batterie wird (eventuell aus dem öffentlichen Netz) geladen. Das kann automatisch durch den Cerbo GX bzw. in anderen Anlagen durch einen entsprechenden Befehl erfolgen.&lt;br /&gt;
Damit die Netzbeladung nicht mit der vollen Ladestromstärke geschieht, wird der Ladestrom auf den gewünschten Wert (hier 21 A -&amp;gt; ca. 1000 W bei einem 48V System) reduziert sofern kein oder zu wenig PV-Überschuß vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== weitere mögliche Aspekte der SOC- und Batterieladesteuerung ====&lt;br /&gt;
&lt;br /&gt;
SolarForecast liefert durch seine internen Logiken bereits sehr hilfreiche Signale zur Steuerung von Batteriesystemen in Form von Readings an. Abhängig von den individuellen Möglichkeiten der vorhandenen Anlage käme zum Beispiel zusätzlich zu einer Steurung des optimalen SOC oder der Zeitfenster für die Batterieaufladung auch eine Steuerung des Ladestroms bzw. der verwendeten Ladeleistung in Betracht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hintergründe:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Das Laden eines Akkus mit möglichst gleichbleibender und geringer Leistung wirkt sich positiv auf dessen Langlebigkeit aus, was u.a. auch daran liegt, dass der Temperaturstreß im Akku bei langsamer Energiezuführung nur gering ist.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom führt zu einem geringen Absacken der Akkuspannung beim (ggf, temporären) Abschalten des Ladestroms, was sich positiv auf die SOC-Schätzung auswirkt.&lt;br /&gt;
    &lt;br /&gt;
* Ein geringer Ladestrom führt, insb. bei Nutzung passiver Balancer (sind in den Akku-Systemen üblicherweise verbaut), zu einer geringen Differenz zwischen den einzelnen Zellspannungen und damit zu einer besseren Kapazitätsausnutzung eins Akkus.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom kann zu einem zeitlich punktgenauen Zielfüllstand (im Winter 100%, ansonsten natürlich weniger) am Ende des Tages führen.&lt;br /&gt;
    &lt;br /&gt;
* Eine geringer Ladestrom führt auch zu geringen Leitungsverlusten, da der Strom quadratisch zu den Leitungsverlusten beiträgt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann auch die Verweildauer oder die Begrenzung des SOC, auf den die Batterie maximal geladen werden soll, Gegenstand von Optimierungen sein.&lt;br /&gt;
&lt;br /&gt;
Die häufig zu findende Empfehlung, Akkus nicht zu lange bei einem SOC von 100% verweilen zu lassen, liegt weniger an dem SOC als solchem, sondern daran, dass &#039;&#039;SOC=100%&#039;&#039; üblicherweise dadurch ermittelt wird, dass eine Zelle im Akku einen Spannungsschwellenwert überschreitet, der – würde dieser Schwellenwert zeitlich länger überschritten sein – zu einer Schädigung des Akkus führen könnte. Schädlich sind insbesondere häufige Nachladevorgänge bei Werten um die 100% SOC, da Zellen dann ja häufiger und damit - integral gesehen - auch länger den o.g. Schwellenwert überschreiten.&lt;br /&gt;
&lt;br /&gt;
Einige Akku-Hersteller, z.B. BYD, haben auf o.g, Grund in der (neueren) Firmware Ihrer Systeme einen SOC-Threshold (bei BYD liegt dieser bei 95%) eingebaut. Dieser Wert muss nach einem erreichten SOC von 100% unterschritten  werden, bevor überhaupt eine weitere Ladung erfolgt. Insbesondere in der dunklen Jahreszeit kann es daher sinnvoll sein, den Akku unter Verwendung von PV-Leistung so zu füllen, dass dieser möglichst nur einmal vor Einbruch der Dunkelheit auf &#039;&#039;SOC=100%&#039;&#039; geladen wird. Hierbei sollte darauf geachtet werden, dass der Ladeschlussstrom des jeweiligen Systems nicht unterschritten wird. &lt;br /&gt;
&lt;br /&gt;
SolarForecast unterstützt die oben betrachtete Batteriesteuerung durch die optionale Angabe von &#039;&#039;&#039;loadAbort&#039;&#039;&#039; im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039;. Das in diesem Kontext erstellte Reading &#039;&#039;&#039;Battery_ChargeAbort_XX&#039;&#039;&#039; stellt die auswertbaren Steuerungsinformationen zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== PV-Prognose und Verbrauch optimierte Beladungssteuerung unter Berücksichtigung einer Wirkleistungsbegrenzung ====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-04-25 143910.png|right|thumb|400px|Batterie Popup &amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Batterie geladen. sobald PV-Überschuß vorhanden ist ohne eine Prognose zu berücksichtigen. Dadurch sind die Batterien im Sommer unter Umständen schon um 10-12 Uhr voll geladen und die Anlage liefert ihre mehr oder weniger volle Energie (je nach Ausrichtung) in das öffentliche Netz. Dann könnte es zu einer Begrenzung der PV-Leistung durch einen Schwellenwert (z.B. 70%-Regelung) oder eventuell Zwangsabregelung durch den Netzbetreiber kommen.&lt;br /&gt;
&lt;br /&gt;
Hintergrund dieser Erweiterung ist das Bestreben, eine optimale Unterstützung bei der Maximierung des Eigenverbrauchs zu geben und einen Beitrag zur Netzstabilität zu leisten.&lt;br /&gt;
Das Ziel der Beladungssteuerung der Batterie ist es, die Ladung der Batterie über den Tag verteilt so zu steuern, dass die Batterie erst dann geladen wird, wenn durch den PV-Überschuß eine Netzeinspeisung erfolgen würde bzw. ein Grenzwert erreicht werden würde, der zu einer Abregelung der PV-Anlage führen könnte.&lt;br /&gt;
Es kann auch zu einer Zwangsabregelung durch den Netzbetreiber führen, was vermieden werden soll.&lt;br /&gt;
 &lt;br /&gt;
Die interne Kalkulationslogik erstellt zu diesem Zweck ein Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039;.&lt;br /&gt;
Dieses Reading gibt dem User ein Signal, ob zu der aktuellen Stunde der Ladevorgang der Batterie freigegeben (1) oder nicht freigegeben werden sollte (0). Die Freigabe zur Ladung bedeutet dass:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; die Batterie mit ihrer vollen Ladeleistung angesteuert werden sollte um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=0&#039;&#039;&#039; die Batterie nur geladen werden sollte wenn der im Attribut plantControl-&amp;gt;feedinPowerLimit definierte Wert überschritten wird&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ist keine Freigabe zur Ladung vorhanden, kann bzw. sollte dennoch eine Ladung der Batterie vorgenommen werden, sofern eine über dem im &amp;lt;br&amp;gt;&lt;br /&gt;
Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limit liegende Einspeiseleistung vorhanden ist. In diesem Status sollte die Batterie nur mit der Differenzleistung von vorhandener Einspeiseleistung und dem gesetzen Einspeiselimit geladen werden und damit das gesetzte Einspeiselimit einhalten ohne die Anlage abzuregeln. Ist die Batterie in einer Balkengrafikebene dargestellt, wird im Mouse-Over Popup die Battrie mit &#039;&#039;&amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;&#039;&#039; gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Möglichkeiten der Batteriesteuerung sind stark von der individuellen Anlage abhängig und können hier nicht beschrieben werden. Ein Umsetzungsbeispiel mit einer Victron-Anlage mit Pylontech Batterie ist weiter unten dargestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Aktivierung und Arbeitsweise =====&lt;br /&gt;
&lt;br /&gt;
Die implementierte Logik zur optimierten Batterie Beladungssteuerung wird aktiviert, wenn folgende Kriterien erfüllt sind: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;capacity&#039;&#039;&#039; in den setupInverterDevXX Atributen ist gesetzt&lt;br /&gt;
* das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; für die jeweilige Batterie ist gesetzt&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;cap&#039;&#039;&#039; im Attribut setupBatteryDevXX der jeweiligen Batterie ist gesetzt&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Die Logik arbeitet wie folgt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Der resultierende Schwellenwert der Wirkleistungsbegrenzung: der Gesamtanlage wird durch die Auswertung der in den Inverter-Attributen setupInverterDevXX  gesetzen Schlüssel limit (optional) und capacity ermittelt. Inverter mit gesetztem Schlüssel feed = grid (deren Energie wird ausschließlich in das öffentlich Netz eingespeist) werden von der Betrachtung in diesem Kontext ausgeschlossen.&lt;br /&gt;
&lt;br /&gt;
;Die benötigte Beladung bis zu maxSoC (im Attribut setupBatteryDevXX) : wird ermittelt und mit der zu erwartenden PV Tagesprognose in Beziehung gesetzt. Sofern die PV-Erzeugung abzgl. Verbrauch noch nicht das Wirkleistungbegrenzungs-Limit erreicht UND noch genügend PV-Überschuß für eine Ladung auf &#039;&#039;maxSoC&#039;&#039; im Laufe der kommenden Stunden des Tages zu erwarten ist, bleibt das Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 0&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
;Wird das Wirkleistungbegrenzungs-Limit erreicht/überschritten und/oder die PV-Überschußprognose: zzgl. eines Sicherheitspuffers unterschritten, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 1&#039;&#039;&#039; gesetzt. Der User kann darauf reagieren und den Batterie Ladevorgang aktivieren. Die Möglichkeiten der Aktivierung sind natürlich von der installierten Anlage abhängig. Das SolarForecast Device greift nicht in die Batteriesteuerung direkt ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders ausgedrückt erfolgt immer dann eine Ladefreigabe, wenn einer der nachfolgenden Sachverhalte &#039;&#039;wahr&#039;&#039; ist:&lt;br /&gt;
&lt;br /&gt;
- die benötigte Ladeenergie (aller installierten Batterien) &amp;gt;= PV-Restüberschuß des Tages (Reading RestOfDayPVforecast) zzgl. Sicherheitsaufschlag&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- der Zeitpunkt des PV-Erzeugungszenit des laufenden Tages überschritten ist (Reading Today_MaxPVforecastTime)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn die aktuelle PV Leistung &amp;gt;= einer eventuellen Wechselrichter-Leistungsbegrenzung ist (Summe aller WR-Begrenzungen)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn das BatSoc-Management _nicht_ aktiviert ist (nicht alle oben genannten Aktivierungskriterien erfüllt sind)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind mehrere Batterien installiert und durch das Management einer Batterie die Einhaltung der genannten Kriterien bzw. Sachverhalte erwirkt wird, bleiben die weiteren Batterien im Modus Ladefreigabe (Battery_ChargeUnrestricted_XX=1).  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Umsetzungsbeispiel Batterie Ladesteuerung mit Victron GX Venus über den Grid Setpoint =====&lt;br /&gt;
&lt;br /&gt;
Ziel der Steuerung ist es abhängig vom Wert des Readings Battery_ChargeUnrestricted_XX (z.B. Battery_ChargeUnrestricted_01) die Ladung des angeschlossenen Batteriesystems zu aktivieren bzw. zu deaktivieren.&lt;br /&gt;
Das vorliegende Beispiel soll umzusetzen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 0 -&amp;gt; Batterie nicht aufladen bzw. nur laden wenn Einspeiselimit überschritten (Attribut plantControl-&amp;gt;feedinPowerLimit)&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 1 -&amp;gt; Batterie aufladen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Grid Setpoint ist ein Parameter in den Victron Systemeinstellungen. Das Victron System wird den eingestellten Grid Setpoint versuchen einzuhalten und bei einem positiven Wert Energie aus dem Netz beziehen bzw. bei einem negativen Grid Setpoint Energie in das Netz einspeisen.&lt;br /&gt;
&lt;br /&gt;
Normalerweise wird das Victron System die erzeugte PV Energie zunächst zur Deckung des Hausverbrauchs verwenden, ist dann noch ein PV Überschuß vorhanden, die Batterien aufladen und bei weiter vohandenen PV Überschuß diese Energie in das öffentliche Netz einspeisen sofern dem System eine Einspeisung erlaubt ist. Anderenfalls werden die Wechselrichter oder MPPT Smartloader heruntergeregelt bzw. limitiert. &lt;br /&gt;
&lt;br /&gt;
In der Standardeinstellung ist beim Victron System ein Grid Setpoint von ca. 20 bis 50 Watt, d.h. das System strebt danach diese Vorgabe zu erfüllen zieht ständig Energie in diesem Bereich aus dem öffentlich Netz von einem gelegentlichen Überschwingen der Regelung abgesehen. Damit ein eventueller PV Überschuß nicht zum Laden der Batterie verwendet, sondern statt dessen in das öffentliche Netz eingespeist wird, muß der Grid Setpoint um diesen Betrag abgesenkt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-24 114403.png|right|thumb|400px|Integration des Grid Setpoint-Managements in den Own_Spec-Bereich]]&lt;br /&gt;
&lt;br /&gt;
Damit man später per Attribut bzw. über den [[#Formatierung_der_Inhalte_im_Bereich_&amp;quot;Graphic_Header_Own_Specification&amp;quot;|Own_Spec-Bereich]] die automatische Ladesteuerung über den Grid Setpoint ein- bzw. ausschalten kann, legen wir ein userattr an:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 userattr &amp;lt;Name&amp;gt; userFn_GridSetpointManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin sind einige Vorbereitungen im Device MQTT2_cerboGX_c0619ab34e08_settings vorzunehmen. Dieses Device ist im vorliegenden Beispiel ein in FHEM vorhandenes MQTT2_DEVICE, über das die Victron CerboGX Einstellungen zugreifbar sowie einstellbar sind. Die Vorgehensweise zur Erstellung des MQTT2_DEVICE ist hier nicht beschrieben und wird vorausgesetzt.&lt;br /&gt;
&lt;br /&gt;
Damit ein entsprechender Set-Befehl zur Einstellung des Grid Setpoints vorhanden ist, werden folgende Attribute gesetzt:&lt;br /&gt;
&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings jsonMap Settings_CGwacs_AcPowerSetPoint_value:GridSetpoint&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings setList GridSetpoint W/c0619ab34e08/settings/0/Settings/CGwacs/AcPowerSetPoint {&amp;quot;value&amp;quot;:$EVTPART1}&lt;br /&gt;
&lt;br /&gt;
Nach dieser Attributierung kann mit einem &amp;quot;&#039;&#039;set MQTT2_cerboGX_c0619ab34e08_settings GridSetpoint &amp;lt;Wert&amp;gt;&#039;&#039;&amp;quot; der Grid Setpoint eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Das Attribut userFn_GridSetpointManagement kann nun im Perl Code ausgewertet werden um das Grid Setpoint-Management ein- bzw. auszuschalten.&lt;br /&gt;
Der nachfolgende Code wird in die Datei &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; eingefügt. Ist diese Datei nicht vorhanden, legen wir sie vorab als Kopie der ausgelieferten 99_myUtils.pm an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Steuerung Start/Stop der Batterieladung über den Victron Grid Setpoint&lt;br /&gt;
############################################################################&lt;br /&gt;
sub gridSetpointMgmt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vicsets   = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                               # Device Victron Einstellungen&lt;br /&gt;
  my $gspdef    = 20;                                                                  # Default Einstellung des Grid Setpoint&lt;br /&gt;
  my $targetgsp = $gspdef;                                                             # Voreinstellung Grid Setpoint&lt;br /&gt;
  my $neggspmax = FHEM::SolarForecast::CurrentVal ($name, &#039;feedinPowerLimit&#039;, 5000);   # max. gewünschte Einspeiseleistung in Watt&lt;br /&gt;
  $neggspmax    = $neggspmax * -1;&lt;br /&gt;
  my $gspm      = AttrVal ($name, &#039;userFn_GridSetpointManagement&#039;, &#039;aus&#039;);             # Freischaltung des Grid Setpoint-Managements&lt;br /&gt;
  my $curgsp    = ReadingsNum ($vicsets, &#039;GridSetpoint&#039;,         $gspdef);             # aktuelle Einstellung Grid Setpoint&lt;br /&gt;
  &lt;br /&gt;
  if ($gspm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name, &#039;Battery_ChargeUnrestricted_01&#039;, 0);         # Ladefreigabe (1 -&amp;gt; Bat Ladefreigabe)&lt;br /&gt;
    my $surp = ReadingsNum ($name, &#039;Current_Surplus&#039;,               0);         # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if (!$bcrq) {                                                               # Grid Setpoint absenken wenn keine .. &lt;br /&gt;
        $targetgsp = $gspdef - $surp;                                           # ..Batterie Ladefreigabe&lt;br /&gt;
        $targetgsp = $neggspmax if($targetgsp &amp;lt; $neggspmax);                    # Begrenzung der Einspeiseleistung&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($curgsp != $targetgsp) {&lt;br /&gt;
	  fhem (&amp;quot;set $vicsets GridSetpoint $targetgsp&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn gridSetpointMgmt -&amp;gt; GridSetpoint in $vicsets set to $targetgsp});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Victron_GridSetpoint_set&#039;, $targetgsp, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Vergleich des Setpoints mit der Vorgabe von &#039;&#039;$neggspmax&#039;&#039; dient dazu die maximale Einspeiseleistung in das öffentliche Netz zu begrenzen. Ist diese Grenze erreicht, wird der noch verbleibende Überschuß in die Batterie geladen. Dadurch wird eine Abregelung der Anlage vermieden wenn der Schwellenwert &#039;&#039;$neggspmax&#039;&#039;erreicht ist sofern die Batterie aufnahmefähig ist und nicht voll geladen ist. &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::gridSetpointMgmt  ($name);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zum Management des automatischen Grid Setpoint und der Anzeige des eingestellten Wertes wird das Attribut und die Readinganzeige in den Own_Spec-Bereich eingebunden, z.B.:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; graphicHeaderOwnspec  #Settings&lt;br /&gt;
                                   SetPoint&amp;amp;nbsp;Management:userFn_GridSetpointManagement&lt;br /&gt;
                                   Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Unterstützung eines netzdienlichen Verhaltens ====&lt;br /&gt;
&lt;br /&gt;
Der Steuerungsprozess der Batterieanlage leistet insgesamt einen kleinen Beitrag zur Netzstabilität, indem die Speicherladung in den Zeitraum der meisten prognostizierten Überschußeinspeisung gelegt wird. Im Sommer kann sich dieser Zeitraum in die Zeit nach dem Maxmimum des prognostizierten PV-Überschusses verlagern, wenn auch danach noch genügend Überschußenergie zu Volladung der Batterie prognostiziert wird. In dem Zusammenhang sollte im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; ein Einspeiselimit gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zur Verdeutlichung soll das Beispiel dienen:&lt;br /&gt;
&lt;br /&gt;
* die Batterie ist zu 60% geladen &lt;br /&gt;
* der User hat upSoC=40 eingestellt&lt;br /&gt;
* der User hat maxSoC=90 eingestellt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Am Vormittag ist genügend Sonne vohanden, das Maximumum der Energie über die Zeit wird aber noch erwartet. &lt;br /&gt;
Zu diesem Zeitpunkt wird das Reading  &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039; auf den Wert &amp;quot;0&amp;quot; gesetzt. Durch den Nutzer erfolgt daraufhin, zum Beipiel über ein Notify, ein anlagenspezifischer Befehl &amp;quot;Ladestop&amp;quot; an die Batterieanlage. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ab diesem Moment wird:&lt;br /&gt;
&lt;br /&gt;
# die Batterie nicht geladen&lt;br /&gt;
# die erzeugte PV-Energie dem Haushalt zur Verfügung gestellt bzw. der verbleibende Überschuß eingespeist, sofern der Überschuß unterhalb des im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limits liegt.&lt;br /&gt;
# ein eventuell über dem Limit &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; vorhandener Überschuß in die Batterie geladen und so die Netzlast verringert sowie die Batterie schonend geladen. (dieser Punkt trifft in den Monaten mit wenig PV-Erzeugung eher nicht zu)  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig liefert die Batterie Energie an das Hausnetz und wird von 60% bis maximal einem SoC-Wert entladen, der durch die [[#Die_dynamische_SOC_Steuerung_mit_Umsetzungsbeispiel|dynamische SOC Steuerung]] bestimmt wird. Dazu muß diese Steuerung natürlich implementiert sein. Sofern der berechnete SoC größer als upSoC ist, wird der maximale Entladungs-SoC auf upSoC gesetzt. &lt;br /&gt;
&lt;br /&gt;
Zusätzlich überprüft das Modul permanent bei jedem Zyklus die Differenz des aktuell vorhandenen SoC zum eingestellten maxSoC.&lt;br /&gt;
Sie soll nicht größer sein um mit dem (noch) zu erwartenden PV-überschuß des Tages der eingestellte maxSoC bzw. dessen Nähe wahrscheinlich erreicht werden kann. &lt;br /&gt;
Sollte der Differenz-Grenzwert erreicht sein, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; gesetzt und der Nutzer sollte dann über einen geeigneten Befehl seine Anlage in den Modus &amp;quot;Laden&amp;quot; umschalten.&lt;br /&gt;
Dieser Vorgang kann beliebig oft während des Tages alternieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Nutzung von batteryTrigger ===&lt;br /&gt;
Ergänzt werden die Möglichkeiten durch das set-Kommando: &lt;br /&gt;
&lt;br /&gt;
 batteryTrigger &amp;lt;1on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;1off&amp;gt;=&amp;lt;Wert&amp;gt; [&amp;lt;2on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;2off&amp;gt;=&amp;lt;Wert&amp;gt; ...] &lt;br /&gt;
&lt;br /&gt;
Das Kommando setzt Triggerpunkte bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %).&lt;br /&gt;
&lt;br /&gt;
Der verwendete SoC wird als resultierender SoC als Summe der aktuellen Ladung aller registrierten Batterie-Geräte im Verhältnis zur installierten Gesamtkapazität gebildet. Das bedeutet, dass alle einzelnen Batterie-Geräte als ein gemeinsamer Cluster betrachtet werden. &lt;br /&gt;
&lt;br /&gt;
Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise definiert werden.&lt;br /&gt;
Überschreiten die letzten drei SoC-Messungen eine definierte Xon-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = on&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
Unterschreiten die letzten drei SoC-Messungen eine definierte Xoff-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = off&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
&lt;br /&gt;
Der Inhalt der Readings kann durch ein User-Programm oder, bei Erzeugung von entsprechenden Events, mittels notify-Device ausgewertet werden um bei Eintreten eines definierten Ereignisses entsprechende Reaktionen auszulösen. Das kann zum Beispiel die Freigabe eines Heizstabes oberhalb eines bestimmten SOC sein oder ein Entladeverbot der Batterie unterhalb eines SOC-Wertes um Reserven für einen eventuellen Stromausfall zu behalten.&lt;br /&gt;
&lt;br /&gt;
Damit die Batterietrigger dynamisch geändert werden können, ist die Einstellung als Set-Kommando und nicht als Attribut ausgeführt.   &lt;br /&gt;
&lt;br /&gt;
Alle Triggerpunkte können mit dem set-Befehl:&lt;br /&gt;
&lt;br /&gt;
 reset batteryTriggerSet&lt;br /&gt;
&lt;br /&gt;
wieder gelöscht werden.&lt;br /&gt;
&lt;br /&gt;
== Verbrauchersteuerung - Registrieren und visualisieren 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;
Die Eigenschaften und das Schaltverhalten wird durch die Angabe der verfügbaren Schlüssel gesteuert. Die Möglichkeiten sind sehr umfangreich. Die nachfolgenden Abschnitte beschreiben die Verwendung am Beispiel oft vorkommender bzw. nachgefragter Sachverhalte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die Phasen der Verbrauchersteuerung ===&lt;br /&gt;
&lt;br /&gt;
Jeder Zyklus eines Verbrauchers durchläuft im Modul die folgenden Phasen:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Planung&#039;&#039;&#039; der Aktivzeiten des Verbrauchers, d.h. wann der Verbraucher geplant eingeschaltet sowie geplant ausgeschaltet wird und damit der Zyklus beendet wird.&lt;br /&gt;
# &#039;&#039;&#039;Start&#039;&#039;&#039; des Zyklus, d.h. Einschalten des Verbrauchers entsprechend der Planungsdaten sofern weitere, in den Consumer-Schlüsseln definierbare Rahmenbedingungen das Einschalten nicht verhindern (z.B. kein oder zu wenig PV-Energieerzeugung / PV-Überschuss)&lt;br /&gt;
# &#039;&#039;&#039;Permanente Überprüfung von&#039;&#039;&#039; eventuell vorhandenen &#039;&#039;&#039;Interruptbedingungen&#039;&#039;&#039; die den Verbraucher temporär ausschalten und, sofern die Interruptbedingung nicht mehr vorliegt, den Verbraucher wieder einschalten und so den gestarteten Zyklus fortsetzen.&lt;br /&gt;
#  &#039;&#039;&#039;Beendigung&#039;&#039;&#039; der Zyklus. Die Beendigung erfolgt entweder (normalerweise) wenn die geplante Endezeit der Zyklus erreicht ist oder eine optionale Endebedingung erfüllt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Steuerung der Phasen ====&lt;br /&gt;
Der Ablauf der Phasen kann durch verschiedene Schlüssel-Wert Paare beeinflusst und gesteuert werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; kann eine &#039;&#039;&#039;zusätzliche externe Bedingung&#039;&#039;&#039; definiert werden um den Einschaltvorgang des Consumers freizugeben. Ist die Bedingung (Regex) nicht erfüllt, erfolgt kein Einschalten des Verbrauchers auch wenn die sonstigen Voraussetzungen wie Zeitplanung, on-Schlüssel, auto-Mode und aktuelle PV-Leistung gegeben sind. Es erfolgt somit eine &#039;&#039;&#039;UND-Verknüpfung&#039;&#039;&#039; des Schlüssels swoncond mit den Planungsdaten und weiteren Einschaltbedingungen.&lt;br /&gt;
&lt;br /&gt;
Der optionale Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; definiert eine &#039;&#039;&#039;vorrangige Ausschaltbedingung&#039;&#039;&#039; (Regex). Sobald diese Bedingung erfüllt ist, wird der Consumer ausgeschaltet auch wenn die geplante Endezeit (consumerXX_planned_stop) noch nicht erreicht ist (&#039;&#039;&#039;ODER-Verknüpfung&#039;&#039;&#039;). Weitere Bedingungen wie off-Schlüssel und auto-Mode müssen zum automatischen Ausschalten erfüllt sein.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; kann während der geplanten Einschaltzeit eine automatische Unterbrechung sowie Wiedereinschaltung des Verbrauchers vorgenommen werden. Der Verbraucher wird temporär ausgeschaltet (interrupted) und wieder eingeschaltet (continued) wenn die Interrupt-Bedingung nicht mehr vorliegt. Die verbleibende Laufzeit wird durch einen Interrupt nicht beeinflusst! &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;power&#039;&#039;&#039; gibt die nominale Leistungsaufnahme des Verbrauchers gemäß seines Datenblattes an. Dieser Wert wird verwendet um die Schaltzeiten des Verbrauchers zu planen und das Schalten in Abhängigkeit des tatsächlichen PV-Überschusses zum Einplanungszeitpunkt zu steuern. Ist &#039;&#039;&#039;power=0&#039;&#039;&#039; gesetzt, wird der Verbraucher unabhängig von einem zum Zeitpunkt des Zyklus-Start eventuell nicht ausreichend vorhandenem PV-Überschuss wie geplant eingeschaltet und somit der Zyklus gestartet.&lt;br /&gt;
&lt;br /&gt;
Durch die Schlüssel &#039;&#039;&#039;notbefore&#039;&#039;&#039; und &#039;&#039;&#039;notafter&#039;&#039;&#039; kann der Startzeitpunkt des Verbrauchers so gesteuert werden, dass der Start des Zyklus nicht vor bzw. nach der angegebenen Zeit eingeplant wird. Diese Steuerung bezieht sich auf die &#039;&#039;Planung&#039;&#039;, d.h. der eigentliche Start des Verbrauchers kann sich unter Umständen durch vorhandene Rahmenbedingungen verzögern. &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; legt die geplanten Einschaltzeit, d.h. die Laufzeit des Zyklus fest. Der Name &#039;&#039;&#039;mintime&#039;&#039;&#039; ist nicht als MInimum-Zeit zu deuten, sondern beschreibt die angegebene Zeit in Minuten die der Zyklus dauern soll.&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist optional, da sich die Standard-Laufzeit des Verbrauchers von dessen Typ abgeleitet wird. Diese Standard Laufzeiten sind:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|dryer&lt;br /&gt;
|90 Minten&lt;br /&gt;
|-&lt;br /&gt;
|dishwasher&lt;br /&gt;
|180 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|washingmachine&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|heater&lt;br /&gt;
|240 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|charger&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|other&lt;br /&gt;
|60 Minuten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Der Verbraucher wurde nicht gestartet obwohl die Startzeit der Einplanung erreicht wurde ===&lt;br /&gt;
&lt;br /&gt;
Wenn die Startzeit des Consumers entsprechend der Einplanung erreicht oder überschritten ist, wird der Consumer eingeschaltet wenn die weiteren Voraussetzungen wahr sind:&lt;br /&gt;
&lt;br /&gt;
* es ist aktuell ein PV-Überschuss vorhanden und der PV-Überschuss deckt die kalkulierten Leistungsaufnahme des Verbrauchers ab. Mit den Schlüsseln &#039;&#039;&#039;power&#039;&#039;&#039; und &#039;&#039;&#039;spignorecond&#039;&#039;&#039; kann die Einschaltung trotz fehlendem PV-Überschuss ermöglicht werden. &lt;br /&gt;
&lt;br /&gt;
* die Angabe im Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; ist wahr (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* das Schalten ist über den Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; freigegeben (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* im Schlüssel &#039;&#039;&#039;on&#039;&#039;&#039; ist ein valides Einschaltkommando hinterlegt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind diese zusätzlichen Bedingungen nicht erfüllt, erfolgt kein Start des eingeplanten Zyklus. Der Verbraucher verbleibt in diesem Fall weiterhin im Status &#039;&#039;planned&#039;&#039; oder &#039;&#039;suspended&#039;&#039;. Die Startbedingungen werden regelmäßig reviewed und der Consumer gestartet sobald alle Startbedingungen wahr sind bzw. Start verhindernde Bedingungen entfallen sind. &lt;br /&gt;
&lt;br /&gt;
Dieser Vorgang erfolgt bis das geplante Ende des Verbaucherzyklus erreicht ist oder die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; zutrifft. Sobald die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; wahr ist, wird der gesamte Planungszyklus des Consumers beendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Kann manuell / automatisiert in den Planungszyklus eines Verbrauchers eingegriffen werden? ===&lt;br /&gt;
&lt;br /&gt;
Die Einplanung und die darauf aufbauenden Schaltprozesse laufen gemäß den hinterlegten Schlüsseloptionen im Modul automatatisch ab ohne dass ein Eingriff durch den Anwender erfolgen muß.&lt;br /&gt;
&lt;br /&gt;
Dennoch kann es gewünscht sein eine Neuplanung oder eine Sofortplanung eines Consumers vorzunehmen weil der Bedarf dazu besteht. Zu diesem Zweck stehen die Set-Kommandos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* consumerNewPlanning &lt;br /&gt;
&lt;br /&gt;
* consumerImmediatePlanning &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
zur Verfügung. &lt;br /&gt;
Beide Befehle initiieren die Consumer-Neuplanung, wobei mit dem Befehl &#039;&#039;consumerImmediatePlanning&#039;&#039; die eventuell im consumerXX Attribut gesetzten Schlüssel notbefore, notafter bzw. mode werden nicht beachtet werden. Dagenen beachtet der Befehl &#039;&#039;consumerNewPlanning&#039;&#039; alle definierten Schlüsseloptionen und dient gewöhnlich dazu einen abgeschlossenen Verbraucherzyklus wiederholt ausführen zu lassen weil die aktuelle Witterungslage dazu geeignet ist. &lt;br /&gt;
&lt;br /&gt;
Ein Anwendungsbeispiel dafür ist zum Beispiel die Ausführung von mehreren Waschmaschinen-Zyklen an einem langen, sonnigen Sommertag.&lt;br /&gt;
Diese beiden Set-Befehle können zum Beispiel über ein auf einen Schalter/Taster reagierendes Notify oder DOIF Device ausgeführt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung eines Verbrauchers mit getrennten Geräten für Messung und Schalten ===&lt;br /&gt;
&lt;br /&gt;
Es existieren in FHEM Geräte, die über verschiedene Kanäle für unterschiedliche Aufgaben verfügen. Diese Kanäle werden jeweils in einem gesonderten Device abgebildet. HomeMatic oder readingsProxy sind Beispiele für solche Varianten.&lt;br /&gt;
&lt;br /&gt;
Um solche Verbraucher einzubinden gibt es im consumerXX Attribut den Schlüssel &#039;&#039;&#039;switchdev&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Bei der Registrierung gibt man als Consumerdevice das Gerät für die Messung an und im Schüssel switchdev das entsprechende FHEM-Device, welches für die Schaltvorgänge benutzt wird. &lt;br /&gt;
Ist switchdev angegeben, beziehen sich die weiteren Schlüssel on, off, swstate, auto und asynchron auf dieses Gerät.&lt;br /&gt;
&lt;br /&gt;
In dem nachfolgenden Beispiel (Homematic) ist &#039;&#039;eg.az.fridge_Pwr&#039;&#039; FHEM Device für die Energiemessung. Die Schlüssel &#039;&#039;pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; geben Readings in diesem Device an damit SolarForecast den Verbrauch und die Energiemengen auslesen kann. Demgegenüber ist im Schlüssel &#039;&#039;switchdev&#039;&#039; das zugehörige Schalter-Device der Kombination angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eg.az.fridge_Pwr&lt;br /&gt;
type=noSchedule switchdev=eg.az.fridge_Sw power=0 icon=fridge pcurr=power:W:5 etotal=energyCalc:Wh &lt;br /&gt;
swstate=state:on:off auto=automatic&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung von Verbrauchern ohne Zeitplanung und aktivem Schalten ===&lt;br /&gt;
Manchmal besteht der Wunsch, Verbraucher in SolarForecast zu integrieren um lediglich folgende Sachverhalte abzubilden:&lt;br /&gt;
&lt;br /&gt;
* Visualisierung des Schaltstatus in der Consumer Legende und/oder der Energieflußgrafik&lt;br /&gt;
* Darstellung des aktuellen Energieverbrauchs in der Energieflußgrafik&lt;br /&gt;
* Erfassung der (externen) Schaltzeiten, d.h. der Zeiten der Gerätenutzung sowie der Verbrauchsdaten um deren Einfluß bei den Planungszeiten anderer Geräte durch SolarForecast berücksichtigen zu lassen&lt;br /&gt;
&lt;br /&gt;
In solchen Fällen werden bei der Registrierung die Schlüssel &#039;&#039;swstate, pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; zur Erfassung der Schaltzustände und der Energieverbrauchs angegeben, jedoch zur Verhinderung der Zeitplanung durch SolarForecast der Schlüssel &#039;&#039;&#039;type=noSchedule&#039;&#039;&#039; gesetzt sowie die Schlüssel &#039;&#039;on&#039;&#039; und &#039;&#039;off&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt eine mögliche Registrierung eines Zwischensteckers (Shelly) zur Erfassung der Daten eines Gefrierschrankes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Shelly.shellyplug4&lt;br /&gt;
type=noSchedule power=65 asynchron=1&lt;br /&gt;
icon=gefrierschrank &lt;br /&gt;
swstate=state:.*on.*:.*off.* &lt;br /&gt;
pcurr=relay_0_power:W:5 etotal=relay_0_energy_Wh:Wh&lt;br /&gt;
&amp;lt;/pre&amp;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;
&lt;br /&gt;
 Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off&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;
&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;
&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. Alternativ kann die Berücksichtigung des zwangsweisen PV Überschuss mit dem Schlüssel &amp;quot;spignorecond&amp;quot; im Consumer-Attribut ausgesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== zusätzliche Readings bzw. Erzeugung von statistischen Readings ==&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den zahlreichen im Modul per Standard erzeugten Readings kann der Anwender weitere Readings generieren lassen.&lt;br /&gt;
Diese zusätzlichen Readings geben entweder einen bestimmten Sachverhalt (Laufzeit, Status der API-Abfragen, etc.) oder einen statistischen Wert, z.B. die Batterieentladung des aktuellen Tages, wieder.&lt;br /&gt;
&lt;br /&gt;
Die zusätzlich erstellten Readings sind durch den Präfix &#039;&#039;&#039;special_&#039;&#039;&#039; im Device gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Diese zusätzlichen Informationen können durch das Setzen einer oder mehrerer Kennzeichen im Attribut &#039;&#039;&#039;ctrlSpecialReadings&#039;&#039;&#039; erzeugt werden. Die mögliche Auswahl wird je nach Bedarf ausgebaut und umfasst zum aktuellen Zeitpunkt (07.02.2025) diese Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;BatPowerIn_Sum: 	die Summe der momentanen Batterieladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;BatPowerOut_Sum: 	die Summe der momentanen Batterieentladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;allStringsFullfilled: 	Erfüllungsstatus der fehlerfreien Generierung aller Strings&lt;br /&gt;
;conForecastTillNextSunrise: 	Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
;currentAPIinterval: 	das aktuelle Abrufintervall der gewählten Strahlungsdaten-API in Sekunden&lt;br /&gt;
;currentRunMtsConsumer_XX: 	die Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; seit dem letzten Einschalten. (letzter Laufzyklus)&lt;br /&gt;
;dayAfterTomorrowPVforecast: 	liefert die Vorhersage der PV Erzeugung für Übermorgen (sofern verfügbar) ohne Autokorrektur (Rohdaten).&lt;br /&gt;
;daysUntilBatteryCare_XX: 	Tage bis zur nächsten Batterie XX Pflege (Erreichen der Ladung &#039;maxSoC&#039; aus Attribut ctrlBatSocManagementXX)&lt;br /&gt;
;lastretrieval_time: 	der letzte Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;lastretrieval_timestamp: 	der Timestamp der letzen Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;response_message: 	die letzte Statusmeldung der gewählten Strahlungsdaten-API&lt;br /&gt;
;runTimeAvgDayConsumer_XX: 	die durchschnittliche Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; an einem Tag&lt;br /&gt;
;runTimeCentralTask: 	die Laufzeit des letzten SolarForecast Intervalls (Gesamtprozess) in Sekunden&lt;br /&gt;
;runTimeTrainAI: 	die Laufzeit des letzten KI Trainingszyklus in Sekunden&lt;br /&gt;
;runTimeLastAPIAnswer: 	die letzte Antwortzeit des Strahlungsdaten-API Abrufs auf einen Request in Sekunden&lt;br /&gt;
;runTimeLastAPIProc: 	die letzte Prozesszeit zur Verarbeitung der empfangenen Strahlungsdaten-API Daten&lt;br /&gt;
;SunMinutes_Remain: 	die verbleibenden Minuten bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;SunHours_Remain: 	die verbleibenden Stunden bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;todayConsumptionForecast: 	Verbrauchsprognose pro Stunde des aktuellen Tages (01-24)&lt;br /&gt;
;todayConForecastTillSunset: 	Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
;todayDoneAPIcalls: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Calls&lt;br /&gt;
;todayDoneAPIrequests: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Requests&lt;br /&gt;
;todayConsumption: 	der gesamte Energieverbrauch (Wh) des Hauses am aktuellen Tag&lt;br /&gt;
;todayGridConsumption: 	die aus dem öffentlichen Netz bezogene Energie am aktuellen Tag&lt;br /&gt;
;todayGridFeedIn: 	die in das öffentliche Netz eingespeiste PV Energie am aktuellen Tag&lt;br /&gt;
;todayMaxAPIcalls: 	die maximal mögliche Anzahl Strahlungsdaten-API Calls. Ein Call kann mehrere API Requests enthalten.&lt;br /&gt;
;todayRemainingAPIcalls: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Calls&lt;br /&gt;
;todayRemainingAPIrequests: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Requests&lt;br /&gt;
;todayBatIn_XX: 	die am aktuellen Tag in die Batterie XX geladene Energie&lt;br /&gt;
;todayBatInSum: 	Summe der am aktuellen Tag in alle Batterien geladene Energie&lt;br /&gt;
;todayBatOut_XX: 	die am aktuellen Tag aus der Batterie XX entnommene Energie&lt;br /&gt;
;todayBatOutSum: 	Summe der am aktuellen Tag aus allen Batterien entnommene Energie&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Manche Angaben sind im Setup des Moduls optional, d.h. sie müssen nicht zwingend beim Setup angegeben werden. Allerdings sind diese Angaben für die Erstellung eines zusätzlichen Readings unter Umständen Voraussetzung. Es empfiehlt sich deshalb bei Setup so viele Informationen wie möglich zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
So ist zum Beispiel für die sinnvolle Erstellung der Informationen &#039;&#039;&#039;todayBatInSum&#039;&#039;&#039; und &#039;&#039;&#039;todayBatOutSum&#039;&#039;&#039; (Readings special_todayBatInSum und special_todayBatOutSum) das Vorhandensein der Schlüssel &#039;&#039;intotal&#039;&#039; und &#039;&#039;outtotal&#039;&#039; im Attribut setupBatteryDevXX notwendig (Beispiel):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupBatteryDev01 MQTT2_cerboGX_c0619ab34e08_battery &lt;br /&gt;
                              pin=BatIn:W pout=BatOut:W charge=SOC_value intotal=BatInTotal:Wh outtotal=BatOutTotal:Wh &lt;br /&gt;
                              cap=InstalledCapacity_Wh:Wh asynchron=1 show=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Fehlersuche ==&lt;br /&gt;
Das Modul SolarForecast ist sehr komplex und es die verschiedensten Datenquellen ausgewertet, zusammengeführt und daraus Ergebnisse berechnet und/oder visualisiert. Wird etwas nicht wie erwartet durch das Modul geliefert, können die Ursachen vielfältig sein. Natürlich kann ein Fehler im Modulcode vorliegen, oftmals gibt es aber andere Ursachen.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgenden Hinweise sollen Hilfe zur Selbsthilfe geben und sind eine Zusammenfassung von realen Fällen die mit dem beschriebenen Wegen und Verfahren gelöst wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die erwartete erzeugte PV-Energie ist im Modul zu gering und wird im Balkendiagramm nicht angezeigt === &lt;br /&gt;
&lt;br /&gt;
Die erzeugte PV-Energie wird nicht richtig angezeigt: Am Vormittag sind keine Werte vorhanden und, wenn dann etwas kommt, ist die Anzeige zu gering. Für 13 und 14 Uhr wurden ca. 5.000Wh erwartet (im Vergleich mit den Daten aus einer anderen Auswertungsquelle). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lösungsweg:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Aus dem List des Devices wurden die für den Fall wesentlichen Readings herausgezogen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVforecast 152 Wh&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVforecast 1400 Wh&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVforecast 2500 Wh&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVforecast 4392 Wh&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVforecast 4000 Wh&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVreal 300 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVforecast 6415 Wh&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVreal 3200 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVforecast 5629 Wh&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVreal 2700 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVforecast 3958 Wh&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVreal 900 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVforecast 945 Wh&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVreal 500 Wh&lt;br /&gt;
   &lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour18_PVforecast 59 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man sieht dass bis 12:00 keine erzeugte Energie vom WR gemeldet wird. Deswegen wird in der Balkengrafik nichts dargestellt. Auch danach bleibt die registrierte PV-Energie hinter den Erwartungen zurück. Zuständig für die Lieferung der PV-Energie an das Modul ist das Reading im Schlüssel:&lt;br /&gt;
&lt;br /&gt;
 setupInverterDev01 SH10rt pv=Total_DC_Power:W &amp;lt;mark&amp;gt;etotal=Total_Export_Energy_from_PV:kWh&amp;lt;/mark&amp;gt; capacity=10000 strings=Hauptdach,Flachdach&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Welche Änderungen es zwischen den Stunden gab, sieht man mit einem &amp;quot;get ... pvHistory XX&amp;quot; (&amp;quot;XX&amp;quot; steht für das Datum, d.h. den Tag, z.B. 02). &amp;lt;br&amp;gt;&lt;br /&gt;
Hier ein Beispiel für die Stunden 10 (9:00 - 9:59) und 11 (10:00 - 10:59). &amp;lt;br&amp;gt;&lt;br /&gt;
Wichtig ist hier der Key etotali01 für den ersten Inverter. Die Differenz zwischen den Werten beider Stunden ist die in der Stunde erzeugte Energie (hier 380 Wh). Diese 380 Wh findest du auch im Key pvrl01 als PVReal für diese Stunde. Das Modul rechnet intern immer mit Wh, kWh werden vorher in Wh umgerechnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
10 =&amp;gt; pvfc: 365, pvrl: 530, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63364714&amp;lt;/mark&amp;gt;, etotali02: 3044110, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;pvrl01: 380&amp;lt;/mark&amp;gt;, pvrl02: 150, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 574, con: 518, gcons: 22, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 1, feedprice: 0.1269&lt;br /&gt;
&lt;br /&gt;
            DoN: 1, sunaz: 137, sunalt: 12&lt;br /&gt;
&lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
      11 =&amp;gt; pvfc: 2966, pvrl: 1862, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63365094&amp;lt;/mark&amp;gt;, etotali02: 3044260, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            pvrl01: 1392, pvrl02: 470, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 774, con: 609, gcons: 25, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 4, feedprice: 0.1269&lt;br /&gt;
           &lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
D.h. wenn zwischen den beiden Stunden keine Differenzen zu finden sind, liegt es sehr wahrscheinlich am Input des Readings:&lt;br /&gt;
&lt;br /&gt;
 etotal=Total_Export_Energy_from_PV:kWh&lt;br /&gt;
&lt;br /&gt;
welches sich in den ersten Stunden nicht ändert und danach auch nur wenig.&lt;br /&gt;
&lt;br /&gt;
Man kann mit dem Attribut:&lt;br /&gt;
&lt;br /&gt;
 ctrlDebug=collectData&lt;br /&gt;
&lt;br /&gt;
die Datensammlung verfolgen (leider entstehen viele Daten im Log). Man sieht welche Werte von dem Inverter/Reading geliefert werden:&lt;br /&gt;
 &lt;br /&gt;
 ....&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; collect Inverter 01 data - device: STP_5000, delivery: default =&amp;gt;&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; pv: 0 W, &amp;lt;mark&amp;gt;etotal: 63378810 Wh&amp;lt;/mark&amp;gt;&lt;br /&gt;
 ....&lt;br /&gt;
&lt;br /&gt;
Dieser Wert muß bei PV Erzeugung kontinuierlich hochzählen. Wenn nicht, muss das angegebene Reading, d.h. die Quelle überprüft werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ergebnis der Prüfung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tatsächlich wurde ein Reading benutzt, das ungeeignet war: Statt &amp;quot;Total_PV_Generation&amp;quot; wurde &amp;quot;Total_export_energy_from_PV&amp;quot; genutzt. In diesem Reading wurde immer die in die Batterie gespeicherte Energie von der gesamten erzeugten Energie abgezogen. Daher war auch vormittags alles 0, da in dieser Periode alle PV-Energie in die Batterie geladen wurde bzw. in weiteren Stunden ein Anteil der dann bei dem PV-Erzeugungswert fehlte.&lt;br /&gt;
&lt;br /&gt;
Nachdem die Ursache beseitigt war, zeigt SolarForecast wieder die erwarteten PV-Erzeugungswerte an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Konfigurationsbeispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Visualisierung solare Vorhersage und reale Erzeugung ===&lt;br /&gt;
&lt;br /&gt;
Zu Beginn jedes neuen Tages gegen 00:00 Uhr werden durch das SolarForecast Device Events für die initiale PV Prognose des kommenden Tages erstellt.&lt;br /&gt;
Der Readingteil dieser Events heißt&lt;br /&gt;
&lt;br /&gt;
 AllPVforecastsToEvent&lt;br /&gt;
&lt;br /&gt;
Die Uhrzeiten der Events sind so aufbereitet und können direkt geloggt werden um sie in einen SVG Plot zu integrieren.&lt;br /&gt;
Im SolarForecast Device ist dieses Reading nicht sichtbar, nur die Events werden erstellt.&lt;br /&gt;
&lt;br /&gt;
Die meteorologischen Bedingungen verändern sich über den Tag permanent. Je nach gewählter Strahlungsdatenquelle (eine API oder DWD Device) erfolgt eine mehr oder weniger dynamische Anpassung der Prognose an die sich verändernde Umwelt.&lt;br /&gt;
&lt;br /&gt;
Aktuelle Prognosedaten sowie die reale PV Erzeugung der vergangenen Stunde können über die Readings&lt;br /&gt;
&lt;br /&gt;
 LastHourPVforecast&lt;br /&gt;
 LastHourPVreal&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-10-20 134050.png|right|thumb|400px|Übersicht solare Vorhersage]]&lt;br /&gt;
geloggt werden. &lt;br /&gt;
&lt;br /&gt;
Werden alle drei Werte in einem SVG kombiniert, kann die Entwicklung der Prognose über den Tag und die Beziehung von Prognose zu realer PV Erzeugnung pro Stunde visualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Für das rechts abgebildete Beispiel des Plots aus einer Datenbank &amp;quot;LogDBShort&amp;quot; sieht das gplot-File wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Created by FHEM/98_SVG.pm, 2024-03-08 15:05:31&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;TL&amp;gt;&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid&lt;br /&gt;
set ylabel &amp;quot;Wh&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Wh&amp;quot;&lt;br /&gt;
set yrange [0:7500]&lt;br /&gt;
set y2range [0:7500]&lt;br /&gt;
&lt;br /&gt;
#LogDBShort SolCast:LastHourPVforecast:::&lt;br /&gt;
#LogDBShort SolCast:LastHourPVreal:::&lt;br /&gt;
#LogDBShort SolCast:AllPVforecastsToEvent:::&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;aktuelle PV Vorhersage&#039; ls l6fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;reale PV Erzeugung&#039; ls l2fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;initiale PV Vorhersage&#039; ls l4 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; In manchen Fällen werden die Vorhersagewerte im SVG-Plot nicht angezeigt wenn FileLog verwendet wird. Ein Setzen des Attribute &amp;quot;fixedrange=3days +1&amp;quot; im SVG löst das Problem. Die Definition des SVG-Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_LogDBShort_SolCast SVG LogDBShort:SVG_LogDBShort_SolCast:HISTORY&lt;br /&gt;
attr SVG_LogDBShort_SolCast fixedrange 3days +1&lt;br /&gt;
attr SVG_LogDBShort_SolCast room Energie-&amp;gt;SolarPrognose&lt;br /&gt;
attr SVG_LogDBShort_SolCast sortby 2&lt;br /&gt;
attr SVG_LogDBShort_SolCast title &amp;quot;Übersicht solare Vorhersage&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Technisch bedingt werden an einem Tag X kurz nach 00:00 Uhr die am Vortag für den Tag X erzeugten Events aktualisiert. Diese Daten erzeugen in der Datenbank einen zweiten Satz an Daten mit dem gleichen Timestamp was für die Anzeige unvorteilhaft ist. &lt;br /&gt;
Um nur die aktualisierten Events von &#039;&#039;&#039;AllPVforecastsToEvent&#039;&#039;&#039; in der Datenbank zu erhalten, bietet sich ein DbRep-Device an. Die nachfolgende Vorschlagsdefinition kann per at-Device jeden Tag kurz vor Mitternacht (z.B. 23:57:10) ausgeführt werden. Es werden immer die in der Vergangenheit geschriebenen (veralteten) Daten aus der Datenbank gelöscht, doppelte Datesätze vermieden und immer die aktuellste initiale Prognose gespeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.Del.AllPVforecastsToEvent DbRep LogDBShort&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent alias Löschen Readings AllPVforecastsToEvent des Folgetages&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent comment ermöglicht dass die Readings AllPVforecastsToEvent am Folgetag wieder neu und aktuell geschrieben werden können&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent devStateIcon initialized:control_3dot_hor_s connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent disable 0&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent event-on-update-reading state&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent icon edit_delete&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent showproctime 1&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent device TYPE=SolarForecast&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_begin next_day_begin&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_end next_day_end&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das angegebene DbLog-Device &#039;&#039;&#039;LogDBShort&#039;&#039;&#039; ist natürlich anzupassen.&lt;br /&gt;
&lt;br /&gt;
Das at-Device zum Starten der Datenbankbereinigung sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define At.Del.AllPVforecastsToEvent at *23:58:10 set Rep.Del.AllPVforecastsToEvent delEntries&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent alias Start Löschen Readings AllPVforecastsToEventn LogDBShort&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent icon clock&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich sind auch hier die eigenen Devicenamen entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
Ab SolarForecast Version 1.51.7 kann die Eventerzeugung für bestimmte SVG Plot-Typen optimiert werden. &amp;lt;br&amp;gt; &lt;br /&gt;
Die Aktivierung dieser Optimierungen ist in der Online Hilfe zum Attribut &#039;&#039;&#039;plantControl-&amp;gt;genPVforecastsToEvent&#039;&#039;&#039; beschrieben. Bei Nutzung des Attributes plantControl-&amp;gt;genPVforecastsToEvent ist ebenfalls das Attribut &#039;&#039;&#039;event-on-update-reading=AllPVforecastsToEvent&#039;&#039;&#039; zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispielkonfiguration 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;
Bitte dabei diese DWD-Version aus dem [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter Contrib] von DS_Starter dazu nutzen&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|55_DWD_OpenData.pm&lt;br /&gt;
|136.2 KB ​&lt;br /&gt;
|29260  &lt;br /&gt;
|DS_Starter&lt;br /&gt;
|55_DWD_OpenData: contrib 1.17.7&lt;br /&gt;
|}&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 downloadTimeout 120&lt;br /&gt;
attr DWD comment Im DWD Wetterdevice verwendet Solarforecast : \&lt;br /&gt;
TTT,Neff,RR1c,ww,SunUp,SunRise,SunSet \&lt;br /&gt;
zusätzlich ist jedoch auch noch Rad1h notwendig \&lt;br /&gt;
wenn dieses DWD-Device als Strahlungsdevice genutzt wird.\&lt;br /&gt;
Die Station 10418 (Lüdenscheid) überträgt aktuell am 09.03.2025 (noch) Rad1h.\&lt;br /&gt;
attr DWD downloadTimeout 120&lt;br /&gt;
attr DWD forecastDays 7&lt;br /&gt;
attr DWD forecastProperties SunUp, SunRise, SunSet, Rad1h, R101, RR1c, TTT, Tx, Tn, Tg, DD, FX1, RR6c, R600, RRhc, Rh00, ww, wwd, Neff&lt;br /&gt;
attr DWD forecastRefresh 1&lt;br /&gt;
attr DWD forecastResolution 1&lt;br /&gt;
attr DWD forecastStation 10418&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 fc_description  -(state fc_time)&lt;br /&gt;
attr DWD verbose 2&lt;br /&gt;
&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;
defmod InverterDummy dummy&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;
defmod 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 feedinPrice 0.08&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 powerCost 0.25&lt;br /&gt;
attr SMA_Energymeter room 015_Zaehler,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;
defmod 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;
attr BatteryDummy userReadings total_pac, power_out, power_in, chargestatus, bat_rated_capacity, bat_loadtotal, bat_unloadtotal&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;
defmod N.PV.TotalConsumption.Dum.Energy notify SMA_Energymeter:Saldo_Wirkleistung:.* {\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung_2 Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&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;MB_USRW610_004&amp;quot;,&amp;quot;Power_Sum__W&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;
fhem &amp;quot;setreading InverterDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(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;
#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;
 # Batterie-total_pac  InverterDummy\&lt;br /&gt;
my $wert7 = sprintf(&amp;quot;%.3f&amp;quot;,((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy bat_rated_capacity &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert7));;\&lt;br /&gt;
 # möglicher Aufruf einer Batterie-Bebladung-Routine....SMABatteryChargewithTibber();;\&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;
defmod Forecast SolarForecast&lt;br /&gt;
attr Forecast DbLogExclude .*&lt;br /&gt;
attr Forecast DbLogInclude Current_BatCharge999&lt;br /&gt;
attr Forecast affectBatteryPreferredCharge 30&lt;br /&gt;
attr Forecast affectConsForecastLastDays 31&lt;br /&gt;
attr Forecast affect70percentRule 0&lt;br /&gt;
attr Forecast comment &amp;quot;wget -qO ./FHEM/76_SolarForecast.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/76_SolarForecast.pm&amp;quot;\&lt;br /&gt;
&amp;quot;wget -qO ./FHEM/55_DWD_OpenData.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/55_DWD_OpenData.pm&amp;quot;\&lt;br /&gt;
&amp;quot;13.01.2025 mit der Version 76_SolarForecast.pm:v1.43.2-s29518/2025-01-12&amp;quot;&lt;br /&gt;
attr Forecast graphicHeaderOwnspec PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal Verbrauch&amp;amp;nbsp;;bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast  Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest FCU-Erzeugung&amp;amp;nbsp;;:Current_PP01\&lt;br /&gt;
attr Forecast consumer01 FBDECT_fbahahttp_11657_0127183 icon=scene_washing_machine@orange type=washingmachine power=10 swstate:state notbefore=09 notafter=20 pcurr=power:W:3 etotal=energy:Wh interruptable=1 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer02 FBDECT_fbahahttp_E8_DF_70_07_3E_57 icon=light_floor_lamp@orange type=other power=15 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer03 FBDECT_fbahahttp_E8_DF_70_07_42_0B icon=raspberrypi@orange type=other power=8 swstate:state pcurr=power:W:1 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer04 FBDECT_fbahahttp_11657_0067275 icon=springbrunnen_icon@orange type=other power=50 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer05 FBDECT_fbahahttp_34_31_C4_D4_31_37 icon=sani_domestic_waterworks@orange type=other power=10 swstate:state pcurr=power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer06 tuya_local_bf5037060f450bdbd4rl0q icon=scene_clothes_dryer@orange type=dryer power=10 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer07 tuya_local_bfac44fb487476efd1vhdu icon=weather_sunset@orange type=noSchedule power=5 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumerControl adviceIcon=light_light_dim_100@gold&lt;br /&gt;
attr Forecast consumerControl showLegend=icon_top&lt;br /&gt;
attr Forecast consumerControl detailLink=1&lt;br /&gt;
attr Forecast ctrlAIdataStorageDuration 1825&lt;br /&gt;
attr Forecast ctrlAIshiftTrainStart 2&lt;br /&gt;
attr Forecast ctrlBatSocManagement01 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlBatSocManagement02 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlDebug none&lt;br /&gt;
attr Forecast plantControl genPVdeviation=continuously&lt;br /&gt;
attr Forecast plantControl cycleInterval=15&lt;br /&gt;
attr Forecast ctrlNextDayForecastReadings 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24&lt;br /&gt;
attr Forecast ctrlNextHoursSoCForecastReadings 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23&lt;br /&gt;
attr Forecast ctrlSpecialReadings BatPowerIn_Sum,BatPowerOut_Sum,SunHours_Remain,SunMinutes_Remain,allStringsFullfilled,conForecastTillNextSunrise,currentAPIinterval,currentRunMtsConsumer_01,currentRunMtsConsumer_02,currentRunMtsConsumer_03,currentRunMtsConsumer_04,currentRunMtsConsumer_05,currentRunMtsConsumer_06,currentRunMtsConsumer_07,dayAfterTomorrowPVforecast,daysUntilBatteryCare_01,daysUntilBatteryCare_02,lastretrieval_time,lastretrieval_timestamp,response_message,runTimeAvgDayConsumer_01,runTimeAvgDayConsumer_02,runTimeAvgDayConsumer_03,runTimeAvgDayConsumer_04,runTimeAvgDayConsumer_05,runTimeAvgDayConsumer_06,runTimeAvgDayConsumer_07,runTimeCentralTask,runTimeLastAPIAnswer,runTimeLastAPIProc,runTimeTrainAI,todayBatIn_01,todayBatIn_02,todayBatOut_01,todayBatOut_02,todayConForecastTillSunset,todayConsumptionForecast,todayDoneAPIcalls,todayDoneAPIrequests,todayGridConsumption,todayGridFeedIn,todayMaxAPIcalls,todayRemainingAPIcalls,todayRemainingAPIrequests&lt;br /&gt;
attr Forecast disable 0&lt;br /&gt;
attr Forecast event-min-interval .*:1800&lt;br /&gt;
attr Forecast event-on-change-reading .*&lt;br /&gt;
attr Forecast flowGraphicControl animate=1 consumerdist=80 h2consumerdist=50 shiftx=0  shifty=0 showconsumer=1 showconsumerdummy=1 showconsumerpower=1 showconsumerremaintime=0 size=400 strokewidth=12&lt;br /&gt;
attr Forecast graphicBeam1Color 3C14FF&lt;br /&gt;
attr Forecast graphicBeam1Content pvReal&lt;br /&gt;
attr Forecast graphicBeam2Color 19FF29&lt;br /&gt;
attr Forecast graphicBeam2Content pvForecast&lt;br /&gt;
attr Forecast graphicBeam3Color D60924&lt;br /&gt;
attr Forecast graphicBeam3Content batsocforecast_02&lt;br /&gt;
attr Forecast graphicBeam3FontColor FFFF0D&lt;br /&gt;
attr Forecast graphicBeam4Color FFFF1F&lt;br /&gt;
attr Forecast graphicBeam4Content batsocforecast_01&lt;br /&gt;
attr Forecast graphicBeam4FontColor 000000&lt;br /&gt;
attr Forecast graphicBeamHeightLevel1 200&lt;br /&gt;
attr Forecast graphicBeamHeightLevel2 200&lt;br /&gt;
attr Forecast graphicHeaderDetail all&lt;br /&gt;
attr Forecast graphicHeaderOwnspec #PV\&lt;br /&gt;
PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal\&lt;br /&gt;
PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast\&lt;br /&gt;
PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast\&lt;br /&gt;
:\&lt;br /&gt;
#\&lt;br /&gt;
AutarkyRate:Current_AutarkyRate\&lt;br /&gt;
Überschuss:Current_Surplus\&lt;br /&gt;
aktueller&amp;amp;nbsp;;Netzbezug:Current_GridConsumption\&lt;br /&gt;
:\&lt;br /&gt;
#Verbrauch\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenuntergang:special_todayConForecastTillSunset\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie01\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_01\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_01\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_01\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_01\&lt;br /&gt;
#Batterie01_tmp\&lt;br /&gt;
Current_PowerBatIn_01:Current_PowerBatIn_01\&lt;br /&gt;
Current_PowerBatOut_01:Current_PowerBatOut_01\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie02\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_02\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_02\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_02\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_02\&lt;br /&gt;
#Batterie02_tmp\&lt;br /&gt;
Current_PowerBatIn_02:Current_PowerBatIn_02\&lt;br /&gt;
Current_PowerBatOut_02:Current_PowerBatOut_02\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Settings\&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto \&lt;br /&gt;
Wetter:graphicShowWeather\&lt;br /&gt;
History:graphicHistoryHour\&lt;br /&gt;
ShowNight:graphicShowNight\&lt;br /&gt;
Debug:ctrlDebug\&lt;br /&gt;
FCU-Modus:FCU-Betriebsmodus@FCU&lt;br /&gt;
attr Forecast graphicHistoryHour 4&lt;br /&gt;
attr Forecast graphicHourCount 24&lt;br /&gt;
attr Forecast graphicLayoutType double&lt;br /&gt;
attr Forecast graphicShowDiff top&lt;br /&gt;
attr Forecast graphicShowNight 1&lt;br /&gt;
attr Forecast graphicShowWeather 1&lt;br /&gt;
attr Forecast group Energy Meter&lt;br /&gt;
attr Forecast room 020_PV,Energie&lt;br /&gt;
attr Forecast setupBatteryDev01 SBS25 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupBatteryDev02 SBS25_2 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupInverterDev01 SB25 pv=total_pac:kW etotal=etotal:kWh capacity=2500 strings=GarageSE limit=70&lt;br /&gt;
attr Forecast setupInverterDev02 SB30 pv=total_pac:kW etotal=etotal:kWh capacity=3000 strings=GarageNW,HausNW limit=70&lt;br /&gt;
attr Forecast setupInverterDev03 SB40 pv=total_pac:kW etotal=etotal:kWh capacity=4000 strings=HausSE1,HausSE2,HausSW limit=70&lt;br /&gt;
attr Forecast setupInverterStrings GarageSE,GarageNW,HausNW,HausSW,HausSE1,HausSE2&lt;br /&gt;
attr Forecast setupMeterDev SMA_Energymeter gcon=Bezug_Wirkleistung:W contotal=Bezug_Wirkleistung_Zaehler:kWh gfeedin=Einspeisung_Wirkleistung:W feedtotal=Einspeisung_Wirkleistung_Zaehler:kWh conprice=0.25:€ feedprice=0.08123:€&lt;br /&gt;
attr Forecast setupOtherProducer01 icon=Heizung_FCU_green@red MB_USRW610_004 pcurr=Power_L1__W:W etotal=Energy_L1_import__kWh:kWh&lt;br /&gt;
attr Forecast setupRadiationAPI DWD&lt;br /&gt;
attr Forecast setupStringPeak GarageSE=2.75 GarageNW=3.200 HausNW=2.230 HausSW=2.230 HausSE1=2.200 HausSE2=2.200&lt;br /&gt;
attr Forecast setupWeatherDev1 DWD&lt;br /&gt;
attr Forecast stateFormat Current_PV&lt;br /&gt;
attr Forecast userReadings Current_BatCharge999 {((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))) / ( (ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0) * 1000)  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0)*1000))*100}&lt;br /&gt;
attr Forecast verbose 2&lt;br /&gt;
&lt;br /&gt;
setstate Forecast 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .FCU_FCU-Betriebsmodus 2&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_ctrlDebug none&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicHistoryHour 4&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowNight 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowWeather 1&lt;br /&gt;
setstate Forecast 2025-01-13 08:24:25 .associatedWith SMA_Energymeter FBDECT_fbahahttp_11657_0127183 FBDECT_fbahahttp_E8_DF_70_07_3E_57 FBDECT_fbahahttp_E8_DF_70_07_42_0B FBDECT_fbahahttp_11657_0067275 FBDECT_fbahahttp_34_31_C4_D4_31_37 tuya_local_bf5037060f450bdbd4rl0q tuya_local_bfac44fb487476efd1vhdu SBS25 SBS25_2 SB25 SB30 SB40 DWD MB_USRW610_004&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .lastupdateForecastValues 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .pvCorrectionFactor_Auto_Soll on_complex_ai&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .signaldone_01 done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .signaldone_02 done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .signaldone_03 done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .signaldone_04 done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .signaldone_05 done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .signaldone_06 done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .signaldone_07 done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .signaldone_08 done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .signaldone_09 done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .signaldone_10 done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .signaldone_11 done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .signaldone_12 done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .signaldone_13 done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .signaldone_14 done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .signaldone_15 done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .signaldone_16 done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .signaldone_17 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .signaldone_18 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_01 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_02 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_01 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_02 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_AutarkyRate 83 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 Current_BatCharge999 10&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_01 12 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_02 8 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Consumption 626 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridConsumption 2 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridFeedIn 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PP_01 746.0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PV 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_01 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_02 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_01 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_02 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumption 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumptionRate 0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Surplus 120 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourGridconsumptionReal 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_ConsumptionForecast 2944 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayConsumptionForecast 3609 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_01 272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PPreal_01 748 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PPreal_01 787 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_01 271 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PPreal_01 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PPreal_01 745 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_01 267 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PPreal_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_01 255 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PPreal_01 752 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_01 226 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_01 50 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PPreal_01 681 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_02 233 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_01 845 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridConsumption 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_01 37 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_02 90 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_01 351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_02 188 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridConsumption 447 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVforecast 127 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridConsumption 1650 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVforecast 478 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVreal 26 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridConsumption 513 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVforecast 868 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVreal 97 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridConsumption 576 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVforecast 1157 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVreal 320 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_01 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_02 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridConsumption 1272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridFeedIn 7 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVforecast 1238 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVreal 945 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_01 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_02 53 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridConsumption 955 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridFeedIn 31 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PPreal_01 562 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVforecast 1168 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVreal 1410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_01 703 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_02 500 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_01 22 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_02 18 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridConsumption 32 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridFeedIn 71 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PPreal_01 777 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVreal 1416 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_01 296 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_02 70 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_01 74 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_02 258 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridConsumption 13 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridFeedIn 17 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PPreal_01 732 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVforecast 880 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVreal 1051 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_01 47 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_02 126 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_01 102 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_02 75 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridConsumption 15 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridFeedIn 23 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PPreal_01 771 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVforecast 117 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVreal 86 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_02 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_02 67 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridConsumption 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridFeedIn 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PPreal_01 723 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_01 349 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_02 124 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_01 73 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_02 450 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridConsumption 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridFeedIn 6 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PPreal_01 671 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecastTime 2025-01-13 14:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVdeviation 30.17 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVforecast 7663 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVreal 5351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunRise 08:28&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunSet 16:46&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_ConsumptionForecast 17043 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour05_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour06_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour07_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour08_PVforecast 10 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour09_PVforecast 161 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour10_PVforecast 275 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour11_PVforecast 532 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour12_PVforecast 730 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour13_PVforecast 1252 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour14_PVforecast 818 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour15_PVforecast 1465 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour16_PVforecast 303 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour17_PVforecast 20 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour18_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour19_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour20_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour21_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour22_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour23_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour24_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_PVforecast 5566 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunRise 08:27&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunSet 16:47&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01 name=&#039;_Waschmaschine&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_start 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_stop 14.01.2025 11:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02 name=&#039;_Esszimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_currentPower 15.3 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03 name=&#039;_FCU&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_currentPower 7.15 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04 name=&#039;_Brunnen&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05 name=&#039;_Zisterne&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06 name=&#039;SW Trockner&#039; state=&#039;unknown&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_stop 14.01.2025 08:30:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07 name=&#039;SW Urlaubslicht-Wohnzimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;noSchedule&#039; info=&#039;von extern umgeschaltet&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 nextCycletime 18:54:09&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 pvCorrectionFactor_10 0.53 (automatic - old factor: 1.00, Sun Alt range: 5, Cloud range: 75, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 pvCorrectionFactor_11 0.56 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 70, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 pvCorrectionFactor_12 0.64 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 pvCorrectionFactor_13 0.88 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 pvCorrectionFactor_14 1.10 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 50, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 pvCorrectionFactor_15 1.01 (automatic - old factor: 1.06, Sun Alt range: 15, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 pvCorrectionFactor_16 1.09 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 45, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 pvCorrectionFactor_17 0.28 (automatic - old factor: 0.52, Sun Alt range: 0, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 pvCorrectionFactor_Auto on_complex_ai&lt;br /&gt;
setstate Forecast 2024-10-30 19:42:19 setupStringAzimuth GarageSE=-55 GarageNW=125 HausNW=125 HausSW=35 HausSE1=-55 HausSE2=-55&lt;br /&gt;
setstate Forecast 2024-10-30 19:37:38 setupStringDeclination GarageSE=40 GarageNW=40 HausNW=50 HausSW=50 HausSE1=50 HausSE2=50&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerIn_Sum 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerOut_Sum 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunHours_Remain 0.00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunMinutes_Remain 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_allStringsFullfilled 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_conForecastTillNextSunrise 9467 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentAPIinterval 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_01 132 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_02 184 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_03 329512 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_04 200 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_05 27 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_06 193 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_07 106 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_dayAfterTomorrowPVforecast 7344 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_01 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_02 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_time 2025-01-13 18:53:54&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_timestamp 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_response_message success&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_01 545.94 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_02 382.10 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_03 1430.13 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_04 262.05 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_05 28.80 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_06 622.63 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_07 276.51 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeCentralTask 0.3744&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIAnswer -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIProc -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeTrainAI 1.2529&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_01 3683.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_02 1617.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_01 2287.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_02 1057.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConForecastTillSunset 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 special_todayConsumptionForecast_01 509 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 special_todayConsumptionForecast_02 499 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 special_todayConsumptionForecast_03 501 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 special_todayConsumptionForecast_04 511 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 special_todayConsumptionForecast_05 503 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 special_todayConsumptionForecast_06 495 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 special_todayConsumptionForecast_07 504 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 special_todayConsumptionForecast_08 561 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 special_todayConsumptionForecast_09 768 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 special_todayConsumptionForecast_10 783 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 special_todayConsumptionForecast_11 692 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 special_todayConsumptionForecast_12 791 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 special_todayConsumptionForecast_13 910 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 special_todayConsumptionForecast_14 1022 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 special_todayConsumptionForecast_15 965 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 special_todayConsumptionForecast_16 812 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 special_todayConsumptionForecast_17 884 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 special_todayConsumptionForecast_18 928 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_19 874 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_20 763 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_21 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_22 765 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_23 643 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_24 601 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIcalls 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIrequests 4532&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridConsumption 5500.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridFeedIn 178.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayMaxAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIrequests n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 state updated&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So sollte es dann als Ergebnis aussehen:&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13.png|zentriert|mini|Ergebnis nach kompletter Einrichtung]]&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13 Teil II.png|alternativtext=Unterer Teil der Anzeige|zentriert|mini]]&lt;br /&gt;
&lt;br /&gt;
== Praxisbeispiele und Lösungsansätze für Steuerungen ==&lt;br /&gt;
=== Fallstudie: Trockner darf pausiert werden, wenn nicht genug PV-Überschuss vorhanden ist, soll aber nach spätestens X Stunden fertig sein ===&lt;br /&gt;
Für diese Aufgabenstellung sind mehrere Schlüssel essentiell wichtig, &#039;&#039;&#039;power&#039;&#039;&#039;, &#039;&#039;&#039;mintime&#039;&#039;&#039;, &#039;&#039;&#039;mode&#039;&#039;&#039; und &#039;&#039;&#039;interruptable&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Die Bedingung, dass der Trockner nach spätestens X Stunden fertig sein soll, steht in einem Widerspruch zu der Möglichkeit den Trockner bei zu wenig PV-Überschuss unterbrechen zu können. Im Extremfall könnte nach dem Start die gesamte Planungszeit ungenügender Überschuss vorliegen und der Trockner nicht arbeiten. Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; (in Minuten) wird nun wie folgt angesetzt:&lt;br /&gt;
&lt;br /&gt;
 mintime = 2,5 x &amp;lt;gewöhnliche Betriebszeit für einen Trockengang (mneed, z.B. 120)&amp;gt; = 300 Minuten&lt;br /&gt;
&lt;br /&gt;
Das bedeutet, der Trockner wird nach 300 Minuten Laufzeit abgeschaltet werden bzw. vom Netz getrennt. Der Trockenvorgang wird natürlich bereits nach 120 Minuten beendet sein, sofern nach Start keine Unterbrechnung des Vorganges erfolgte. Wurde der Vorgang unterbrochen, soll der Trockner innerhalb &lt;br /&gt;
&lt;br /&gt;
 X+120 bis X+300 &lt;br /&gt;
&lt;br /&gt;
fertig sein. &lt;br /&gt;
&lt;br /&gt;
Demnach ist die ausgeführte Laufzeit des Trockners permanent zu überwachen, zu summieren (rtsum) und die notwendige Restzeit (mneed - rtsum) mit der noch verbleibenden Restzeit (mrest) bis zur geplanten Abschaltung des Consumers zu vergleichen. Ist der Consumer gestartet, wird die Laufzeit in der pvHistory für jede Stunde des Tages im Schlüssel &#039;&#039;minutescsmXX&#039;&#039; (XX = Consumernummer) aufgezeichnet und kann darüber ausgewertet werden. Somit ist:&lt;br /&gt;
&lt;br /&gt;
 msum = for (01 .. 24) {Summe von minutescsmXX} des aktuellen Tages&lt;br /&gt;
&lt;br /&gt;
Solange die Bedingung &lt;br /&gt;
&lt;br /&gt;
 mrest &amp;gt;= (mneed - msum)&lt;br /&gt;
&lt;br /&gt;
zutrifft, darf der Trockner unterbrochen werden, anderenfalls darf er nicht mehr unterbrochen werden da die Restzeit evtl. nicht ausreichen könnte um den Vorgang abzuschließen. Für die Planung des Trockners wird der Consumer wie gewöhnlich nach dem Bedarf im Modul registriert. Für die Steuerung der Unterbrechbarkeit wird noch ein Code erstellt, welcher im Trockner-Device &#039;&#039;Dryerdev&#039;&#039; das Reading &#039;&#039;SF_Int&#039;&#039; zur Unterbrechnungssteuerung verwaltet. Dieses Reading wird dem Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; übergeben. Für das Beispiel wird der Consumer &#039;07&#039; verwendet, es kann natürlich jede andere freie Nummer verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Dryerdev:Trockner&lt;br /&gt;
                        icon=scene_cloves_dryer type=dryer power=2000 mode=must mintime=300 &lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic asynchron=1&lt;br /&gt;
                        interruptable=Dryerdev:SF_Int:1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Kombination &#039;&#039;&#039;auto=automatic&#039;&#039;&#039; eröffnet die Möglickeit, in der Consumer-Legende den Trockner-Start zusätzlich manuell freizugeben oder zu verbieten. &lt;br /&gt;
&lt;br /&gt;
Im nachfolgenden Code werden modulinterne Subroutinen verwendet. Diese sind inklusive dem Paket &#039;&#039;FHEM::SolarForecast::&#039;&#039; anzugeben. Die erstellte Subroutine wird in die 99_mySolarForecastUtils.pm eingefügt. Die Datei 99_mySolarForecastUtils.pm wird vorher von 99_myUtils.pm kopiert und enthält für die Übersichtlichkeit nur Routinen für SolarForecast.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Trocknersteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub dryControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # gewöhlich benötigte Zeit für &lt;br /&gt;
                                                                                  # einen Trockengang, z.B. 120 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $dryer     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename des Trockners&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Trockner-Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit des Trockners&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      my $dhash = $defs{$dryer};&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 1, 0);                        # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 0, 0);                        # keine Interrupt-Freigabe&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die gewöhnliche Laufzeit des Trockners für einen Trockenvorgang (120 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::dryControl ($name, &#039;07&#039;, 120);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Fallstudie: Umwälzpumpe Pool soll X Stunden am Tag laufen. Ist kein PV-Überschuß vorhanden, müssen die X Stunden/Tag trotzdem erreicht werden ===&lt;br /&gt;
&lt;br /&gt;
Die Vorgehensweise ähnelt der Fallstudie zuvor. Verändernd kommt hinzu, dass der Planungszeitraum bewusst sehr lang angesetzt wird mit der Option, den Zyklus des Consumers vorfristig zu beenden sobald die Laufzeit von X Stunden am Tag erreicht ist. &lt;br /&gt;
Im folgenden Beispiel soll die Pumpe 5 Stunden am Tag (300 Minuten) laufen und dabei mögliche PV-Überschüsse ausnutzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Pump:Zirkulationspumpe&lt;br /&gt;
                        icon=sani_pump type=other power=50 mode=must mintime=780 notafter=09&lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic &lt;br /&gt;
                        interruptable=1 swoffcond=Pump:SF_Abort:1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit dieser Registrierung wird die Pumpe ca. 09 Uhr täglich starten. Wenn kein bzw. ungenügender PV-Überschuß vorhanden ist, erfolgt eine Unterbrechung nach dem Start. Ist genügender PV-Überschuß (wieder) vorhanden, erfolgt keine Unterbrechnung (mehr). Zusätzlich wird über den Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; eine vorfristige Beendigung veranlasst, sobald die gewünschte Tageslaufzeit erreicht ist.&lt;br /&gt;
&lt;br /&gt;
Zur Verwaltung des Schlüssels &#039;&#039;interruptable&#039;&#039; und des Readings &#039;&#039;SF_Abort&#039;&#039; verwenden wir eine leicht veränderte Subroutine aus dem vorhergehenden Fallbeispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Pumpensteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub pumpControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # Soll-Pumpenzeit, z.B. 300 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $pump      = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename der Pumpe&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;);&lt;br /&gt;
  my $intbl     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;interruptable&#039;, 1); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
  my $dhash     = $defs{$pump};&lt;br /&gt;
&lt;br /&gt;
  readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 0, 0);                                # default keine Zyklusbeendigung&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Pumpen Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit der Pumpe&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
     &lt;br /&gt;
      if ($msum &amp;gt;= $mneed) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 1, 0);                       # vorfristige Zyklusbeendigung&lt;br /&gt;
          return;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=1&amp;quot;) if(!$intbl);  # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=0&amp;quot;) if($intbl);   # keine Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Befehl &#039;&#039;attrKeyVal&#039;&#039; setzt den Schlüssel &#039;&#039;interruptable&#039;&#039; im Attribut &#039;&#039;consumer07&#039;&#039; dynamisch. Diese Strukturänderung wird automatisch im System gespeichert, sofern &#039;&#039;global-&amp;gt;autosave=1&#039;&#039; gesetzt ist. Diese Einstellung ist der FHEM default.  &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die Mindestlaufzeit der Umwälzpumpe (300 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::pumpControl ($name, &#039;07&#039;, 300);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamische Ladestromsteuerung eines Victron MultiPlus II Chargers mit Pylontech Batterie ===&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;
&lt;br /&gt;
 set &amp;lt;Device&amp;gt; MaxChargeCurrent &amp;lt;Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
eingestellt bzw. variiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Modul bietet dem Nutzer die Möglichkeit in dem Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltene Code wird am Ende jedes Zyklus (siehe Attribut &#039;&#039;plantControl-&amp;gt;cycleInterval&#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;
&lt;br /&gt;
&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 $mppt1   = &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common&#039;;              # SmartLoader Device&lt;br /&gt;
  my $maxcspc = 105;                        # max. Ladesollstrom (A) nominal&lt;br /&gt;
  my $spcorr  = 0.9;                        # Korrekturfaktor Überschuss 90%&lt;br /&gt;
  my $sch     = 0.25;                       # Verkürzungsfaktor Zeit bis Vollladung vor Sunset             &lt;br /&gt;
  &lt;br /&gt;
  my $cclvl0  = 15;                         # Ladestrom Level 0 max. 5  A (240 W) pro WR  (720  W)&lt;br /&gt;
  my $cclvl1  = 27;                         # Ladestrom Level 1 max. 9  A (432 W) pro WR  (1296 W)&lt;br /&gt;
  my $cclvl2  = 54;                         # Ladestrom Level 2 max. 18 A (864 W) pro WR  (2592 W)&lt;br /&gt;
  my $cclvl3  = 81;                         # Ladestrom Level 3 max. 27 A (1296 W) pro WR (3888 W)&lt;br /&gt;
  ###############&lt;br /&gt;
  &lt;br /&gt;
  my $cofc   = ReadingsNum ($name,  &#039;special_todayConForecastTillSunset&#039;, 0);&lt;br /&gt;
  my $pvfc   = ReadingsNum ($name,  &#039;RestOfDayPVforecast&#039;, 0);&lt;br /&gt;
  my $cpv    = ReadingsNum ($name,  &#039;Current_PV&#039;,          0);&lt;br /&gt;
  my $mppt1c = ReadingsNum ($mppt1, &#039;DC_0_Current_value&#039;,  0);             # Load I MPPT1 (max. 44 A)&lt;br /&gt;
  my $ssts   = CurrentVal  ($hash,  &#039;sunsetTodayTs&#039;,        0);&lt;br /&gt;
  my $srts   = CurrentVal  ($hash,  &#039;sunriseTodayTs&#039;,       0);&lt;br /&gt;
  my $sdiff  = ($ssts - $srts) / 3600;                                     # Sonnengang heute in h &lt;br /&gt;
  &lt;br /&gt;
  my $solh   = ReadingsNum ($name, &#039;special_SunHours_Remain&#039;, 0);          # h bis SunSet&lt;br /&gt;
  $solh      = $solh - ($sdiff * $sch);                                    # h bis SunSet - X&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;              # Ah Bat bis SOC&lt;br /&gt;
  $ahrem     = sprintf &amp;quot;%.0f&amp;quot;, $ahrem;&lt;br /&gt;
  &lt;br /&gt;
  my $fcdiff = ($pvfc - $cofc) * $spcorr;     # Korrektur d. noch prognostizierten Überschussenergie &lt;br /&gt;
  $fcdiff    = $fcdiff &amp;lt; 0 ? 0 : $fcdiff;     # Wh&lt;br /&gt;
  &lt;br /&gt;
  my $loadcur = $maxcspc;&lt;br /&gt;
  &lt;br /&gt;
  if ($cpv &amp;amp;&amp;amp; $solh &amp;amp;&amp;amp; $ahrem &amp;amp;&amp;amp; $fcdiff &amp;gt; $ahrem) {  # Ladeanforderung und Überschuss übersteigt &lt;br /&gt;
                                                      # Lademenge&lt;br /&gt;
      my $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($ahrem / $solh);    # A = Ah / h -&amp;gt; A Soll Schätzung&lt;br /&gt;
&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Battery charging process should be completed }.&lt;br /&gt;
                      qq{in &amp;gt;$solh&amp;lt; hours});&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; raw Target charging current: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($cspc - $mppt1c);      # SmartLoader IST berücksichtigen&lt;br /&gt;
	  &lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Charge Current minus MPPT load Current &amp;gt;$mppt1c&amp;lt;: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $loadcur = $cspc &amp;lt;= 0       ? 0       :     # nur MPPT Ladung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl0 ? $cclvl0 :     # Übergangsbereich&lt;br /&gt;
                 $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;
	  Log3 ($name, 3, qq{$name - userFn -&amp;gt; MaxChargeCurrent calculated: $loadcur});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent&#039;,       $loadcur.&#039; A&#039;,          1);&lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_HoursUntilChargeFinish&#039;, sprintf (&amp;quot;%.2f&amp;quot;,$solh), 1);&lt;br /&gt;
  CommandSet           (undef, &amp;quot;$vebus MaxChargeCurrent $loadcur&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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. 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;special_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;special_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;Verkürzungsfaktor Zeit bis Vollladung vor Sunset&#039;&#039;) reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche mindest Ladestromstärke ermittelt.&lt;br /&gt;
&lt;br /&gt;
&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 auch während der MQTT Intergration 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;
=== Poolheizung in Abhängigkeit von vorhandenem Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren) ===&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;consumer01&#039;&#039; wird beispielhaft wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr Forecast consumer01 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;&lt;br /&gt;
&lt;br /&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. &lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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, einen 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 Überschuss 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;. &lt;br /&gt;
&lt;br /&gt;
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;
=== PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) ===&lt;br /&gt;
[https://evcc.io evcc] ist ein Energie-Management-System, mit dem u.a. Überschussladen von Elektroautos möglich ist. Hier ist beschreiben, wie die SolarForecast-Vorhersagedaten per API von evcc abgerufen werden.&lt;br /&gt;
Lege im SolarForecast-Device ein User-Reading mit dem Namen forecast_json an. Es wandelt die Forecast-Werte in JSON und ins UTC-Zeitformat um, so dass evcc die Daten einlesen kann. Der Code wird nur ausgeführt, wenn das Reading nextCycletime ein Event erzeugt.&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
forecast_json:nextCycletime.* {&lt;br /&gt;
&lt;br /&gt;
    use strict;&lt;br /&gt;
    use warnings;&lt;br /&gt;
    use JSON;&lt;br /&gt;
    use DateTime;&lt;br /&gt;
    use DateTime::Format::Strptime;&lt;br /&gt;
&lt;br /&gt;
    my $hour = 0;&lt;br /&gt;
    my @output;&lt;br /&gt;
&lt;br /&gt;
    # Parser für Datum mit CET/CEST&lt;br /&gt;
    my $parser = DateTime::Format::Strptime-&amp;gt;new(&lt;br /&gt;
        pattern   =&amp;gt; &#039;%Y-%m-%d %H:%M:%S&#039;,&lt;br /&gt;
        time_zone =&amp;gt; &#039;Europe/Berlin&#039;,&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    # Alle NextHour-Daten durchsuchen&lt;br /&gt;
    while ($hour &amp;lt; 100) {&lt;br /&gt;
        my $hour_str = sprintf(&#039;NextHour%02d&#039;, $hour);&lt;br /&gt;
        my $start_str = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;starttime&#039;, &#039;na&#039;); &lt;br /&gt;
        my $pvfc = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;pvfc&#039;, &#039;na&#039;);&lt;br /&gt;
&lt;br /&gt;
        # Schleife beenden, wenn keine Werte mehr vorhanden sind&lt;br /&gt;
        last if $start_str eq &#039;na&#039; or $pvfc eq &#039;na&#039;;&lt;br /&gt;
&lt;br /&gt;
        # parse und konvertiere Zeit&lt;br /&gt;
        my $start_dt = $parser-&amp;gt;parse_datetime($start_str);&lt;br /&gt;
        my $end_dt   = $start_dt-&amp;gt;clone-&amp;gt;add(hours =&amp;gt; 1);&lt;br /&gt;
&lt;br /&gt;
        # nach UTC konvertieren&lt;br /&gt;
        $start_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
        $end_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $start_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            end   =&amp;gt; $end_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            value =&amp;gt; 0 + $pvfc,&lt;br /&gt;
        };&lt;br /&gt;
        &lt;br /&gt;
        $hour++;&lt;br /&gt;
    }  &lt;br /&gt;
&lt;br /&gt;
    # Ausgabe als JSON&lt;br /&gt;
    my $json = JSON-&amp;gt;new-&amp;gt;utf8-&amp;gt;pretty-&amp;gt;encode(\@output);&lt;br /&gt;
    return $json;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Datei:Screenshot 2025-08-04 104835.png|right|thumb|300px|Darstellung der PV-Vorhersage in evcc auf Basis der SolarForecast-Daten]]&lt;br /&gt;
Die Kommunikation läuft über den integrierten FHEM-Webserver, der die JSON-Daten aus dem Reading forecast_json veröffentlicht. Dazu wird in FHEM eine separate Webinstanz auf einem neuen Port erstellt, die ohne [[CsrfToken-HowTo|CSFR-Token]] (Achtung, Auswirkungen auf die Sicherheit beachten!) und nur von localhost aufrufbar ist (Voraussetzung: evcc läuft auf derselben Maschine wie FHEM):&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
define WEBapi FHEMWEB 8089&lt;br /&gt;
attr WEBapi csrfToken none&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;In der [https://docs.evcc.io/docs/tariffs#pv-vorhersage evcc-Konfig unter tariffs] steht die Quelle für die Solar-Vorhersage. Der FHEM-Befehl {ReadingsVal(&#039;solarforecast_dev&#039;,&#039;forecast_json&#039;,&#039;[]&#039;)} wird encoded und in die uri eingetragen. Trage statt solarforecast_dev den passenden Namen deines SolarForecast-Device ein. evcc holt die Daten aus dem Reading forecast_json dann regelmäßig ab.&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
solar:&lt;br /&gt;
  type: custom&lt;br /&gt;
  interval: 20m    &lt;br /&gt;
  forecast:&lt;br /&gt;
    source: http&lt;br /&gt;
    uri: http://localhost:8089/fhem?cmd=%7BReadingsVal%28%27solarforecast_dev%27%2C%27forecast_json%27%2C%27%5B%5D%27%29%7D&amp;amp;XHR=1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Zur Verbesserung der Sicherheit kann das neue WEBapi Device auch ein [[CsrfToken-HowTo#csrfToken festlegen|festes CSFR-Token]] verwenden. Dieses Token muss dann in der evcc-Konfiguration an die uri mittels &amp;amp;fwcsrf=&amp;lt;festes token&amp;gt; angehängt werden.&lt;br /&gt;
&lt;br /&gt;
== weiterführende Links ==&lt;br /&gt;
* Forenthema &amp;quot;{{Link2Forum|Topic=137058|LinkText=76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support}}&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;
* Photovoltaik Ingenieurbüro Junge: https://www.ing-büro-junge.de/html/photovoltaik.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung&amp;diff=40308</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=40308"/>
		<updated>2025-08-04T17:27:07Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Hinweis|Die vorliegende Wiki-Seite befindet sich im Aufbau.}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Solarprognose und Verbrauchersteuerung&lt;br /&gt;
|ModType=d&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 Prognosewerte können die SolCast API, OpenMeteo API, Forecast.Solar API, Victron VRM Portal API oder alternativ DWD Stahlungswerte-Stationen verwendet werden&lt;br /&gt;
&lt;br /&gt;
::* optionale KI Unterstützung der PV-Prognose bei Verwendung von geeigneten Solar-API&#039;s&lt;br /&gt;
&lt;br /&gt;
::* es wird sowohl die Erzeugungsprognose als auch eine Verbrauchsprognose sowie SoC Prognose (bei Batterie-Integration) erstellt&lt;br /&gt;
&lt;br /&gt;
::* Wetterdaten werden über DWD Wetter-Stationen oder verschiedene API integriert. Es können verschiedene API zur Gewinnung von Solar- und Wetterdaten kombiniert werden. &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 FHEM-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 Integration von bis zu 4 Inverter und Smartloader (DC-DC Batterieladegeräte) ist möglich&lt;br /&gt;
&lt;br /&gt;
::* eine Integration von bis zu 3 nicht PV-Energieerzeugern wie BHKW, Windrädern oder Notstromaggregaten ist möglich&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;
::* Einbindung von bis zu drei Batteriespeichersystemen&lt;br /&gt;
&lt;br /&gt;
::* Bereitstellung von Leitwerten zur optimalen Einstellung/Steuerung von Batteriespeichersystemen&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 Benutzererlebnis 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;
Das Wiki gibt allgemeingültige und teilweise sehr spezifische bzw. tiefgehende Informationen und Handlungsempfehlungen zum SolarForecast Modul. Die dargestellten Informationen beziehen sich auf den zum Zeitpunkt der Wiki-Erstellung vorhandenen Entwicklungsstand des Moduls. Durch die stetige Weiterentwicklung können sich Abweichungen zum beschriebenen Inhalt ergeben oder zur Obsoleszenz dieser Inhalte führen. &lt;br /&gt;
&lt;br /&gt;
Vergleiche deshalb die Informationen immer mit der aktuellen Befehls-Referenz zum Modul!&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Ein SolarForecast Device wird mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 define &amp;lt;Name&amp;gt; SolarForecast &lt;br /&gt;
&lt;br /&gt;
angelegt. Nach der Definition wird der User durch einen Dialog geführt, der einige unerlässliche Einstellungen abfragt und in den entsprechenden Attributen und Readings persistiert. Alle Attribute und Readings die eine Einstellung der Anlage bewirken, sind mit dem Präfix &amp;quot;setup&amp;quot; versehen. &lt;br /&gt;
&lt;br /&gt;
Die Verwendung von setup-Readings gestattet es die Anlagenparameter dynamisch im Betrieb zu verändern. So kann mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringAzimuth   bzw.&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringDeclination &lt;br /&gt;
&lt;br /&gt;
die Ausrichtung und der Neigungswinkel der PV-Module ständig angepasst werden, was zum Beispiel bei einer dem Sonnenstand nachgeführten Anlage von Bedeutung ist.&lt;br /&gt;
&lt;br /&gt;
Die abgefragten Einstellungen während des Dialoges sind ausführlich in den entsprechenden Attributen bzw. Set-Kommandos erläutert. Die benötigten Informationen sind anhängig von der gewählten Prognose-API und können im Umfang variieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 213257.png|right|thumb|400px|Anlagenprüfung über Drucktaste in der Kopfgrafik]]&lt;br /&gt;
&lt;br /&gt;
Sobald alle verlangten Einstellungen vorgenommen sind, sollte eine Anlagenprüfung mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; plantConfiguration check&lt;br /&gt;
&lt;br /&gt;
oder über die angebotene Drucktaste in der Grafik durchgeführt werden. Es wird eine Plausibilitätsprüfung vorgenommen und das Ergebnis sowie eventuelle Hinweise bzw. Fehler ausgegeben.&lt;br /&gt;
Die Prüfung kann beliebig wiederholt werden und sollte sich bei jeder Einstellungsänderung der Anlage durchgeführt werden. Dadurch wird die Wahrscheinlichkeit von fehlerhaften Einstellungen minimiert.&lt;br /&gt;
&lt;br /&gt;
Neben den grundlegenden Einstellungen können im Device weitere sekundäre Anlagenkomponenten wie Batteriesystem(e) (Attribut setupBatteryDev1 - setupBatteryDev3), weitere Wetter-Devices (Attribut setupWeatherDev1 - setupWeatherDev3) oder sonstige Erzeuger (z.B. BHKW, Winderzeugung, Notstromaggregat) integriert werden (Attribut setupOtherProducer01 - setupOtherProducer03).&lt;br /&gt;
&lt;br /&gt;
Die verlangten Parameter der Anlage werden in der Online-Hilfe umfassend beschrieben und deren Funktion erschließt sich zum größten Teil selbst. Dennoch soll nachfolgend auf einige Punkte im Zusammenhang der Einrichtung eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Hinweise zur Struktur der Attribute ===&lt;br /&gt;
&lt;br /&gt;
Durch die umfangreichen Funktionen des Moduls würde bei Nutzung der im FHEM herkömmlich vorhandenen Attributstruktur die Anzahl der benötigten Attribute extrem stark steigen und nicht sinnvoll genutzt werden können. Deshalb gibt es neben den &#039;&#039;gewöhnlichen&#039;&#039; Attributen mit einfachen Werteauswahlmöglichkeiten oder Eingaben (z.B. ctrlDebug, ctrlSpecialReadings) sogenannte &#039;&#039;zusammengesetzte&#039;&#039; Attribute, deren Inhalt durch &#039;&#039;&#039;Schlüssel=Wert Paare&#039;&#039;&#039; gebildet wird und dadurch deutlich mehr Funktionen und Informationen transportieren als ein gewöhnliches Attribut.&lt;br /&gt;
&lt;br /&gt;
Für zusammengesetzte Attribute besteht die zusätzliche Möglichkeit, gewünschte Änderungen der Schlüssel=Wert Paare selektiv vornehmen zu können, ohne das gesamte Attribut aufrufen und ändern zu müssen. Die Vorgang, der vor allem für programmtechnische Manipulationen gedacht ist, kann durch eine Set-Funktion ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; attrKeyVal &amp;lt;Attribut&amp;gt; [&amp;lt;Gerät&amp;gt;] &amp;lt;Schlüssel=Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiele für zusammengesetzte Attribute sind:&lt;br /&gt;
&lt;br /&gt;
* aiControl&lt;br /&gt;
* plantControl&lt;br /&gt;
* setup* Attribute&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktionen der Attribute werden durch einen Präfix geclustert und so inhaltlich, aber vor allem auch in der Attribute Drop-Down Liste, strukturiert dargestellt.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der &#039;&#039;&#039;Präfixe&#039;&#039;&#039; sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ai&#039;&#039;&#039; - Steuerungsfunktionen für KI (z.B. aiControl)&lt;br /&gt;
* &#039;&#039;&#039;consumer&#039;&#039;&#039; - Registrierung und Einstellungen für Verbraucher (z.B. consumer02, consumerControl)&lt;br /&gt;
* &#039;&#039;&#039;ctrl&#039;&#039;&#039; - Steuerungsfunktion allgemeiner Art (z.B. ctrlDebug, ctrlSpecialReadings, ctrlUserExitFn)&lt;br /&gt;
* &#039;&#039;&#039;flowGraphic&#039;&#039;&#039; - Einstellungen für die Energieflußgrafik (z.B. flowGraphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphic&#039;&#039;&#039; - Einstellung für die Grafik allgemein (z.B. graphicSelect, graphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphicBeam&#039;&#039;&#039; -  Einstellungen bestimmte Balkeneigenschaften in der Balkengrafik (z.B. graphicBeamHeightLevel1)&lt;br /&gt;
* &#039;&#039;&#039;plant&#039;&#039;&#039; - übergreifende Einstellungen betreffend der gesamten PV-Anlage bzw. des SolarForecast-Devices (z.B. plantControl)&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039; - Registrierung von Geräten in der Gesamtanlage und Einstellung deren Eigenschaften (Inverter, Zähler, Batterien usw.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Einrichtung der Wechselrichter mit setupInverterDevXX ===&lt;br /&gt;
&lt;br /&gt;
Mit den Attributen setupInverterDev01 bis setupInverterDevXX werden die vorhandenen Wechselrichter der Anlage registriert.&lt;br /&gt;
Das Modul unterscheidet verschiedene Wechselrichter-Typen, die sich durch ihre Arbeitsweise innerhalb der Anlage unterscheiden. Die Schlüssel=Wert Paare in den Attributen können mehrzeilig organisiert werden. Das erleichtert die Übersicht wenn viele dieser Parameter eingegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;PV-Wechselrichter: Es ist der Standard Wechselrichter in einer PV-Anlage. An ihn sind die Solarzellen bzw. Strings angeschlossen. Die zugeordneten Strings können mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ohne diese Angabe werden diesem Gerät alle definierten Strings (siehe Attribut &#039;&#039;setupInverterStrings&#039;&#039;) zugeordnet. Der Wechselrichter liefert seine Energie in das Hausnetz. Alternativ kann mit der Angabe &#039;&#039;&#039;feed=grid&#039;&#039;&#039; die Funktion des Wechselrichters geändert werden. Diese Angabe sagt aus, dass dieser Wechselrichter ausschließlich in das öffentliche Netz einspeist.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel-Setup eines PV-Wechselrichters (SMA STP):&lt;br /&gt;
&lt;br /&gt;
 STP_5000 pvIn=string_1_pdc:kW pvOut=total_pac:kW etotal=etotal:kWh capacity=5000 strings=Süddach asynchron=1 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Solar-Ladegeräte: Solar-Ladegeräte sind DC-DC Wandler und liefern die Energie der angeschlossenen Solarzellen nicht in das Wechselstromnetz, sondern laden direkt eine Batterie bzw. versorgen einen Batteriewechselrichter auf der Gleichstromseite. Die Funktion als Solar-Ladegerät wird mit &#039;&#039;&#039;feed=bat&#039;&#039;&#039; aktiviert, die relevanten Strings können ebenfalls mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ein Beispiel eines Solar-Ladegerätes ist ein Victron SmartSolar MPPT. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel für das Setup eines Solar-Ladegeräts (SmartSolar Charger MPPT):&lt;br /&gt;
&lt;br /&gt;
 MQTT2_cerboGX_c0619ab34e08_solarcharger_Common pv=Yield_Power_value:W etotal=Yield_System_value:kWh capacity=2080 strings=Schleppdach feed=bat synchron=0 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Batterie-Wechselrichter: Dieses Gerät hat keine angeschlossenen Solarzellen und arbeitet als DC-AC bzw. AC-DC Wandler zwischen einer Batterie (=Gleichstromquelle) und dem Wechselstrom-Hausnetz. Die Funktion als Batterie-Wechselrichter wird mit der Angabe &#039;&#039;&#039;strings=none&#039;&#039;&#039; aktiviert. Die Schlüssel &#039;&#039;etotal&#039;&#039; und &#039;&#039;pv&#039;&#039; können bei einem Batterie-Wechselrichter ohne zugeordnete Solarzellen nicht gesetzt werden. Ein Beispiel eines Batterie-Wechselrichter ist der Victron MultiPlus II.&lt;br /&gt;
&lt;br /&gt;
Ein Setup-Beispiel für einen Batterie-Wechselrichter (Victron MultiPlus II):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dc2ac=DC_IN:W&lt;br /&gt;
ac2dc=DC_OUT:W&lt;br /&gt;
capacity=7200&lt;br /&gt;
strings=none&lt;br /&gt;
icon=inverter@darkorange:inverter@grey&lt;br /&gt;
asynchron=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Eigenschaften des Wechselrichters werden durch eine Reihe von &amp;lt;Schlüssel=Wert&amp;gt; Paaren festgelegt. Auf einige dieser Paramter soll hier eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Ausgewählte Schlüssel=Wert Paare ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;pvIn=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvIn&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell zugeführte PV-Leistung bereitstellt. Der Schlüssel ist optional und dient in erster Linie dazu den entsprechenden Input-Wert in der Flußgrafik anzuzeigen sofern man das Attribut flowGraphicControl-&amp;gt;showGenerators=1 setzt. Dadurch ist auch der Eigenverbrauch des Inverters bzw. dessen Wandlungsverlust visuell abschätzbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pvOut=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvOut&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell erzeugte Leistung als positiven Wert liefert. Für einen PV-Wechselrichter (DC-&amp;gt;AC) oder Solar-Ladegerät (DC-&amp;gt;DC) ist es die erzeugte PV-Leistung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ac2dc=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter vom Hausnetz in Richtung Batterie (AC-&amp;gt;DC) wandelt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;dc2ac=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter aus einer Gleichstromquelle, d.h. einer Batterie oder einem Solar-Ladegerät, in Richtung des Hausnetzes (AC) wandelt . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;capacity=&amp;lt;max. WR-Leistung&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In dem Schlüssel &#039;&#039;capacity&#039;&#039; wird die maximal mögliche Leistung in Watt (ohne Einheit) angegeben, die der Wechselrichter lt. seinem Datenblatt in der Lage ist zu leisten. &lt;br /&gt;
&lt;br /&gt;
Die Angabe &#039;&#039;capacity&#039;&#039; hat in erster Linie die Aufgabe, die max. mögliche PV-Leistung für die Prognose zu begrenzen. Oft sind die installierten Peak-Leistungen der PV-Module höher als die angeschlossene Wechselrichter-Leistung bzw. kommt es vor, dass die KI / (korrigierte) API-Prognose über der maximal möglichen Wechselrichter-Leistung liegt. In diesen Fällen wird die Prognose auf die angegebene &#039;&#039;capacity&#039;&#039; begrenzt.&lt;br /&gt;
&lt;br /&gt;
Der Wert in diesem Schlüssel kann, wie andere Schlüssel auch, dynamisch zur Laufzeit mit dem Set-Befehl &amp;quot;[[#Hinweise zur Struktur der Attribute|set &amp;lt;Name&amp;gt; attrKeyVal ...]]&amp;quot; geändert werden. Ein Beispiel zur Anwendung ergibt sich aus folgendem Szenario.&lt;br /&gt;
&lt;br /&gt;
Gegeben sei eine Anlage die aus Solarzellen (1300 W Peak) mit einem Solar-Ladegerät mit max. 1800 W Leistung, einer Batterie und einem Batterie-Wechselrichter besteht. Die Anlage versorgt nur das Hausnetz. Eine Netzeinspeisung ist nicht vorgesehen oder nicht erlaubt.  &lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, es ist ein Tag voller Sonnenschein prognostiziert und die Batterie ist zunächst entladen. Der Haushalt verbraucht 300 W. Dann würden die PV-Module Module ihre volle Leistung von 1300 W Peak leisten können, die sich auch in der Balken-Vorhersage niederschlägt. Die Leistung wird nicht begrenzt, weil:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* sie niedriger ist als die nominale und angegebene Wechselrichter Kapazität von &#039;&#039;capacity=1800&#039;&#039;&lt;br /&gt;
* die erzeugte Energie anteilig für die Verorgung des Hauses und die Aufladung der Batterie verwendet wird&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders verhält es sich wenn nach einer gewissen Zeit die Batterie voll ist und weiterhin volle PV Leistung zur Verfügung steht. In diesem Fall würde der Haushalt seine benötigte Leistung von 300 W abnehmen, aber das Solar-Ladegerät kann keine weitere Leistung mehr abgeben, da die Batterie bereits voll geladen ist, d.h. die Anlagensteuerung würde die PV-Anlage abregeln. In diesem Fall, wenn es einen längeren Zeitraum betrifft, muß auch die Prognose PV-Energie auf 300 Wh (bzw. den durchschnittlichen Energieverbrauch des Hauses pro Stunde) begrenzt werden, damit die PV-Prognose nach unten angepasst wird und so eine realitätsnahere Prognose ermöglicht wird. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;icon=&amp;lt;aktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;][:&amp;lt;inaktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Jeder Wechselrichter wird im Standard durch ein Icon getrennt nach Tag und Nacht, d.h. je nach Aktiv-Status und Inaktiv-Status, symbolisiert.&lt;br /&gt;
&lt;br /&gt;
;Tag bzw. Aktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Sonnensymbol im Standard verwendet. Batterie-Wechselrichter verwenden ein gefärbtes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
;Nacht bzw. Inaktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Symbol der aktuellen Mondphasen im Standard verwendet. Batterie-Wechselrichter verwenden ein ausgegrautes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie angegeben, kann man für Tag und Nacht jeweils ein Wunsch-Icon, wenn gewünscht mit einer alternativen Färbung, auswählen.&lt;br /&gt;
&lt;br /&gt;
 icon=inverter@darkorange:inverter@gray&lt;br /&gt;
&lt;br /&gt;
Soll nur das Icon für die Nacht bzw. Inaktivät geändert werden, kann dies in dieser Form angegeben werden:&lt;br /&gt;
&lt;br /&gt;
 icon=:inverter@gray  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(beachte den führenden &#039;:&#039;)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Der integrierte SolarForecast Grafikbereich ==&lt;br /&gt;
Das SolarForecast Modul beinhaltet eine Grafikdarstellung die sich in mehrere Bereiche gliedert. Diese Bereiche können über Attribute ein- bzw. ausgeblendet sowie die Inhalte festgelegt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 223545.png|right|thumb|400px|Bereiche der integrierten Grafik]]&lt;br /&gt;
&lt;br /&gt;
Der nebenstehende Screenshot gibt die Gliederung der Grafikbereiche wieder:&lt;br /&gt;
&lt;br /&gt;
 1 - der Kopfbereich (Graphic Header)&lt;br /&gt;
 2 - durch den Nutzer selbst definierbarer Inhalt (Graphic Header Own Specification) als Teil des Kopfbereiches&lt;br /&gt;
 3 - Bereich Verbraucherdarstellung (Consumer Legend)&lt;br /&gt;
 4 - Bereich Balkengrafik (Beam Graphic)&lt;br /&gt;
 5 - Energieflußgrafik (Flow Graphic)&lt;br /&gt;
&lt;br /&gt;
Jeder dieser Bereiche hat spezifische Steuerungsattribute zur Anpassung des Verhaltens und ggf. des Inhalts.&lt;br /&gt;
&lt;br /&gt;
=== 1 - Der Grafik Kopfbereich ===&lt;br /&gt;
Im Kopfbereich befinden sich fest verankerte Informationen zur verwendeten Vorhersage-API sowie deren Status, Informationen zum Sonnenaufgang und Sonnenuntergang, dem aktuellen Gesamtstatus des SolarForecast Devices, Abweichungskennzahlen der PV Vorhersage sowie weitere Kennzeichen zur Verfügung.&lt;br /&gt;
Über zwei Drucktasten kann eine Anlagenprüfung durchgeführt und in den Spportthread des Moduls im FHEM Forum abgesprungen werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;graphicHeaderShow&#039;&#039;&#039; kann der gesamte Kopfbereich 1 und 2 (nutzereigener Teilbereich) ausgeblendet werden. Wird der Kopbereich ausgeblendet, ist es hilfreich mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;showLink&#039;&#039;&#039; einen Link zur Detailgrafik einzufügen da der in der Kopfgrafik integrierte Link in diesem Fall nicht mehr zur Verfügung steht. &lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;graphicHeaderDetail&#039;&#039;&#039; definiert welche Bereiche des Grafikkopfes angezeigt werden sollen. Es kann die Anzeige des Energieverbrauches, der PV-Erzeugung und der vom Nutzer selbst definierte Inhalt miteinander frei kombiniert werden.&lt;br /&gt;
&lt;br /&gt;
=== 2 - Der Bereich mit selbst definierbarem Inhalt (Graphic Header Own Specification) ===&lt;br /&gt;
In diesem Bereich kann der User beliebige Readings, Set-Kommandos und Attribute des SolarForecast Devices oder anderer Devices, die sich im gleichen FHEM-System wie das SolarForecast Device befinden, anzeigen lassen.&lt;br /&gt;
&lt;br /&gt;
Dieser Bereich ist als Tabelle mit einer beliebigen Anzahl von Zeilen organisiert. Jede Zeile beinhaltet ein Kommentarfeld und vier Nutzfelder zur Darstellung ausgewähler Werte + Label. Der Bereich bzw. der Inhalt des Bereiches wird mit dem Attribut &#039;&#039;&#039;graphicHeaderOwnspec&#039;&#039;&#039; definiert.  &lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt ein real gesetztes graphicHeaderOwnspec Attribut. Die Leerzeilen sind nicht notwendig, erhöhen aber die Lesbarkeit der Struktur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
Autarkierate:Current_AutarkyRate&lt;br /&gt;
PV&amp;amp;nbsp;übermorgen:special_dayAfterTomorrowPVforecast&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;Sunset:special_todayConForecastTillSunset&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;nächsten&amp;amp;nbsp;Sunrise:special_conForecastTillNextSunrise&lt;br /&gt;
&lt;br /&gt;
#Batterie&lt;br /&gt;
BatteryLive&amp;amp;nbsp;Status:userFn_BatLive_State&lt;br /&gt;
SoC&amp;amp;nbsp;Limit:Settings_CGwacs_BatteryLife_MinimumSocLimit_value@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SoC&amp;amp;nbsp;Ist:SOC_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
SOC&amp;amp;nbsp;Optimum:Battery_OptimumTargetSoC&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
aktuelle&amp;amp;nbsp;Ladung:userFn_Bat_EnergyState&lt;br /&gt;
Verfügbar:userFn_BatLive_UsableEnergy&lt;br /&gt;
benötigte&amp;amp;nbsp;Ladeenergie:userFn_Bat_EnergyRemain&lt;br /&gt;
Ladefreigabe:Battery_ChargeRecommended&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
akt.&amp;amp;nbsp;DC&amp;amp;nbsp;Strom:DC_Current_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
Restladezeit&amp;amp;nbsp;Ziel:userFn_Bat_HoursUntilChargeFinish&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Soll:userFn_Bat_MaxChargeCurrent_set&lt;br /&gt;
:&lt;br /&gt;
&lt;br /&gt;
#Settings&lt;br /&gt;
Batterie&amp;amp;nbsp;Lademanagement:userFn_BatteryChargeManagement&lt;br /&gt;
SoC&amp;amp;nbsp;Management:userFn_BatterySoCManagement&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Ist:MaxChargeCurrent@MQTT2_cerboGX_c0619ab34e08_vebus&lt;br /&gt;
SmartSolar&amp;lt;br&amp;gt;Einspeisung:OvervoltageFeedIn@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
MPII&amp;amp;nbsp;Limit&amp;lt;br&amp;gt;Einspeisung&amp;amp;nbsp;(W):MaxFeedInPower@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SOC&amp;amp;nbsp;Limit&amp;amp;nbsp;Soll:MinimumSocLimit@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Verbr.&amp;amp;nbsp;Neuplanung:consumerNewPlanning&lt;br /&gt;
Wetteranzeige:graphicShowWeather &lt;br /&gt;
&lt;br /&gt;
Anzeige&amp;amp;nbsp;Nachtstunden:graphicShowNight&lt;br /&gt;
hist.&amp;amp;nbsp;Stunden:graphicHistoryHour&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto&lt;br /&gt;
Victron&amp;amp;nbsp;BatteryLife&amp;lt;br&amp;gt;(1=an,10=aus):BatteryLife@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Debug:ctrlDebu&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Kommentarfeld am Beginn einer Zeile wird durch ein &#039;&#039;&#039;#&#039;&#039;&#039; gekennzeichnet. Folgt dem # ein String, wird dieser String als Kommentarangabe gewertet und in der Grafik ausgegeben. Ein leeres Kommentarfeld wird lediglich durch ein # gefolgt von einem Leerzeichen oder NL beschrieben:&lt;br /&gt;
&lt;br /&gt;
 #:&amp;lt;Text&amp;gt;  (bzw nur # für einen &#039;leeren&#039; Titel)&lt;br /&gt;
&lt;br /&gt;
Ein Netzfeld bzw. ein Datensatz wird durch die Angabe von einem Label und dem darzustellenden Wert getrennt durch &#039;:&#039; definiert:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Label&amp;gt;:&amp;lt;Reading, Attribut oder Set-Kommando&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das System erkennt selbständig, ob es sich bei der Angabe um ein Reading, Attribut oder ein Set-Kommando handelt. Sollen Readings, Set-Kommandos und Attribute anderer Devices als dem SolarForecast-Device angezeigt werden, kann dies einfach durch Zusatz von&lt;br /&gt;
&lt;br /&gt;
 ....@&amp;lt;Device-Name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
an den Parameter erreicht werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-12-05 203916.png|right|thumb|400px|Darstellung eigener Grafikbereich]]&lt;br /&gt;
Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten &amp;quot;Wh&amp;quot; bzw. &amp;quot;kWh&amp;quot; werden entsprechend der Einstellung des Attributs &#039;&#039;&#039;graphicEnergyUnit&#039;&#039;&#039; umgerechnet. Im Label sind Leerzeichen durch &amp;quot;&amp;amp;amp;nbsp;&amp;quot; einzufügen, ein Zeilenumbruch durch &amp;quot;&amp;amp;lt;br&amp;amp;gt;&amp;quot;. Ein leeres Feld in einer Zeile wird durch &amp;quot;:&amp;quot; ohne eine weitere Angabe erzeugt.&lt;br /&gt;
&lt;br /&gt;
Die nebenstehende Abbildung zeigt die reale Darstellung der oben angegebenen Struktur im Attribut graphicHeaderOwnspec.&lt;br /&gt;
&lt;br /&gt;
==== Formatierung der Inhalte im Bereich &amp;quot;Graphic Header Own Specification&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
Die angezeigten Inhalte, wie z.B. Readingwerte, des User eigenen Bereiches (Attribut graphicHeaderOwnspec) können durch Spezifikationen im Attribut &#039;&#039;&#039;graphicHeaderOwnspecValForm&#039;&#039;&#039; manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
Die Online-Hilfe zum Attribut graphicHeaderOwnspecValForm erläutert die verfügbaren Möglichkeiten und Optionen.&lt;br /&gt;
Als Beispiel hier einige mögliche Notationen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &#039;userFn_Bat_HoursUntilChargeFinish&#039;                        =&amp;gt; &amp;quot;($VALUE).&#039; Stunden&#039;&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_battery.SOC_value&#039;             =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Settings_CGwacs_BatteryLife_MinimumSocLimit_value&#039;        =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Info_MaxChargeCurrent_value&#039;                              =&amp;gt; &amp;quot;($VALUE).&#039; A&#039;&amp;quot;,&lt;br /&gt;
  &#039;DC_Current_value&#039;                                         =&amp;gt; &amp;quot;%.0f A&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common.Regulated&#039; =&amp;gt; &amp;quot;($VALUE eq &#039;1&#039; ? &#039;Ja&#039; : &#039;Nein&#039;)&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine Besonderheit besteht bei darzustellenden Werten die die Einheiten &#039;Wh&#039; bzw. &#039;kWh&#039; besitzen. Diese Werte und Einheiten werden automatisch entsprechend des gesetzten Attributes graphicEnergyUnit umgerechnet und angezeigt.&lt;br /&gt;
&lt;br /&gt;
Soll in diesen Fällen eine automatische Formatierung umgangen werden, kann eine solche Notation verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &#039;Today_PVforecast&#039; =&amp;gt; &amp;quot;(sprintf &#039;%.1f &amp;amp;amp;nbsp;kWh&#039;, ($VALUE / 1000))&amp;quot;,&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Die Angabe von &amp;amp;amp;nbsp; vor &#039;kWh&#039; verhindert die Erkennung der Einheit und so auch die automatische Umsetzung durch das Modul. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 3 - Bereich Verbraucherdarstellung (Consumer Legend) ===&lt;br /&gt;
Dieser Grafikbereich zeigt die im Modul registrierten Verbraucher sowie deren Status und weitere Informationen an. Sind die Voraussetzungen gegeben, d.h. entsprechende Schlüssel in der ConsumerXX-Attributen gesetzt, können die Verbraucher über das Paneel manuell geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Zur Anpassung der Darstellung sind verschiedene Attribute verfügbar:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;consumerControl-&amp;gt;showLegend: Definiert die Lage bzw. Darstellungsweise der Verbraucherlegende sofern Verbraucher im SolarForecast Device registriert sind.&lt;br /&gt;
;consumerControl-&amp;gt;adviceIcon: Definiert die Art der Information über die geplanten Schaltzeiten eines Verbrauchers in der Verbraucherlegende. &lt;br /&gt;
;consumerControl-&amp;gt;detailLink: Wenn gesetzt, ist der jeweilige Verbraucher klickbar um direkt zur Detailansicht des jeweiligen Geräts auf einer neuen Browserseite zu gelangen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Standard wird das Verbraucherpaneel zwischen dem Kopfbereich und der ersten Balkengrafik Ebene dargestellt. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;showLegend&#039;&#039;&#039; und Argument &#039;&#039;&#039;icon_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_bottom&#039;&#039;&#039; kann das Verbraucherpaneel an das Ende des Grafikbereiches verschoben werden.&lt;br /&gt;
Die Verwendung von &#039;&#039;&#039;text_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_top&#039;&#039;&#039; blendet die Icon-Spalte im Verbraucherpaneel aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Screenshot 2025-02-08 093239.png|Darstellung mit consumerControl showLegend=icon_top (default)&lt;br /&gt;
File:Screenshot 2025-02-08 093646.png|Darstellung mit consumerControl showLegend=icon_bottom&lt;br /&gt;
File:Screenshot 2025-02-08 152018.png|Darstellung mit consumerControl showLegend=text_top bzw. text_bottom&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 213634.png|right|thumb|400px|]]&lt;br /&gt;
Ein Mouse-Over über das Uhrensymbol zeigt nähere Informationen zum Status, den Planungsdaten, Modus und weitere Daten des Verbrauchers. Der Schalter &amp;quot;Aus/Ein&amp;quot; visualisiert den Schaltzustand des Verbrauchers und können auch zum manuellen Schalten des Verbrauchers dienen. Voraussetzung ist, dass im consumer-Attribut die Schlüssel &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; mit den Set-Kommandos zum Schalten des Verbrauchers defininiert sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 222210.png|right|thumb|300px|]]&lt;br /&gt;
Der Auto-Schieberegler zeigt einerseits den Freigabestatus zum Schalten des Verbrauchers durch das SolarForecast Modul und kann andererseits manuell betätigt werden. Der Status des Reglers korrespondiert mit dem im zugehörigen Consumer Attribut vorhandenen Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; angegebenen Reading-Wert.&lt;br /&gt;
&lt;br /&gt;
Die Verbraucherbezeichnungen in dem Paneel können in der Standardkonfiguration angeklickt werden um direkt zur Detailansicht des Devices zu gelangen. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;detailLink&#039;&#039;&#039; kann der Link zur Detailansicht deaktiviert werden.&lt;br /&gt;
&lt;br /&gt;
Das Uhrensymbol kann mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;adviceIcon&#039;&#039;&#039; geändert und/oder dessen Farbe angepasst, sowie einen Informationstext statt eines Icons angezeigt werden. &lt;br /&gt;
&lt;br /&gt;
=== 4 - Bereich Balkengrafik (Beam Graphic) ===&lt;br /&gt;
&lt;br /&gt;
Die Balkengrafik des Moduls ist ein wesentliches Visualisierungshilfsmittel. Im Auslieferungszustand existiert eine Balkengrafikebene, die &#039;&#039;&#039;Ebene 1&#039;&#039;&#039;.&lt;br /&gt;
Jede Ebene kann zwei Balkendiagramme mit auswählbaren Inhalten, Farben und einstellbarem LayoutTyp darstellen. In Ebene 1 kann die Wettervorhersage eingebettet oder, bei Vorhandensein von Batteriegeräten, die zukünftigen Zeiten mit empfohlener Ladefreigabe und SoC-Prognose eingeblendet werden. &lt;br /&gt;
&lt;br /&gt;
Welche Daten in welchen Zeiträumen dargestellt werden sollen, die Bestimmung des Layouts, die Gestaltung der Balken und einiges mehr wird durch Attribute gesteuert. Ein Teil dieser Einstellungen wird über das zusammengesetzete Attribut &#039;&#039;&#039;graphicControl-&amp;gt;&#039;Schlüssel&#039;=&#039;Wert&#039;&#039;&#039;&#039; eingestellt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;grundsätzliche Layout Definitionen&#039;&#039;&#039;&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204342.png|right|thumb|400px|Standardanzeige mit Wetter-Icons, gesetzen Attributen graphicBeam1Color=D4C177, graphicHistoryHour=11]]&lt;br /&gt;
&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingTop:Legt den Platz in px im Balkendiagramm fest, der zwischen dem oberen Rand der jeweiligen Balkengrafik Ebene und der ersten Text- oder Iconreihe dieser Ebene eingefügt wird.&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingBottom:Legt den Platz in px im Balkendiagramm fest, der zwischen der letzten Text- oder Iconreihe der jeweiligen Balkengrafik Ebene und dem unteren Rand dieser Ebene eingefügt wird. &lt;br /&gt;
;graphicControl-&amp;gt;layoutType:Layout-Optionen zur grundlegenden Gestaltung der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourStyle:Format der Zeitangabe in der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourCount:Anzahl der darzustellenden Balken/Stunden in der Balkengrafk&lt;br /&gt;
[[Datei:Screenshot Screenshot 2025-05-21 153613.png|right|thumb|400px|Erweiterung des oberen und unteren Abstandes mit den Attributen graphicControl-&amp;gt;beamPaddingTop und graphicControl-&amp;gt;beamPaddingBottom]]&lt;br /&gt;
;graphicControl-&amp;gt;energyUnit:definiert die Einheit zur Anzeige der elektrischen Leistung in der Grafik&lt;br /&gt;
;graphicHistoryHour:Anzahl der vorangegangenen Stunden die in der Balkengrafik dargestellt werden&lt;br /&gt;
;graphicControl-&amp;gt;beamWidth:Vorgabe Breite der Balken der Balkengrafik in px (sonst automatische Bestimmung) &lt;br /&gt;
;graphicBeamHeightLevel1:Multiplikator zur Festlegung der maximalen Balkenhöhe der jeweiligen Ebene (hier Ebene 1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;Definition der Inhalte und Balkeneigenschaften&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204756.png|right|thumb|400px|Wie oben aber mit gesetzem Attribut graphicShowNight=1]]&lt;br /&gt;
;graphicBeam1Color:Farbauswahl des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2Color:Farbauswahl des sekundären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam1Content:Legt den darzustellenden Inhalt des primären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam2Content:Legt den darzustellenden Inhalt des sekundären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam1FontColor:Auswahl der Schriftfarbe des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2FontColor:Auswahl der Schriftfarbe des sekundären Balkens (Ebene 1)&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 205024.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=0 (ohne Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;zusätzliche Optionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;graphicShowNight:Anzeigen oder Verbergen der Nachtstunden in der Balkengrafik&lt;br /&gt;
;graphicShowWeather:Wettericons in der Balkengrafik anzeigen/verbergen (nur Ebene 1)&lt;br /&gt;
;graphicWeatherColor:Farbe der Wetter-Icons für die Tagesstunden&lt;br /&gt;
;graphicWeatherColorNight:Farbe der Wetter-Icons für die Nachtstunden&lt;br /&gt;
;graphicShowDiff:Zusätzliche Anzeige der Differenz &amp;quot;&amp;lt;primärer Balkeninhalt&amp;gt; - &amp;lt;sekundärer Balkeninhalt&amp;gt;&amp;quot; im Kopf- oder Fußbereich der Balkengrafik&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die genaue Beschreibung und deren Optionen sind der aktuellen Online-Hilfe zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Für alle Ebenen gilt:&#039;&#039;&#039; Ein Attribut mit einer ungeraden Balkennummer (z.B. graphicBeam1Content) bezieht sich immer auf den primären Balken, ein Attribut mit einer geraden Balkennummer (z.B. graphicBeam2Content) bezieht sich immer auf den sekundären Balken.&lt;br /&gt;
&lt;br /&gt;
Die Balken haben, wie die meisten Elemente in der Balkengrafik, eine Mouse-Over Eigenschaft welche relevante Informationen zu den dargestellten Werten anzeigt. &lt;br /&gt;
&lt;br /&gt;
Sind die Nachtunden mit &#039;&#039;&#039;graphicShowNight&#039;&#039;&#039; ausgeblendet, werden keine Balken angezeigt sofern es keine Werte anzuzeigen gibt. Sollten dennoch Werte ungleich 0 anzuzeigen sein, werden diese Werte auch trotz ausgeblendeter Nachstunden angezeigt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 2 ====&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 211741.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=01 (mit Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 2&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam3Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam4Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 4 für Balken 4) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wetter-Icons können nur in Ebene 1 integriert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 2 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 2 gibt, eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgende Ebene.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 3 ====&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 3&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam5Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam6Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 5 für Balken 5) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 3 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 3 gibt, ist eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgenden Ebenen, d.h. auch auf die Ebene 3.&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 5 - Die Energieflußgrafik (Flow Graphic) ===&lt;br /&gt;
[[Datei:Screenshot 2025-02-13 213424.png|right|thumb|400px|Energieflußgrafik mit Verbrauchern in der Nachtdarstellung (Mondphasen) nach Sonnenuntergang]]&lt;br /&gt;
&lt;br /&gt;
Die Energieflußgrafik stellt die registrierten Erzeuger, Batterien, Netzzugänge und Verbraucher strukturiert in mehreren Ebenen dar:&lt;br /&gt;
&lt;br /&gt;
;Ebene 1: In der oberen Ebene befinden sich die PV-Generatoren, Smart-Loader sowie sonstigen Erzeuger &lt;br /&gt;
;Ebene 2: Die mittlere Ebene organisiert den Zugang zum öffentlichen Netz, dem Hausknoten, dem Batterieknoten sowie einem Dummy-Verbraucher (Lampensymbol) für den Energieverbrauch des Hauses der keinem der registrierten Verbraucher zugeordnet werden kann.&lt;br /&gt;
;Ebene 3: In der unteren Ebene werden die registrierten Verbraucher dargestellt. Unterhalb der Verbrauchersymbole werden der aktuelle Verbrauch (bzw. der On/Off-Zustand) sowie darunter die Restlaufzeit (Minuten) des Verbrauchers, sofern er durch das Modul geplant und gestartet wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Position und Gestaltung der Grafikelemente ist umfangreich über das Attribut &#039;&#039;&#039;flowGraphicControl&#039;&#039;&#039; und den darin verfügbaren Schlüsseln einstellbar.&lt;br /&gt;
Die Bedeutung der Schlüssel ist in der Online-Hilfe zum Attribut mit einem Beispiel beschrieben. &lt;br /&gt;
&lt;br /&gt;
Darüber hinaus enthalten die Setup-Attribute &#039;&#039;&#039;setupInverterDevXX&#039;&#039;&#039;, &#039;&#039;&#039;setupOtherProducerXX&#039;&#039;&#039; und &#039;&#039;&#039;consumerXX&#039;&#039;&#039; weitere Einstellungsmöglichkeiten um deren Icons und Färbungen in der Flußgrafik individuell einstellen zu können. So sind zum Beispiel die Icons der PV-Inverter und deren Färbung mit dem Schlüssel &#039;&#039;&#039;icon&#039;&#039;&#039; der setupInverterDevXX-Attribute in Abhängigkeit von Tag und Nacht separat definierbar.&lt;br /&gt;
&lt;br /&gt;
In den Verbraucher-Attributen ist mit dem Schlüssel &#039;&#039;&#039;noshow&#039;&#039;&#039; die Sichtbarkeit in der Flußgrafik definierbar.&lt;br /&gt;
&lt;br /&gt;
Generell steuert das Attribut &#039;&#039;&#039;graphicSelect&#039;&#039;&#039; die Ein- bzw. Ausblendung der gesamten Flußgrafik.&lt;br /&gt;
&lt;br /&gt;
== Die Verbrauchsprognose ==&lt;br /&gt;
Im Gegensatz zu der PV Prognose gibt es keine API oder andere externen Datenquellen die für die Verbrauchsprognose herangezogen werden könnten.&lt;br /&gt;
&lt;br /&gt;
Zum Zweck der Verbrauchsermittlung verwendet das Modul die Meterdaten aus dem Attribut &#039;&#039;setupMeterDev&#039;&#039; sowie den weiteren setup-Attributen &#039;&#039;setupInverterDevXX&#039;&#039;. &lt;br /&gt;
Sind auch andere Erzeuger (BHKW, Windanlagen, etc.) bzw. eine Batterie vorhanden, sind ebenfalls die Attribute &#039;&#039;setupOtherProducerXX&#039;&#039; bzw. &#039;&#039;setupBatteryDev&#039;&#039; für die Berechnung des Hausverbrauchs relevant. In diesen Attributen gibt es die Schlüssel &#039;&#039;*total&#039;&#039; die teilweise optional sind. Für die Verbrauchsprognose bilden sie jedoch die Berechnungsgrundlage und sind deswegen für diese Funktionalität wichtig anzugeben.&lt;br /&gt;
&lt;br /&gt;
Die Verbrauchswerte werden stundengenau erfasst und im Datenspeicher &#039;&#039;pvHistory&#039;&#039; für 31 Tage, sowie im Datenspeicher &#039;&#039;pvCircular&#039;&#039; 210 Tage gespeichert. Die beiden Datenspeicher übernehmen unterschiedliche Aufgaben im Rahmen der Prognoseerstellung. Auf Grundlage der gespeicherten und somit historischen Verbrauchswerte erstellt das Modul eine Prognose für die kommende Zeit.&lt;br /&gt;
&lt;br /&gt;
Mit dem Kommando &lt;br /&gt;
&lt;br /&gt;
   &amp;quot;get ... pvHistory [Tag]&amp;quot; &lt;br /&gt;
&lt;br /&gt;
wird der Inhalt aufgelistet. Die Schlüssel &#039;&#039;confc&#039;&#039;, &#039;&#039;con&#039;&#039; und &#039;&#039;gcon&#039;&#039; zeigen die Verbrauchsprognose, den Verbrauch und den Netzbezug der jeweiligen Stunde des gewählten Tages.&lt;br /&gt;
Die Stunde &amp;quot;99&amp;quot; zeigt die Summen dieser Schlüsssel für den Tag:&lt;br /&gt;
&lt;br /&gt;
      99 =&amp;gt; etotal: , pvfc: 782, pvrl: 0, rad1h: -&lt;br /&gt;
            confc: 14540, con: 13873, gcon: 13873, gfeedin: 0&lt;br /&gt;
            batintotal: , batin: 0, batouttotal: , batout: 0&lt;br /&gt;
            batmaxsoc: -, batsetsoc: -&lt;br /&gt;
            wid: , wcc: , wrp: , pvcorrf: , dayname: So&lt;br /&gt;
            cyclescsm01: 0&lt;br /&gt;
            cyclescsm02: 0&lt;br /&gt;
            cyclescsm03: 0&lt;br /&gt;
            cyclescsm04: 1, hourscsme04: 0.00&lt;br /&gt;
            cyclescsm05: 0&lt;br /&gt;
            cyclescsm06: 0&lt;br /&gt;
            cyclescsm07: 1, hourscsme07: 0.00&lt;br /&gt;
            cyclescsm08: 1, hourscsme08: 0.00&lt;br /&gt;
            cyclescsm09: 1, hourscsme09: 0.03 &lt;br /&gt;
&lt;br /&gt;
In dem Beispiel wurden für den Tag 14540 Wh Verbrauch prognostiziert, 13873 Wh tatsächlich verbraucht und davon 13873 Wh aus dem Netz bezogen. Leider war an diesem Tag keinerlei PV Ertrag vorhanden, was man auch an dem Schlüssel &#039;&#039;pvrl&#039;&#039; erkennen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Inhalt des pvCircular-Speichers kann mit dem Befehl  &lt;br /&gt;
&lt;br /&gt;
     &amp;quot;get ... pvCircular [Tag]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Das nachfolgende Beispiel zeigt die Ausgabe für die Tagesstunde 23:&lt;br /&gt;
&lt;br /&gt;
 23 =&amp;gt; pvapifc: 0, pvaifc: -, pvfc: 0, aihit: 0, pvrl: 0&lt;br /&gt;
       batin01: 0, batin02: -, batin03: -&lt;br /&gt;
       batout01: 619, batout02: -, batout03: -&lt;br /&gt;
       confc: 650, gcon: 23, gfeedin: 0, wcc: 40, rr1c: 0.00&lt;br /&gt;
       temp: -6.00, wid: 100, wtxt: Bewölkungsentwicklung nicht beobachtet&lt;br /&gt;
       pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
       ... &lt;br /&gt;
       con_all =&amp;gt; Sa  @ 617 762&lt;br /&gt;
                  Di  @ 693 645&lt;br /&gt;
                  Mo  @ 620 679&lt;br /&gt;
                  So  @ 669 666 636&lt;br /&gt;
                  Mi  @ 701 626&lt;br /&gt;
                  Do  @ 612 642&lt;br /&gt;
                  Fr  @ 615 606&lt;br /&gt;
&lt;br /&gt;
Der Schüssel &#039;&#039;con_all&#039;&#039; enthält einen Hash aus Arrays die für jeden Wochentag (Mo..So) bis zu 30 Verbrauchswerte (in Wh) für die angezeigte Stunde speichern. Wie hier erkennbar ist, wurden an den drei vergangenen Sonntagen jweils 669 Wh, 666 Wh bzw. 636 Wh in der Stunde 23 (22:00-22:59) verbraucht.&lt;br /&gt;
Der Median aus diesen Werten geht in die Verbrauchsprognose ein. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wochentagsnamen Mo..So sind von den installierten Locales auf Betriebsystemebene abhängig. Ist keine deutsche locale installiert, werden die englischen Wochentagsnamen Mon..Sun verwendet. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Wie wird der Verbrauch des Hauses ermittelt und gespeichert? ===&lt;br /&gt;
Die Verbrauchsdaten des Hauses werden auf Stundenbasis ermittelt und gespeichert. Das &amp;quot;Haus&amp;quot; steht als Synonym aller im Kontext des Solarforecast Devices zusammengeführten Inverter (setupInverterDevXX), sonstigen Erzeuger (setupOtherProducerXX), Netzanschlüsse (setupMeterDev), Verbraucher (consumerXX) und Batterien (setupBatteryDev).&lt;br /&gt;
&lt;br /&gt;
Alle diese Daten werden durch das Modul mit jedem ausgeführten Zyklus (Attribut plantControl-&amp;gt;cycleInterval) und, wenn ein Event eines als &#039;asynchron&#039; definierten Devices auftritt, gesammelt und daraus permanent ein aktualisierter Verbrauch berechnet. Die Berechnung beschreibt folgende Formel:&lt;br /&gt;
&lt;br /&gt;
 PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung - Verbrauch = 0&lt;br /&gt;
&lt;br /&gt;
bzw.&lt;br /&gt;
 &lt;br /&gt;
 Verbrauch (Wh) = PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung&lt;br /&gt;
            con = PV           + PP                 - GridIn          + GridCon   - BatIn          + BatOut&lt;br /&gt;
&lt;br /&gt;
Die PV-Erzeugung beinhaltet die Summe aller durch die angegebnen Inverter (setupInverterDev01 .. setupInverterDevXX) erzeugten Energien. Die &amp;quot;sonstige Erzeugung&amp;quot; summiert sich aus den Werten aller angegebenen Producer (setupOtherProducer01 .. setupOtherProducerXX). Der Verbrauch wird durch die registrierten Geräte consumerXX teilweise direkt erfasst, ist aber grundsätzlich unvollständig da nicht alle Verbrauchswerte im &amp;quot;Haus&amp;quot; gemessen und durch das Modul erfasst werden können.&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel zeigt das Ergebnis bei 300 Wh PV-Erzeugung und gleichzeitige 500 Wh Netzbezug:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 300 + 0 - 0 + 500 - 0 + 0 = 800 Wh&lt;br /&gt;
&lt;br /&gt;
Bei 1300Wh PV-Erzeugung, 100 Wh Netzeinspeisung sowie 200 Wh Batterieladung ergibt sich der Verbrauch zu:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 1300 + 0 - 100 + 0 - 200 + 0 = 1000 Wh&lt;br /&gt;
&lt;br /&gt;
Ohne Erzeugung, aber mit der Energielieferung von 500 Wh aus der Batterie, 800 Wh Netzbezug (mit einem Anteil Batterienachladung aus dem Netz von 200 Wh) sieht die Verbrauchsrechnung wie folgt aus: &lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 0 + 0 - 0 + 800 - 200 + 500 = 1100 Wh&lt;br /&gt;
&lt;br /&gt;
Der so ermittelte Verbrauchsert wird mit jedem Zyklus in der pvHistory im Schlüssel &amp;quot;con&amp;quot; gespeichert. Man kann sich die gespeicherten Werte mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;name&amp;gt; pvHistory [&amp;lt;Tag&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Nachfolgendes Beispiel zeigt einen Datensatz für die Stunde 8 eines Tages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      08 =&amp;gt; pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotali01: 62940734, etotali02: 2928860, etotali03: -&lt;br /&gt;
            pvrl01: 0, pvrl02: 0, pvrl03: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 630, con: 962, gcons: 962, conprice: 0.2958&lt;br /&gt;
            gfeedin: 0, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 120, sunalt: -3&lt;br /&gt;
            batintotal: 3713815.07742543, batouttotal: 3604468.26993988, batin: 0, batout: 0&lt;br /&gt;
            wid: 161, wcc: 89, rr1c: 0.00, pvcorrf: 0.27/0.00 temp: 7.40, &lt;br /&gt;
            csmt01: 110996.12, csme01: 32.1399999999994, minutescsm01: 30&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 2513.67, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1581293.6, csme04: 136.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 1662.17, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 90.53, csme06: 0, minutescsm06: 0&lt;br /&gt;
            csmt07: 39.75, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 38050, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 131627, csme09: 33.2000000000116, minutescsm09: 39&lt;br /&gt;
            minutescsm10: 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Schlüssel &amp;quot;con&amp;quot; ist der gespeicherte Verbrauch von 962 Wh ersichtlich.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit bekommt man mit dem Attribut &#039;&#039;ctrlDebug=collectData&#039;&#039; einen Einblick in die Verbrauchsermittlung bei jedem Zyklus und kann so die Eingangswerte und das daraus resultierende Ergebnis im FHEM Log nachverfolgen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
2024.11.28 11:38:20.080 1: SolCast DEBUG&amp;gt; EnergyConsumption input -&amp;gt; PV: 96, PP: 0, GridIn: 0, GridCon: 582, BatIn: 5, BatOut: 0&lt;br /&gt;
2024.11.28 11:38:20.081 1: SolCast DEBUG&amp;gt; EnergyConsumption result -&amp;gt; 673 Wh&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie wird die Verbrauchsprognose erstellt? ===&lt;br /&gt;
&lt;br /&gt;
Aus den gespeicherten con-Werten (Verbrauchsdaten) der pvCircular (Schlüssel con_all) sowie Einträgen der pvHistory wird der Median der historischen Tage ermittelt und für den kommenden Tag bzw. die kommen Stunden zur Prognose angewendet. Dabei geht per default jeder verfügbare historische Tag gleichberechtigt in die Prognose ein. Mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039; kann festgelegt werden, dass nur gleiche Wochentage (Mo..So) für die Prognose verwendet werden. Hierbei spielt die Vermutung, dass das Verbrauchsverhalten eine gewisse Korrelation zum Wochentag hat, eine Rolle. &lt;br /&gt;
&lt;br /&gt;
Verwendet man die Einstellung consForecastIdentWeekdays=1, hat es sich als vorteilhaft erwiesen, das Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays&#039;&#039;&#039; auf einen niedrigeren Wert als den Default zu setzen. Eine Einstellung auf &#039;8&#039; zum Beispiel verwendet den Median der gleichen Wochentage der vergangenenen 8 Wochen. Dadurch wird nicht zu weit in die Vergangenheit verzweigt und so eine langsame Veränderung des Verbrauchsmedian, zum Beispiel hervorgerufen durch den Übergang vom Winter in das Frühjahr hinein, abgebildet.&lt;br /&gt;
&lt;br /&gt;
Weiteren Einfluß auf die Verbrauchsprognose kann mit dem Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; im Consumerattribut genommen werden. Insbesondere bei der unregelmäßigen Nutzung von Verbrauchern mit hoher Leistung kann die Projektion der aufgezeichneten historischen Werte in die Prognose zu unverhältnismäßig hohen Verbrauchswerwartunden führen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Möglicherweise führt in Fällen die Verwendung eine der nachfolgenden Optionen zu einem besseren Ergebnis:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;1 -&#039;&#039;&#039; die allgemeine Verbrauchsprognose wird um die gespeicherten Energieverbrauchsanteile reduziert.&lt;br /&gt;
* &#039;&#039;&#039;2 -&#039;&#039;&#039; wie bei &#039;1&#039;, jedoch gehen die Planungsdaten des Verbrauchers bei der Prognose der kommenden Stunden wieder mit ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;&#039;exconfc&#039;&#039;&#039; in einem der Consumer verwendet, sollte&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays=4&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
eingestellt werden. Hintergrund ist, dass die Verbrauchsanteile der jeweiligen Verbraucher nur maximal 31 Tage in der pvHistory verfügbar sind. Für längere Zeiträume stehen nur Gesamtsummen des Verbrauchs in der pvCircular zu Verfügung.  &lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=1&#039;&#039;&#039; werden die in der Historie aufgezeichneten Verbrauchsbestandteile aus einer Prognose herausgerechnet. Konkret werden die in der pvHistory aufgezeichneten Verbrauchsbestandteile für die relevante Stunde ermittelt und daraus ein Durchschnitt gebildet der vom Prognosewert subtrahiert wird. Mit dem Attributwert plantControl-&amp;gt;consForecastIdentWeekdays=1 werden wiederum nur identische Wochentage (Mo .. So) zusammengefasst.&lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=2&#039;&#039;&#039; erfolgt ebenso die Eliminierung des Verbrauchsanteils, es wird jedoch auf die Planungsdaten für diesen Verbraucher zugegriffen und die geplanten Energieanteile wiederum der Verbrauchsprognose für die kommenden Stunden hinzugerechnet.&lt;br /&gt;
&lt;br /&gt;
In beiden Anwendungsfällen ist es notwendig, dass dem Modul durch die Angabe entsprechender Readings der Energieverbrauch im Setup des Consumers bekannt gemacht wird damit diese Energieanteile registriert werden können. Allgemein funktioniert die Verbrauchsprognose gut wenn Verbrauchsprozesse regelmäßig in einem wiederkehrenden Zeitraster ablaufen, der Verbrauch durch persönliche Rituale bestimmt ist. So zum Beispiel könnte am Dienstag und Samstag gewöhnlich die Waschmaschine laufen, das E-Auto täglich aufgeladen werden und gebügelt wird oft am Sonntag Nachmittag.&lt;br /&gt;
&lt;br /&gt;
Unregelmäßige Nutzung, vor allem vom Großverbrauchern, lässt sich nur sehr schwer und ungenügend auf zukünftige Verbrauchsprognosen projizieren.&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis der Prognose wird im Kopf der Grafik in der Zeile &#039;&#039;Verbrauch&#039;&#039; sowie in diversen Readings wie &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RestOfDayConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den Rest des Tages)&lt;br /&gt;
* &#039;&#039;&#039;NextHours_Sum04_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für die nächsten 4 Stunden)&lt;br /&gt;
* &#039;&#039;&#039;Tomorrow_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den kommenden Tag)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
angezeigt.&lt;br /&gt;
&lt;br /&gt;
Weitere Aggregationen kann man sich über das Attribut &#039;&#039;&#039;ctrlStatisticReadings&#039;&#039;&#039; bei Bedarf zuschalten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;conForecastTillNextSunrise&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
* &#039;&#039;&#039;todayConForecastTillSunset&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
* &#039;&#039;&#039;todayConsumptionForecast&#039;&#039;&#039; - Verbrauchsprognose aufgesplittet pro Stunde des aktuellen Tages (01-24) &lt;br /&gt;
 &lt;br /&gt;
==== Debugging der Verbrauchsprognose ====&lt;br /&gt;
Um sich einen Einblick über die Erstellung der Verbrauchsprognose zu verschaffen, bietet sich die Einschaltung von:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
an. Mit diesem gesetzten Attribut wird die Erstellung der Prognose im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; ################### Start Consumption forecast ###################&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; Basics - installed locale: de_DE.UTF-8, used scheme: DE&lt;br /&gt;
2025.02.27 19:52:00.064 1: SolCast DEBUG&amp;gt; process Today dayname: Do, Tomorrow dayname: Fr&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 01 - 74.43 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 10 - 290.77 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 24 - 660.70 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 20, hod: 07 - 459.93 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;07&#039; register for exclude day 20, hod: 02 - 0.33 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 30, hod: 08 - 264.78 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next Hours (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; excl. hist 74 Wh for Hour 01, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; estimated cons of Hour 01: 436 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; excl. hist 0 Wh for Hour 02, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 02: 428 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 03: 458 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 04: 503 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 05: 489 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 06: 482 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; excl. hist 460 Wh for Hour 07, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 07: 274 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 265 Wh for Hour 08, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 08: 441 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 09: 558 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 291 Wh for Hour 10, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 10: 443 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 11: 881 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 12: 794 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 13: 840 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 14: 660 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 15: 812 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 16: 752 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 17: 597 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 18: 652 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 19: 634 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 20: 628 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 21: 713 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 22: 596 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 23: 629 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; excl. hist 661 Wh for Hour 24, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons of Hour 24: 660 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons Tomorrow: 16848 Wh, Individual hourly values considered: 72, exclude: 0 Wh (avg of 0 entities)&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Store Consumption forecast values (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour00&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;20&#039; confc: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour01&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;21&#039; confc: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour02&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;22&#039; confc: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour03&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;23&#039; confc: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store &#039;NextHour04&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;24&#039; confc: 660&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour05&#039; hod &#039;01&#039; confc: 436, confcEx: 436&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour06&#039; hod &#039;02&#039; confc: 428, confcEx: 428&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour07&#039; hod &#039;03&#039; confc: 458, confcEx: 458&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour08&#039; hod &#039;04&#039; confc: 503, confcEx: 503&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour09&#039; hod &#039;05&#039; confc: 489, confcEx: 489&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour10&#039; hod &#039;06&#039; confc: 482, confcEx: 482&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour11&#039; hod &#039;07&#039; confc: 274, confcEx: 274&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour12&#039; hod &#039;08&#039; confc: 441, confcEx: 441&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour13&#039; hod &#039;09&#039; confc: 558, confcEx: 558&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour14&#039; hod &#039;10&#039; confc: 443, confcEx: 443&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour15&#039; hod &#039;11&#039; confc: 881, confcEx: 881&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour16&#039; hod &#039;12&#039; confc: 794, confcEx: 794&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour17&#039; hod &#039;13&#039; confc: 840, confcEx: 840&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour18&#039; hod &#039;14&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour19&#039; hod &#039;15&#039; confc: 812, confcEx: 812&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour20&#039; hod &#039;16&#039; confc: 752, confcEx: 752&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour21&#039; hod &#039;17&#039; confc: 597, confcEx: 597&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour22&#039; hod &#039;18&#039; confc: 652, confcEx: 652&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour23&#039; hod &#039;19&#039; confc: 634, confcEx: 634&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour24&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour25&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour26&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour27&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour28&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; consumption calculated - day: 27, hod: 20, con: 574 Wh&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; write pvCircular consumption - hod: 99, todayConsumption: 11210 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe startet mit &#039;&#039;&amp;quot;Start Consumption forecast&#039;&#039;&amp;quot;, es werden die zu exkludierenden historischen Daten für jeden Consumer bzgl. jedem Tag (day) und Stunde des Tages (hod) getrennt registriert. Diese Werte werden durch die gespeicherte Einträge in der pvHistory (max. 31 historische Tage) geliefert. &lt;br /&gt;
&lt;br /&gt;
Im nächsten Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next Hours (new median)&amp;quot;&#039;&#039; werden die Prognosen für die nächsten Stunden kalkuliert und die zuvor registrierten Excludes angewendet. Die Prognose für den kommenden Tag ist im Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next day (new median)&amp;quot;&#039;&#039; protokolliert. Die Prognose für den kommenden Tag ist nicht einfach die Summe der Prognose der nächsten Stunden, denn in den kommenden Stunden werden auch die verfügbaren Planungen der Consumer einbezogen. Für den kommenden Tag können diese Werte unter Umständen nicht einbezogen werden da sie zum Zeitpunkt X noch nicht verfügbar sind.&lt;br /&gt;
&lt;br /&gt;
Im Abschnitt &#039;&#039;&amp;quot;Store Consumption forecast values (new median)&amp;quot;&#039;&#039; erscheinen die effektiv gespeicherten Werte. Diese sind die Grandlage für die grafische Darstellung sowie weiteren Kalkulationen.&lt;br /&gt;
&lt;br /&gt;
=== Wie kann eine fehlerhafte Verbrauchsprognose korrigiert werden? ===&lt;br /&gt;
Wie im vorherigen Abschnitt beschrieben, wird die Prognose aus den gespeicherten &amp;quot;con&amp;quot;-Werten der vergangenen Tage (bzw. Stunden) abgeleitet. &lt;br /&gt;
Grundsätzlich muß zunächst sichergestellt werden, dass die auszulesenden Readings der angegebenen Energiezähler sowie deren Einheiten! korrekt eingestellt sind. Das gilt ebenfalls für die registrierten Verbraucher im Modul.&lt;br /&gt;
&lt;br /&gt;
Für einen ersten Überblick bietet sich das Debug Attribut an zu setzen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
Beispielausgabe des Debug:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2024.09.21 13:28:27.041 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day ###################&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;01&amp;lt; considering possible exclusions: 14082&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;08&amp;lt; considering possible exclusions: 16446&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;15&amp;lt; considering possible exclusions: 14568&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;25&amp;lt; considering possible exclusions: 15522&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; estimated Consumption for tomorrow: 15154, days for avg: 4&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next hours ###################&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 14 -&amp;gt; 850 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 14 -&amp;gt; 643 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 14 -&amp;gt; 590 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 14 -&amp;gt; 522 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 13:00:00, confc: 651, days for avg: 4, hist. consumption registered consumers: 560.97&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 15 -&amp;gt; 720 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 15 -&amp;gt; 743 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 15 -&amp;gt; 897 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 15 -&amp;gt; 557 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 14:00:00, confc: 729, days for avg: 4, hist. consumption registered consumers: 620.97&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 16 -&amp;gt; 676 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 16 -&amp;gt; 790 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 16 -&amp;gt; 785 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 16 -&amp;gt; 581 Wh&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 15:00:00, confc: 708, days for avg: 4, hist. consumption registered consumers: 647.29&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 17 -&amp;gt; 622 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 17 -&amp;gt; 639 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 17 -&amp;gt; 646 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 17 -&amp;gt; 572 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 16:00:00, confc: 619, days for avg: 4, hist. consumption registered consumers: 618.30&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 18 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 18 -&amp;gt; 614 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 18 -&amp;gt; 580 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 18 -&amp;gt; 480 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 17:00:00, confc: 567, days for avg: 4, hist. consumption registered consumers: 583.41&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 19 -&amp;gt; 615 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 19 -&amp;gt; 1659 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 19 -&amp;gt; 597 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 19 -&amp;gt; 618 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 18:00:00, confc: 872, days for avg: 4, hist. consumption registered consumers: 636.97&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 20 -&amp;gt; 611 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 20 -&amp;gt; 1124 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 20 -&amp;gt; 546 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 20 -&amp;gt; 479 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 19:00:00, confc: 690, days for avg: 4, hist. consumption registered consumers: 578.87&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 21 -&amp;gt; 1474 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 21 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 21 -&amp;gt; 619 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 21 -&amp;gt; 433 Wh&lt;br /&gt;
2024.09.21 13:28:27.058 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Im ersten Teil wird die erwartete Consumption für den nächsten Tag unter Berücksichtigung möglicher Ausschlüsse von Verbrauchern ausgegeben. Ausschlüsse von Verbrauchern ergeben sich wenn in dem Verbraucherattribut der Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; gesetzt ist. Er besagt, dass die Verbrauchswerte des Verbrauchers in eine zukünftige Prognose nicht eingehen sollen. Zum Beispiel wenn ein Verbraucher mit sehr hohen Verbrauchswerten nur sporadisch eingesetzt wird und dadurch die Prognose stark verfälschen würde. Es ist auch zu sehen, dass bedingt durch das Attribut &#039;&#039;&#039;affectConsForecastIdentWeekdays = 1&#039;&#039;&#039; nur die historischen Tage 01, 08, 15 und 25 berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Teil wird die berechnete Erwartung für die nächsten Stunden ausgegeben. &lt;br /&gt;
Zur Beschreibung der Fehlersuche gehen wir davon aus, dass die Prognose von 780 Wh am 2024-09-21 20:00:00 zu hoch erscheint weil am Tag &amp;quot;07&amp;quot; ein Wert von 1474 Wh gespeichert ist:&lt;br /&gt;
&lt;br /&gt;
 SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt geben wir die historischen Werte für den Tag 07 aus:&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;Name&amp;gt; pvHistory 07&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz interessiert die Stunde 21. Sie resultiert aus der obigen Angabe &amp;quot;starttime: xxxx-xx-xx 20:00:00&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      21 =&amp;gt; etotal: 64354660, pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 496, con: 1474, gcons: 23, conprice: 0.2958&lt;br /&gt;
            gfeedin: 5, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 289, sunalt: -8&lt;br /&gt;
            batintotal: 3064096.92456668, batouttotal: 2958021.37946804, batin: 0, batout: 1460&lt;br /&gt;
            wid: 101, wcc: 20, rr1c: 0.00, pvcorrf: 1.00/-temp: 26.00, &lt;br /&gt;
            csmt01: 64262.43, csme01: 28.8099999999977, minutescsm01: 25&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 0, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1389417.4, csme04: 94.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 0, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 290.15, csme06: 6.66999999999996, minutescsm06: 54&lt;br /&gt;
            csmt07: 0, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 32800, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 103987.8, csme09: 38, minutescsm09: 43&lt;br /&gt;
            csmt10: 9151.24999999783, csme10: 3.99999999997999, minutescsm10: 60&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz sind die Energieverbrauchsanteile der im Device registrierten Verbraucher mit dem Schlüssel &amp;quot;csmeXX&amp;quot; gespeichert. Dabei ist &amp;quot;XX&amp;quot; die Verbrauchernummer. In dem Beispiel existieren die Anteile csme01 und csme03 - csme10. Keiner dieser Verbraucher hat einen auffälligen Verbrauchswert gespeichert, d.h. die Messung der Verbraucher scheidet als Problemquelle aus. Wäre ein unverhältmismäßig hoher Verbrauch bei einem der Verbraucher feststellbar, müssten die Schlüssel &#039;&#039;&#039;pcurr&#039;&#039;&#039; und &#039;&#039;&#039;etotal&#039;&#039;&#039; im consumerXX-Attribut geprüft, sowie die Datenlieferung des Consumerdevices selbst geprüft werden.  &lt;br /&gt;
&lt;br /&gt;
Es wurde offensichtlich ein hoher Verbrauch von einem nicht registrierten Verbraucher verursacht oder durch die Übertragung eines Meßfehlers des Devices, angegeben im Attribut &#039;&#039;&#039;setupMeterDev&#039;&#039;&#039;, in das SolarForecast Device übertragen. Eine weitere Analyse ist an dieser Stelle nicht möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Behebung des falschen Wertes kann ein Reset der gespeicherten Consumption der relevanten Stunde durchgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; reset consumptionHistory 07 21&lt;br /&gt;
&lt;br /&gt;
== Modulinterne Datenstrukturen ==&lt;br /&gt;
Das Modul speichert die verschiedenen historischen und aktuellen Daten wie PV-Prognose, Witterungsdaten (Regen, Bewölkung), Strahlungsdaten, Einspeisung, Bezug, reale Erzeugungsdaten und vieles mehr zur Laufzeit im Arbeitsspeicher. Dadurch ist die Verarbeitung dieser Daten im Vergleich zu Lesevorgängen aus dem Filesystem bzw. einer Datenbank sehr performant. Allerdings würden diese Daten bei einem FHEM Absturz bzw. bei einem regulären Shutdown verlorengehen.&lt;br /&gt;
&lt;br /&gt;
Deswegen werden die relevanten Daten regelmäßig in Dateien gesichert und bei Bedarf wiederhergestellt. Diese Dateien befinden sich im Verzeichnis &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; und heißen &#039;&#039;&#039;.*_SolarForecast_.*&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Die Daten werden in jedem Zyklus der Zentralschleife (CentralTask) gesammelt bzw. berechnet. Der Zyklus wird mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;cycleInterval&#039;&#039;&#039; eingestellt.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit können diese Daten über get-Kommandos abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvHistory [Tag]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der pvHistory Datenspeicher enthält die vergangenen Kennwerte der letzten 31 Tage mit einer Genauigkeit von einer Stunde. Es werden die Prognosewerte für Erzeugung und Verbrauch, die realen Werte für Erzeugung und Verbrauch sowie ebenso die Laufzeiten jedes einzelnen Verbrauchers (Consumer) festgehalten. Für jeden Tag gibt es die Stunde &amp;quot;99&amp;quot; die eine Summierung der Stundenwerte des Tages bzw. Sonderschlüssel enthält.&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf lässt sich mit dem Befehl &amp;quot;set ... reset pvHistory&amp;quot; der gesamte Inhalt des Speichers löschen (nicht empfohlen). Selektiver funktioniert die Datenlöschung mit &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt;&amp;quot; (Daten eines bestimmten Tages löschen) bzw. &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt; &amp;lt;Stunde&amp;gt;&amp;quot; (Daten der Stunde  eines bestimmten Tages löschen). Die letzten beiden Kommandos müssen über die Kommandozeile im Browser ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvCircular &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Ringspeicher enthält Daten der letzten 24 Stunden sowie fortwährend berechnete Werte wie Korrekturfaktoren der PV-Erzeugung und Prognosequalität.&lt;br /&gt;
Neue Stundenwerte des Tages überschreiben die gespeicherten Schüssel des vorangegangenen Tages sofern es sich nicht um fortwährend berechnete Werte handelt. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... nextHours&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Speicher enthält sämtliche Prognosewerte der kommenden Stunden beginnend mit der aktuellen Stunde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... radiationApiData&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Abhängig von der ausgewählten Strahlungsdaten API enthält dieser Speicher die von der API gelieferten Rohdaten sowie evtl. weitere für die Funktion benötigte Daten wie API-Keys, Response Messages, Anzahl der API Abruf und weitere.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valCurrent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Struktur wird nicht regelmäßig im Filesystem gespeichert und enthält immer aktuell gesammelte oder berechnete/gelieferte Daten wie z.B. die Autarkierate, letze Laufzeit der Zentralschleife (CentralTask), Zeit des Sonnenauf- und untergangs sowie weitere Betriebsdaten. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valConsumerMaster [XX]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zeigt die Daten der aktuell im SolarForecast Device registrierten Verbraucher. Mit der Nummer &#039;&#039;&#039;XX&#039;&#039;&#039; kann ein bestimmter Verbraucher angesprungen werden. Die Nummer korrespondiert mit dem entsprechenden &#039;&#039;&#039;consumerXX&#039;&#039;&#039; Attribut.&lt;br /&gt;
Neben anderen Betriebs- und Energiedaten werden insbesondere folgende Daten ermittelt, die für die zukünftige Planung der Verbraucherschaltzeiten relevant sind:&lt;br /&gt;
&lt;br /&gt;
* epieces - prognostizierte Energiescheiben pro Betriebsstunde &lt;br /&gt;
&lt;br /&gt;
Ausgehend von gespeicherten historischen Verbrauchsdaten des Verbrauchers wird der Energieverbrauch des Verbrauchers in seiner ersten Betriebsstunde prognostiziert, was insbesondere für die Planung der optimalen Startzeit des Verbrauchers in Bezug zu der prognostizierten PV Energie und den Verbrauchswerten weiterer vorhandener bzw. zu planender Verbraucher Berücksichtigung findet. Weitere Informationen zur Verbrauchersteuerung in diesem  [[#Verbrauchersteuerung_-_Registrieren_und_visualisieren_von_Verbrauchern|Abschnitt]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Schnittstelle für Modulautoren bzw. eigenen Code ===&lt;br /&gt;
&lt;br /&gt;
Die im vorherigen Artikel beschriebenen internen Datenstrukturen können durch externen Code abgefragt und ausgewertet werden.&lt;br /&gt;
Dazu stehen die folgenden Funktionen zur Verfügung. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]BatteryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Bn&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valBattery&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CurrentVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valCurrent&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]InverterVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valInverter&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ProducerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valProducer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]HistoryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Day&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvHistory&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CircularVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvCircular&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]NexthoursVal (&#039;&amp;lt;Name&amp;gt;&#039;, &amp;lt;nhr&amp;gt;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... nextHours&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ConsumerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valConsumerMaster&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]RadiationAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;DateTime&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... radiationApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]WeatherAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;TimeCode&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... weatherApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StatusAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;QTag&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... statusApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StringVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valStrings&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Angabe des Packages (FHEM::SolarForecast::) ist nur notwendig wenn die Funktionen von außerhalb des SolarForecast-Devices aufgerufen werden. Innerhalb des Devices (Code-Ausführung im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039;) kann darauf verzichtet werden.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der Platzhalter sind:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     &amp;lt;Name&amp;gt;     - Name des SolarForecast Devices&lt;br /&gt;
     &amp;lt;Day&amp;gt;      - abzufragender Tag (01 - 31)&lt;br /&gt;
     &amp;lt;Bn&amp;gt;       - Batterie Nummer (01, 02, ...)&lt;br /&gt;
     &amp;lt;DateTime&amp;gt; - Startzeit der Form YYYY-MM-DD hh:00:00&lt;br /&gt;
     &amp;lt;TimeCode&amp;gt; - Zeitwert der Form fcX_XX (z.B. fc1_19)&lt;br /&gt;
     &amp;lt;APIname&amp;gt;  - Hauptname der API gemäß setupWeatherDev1 (z.B. OpenMeteo)&lt;br /&gt;
     &amp;lt;String&amp;gt;   - Name des PV-Modulstrings wie im Attribut &#039;setupInverterStrings&#039;&lt;br /&gt;
     &amp;lt;QTag&amp;gt;     - Question Tag, z.B. &#039;?All&#039;&lt;br /&gt;
     &amp;lt;Nr&amp;gt;       - laufende Nummer des Verbrauchers / Gerätes (01, 02, 03, 04,...)&lt;br /&gt;
     &amp;lt;HoD&amp;gt;      - abzufragende Stunde (01 - 24, 99)&lt;br /&gt;
     &amp;lt;nhr&amp;gt;      - nächste Stunde (NextHour00, NextHour01,...)&lt;br /&gt;
     &amp;lt;Key&amp;gt;      - der abzufragende Schlüssel &lt;br /&gt;
     &amp;lt;default&amp;gt;  - def default-Rückgabewert&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Auswerten von internen Arrays ===&lt;br /&gt;
&lt;br /&gt;
Die meisten der internen Datenstrukturen liefern bei der Abfrage einen einfachen String oder numerischen Wert der ausgewertet werden kann. Es gibt allerdings auch intern gespeicherte Wertelisten. Werden die Listenstrukturen mit den oben beschriebenen Befehlen abgefragt, wird eine Referenz auf die Liste geliefert sofern sie vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
Um auf die Werte einer solchen Liste zuzugreifen, ist am Beispiel des Arrays &#039;&#039;surplusslidereg&#039;&#039; aus dem Current-Speicher (get ... valCurrent) dargestellt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
my $splref = CurrentVal ($name, &#039;surplusslidereg&#039;, &#039;.&#039;);&lt;br /&gt;
my $spser  = ref $splref eq &#039;ARRAY&#039; ? join &#039; &#039;, @{$splref} : undef;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Variable $spser enthält bei Vorhandensein der Liste einen String, der die Listenelemente von &#039;surplusslidereg&#039; durch Leerzeichen getrennt enthält.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backup und Wiederherstellung der Moduldaten ==&lt;br /&gt;
Neben der Datenhaltung in den Attributen und Readings des SolarForecast Devices, erzeugt jedes SolarForecast Device Dateien im Verzeichnis  &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; mit folgenden Inhalten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PVH_SolarForecast_&amp;lt;name&amp;gt;        - PV History&lt;br /&gt;
PVC_SolarForecast_&amp;lt;name&amp;gt;        - PV Circular&lt;br /&gt;
PVCfg_SolarForecast_&amp;lt;name&amp;gt;      - PV Anlagenkonfiguration&lt;br /&gt;
PVCsm_SolarForecast_&amp;lt;name&amp;gt;      - Consumer Status&lt;br /&gt;
ScApi_SolarForecast_&amp;lt;name&amp;gt;      - Strahlungswerte aus verwendeter API&lt;br /&gt;
StatApi_SolarForecast_&amp;lt;name&amp;gt;    - Statusdaten der verwendeten API&#039;s&lt;br /&gt;
WeatherApi_SolarForecast_&amp;lt;name&amp;gt; - Wetterdaten der gewählten Wetter-API (außer DWD-Device)&lt;br /&gt;
AItra_SolarForecast_&amp;lt;name&amp;gt;      - KI Entscheidungsquelle (trainierte Daten)&lt;br /&gt;
AIraw_SolarForecast_&amp;lt;name&amp;gt;      - KI Input Daten = Raw Trainigsdaten&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nach Ausprägung und eingesetzten Features des SolarForecast Devices sind alle oder nur ein Teil dieser Dateien vorhanden. Dabei ist &#039;&#039;&#039;&amp;lt;name&amp;gt;&#039;&#039;&#039; der Name des SolarForecast Devices.&lt;br /&gt;
&lt;br /&gt;
Bei einem Filebackup des FHEM-Servers ist darauf zu achten, dass diese Dateien in dem Backup enthalten sind. Der Inhalt der Dateien ist nicht statisch, sondern kann sich dynamisch aktualisieren. Um im Bedarfsfall einen aktuellen Datenstand zu haben, ist mindestens ein tägliches Backup dieser Dateien empfehlenswert. Eventuell auch öfter mit Hilfe einer Versionierung welche z.B. immer die letzten 3 Versionen aufbewahrt.&lt;br /&gt;
&lt;br /&gt;
Beim Start von FHEM werden bestimmte Dateien automatisch gelesen und in das SolarForecast Device importiert. &lt;br /&gt;
Der Vorgang ist mit verbose=3 im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2023.10.02 09:57:07.967 3: SolCast6 - cached data &amp;quot;pvHistory&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.969 3: SolCast6 - cached data &amp;quot;pvCircular&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;consumerMaster&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;radiationApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;statusApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;weatherApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.974 3: SolCast6 - cached data &amp;quot;aiTrainedData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.976 3: SolCast6 - cached data &amp;quot;aiRawData&amp;quot; restored&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bestimmte Betriebsdaten, wie z.B. die witterungsabhängigen Korrekturfaktoren (circular) oder die KI-Daten (aitrained/airaw), bauen sich über die Zeit immer granularer auf und stellen einen wertvollen Datenbestand dar.&lt;br /&gt;
&lt;br /&gt;
Wird das SolarForecast Device gelöscht und anschließend wieder neu mit dem gleichen Namen definiert, können die bisher verfügbaren Daten sehr einfach wiederhergestellt werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. starten von FHEM (bestimmte Daten werden automatisch importiert)&lt;br /&gt;
* 5. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Soll das neue SolarForecast Device mit einem anderen Namen oder weitere SolarForecast Devices erstellt werden, welche die Betriebsdaten des primären Devices verwenden sollen, ist wie folgt vorzugehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. umbenenen der Dateien, wobei &amp;lt;name&amp;gt; durch den Namen des neuen SolarForecast Devices ersetzt wird&lt;br /&gt;
* 5. starten von FHEM (die Daten werden automatisch importiert)&lt;br /&gt;
* 6. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn sich die SolarForecast Devices hinsichtlich ihres Models oder der integrierten Consumer unterscheiden, sind die Dateien &amp;quot;PVCsm_SolarForecast_&amp;lt;name&amp;gt; &amp;quot; , &amp;quot;ScApi_SolarForecast_&amp;lt;name&amp;gt;&amp;quot; von dem Verfahren auszuschließen.&lt;br /&gt;
&lt;br /&gt;
== Batterieintegration und -steuerung ==&lt;br /&gt;
&lt;br /&gt;
=== Wie eine Batterie eingebunden wird ===&lt;br /&gt;
Wie immer muß die Batterieanlage zunächst mit einem für die Batterie spezifischen FHEM-Device in FHEM definiert sein.&lt;br /&gt;
In diesem Device werden Readings erwartet die folgende Werte bereitstellen:&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieentladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die installierte Batteriekapazität liefert (&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; dieser Schlüssel ist für die Aktivierung des Batterie SOC-Managements und die grafische Anzeige des SOC wesentlich!)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Lade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Entlade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* Reading welches den aktuellen Ladezustand (SOC in Prozent) liefert (optional)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Batterie, bzw. das Batteriedevice wird mit dem Attribut &#039;&#039;&#039;setupBatteryDev&#039;&#039;&#039; im SolarForecast Device registriert. Die Syntax des Attributes ist in  der Online-Hilfe zum Attribut umfassend erläutert. &lt;br /&gt;
Auch wenn manche Readings optional sind, wird empfohlen alle Werte bereitzustellen um alle Batterie-Funktionen im Modul nutzen zu können. Durch die Weiterentwicklung des Moduls können optionale Readings später auch obligatorisch werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Visualisierung der Batterie in der Balkengrafik ====&lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;setupBatteryDevXX&#039;&#039;&#039; verfügt über den Schlüssel &#039;&#039;&#039;show&#039;&#039;&#039;, mit dem die Einblendung des bzw. der Batteriesymbole in den Ebenen der Balkengrafik gesteuert werden kann:&lt;br /&gt;
[[Datei:Screenshot 2025-02-23 192002.png|right|thumb|400px|Einblendung der Batterieleiste und Darstellung des Batterie-SoC als Balkencontent in der zweiten Ebene]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 0 - keine Anzeige des Gerätes (default)&lt;br /&gt;
* 1 - Anzeige des Gerätes in der Balkengrafik Ebene 1&lt;br /&gt;
* 2 - Anzeige des Gerätes in der Balkengrafik Ebene 2 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Symbole und die Farbgebung der Batterie(n) können mittels des Schlüssels &#039;&#039;&#039;icon&#039;&#039;&#039; verändert werden. Die Online-Hilfe gibt weitere Informationen zur Ausgestaltung. &lt;br /&gt;
&lt;br /&gt;
In der Batteriedarstellung wird das Symbol der aktuellen Stunde hervorgehoben. Ein Mouse-Over zeigt wesentliche Betriebszustände der Batterie. Die Batteriesymbole vergangener Stunden zeigen mit einem Mouse-Over die erreichten SoC (State of Charge) Stände. Die kommenden Stunden visualisieren die folgenden Prognosen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der prognostizierte SoC unter Berücksichtigung der PV-Prognose und der [[#Aktivierung_des_Batterie_SOC-Managements|Batteriesteuerung]] sofern sie im Modul aktiviert ist.&lt;br /&gt;
* eine Freigabe bzw. Empfehlung der Batterieladung zur [[#Unterstützung_eines_netzdienlichen_Verhaltens|Unterstützung eines netzdienlichen Verhaltens]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Neben der Einblendung der Batterieleiste über der Balkengrafik selbst können bestimmte Batteriekennwerte als Balkeninhalt dargestellt werden. Die Auswahl erfolgt über das Attribut &#039;&#039;&#039;graphicBeamXContent&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Aktivierung des Batterie SOC- und Lade-Managements ===&lt;br /&gt;
Das integrierte SOC- und Lade-Management verfolgt insbesondere zwei Ziele: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* den Ladezustand der Batterie(n) zu optmimieren, was besonders in den Monaten mit geringerer PV-Erzeugung einen wertvollen Beitrag zur Erhöhung der Autarkierate und Batteriepflege leisten kann&lt;br /&gt;
 &lt;br /&gt;
* eine PV-Prognose und Verbrauch optimierte Beladungssteuerung, die in den Monaten mit hoher PV-Erzeugung hilft eine evtl. Abregelung der Anlage zu verhindern, die Batterie ausgewogen über den Tag zu laden und ein netzdienliches Verhalten zu unterstützen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese beiden Aspekte der Batteriesteuerung werden in den folgenden Abschnitten beschrieben. Sind mehrere Batterien installiert, kann die Steuerung getrennt für jede einzelne Batterie aktiviert und eingestellt werden. Dabei ist zu beachten, dass vom Modul nur Signale und Readings bereitgestellt werden, die durch eine entsprechende Routine ausgewertet werden können um spezifische Befehle zur Umsetzung der Steuerung an das Batteriesystem zu senden. &lt;br /&gt;
 &lt;br /&gt;
Für eine Aktivierung des Managements muß zunächst das Batterie-Device wie im vorigen Abschnitt im SolarForecast Device registriert werden.&lt;br /&gt;
Das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; aktiviert die im Modul integrierte SOC- und Lade-Management Routine: &lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; ctrlBatSocManagement01 lowSoc=&amp;lt;Wert&amp;gt; upSoC=&amp;lt;Wert&amp;gt; [maxSoC=&amp;lt;Wert&amp;gt;] [careCycle=&amp;lt;Wert&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
Die einzelnen Schlüssel werden der Kalkulationsroutine als Steuerungsparameter übergeben und bedeuten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;lowSoc:unterer Mindest-SoC, die Batterie wird nicht tiefer als dieser Wert entladen (muß &amp;gt; 0 sein). Dieser Wert kann zum Beispiel dazu dienen, stets eine Mindestenergiemenge für den Fall eines Stromausfalls im öffentlichen Netz in den Batterien vorzuhalten.&lt;br /&gt;
&lt;br /&gt;
;upSoC:oberer Mindest-SoC, Der übliche Wert des optimalen SoC bewegt sich in Perioden mit hohen PV-Überschuß tendenziell zwischen &#039;lowSoC&#039; und &#039;upSoC&#039;, in Perioden mit geringer PV-Ausbeute bzw. geringem PV Energieüberschuß bewegt sich der optimale SoC tendenziell zwischen &#039;upSoC&#039; und &#039;maxSoC&#039;. Die Einstellung von upSoC=50 für ein ausgewogenes Verhalten kann als guter Startwert dienen.&lt;br /&gt;
&lt;br /&gt;
;maxSoC:maximaler Mindest-SoC, d.h. der SoC Wert der mindestens im Abstand von &#039;careCycle&#039; Tagen erreicht werden muß um den Ladungsausgleich im Speicherverbund auszuführen. Die Angabe ist optional (muß &amp;lt;= 100 sein, default: 95)&lt;br /&gt;
&lt;br /&gt;
;careCycle:maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens &#039;maxSoC&#039; auftreten darf. Die Angabe ist optional. (default: 20)&lt;br /&gt;
&lt;br /&gt;
;loadAbort: definiert eine vom Anwender gewünnschte Bedingung für einen generellen Ladeabbruch und Wiederfreigabe der Lademöglichkeit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle Werte sind ganze Zahlen in %. Dabei gilt: &lt;br /&gt;
&lt;br /&gt;
 lowSoc &amp;lt; upSoC &amp;lt; maxSoC&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====  Erläuterung der Batterie-Steuerungsreadings ==== &lt;br /&gt;
&lt;br /&gt;
Für die Steuerung des Batteriesystems gibt es im SolarForecast einen Satz an Readings, die unterschiedliche Zustände signalisieren und für entsprechende Steuerungsaufgaben bezüglich der Batteriesysteme eingesetzt werden können. In den nachfolgenden Abschnitten werden diese Zusammenhänge noch dataillierter beschrieben.&lt;br /&gt;
&lt;br /&gt;
;Hinweis: SolarForecast stellt lediglich Steuerungsinformationen zur Verfügung. Die Umsetzung des Eingriffs in das Batteriesystem erfolgt durch den Anwender selbst über entsprechende Skripte. In den thematischen Abschnitten werden Beispiele für solche Steuerungsskripte vorgestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle erstellten Readings gelten für ein Batteriesystem, es können mehrere Batteriesysteme in SolarForecast integriert sein. Die Endung &#039;&#039;XX&#039;&#039; der Readings beschreibt die Nummer des Batteriesystems und korrespondiert mit der Endung des entsprechenden Attributes &#039;&#039;ctrlBatSocManagementXX&#039;&#039; bzw. &#039;&#039;setupBatteryDevXX&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Battery_OptimumTargetSoC_XX: Mit den im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; hinterlegten Parametern unter Berücksichtigung von PV- und Verbrauchsprognosen wird ein optimaler SOC-Wert errechnet. Dieser Wert dient zur Einstellung des unteren SOC des Batteriesystems.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeRequest_XX: Dieses Reading signalisiert mit 1 eine Anforderung zur Zwangsladung der Batterie um die Batterie vor Schäden zu schützen (wenn der SOC unter ctrlBatSocManagementXX-&amp;gt;lowSoc gefallen ist) oder wenn der aktuelle SOC unter den berechneten Mindest-SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeUnrestricted_XX: Dieses Reading kann den Wert &#039;&#039;&#039;0&#039;&#039;&#039; oder &#039;&#039;&#039;1&#039;&#039;&#039; einnehmen. Ist der Inhalt 0, sollte die Batterie nur geladen werden, wenn der im Attribut &#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039; definierte Wert überschritten wird. Ist der Inhalt 1, sollte die Batterie mit der vollen zur Verfügung stehenden Ladeleistung angesteuert werden, um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeAbort_XX: Im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; kann mit dem Schlüssel &#039;&#039;loadAbort&#039;&#039; eine Bedingung definiert werden, bei deren Eintritt die Ladung der Batterie abgebrochen werden soll. In diesem Fall wird &#039;&#039;Battery_ChargeAbort_XX=1&#039;&#039; gesetzt. Mit einem entsprechenden Befehl kann der Anwender das Batteriesystem anweisen den Ladevorgang abzubrechen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Nutzung des Batterie SOC-Management ====&lt;br /&gt;
&lt;br /&gt;
Oftmals wird durch die Anlagenhersteller ein hoher statischer SOC eingestellt bzw. empfohlen, der eine längere Verharrungszeit auf einem tiefen SOC-Wert verhindern soll. Allerdings wechseln sich in auch in den Herbst-, Frühlings- und Wintermonaten Zeiten mit wenig PV-Erzeugung mit Phasen stärkerer Solarstrahlung bei klarem Himmel und Sonnenschein ab.&lt;br /&gt;
&lt;br /&gt;
Ein statischer SOC würde dazu führen, dass in den erwähnten Phasen zuviel Energie in das öffentliche Netz eingespeist wird. Dies soll verhindert werden da die wertvolle Energie besser im eigenen Netz gespeichert und in Dunkelphasen verwendet werden kann. Andererseits soll die Batterie nicht zu lange auf einem tiefen SOC verbleiben und außerdem in gewissen Abständen auf einen so hohen SOC geladen werden der den internen Zellausgleich ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Die SOC Kalkulationsroutine des Moduls errechnet unter Berücksichtigung des prognostizierten PV-Ertrages der kommenden Tage, des aktuellen SOC und der im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; (nachfolgend beschrieben) angegebenen Steuerparameter den Vorschlag für eine optimale SOC-Einstellung. Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert.&lt;br /&gt;
&lt;br /&gt;
Durch das Modul selbst findet keine Steuerung der Batterie statt. Es stellt entsprechende Readings zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen SoC.&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SoC unter den optimalen SoC gefallen ist. In diesem Fall sollte die Batterie, unter Umständen mit Netzstrom, zwangsgeladen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Readings können zur Steuerung des SoC (State of Charge) sowie zur Steuerung des verwendeten Ladestroms der Batterie verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ermittlung des optimalen SOC erfolgt nach folgender Logik:&lt;br /&gt;
&lt;br /&gt;
# 	Ausgehend von &#039;lowSoc&#039; wird der Mindest-SoC kurz vor Sonnenuntergang um 5% inkrementiert sofern am laufenden Tag &#039;maxSoC&#039; nicht erreicht wurde und die PV-Prognose keinen hinreichenden Ertrag des kommenden Tages vorhersagt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Wird &#039;maxSoC&#039; (wieder) erreicht, wird Mindest-SoC um 5%, aber nicht tiefer als &#039;lowSoc&#039;, verringert. Ist der berechnete Mindest-SoC größer als &#039;upSoc&#039;, wird der Mindest-SoC auf &#039;upSoc&#039; gesetzt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#   Mindest-SoC wird soweit verringert, dass die prognostizierte PV Energie des aktuellen bzw. des folgenden Tages von der Batterie aufgenommen werden kann. Mindest-SoC wird typisch auf &#039;upSoc&#039; und nicht tiefer als &#039;lowSoc&#039; verringert.  &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Das Modul erfasst den letzten Zeitpunkt am &#039;maxSoC&#039;-Level, um eine Ladung auf &#039;maxSoC&#039; mindestens alle &#039;careCycle&#039; Tage zu realisieren. Zu diesem Zweck wird der optimierte SoC in Abhängigkeit der Resttage bis zum nächsten &#039;careCycle&#039; Zeitpunkt derart verändert, dass durch eine tägliche 5% SoC-Steigerung &#039;maxSoC&#039; am &#039;careCycle&#039; Zeitpunkt rechnerisch erreicht wird. Wird zwischenzeitlich &#039;maxSoC&#039; erreicht, beginnt der &#039;careCycle&#039; Zeitraum erneut. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im fünften Schritt werden die Grenzen &#039;lowSoc&#039; und &#039;upSoc&#039; berücksichtigt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im letzten Schritt erfolgt Generierung des Readings &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; zur Signalisierung einer eventuell empfohlenen Zwangsladung auf den berechneten Min-SoC. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei sehr wenig Erzeugungungsprognose, d.h. wenn sich der berechnete Min-SoC oberhalb von &#039;upSoC&#039; bewegt, wird &#039;upSoC&#039; eingestellt. Liegt der berechnete Min-SoC unterhalb von &#039;upSoC&#039;, ist jedoch größer als &#039;lowSoC&#039;, wird der berechnete SOC im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; eingestellt. Somit eignet sich die Angabe im Schlüssel &#039;upSoC&#039; um in Zeiten geringer Solarenergieerzeugung die Batterie für eine Notstromerzeugung auf mindestens diesem Wert zu halten. Sollte die PV-Prognose kurzfristig einen größeren Ertrag vorhersagen als die Batterie durch die Einhaltung von &#039;upSoC&#039; aufnehmen kann, wird der Min-SoC unter &#039;upSoC&#039; abgesenkt um möglichst allen PV-Überschuß in der Batterie zu speichern und somit dem Eigenverbrauch zuzuführen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der berechnete Mindest-SoC ist immer nur ein unterer Grenzwert. Die Batterie kann durch Ladevorgänge natürlich jederzeit einen höheren als den im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; dargestellten optimalen SoC haben. Der optimale SoC sollte nicht unterschritten werden um die oben genannten Zusammenhänge abbilden zu können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Die dynamische SOC Steuerung mit Umsetzungsbeispiel =====&lt;br /&gt;
Das Modul bietet eine Unterstützung zur automatisierten Einstellung eines optimalen SoC Wertes.&lt;br /&gt;
&lt;br /&gt;
Ziel ist es, den Minimum SoC in Abhängigkeit der zu erwartenden Solarerträge des aktuellen und des folgenden Tages so einzustellen, dass der prognostizierte Solarertrag von der Batterie aufgenommen werden kann. Die Einspeisung in das öffentliche Netz soll minimiert werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin soll ein unterer SoC nicht unterschritten, sowie ein oberer Minimum SoC im Normalfall nicht überschritten werden. Der obere Grenzwert stellt sicher, dass die Batterie mindestens bis zu diesem Wert wieder entladen werden kann. Dadurch bleibt innerhalb der Batterie immer genügend Kapazität verfügbar um unvorhergesehene PV Energie aufnehmen zu können.&lt;br /&gt;
&lt;br /&gt;
Aktiviert wird die Unterstützung der Batteriesteuerung durch das Setzen des Attributes &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; z.B. mit diesen Angaben:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagementXX lowSoc=x upSoC=x maxSoC=x careCycle=x &lt;br /&gt;
&lt;br /&gt;
so zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=98 careCycle=20&lt;br /&gt;
&lt;br /&gt;
Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert. &lt;br /&gt;
Ist dieses Attribut gesetzt, werden Steuerungs-Readings erstellt, die der Nutzer auswerten und seine Batterieanlage z.B. via notify oder DOIF steuern kann. &amp;lt;bR&amp;gt;&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen Mindest-SoC.&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SOC unter den optimalen SOC bzw. minimalen SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
Die Schlüssel &#039;&#039;&#039;lowSoc&#039;&#039;&#039; und &#039;&#039;&#039;upSoC&#039;&#039;&#039; sind die unteren und oberen Grenzen, zwischen denen sich der Minimum SoC im normalen Betrieb bewegen soll.&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;maxSoC&#039;&#039;&#039; stellt eine Ladungsgrenze dar, die mindestens alle X (careCycle) Tage erreicht werden soll. Zu diesem Zweck errechnet das Modul die Anzahl der nötigen Erhöhungen der Minimum Batterieladung von 5% pro Tag um ausgehend vom aktuellen SoC-Level. Der resultierende Minimum SoC Wert wird entsprechend angepasst. Wurde der einstellte maxSoC Level erreicht, startet der Wartungszyklus (careCycle) erneut. &amp;lt;br&amp;gt;&lt;br /&gt;
Der maxSoC in Verbindung mit dem durch &#039;&#039;&#039;careCycle&#039;&#039;&#039; definierten Zyklus soll sicherstellen, dass der Batterieverbund in regelmäßigen Abständen einen Ladungsausgleich vollziehen kann. &lt;br /&gt;
&lt;br /&gt;
Durch die Modullogik erfolgt eine 5 protentige Anhebung des Minimum SoC wenn am Vortag maxSoC nicht erreicht wurde. Die Anhebung erfolgt aber nicht über upSoC. upSoC ist die obere Grenze des Minimum SoC. Wird am Vortag mindestens die maxSoC Ladung erreicht, verringert sich der Minimum SoC wieder schrittweise um 5%, aber nicht tiefer als lowSoc.&lt;br /&gt;
&lt;br /&gt;
Ergänzt wird die Logik noch um die PV Vorhersage. Dabei wird die obige Minimum SoC Berechnung um die Erwartung der PV Erwartung am aktuellen und folgenden Tag korrigiert. Das bedeutet, dass der Minimum SoC z.B. von heute 50% auf 10% abgesenkt und dadurch die gespeicherte Energie dem Haushalt zugeführt wird, wenn am heutigen oder kommenden Tag eine entsprechende PV Energie zu erwarten ist um die Batterie wieder vollständig zu zuladen.&lt;br /&gt;
Dadurch ist immer genügend &amp;quot;Freiplatz&amp;quot; in der Batterie und andererseits hat die Batterie in langen Dunkelphasen eine Reserve für einen eventuellen Stromausfall (falls der abgesichert werden soll) und wird vor einem dauerhaften tiefen SoC geschützt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Umsetzungsbeispiel =====&lt;br /&gt;
&lt;br /&gt;
Wie das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; genutzt werden kann, wird am Beispiel einer Victron Batterieanlage gezeigt. Die Anlage wird durch Cerbo GX Gerät gesteuert. Der Cerbo GX ist per MQTT2 in FHEM eingebunden. Umgesetzt ist die Steuerung der Batterie &#039;01&#039;, d.h. die Angabe &#039;XX&#039; ist durch &#039;01&#039; ersetzt.&lt;br /&gt;
&lt;br /&gt;
Die folgende kleine Logik ist in einem &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; File eingebaut und wird regelmäßig mit&lt;br /&gt;
&lt;br /&gt;
 batSocChargeMgmnt (&#039;&amp;lt;Name SolarForecast Device&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
aufgerufen. Der Aufruf erfolgt durch Angabe der Routine im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; des SolarForecast Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
  # Hinweis: die Zeichen &#039;::&#039; vor der Routine sind durch das SolarForecast Package bedingt&lt;br /&gt;
  ::batSocChargeMgmnt ($name);&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Routine wird dadurch automatisch am Ende jedes Zyklus (siehe Attribut plantControl-&amp;gt;cycleInterval) ausgeführt.&lt;br /&gt;
Um die SOC Managementfunktion nach Bedarf ein- bzw. ausschalten zu können wird zunächst im SolarForecast Device ein userattr zur Steuerung der SOC-Logik angelegt:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; userattr userFn_BatterySoCManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
Die Perl Routine &#039;&#039;&#039;batSocChargeMgmnt&#039;&#039;&#039; ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#  Batterie SOC und Max. Ladestrom Management&lt;br /&gt;
############################################################################&lt;br /&gt;
sub batSocChargeMgmnt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vebus   = &#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;;                            # Victron Vebus Device&lt;br /&gt;
  my $vicsets = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                         # Victron Einstellungen&lt;br /&gt;
&lt;br /&gt;
  my $maxcspc = 105;                                                           # max. Ladestrom (A) Victron MPII Verbund&lt;br /&gt;
  my $actmcc  = ReadingsNum ($vebus, &#039;MaxChargeCurrent&#039;, undef);               # akt. Ladestromeinstellung&lt;br /&gt;
  my $load    = $actmcc // $maxcspc;                                           # Soll-Ladestrom (A)&lt;br /&gt;
&lt;br /&gt;
  ## Battery SoC Management&lt;br /&gt;
  ###########################&lt;br /&gt;
  my $ubsm = AttrVal ($name, &#039;userFn_BatterySoCManagement&#039;, &#039;aus&#039;); &lt;br /&gt;
  &lt;br /&gt;
  if ($ubsm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name,    &#039;Battery_ChargeRequest_01&#039;,     0);&lt;br /&gt;
    my $csoc = ReadingsNum ($vicsets, &#039;MinimumSocLimit&#039;,             10);      # akt. SoC&lt;br /&gt;
    my $osoc = ReadingsNum ($name,    &#039;Battery_OptimumTargetSoC_01&#039;, 10);      # Soll-SoC&lt;br /&gt;
    my $surp = ReadingsNum ($name,    &#039;Current_Surplus&#039;,              0);      # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if ($csoc != $osoc) {&lt;br /&gt;
      CommandSet (undef, &amp;quot;$vicsets MinimumSocLimit $osoc&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn SoCMgmnt -&amp;gt; MinimumSocLimit in $vicsets set to $osoc %});&lt;br /&gt;
    }&lt;br /&gt;
	                                           &lt;br /&gt;
    if ($bcrq &amp;amp;&amp;amp; $surp &amp;lt; 1000) {                                              # max. Strom b. Battery_ChargeRequest &lt;br /&gt;
      $load = 21;&lt;br /&gt;
    }&lt;br /&gt;
	else {&lt;br /&gt;
	  $load = $maxcspc;&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Batterie Einstellung MaxChargeCurrent&lt;br /&gt;
  ##########################################&lt;br /&gt;
  if ($load != $actmcc) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$vebus MaxChargeCurrent $load&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
    Log3 ($name, 3, qq{$name - userFn ChargeMgmnt -&amp;gt; MaxChargeCurrent in $vebus set }.&lt;br /&gt;
                    qq{from old $actmcc A to $load A});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent_set&#039;, $load, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist im SolarForecast Device das Reading  &#039;&#039;&#039;Battery_ChargeRequest_01&#039;&#039;&#039; gesetzt, ist der aktuelle SOC kleiner als der optimale SOC und die Batterie wird (eventuell aus dem öffentlichen Netz) geladen. Das kann automatisch durch den Cerbo GX bzw. in anderen Anlagen durch einen entsprechenden Befehl erfolgen.&lt;br /&gt;
Damit die Netzbeladung nicht mit der vollen Ladestromstärke geschieht, wird der Ladestrom auf den gewünschten Wert (hier 21 A -&amp;gt; ca. 1000 W bei einem 48V System) reduziert sofern kein oder zu wenig PV-Überschuß vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== weitere mögliche Aspekte der SOC- und Batterieladesteuerung ====&lt;br /&gt;
&lt;br /&gt;
SolarForecast liefert durch seine internen Logiken bereits sehr hilfreiche Signale zur Steuerung von Batteriesystemen in Form von Readings an. Abhängig von den individuellen Möglichkeiten der vorhandenen Anlage käme zum Beispiel zusätzlich zu einer Steurung des optimalen SOC oder der Zeitfenster für die Batterieaufladung auch eine Steuerung des Ladestroms bzw. der verwendeten Ladeleistung in Betracht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hintergründe:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Das Laden eines Akkus mit möglichst gleichbleibender und geringer Leistung wirkt sich positiv auf dessen Langlebigkeit aus, was u.a. auch daran liegt, dass der Temperaturstreß im Akku bei langsamer Energiezuführung nur gering ist.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom führt zu einem geringen Absacken der Akkuspannung beim (ggf, temporären) Abschalten des Ladestroms, was sich positiv auf die SOC-Schätzung auswirkt.&lt;br /&gt;
    &lt;br /&gt;
* Ein geringer Ladestrom führt, insb. bei Nutzung passiver Balancer (sind in den Akku-Systemen üblicherweise verbaut), zu einer geringen Differenz zwischen den einzelnen Zellspannungen und damit zu einer besseren Kapazitätsausnutzung eins Akkus.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom kann zu einem zeitlich punktgenauen Zielfüllstand (im Winter 100%, ansonsten natürlich weniger) am Ende des Tages führen.&lt;br /&gt;
    &lt;br /&gt;
* Eine geringer Ladestrom führt auch zu geringen Leitungsverlusten, da der Strom quadratisch zu den Leitungsverlusten beiträgt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann auch die Verweildauer oder die Begrenzung des SOC, auf den die Batterie maximal geladen werden soll, Gegenstand von Optimierungen sein.&lt;br /&gt;
&lt;br /&gt;
Die häufig zu findende Empfehlung, Akkus nicht zu lange bei einem SOC von 100% verweilen zu lassen, liegt weniger an dem SOC als solchem, sondern daran, dass &#039;&#039;SOC=100%&#039;&#039; üblicherweise dadurch ermittelt wird, dass eine Zelle im Akku einen Spannungsschwellenwert überschreitet, der – würde dieser Schwellenwert zeitlich länger überschritten sein – zu einer Schädigung des Akkus führen könnte. Schädlich sind insbesondere häufige Nachladevorgänge bei Werten um die 100% SOC, da Zellen dann ja häufiger und damit - integral gesehen - auch länger den o.g. Schwellenwert überschreiten.&lt;br /&gt;
&lt;br /&gt;
Einige Akku-Hersteller, z.B. BYD, haben auf o.g, Grund in der (neueren) Firmware Ihrer Systeme einen SOC-Threshold (bei BYD liegt dieser bei 95%) eingebaut. Dieser Wert muss nach einem erreichten SOC von 100% unterschritten  werden, bevor überhaupt eine weitere Ladung erfolgt. Insbesondere in der dunklen Jahreszeit kann es daher sinnvoll sein, den Akku unter Verwendung von PV-Leistung so zu füllen, dass dieser möglichst nur einmal vor Einbruch der Dunkelheit auf &#039;&#039;SOC=100%&#039;&#039; geladen wird. Hierbei sollte darauf geachtet werden, dass der Ladeschlussstrom des jeweiligen Systems nicht unterschritten wird. &lt;br /&gt;
&lt;br /&gt;
SolarForecast unterstützt die oben betrachtete Batteriesteuerung durch die optionale Angabe von &#039;&#039;&#039;loadAbort&#039;&#039;&#039; im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039;. Das in diesem Kontext erstellte Reading &#039;&#039;&#039;Battery_ChargeAbort_XX&#039;&#039;&#039; stellt die auswertbaren Steuerungsinformationen zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== PV-Prognose und Verbrauch optimierte Beladungssteuerung unter Berücksichtigung einer Wirkleistungsbegrenzung ====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-04-25 143910.png|right|thumb|400px|Batterie Popup &amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Batterie geladen. sobald PV-Überschuß vorhanden ist ohne eine Prognose zu berücksichtigen. Dadurch sind die Batterien im Sommer unter Umständen schon um 10-12 Uhr voll geladen und die Anlage liefert ihre mehr oder weniger volle Energie (je nach Ausrichtung) in das öffentliche Netz. Dann könnte es zu einer Begrenzung der PV-Leistung durch einen Schwellenwert (z.B. 70%-Regelung) oder eventuell Zwangsabregelung durch den Netzbetreiber kommen.&lt;br /&gt;
&lt;br /&gt;
Hintergrund dieser Erweiterung ist das Bestreben, eine optimale Unterstützung bei der Maximierung des Eigenverbrauchs zu geben und einen Beitrag zur Netzstabilität zu leisten.&lt;br /&gt;
Das Ziel der Beladungssteuerung der Batterie ist es, die Ladung der Batterie über den Tag verteilt so zu steuern, dass die Batterie erst dann geladen wird, wenn durch den PV-Überschuß eine Netzeinspeisung erfolgen würde bzw. ein Grenzwert erreicht werden würde, der zu einer Abregelung der PV-Anlage führen könnte.&lt;br /&gt;
Es kann auch zu einer Zwangsabregelung durch den Netzbetreiber führen, was vermieden werden soll.&lt;br /&gt;
 &lt;br /&gt;
Die interne Kalkulationslogik erstellt zu diesem Zweck ein Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039;.&lt;br /&gt;
Dieses Reading gibt dem User ein Signal, ob zu der aktuellen Stunde der Ladevorgang der Batterie freigegeben (1) oder nicht freigegeben werden sollte (0). Die Freigabe zur Ladung bedeutet dass:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; die Batterie mit ihrer vollen Ladeleistung angesteuert werden sollte um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=0&#039;&#039;&#039; die Batterie nur geladen werden sollte wenn der im Attribut plantControl-&amp;gt;feedinPowerLimit definierte Wert überschritten wird&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ist keine Freigabe zur Ladung vorhanden, kann bzw. sollte dennoch eine Ladung der Batterie vorgenommen werden, sofern eine über dem im &amp;lt;br&amp;gt;&lt;br /&gt;
Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limit liegende Einspeiseleistung vorhanden ist. In diesem Status sollte die Batterie nur mit der Differenzleistung von vorhandener Einspeiseleistung und dem gesetzen Einspeiselimit geladen werden und damit das gesetzte Einspeiselimit einhalten ohne die Anlage abzuregeln. Ist die Batterie in einer Balkengrafikebene dargestellt, wird im Mouse-Over Popup die Battrie mit &#039;&#039;&amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;&#039;&#039; gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Möglichkeiten der Batteriesteuerung sind stark von der individuellen Anlage abhängig und können hier nicht beschrieben werden. Ein Umsetzungsbeispiel mit einer Victron-Anlage mit Pylontech Batterie ist weiter unten dargestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Aktivierung und Arbeitsweise =====&lt;br /&gt;
&lt;br /&gt;
Die implementierte Logik zur optimierten Batterie Beladungssteuerung wird aktiviert, wenn folgende Kriterien erfüllt sind: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;capacity&#039;&#039;&#039; in den setupInverterDevXX Atributen ist gesetzt&lt;br /&gt;
* das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; für die jeweilige Batterie ist gesetzt&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;cap&#039;&#039;&#039; im Attribut setupBatteryDevXX der jeweiligen Batterie ist gesetzt&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Die Logik arbeitet wie folgt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Der resultierende Schwellenwert der Wirkleistungsbegrenzung: der Gesamtanlage wird durch die Auswertung der in den Inverter-Attributen setupInverterDevXX  gesetzen Schlüssel limit (optional) und capacity ermittelt. Inverter mit gesetztem Schlüssel feed = grid (deren Energie wird ausschließlich in das öffentlich Netz eingespeist) werden von der Betrachtung in diesem Kontext ausgeschlossen.&lt;br /&gt;
&lt;br /&gt;
;Die benötigte Beladung bis zu maxSoC (im Attribut setupBatteryDevXX) : wird ermittelt und mit der zu erwartenden PV Tagesprognose in Beziehung gesetzt. Sofern die PV-Erzeugung abzgl. Verbrauch noch nicht das Wirkleistungbegrenzungs-Limit erreicht UND noch genügend PV-Überschuß für eine Ladung auf &#039;&#039;maxSoC&#039;&#039; im Laufe der kommenden Stunden des Tages zu erwarten ist, bleibt das Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 0&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
;Wird das Wirkleistungbegrenzungs-Limit erreicht/überschritten und/oder die PV-Überschußprognose: zzgl. eines Sicherheitspuffers unterschritten, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 1&#039;&#039;&#039; gesetzt. Der User kann darauf reagieren und den Batterie Ladevorgang aktivieren. Die Möglichkeiten der Aktivierung sind natürlich von der installierten Anlage abhängig. Das SolarForecast Device greift nicht in die Batteriesteuerung direkt ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders ausgedrückt erfolgt immer dann eine Ladefreigabe, wenn einer der nachfolgenden Sachverhalte &#039;&#039;wahr&#039;&#039; ist:&lt;br /&gt;
&lt;br /&gt;
- die benötigte Ladeenergie (aller installierten Batterien) &amp;gt;= PV-Restüberschuß des Tages (Reading RestOfDayPVforecast) zzgl. Sicherheitsaufschlag&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- der Zeitpunkt des PV-Erzeugungszenit des laufenden Tages überschritten ist (Reading Today_MaxPVforecastTime)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn die aktuelle PV Leistung &amp;gt;= einer eventuellen Wechselrichter-Leistungsbegrenzung ist (Summe aller WR-Begrenzungen)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn das BatSoc-Management _nicht_ aktiviert ist (nicht alle oben genannten Aktivierungskriterien erfüllt sind)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind mehrere Batterien installiert und durch das Management einer Batterie die Einhaltung der genannten Kriterien bzw. Sachverhalte erwirkt wird, bleiben die weiteren Batterien im Modus Ladefreigabe (Battery_ChargeUnrestricted_XX=1).  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Umsetzungsbeispiel Batterie Ladesteuerung mit Victron GX Venus über den Grid Setpoint =====&lt;br /&gt;
&lt;br /&gt;
Ziel der Steuerung ist es abhängig vom Wert des Readings Battery_ChargeUnrestricted_XX (z.B. Battery_ChargeUnrestricted_01) die Ladung des angeschlossenen Batteriesystems zu aktivieren bzw. zu deaktivieren.&lt;br /&gt;
Das vorliegende Beispiel soll umzusetzen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 0 -&amp;gt; Batterie nicht aufladen bzw. nur laden wenn Einspeiselimit überschritten (Attribut plantControl-&amp;gt;feedinPowerLimit)&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 1 -&amp;gt; Batterie aufladen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Grid Setpoint ist ein Parameter in den Victron Systemeinstellungen. Das Victron System wird den eingestellten Grid Setpoint versuchen einzuhalten und bei einem positiven Wert Energie aus dem Netz beziehen bzw. bei einem negativen Grid Setpoint Energie in das Netz einspeisen.&lt;br /&gt;
&lt;br /&gt;
Normalerweise wird das Victron System die erzeugte PV Energie zunächst zur Deckung des Hausverbrauchs verwenden, ist dann noch ein PV Überschuß vorhanden, die Batterien aufladen und bei weiter vohandenen PV Überschuß diese Energie in das öffentliche Netz einspeisen sofern dem System eine Einspeisung erlaubt ist. Anderenfalls werden die Wechselrichter oder MPPT Smartloader heruntergeregelt bzw. limitiert. &lt;br /&gt;
&lt;br /&gt;
In der Standardeinstellung ist beim Victron System ein Grid Setpoint von ca. 20 bis 50 Watt, d.h. das System strebt danach diese Vorgabe zu erfüllen zieht ständig Energie in diesem Bereich aus dem öffentlich Netz von einem gelegentlichen Überschwingen der Regelung abgesehen. Damit ein eventueller PV Überschuß nicht zum Laden der Batterie verwendet, sondern statt dessen in das öffentliche Netz eingespeist wird, muß der Grid Setpoint um diesen Betrag abgesenkt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-24 114403.png|right|thumb|400px|Integration des Grid Setpoint-Managements in den Own_Spec-Bereich]]&lt;br /&gt;
&lt;br /&gt;
Damit man später per Attribut bzw. über den [[#Formatierung_der_Inhalte_im_Bereich_&amp;quot;Graphic_Header_Own_Specification&amp;quot;|Own_Spec-Bereich]] die automatische Ladesteuerung über den Grid Setpoint ein- bzw. ausschalten kann, legen wir ein userattr an:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 userattr &amp;lt;Name&amp;gt; userFn_GridSetpointManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin sind einige Vorbereitungen im Device MQTT2_cerboGX_c0619ab34e08_settings vorzunehmen. Dieses Device ist im vorliegenden Beispiel ein in FHEM vorhandenes MQTT2_DEVICE, über das die Victron CerboGX Einstellungen zugreifbar sowie einstellbar sind. Die Vorgehensweise zur Erstellung des MQTT2_DEVICE ist hier nicht beschrieben und wird vorausgesetzt.&lt;br /&gt;
&lt;br /&gt;
Damit ein entsprechender Set-Befehl zur Einstellung des Grid Setpoints vorhanden ist, werden folgende Attribute gesetzt:&lt;br /&gt;
&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings jsonMap Settings_CGwacs_AcPowerSetPoint_value:GridSetpoint&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings setList GridSetpoint W/c0619ab34e08/settings/0/Settings/CGwacs/AcPowerSetPoint {&amp;quot;value&amp;quot;:$EVTPART1}&lt;br /&gt;
&lt;br /&gt;
Nach dieser Attributierung kann mit einem &amp;quot;&#039;&#039;set MQTT2_cerboGX_c0619ab34e08_settings GridSetpoint &amp;lt;Wert&amp;gt;&#039;&#039;&amp;quot; der Grid Setpoint eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Das Attribut userFn_GridSetpointManagement kann nun im Perl Code ausgewertet werden um das Grid Setpoint-Management ein- bzw. auszuschalten.&lt;br /&gt;
Der nachfolgende Code wird in die Datei &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; eingefügt. Ist diese Datei nicht vorhanden, legen wir sie vorab als Kopie der ausgelieferten 99_myUtils.pm an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Steuerung Start/Stop der Batterieladung über den Victron Grid Setpoint&lt;br /&gt;
############################################################################&lt;br /&gt;
sub gridSetpointMgmt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vicsets   = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                               # Device Victron Einstellungen&lt;br /&gt;
  my $gspdef    = 20;                                                                  # Default Einstellung des Grid Setpoint&lt;br /&gt;
  my $targetgsp = $gspdef;                                                             # Voreinstellung Grid Setpoint&lt;br /&gt;
  my $neggspmax = FHEM::SolarForecast::CurrentVal ($name, &#039;feedinPowerLimit&#039;, 5000);   # max. gewünschte Einspeiseleistung in Watt&lt;br /&gt;
  $neggspmax    = $neggspmax * -1;&lt;br /&gt;
  my $gspm      = AttrVal ($name, &#039;userFn_GridSetpointManagement&#039;, &#039;aus&#039;);             # Freischaltung des Grid Setpoint-Managements&lt;br /&gt;
  my $curgsp    = ReadingsNum ($vicsets, &#039;GridSetpoint&#039;,         $gspdef);             # aktuelle Einstellung Grid Setpoint&lt;br /&gt;
  &lt;br /&gt;
  if ($gspm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name, &#039;Battery_ChargeUnrestricted_01&#039;, 0);         # Ladefreigabe (1 -&amp;gt; Bat Ladefreigabe)&lt;br /&gt;
    my $surp = ReadingsNum ($name, &#039;Current_Surplus&#039;,               0);         # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if (!$bcrq) {                                                               # Grid Setpoint absenken wenn keine .. &lt;br /&gt;
        $targetgsp = $gspdef - $surp;                                           # ..Batterie Ladefreigabe&lt;br /&gt;
        $targetgsp = $neggspmax if($targetgsp &amp;lt; $neggspmax);                    # Begrenzung der Einspeiseleistung&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($curgsp != $targetgsp) {&lt;br /&gt;
	  fhem (&amp;quot;set $vicsets GridSetpoint $targetgsp&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn gridSetpointMgmt -&amp;gt; GridSetpoint in $vicsets set to $targetgsp});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Victron_GridSetpoint_set&#039;, $targetgsp, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Vergleich des Setpoints mit der Vorgabe von &#039;&#039;$neggspmax&#039;&#039; dient dazu die maximale Einspeiseleistung in das öffentliche Netz zu begrenzen. Ist diese Grenze erreicht, wird der noch verbleibende Überschuß in die Batterie geladen. Dadurch wird eine Abregelung der Anlage vermieden wenn der Schwellenwert &#039;&#039;$neggspmax&#039;&#039;erreicht ist sofern die Batterie aufnahmefähig ist und nicht voll geladen ist. &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::gridSetpointMgmt  ($name);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zum Management des automatischen Grid Setpoint und der Anzeige des eingestellten Wertes wird das Attribut und die Readinganzeige in den Own_Spec-Bereich eingebunden, z.B.:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; graphicHeaderOwnspec  #Settings&lt;br /&gt;
                                   SetPoint&amp;amp;nbsp;Management:userFn_GridSetpointManagement&lt;br /&gt;
                                   Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Unterstützung eines netzdienlichen Verhaltens ====&lt;br /&gt;
&lt;br /&gt;
Der Steuerungsprozess der Batterieanlage leistet insgesamt einen kleinen Beitrag zur Netzstabilität, indem die Speicherladung in den Zeitraum der meisten prognostizierten Überschußeinspeisung gelegt wird. Im Sommer kann sich dieser Zeitraum in die Zeit nach dem Maxmimum des prognostizierten PV-Überschusses verlagern, wenn auch danach noch genügend Überschußenergie zu Volladung der Batterie prognostiziert wird. In dem Zusammenhang sollte im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; ein Einspeiselimit gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zur Verdeutlichung soll das Beispiel dienen:&lt;br /&gt;
&lt;br /&gt;
* die Batterie ist zu 60% geladen &lt;br /&gt;
* der User hat upSoC=40 eingestellt&lt;br /&gt;
* der User hat maxSoC=90 eingestellt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Am Vormittag ist genügend Sonne vohanden, das Maximumum der Energie über die Zeit wird aber noch erwartet. &lt;br /&gt;
Zu diesem Zeitpunkt wird das Reading  &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039; auf den Wert &amp;quot;0&amp;quot; gesetzt. Durch den Nutzer erfolgt daraufhin, zum Beipiel über ein Notify, ein anlagenspezifischer Befehl &amp;quot;Ladestop&amp;quot; an die Batterieanlage. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ab diesem Moment wird:&lt;br /&gt;
&lt;br /&gt;
# die Batterie nicht geladen&lt;br /&gt;
# die erzeugte PV-Energie dem Haushalt zur Verfügung gestellt bzw. der verbleibende Überschuß eingespeist, sofern der Überschuß unterhalb des im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limits liegt.&lt;br /&gt;
# ein eventuell über dem Limit &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; vorhandener Überschuß in die Batterie geladen und so die Netzlast verringert sowie die Batterie schonend geladen. (dieser Punkt trifft in den Monaten mit wenig PV-Erzeugung eher nicht zu)  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig liefert die Batterie Energie an das Hausnetz und wird von 60% bis maximal einem SoC-Wert entladen, der durch die [[#Die_dynamische_SOC_Steuerung_mit_Umsetzungsbeispiel|dynamische SOC Steuerung]] bestimmt wird. Dazu muß diese Steuerung natürlich implementiert sein. Sofern der berechnete SoC größer als upSoC ist, wird der maximale Entladungs-SoC auf upSoC gesetzt. &lt;br /&gt;
&lt;br /&gt;
Zusätzlich überprüft das Modul permanent bei jedem Zyklus die Differenz des aktuell vorhandenen SoC zum eingestellten maxSoC.&lt;br /&gt;
Sie soll nicht größer sein um mit dem (noch) zu erwartenden PV-überschuß des Tages der eingestellte maxSoC bzw. dessen Nähe wahrscheinlich erreicht werden kann. &lt;br /&gt;
Sollte der Differenz-Grenzwert erreicht sein, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; gesetzt und der Nutzer sollte dann über einen geeigneten Befehl seine Anlage in den Modus &amp;quot;Laden&amp;quot; umschalten.&lt;br /&gt;
Dieser Vorgang kann beliebig oft während des Tages alternieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Nutzung von batteryTrigger ===&lt;br /&gt;
Ergänzt werden die Möglichkeiten durch das set-Kommando: &lt;br /&gt;
&lt;br /&gt;
 batteryTrigger &amp;lt;1on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;1off&amp;gt;=&amp;lt;Wert&amp;gt; [&amp;lt;2on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;2off&amp;gt;=&amp;lt;Wert&amp;gt; ...] &lt;br /&gt;
&lt;br /&gt;
Das Kommando setzt Triggerpunkte bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %).&lt;br /&gt;
&lt;br /&gt;
Der verwendete SoC wird als resultierender SoC als Summe der aktuellen Ladung aller registrierten Batterie-Geräte im Verhältnis zur installierten Gesamtkapazität gebildet. Das bedeutet, dass alle einzelnen Batterie-Geräte als ein gemeinsamer Cluster betrachtet werden. &lt;br /&gt;
&lt;br /&gt;
Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise definiert werden.&lt;br /&gt;
Überschreiten die letzten drei SoC-Messungen eine definierte Xon-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = on&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
Unterschreiten die letzten drei SoC-Messungen eine definierte Xoff-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = off&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
&lt;br /&gt;
Der Inhalt der Readings kann durch ein User-Programm oder, bei Erzeugung von entsprechenden Events, mittels notify-Device ausgewertet werden um bei Eintreten eines definierten Ereignisses entsprechende Reaktionen auszulösen. Das kann zum Beispiel die Freigabe eines Heizstabes oberhalb eines bestimmten SOC sein oder ein Entladeverbot der Batterie unterhalb eines SOC-Wertes um Reserven für einen eventuellen Stromausfall zu behalten.&lt;br /&gt;
&lt;br /&gt;
Damit die Batterietrigger dynamisch geändert werden können, ist die Einstellung als Set-Kommando und nicht als Attribut ausgeführt.   &lt;br /&gt;
&lt;br /&gt;
Alle Triggerpunkte können mit dem set-Befehl:&lt;br /&gt;
&lt;br /&gt;
 reset batteryTriggerSet&lt;br /&gt;
&lt;br /&gt;
wieder gelöscht werden.&lt;br /&gt;
&lt;br /&gt;
== Verbrauchersteuerung - Registrieren und visualisieren 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;
Die Eigenschaften und das Schaltverhalten wird durch die Angabe der verfügbaren Schlüssel gesteuert. Die Möglichkeiten sind sehr umfangreich. Die nachfolgenden Abschnitte beschreiben die Verwendung am Beispiel oft vorkommender bzw. nachgefragter Sachverhalte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die Phasen der Verbrauchersteuerung ===&lt;br /&gt;
&lt;br /&gt;
Jeder Zyklus eines Verbrauchers durchläuft im Modul die folgenden Phasen:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Planung&#039;&#039;&#039; der Aktivzeiten des Verbrauchers, d.h. wann der Verbraucher geplant eingeschaltet sowie geplant ausgeschaltet wird und damit der Zyklus beendet wird.&lt;br /&gt;
# &#039;&#039;&#039;Start&#039;&#039;&#039; des Zyklus, d.h. Einschalten des Verbrauchers entsprechend der Planungsdaten sofern weitere, in den Consumer-Schlüsseln definierbare Rahmenbedingungen das Einschalten nicht verhindern (z.B. kein oder zu wenig PV-Energieerzeugung / PV-Überschuss)&lt;br /&gt;
# &#039;&#039;&#039;Permanente Überprüfung von&#039;&#039;&#039; eventuell vorhandenen &#039;&#039;&#039;Interruptbedingungen&#039;&#039;&#039; die den Verbraucher temporär ausschalten und, sofern die Interruptbedingung nicht mehr vorliegt, den Verbraucher wieder einschalten und so den gestarteten Zyklus fortsetzen.&lt;br /&gt;
#  &#039;&#039;&#039;Beendigung&#039;&#039;&#039; der Zyklus. Die Beendigung erfolgt entweder (normalerweise) wenn die geplante Endezeit der Zyklus erreicht ist oder eine optionale Endebedingung erfüllt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Steuerung der Phasen ====&lt;br /&gt;
Der Ablauf der Phasen kann durch verschiedene Schlüssel-Wert Paare beeinflusst und gesteuert werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; kann eine &#039;&#039;&#039;zusätzliche externe Bedingung&#039;&#039;&#039; definiert werden um den Einschaltvorgang des Consumers freizugeben. Ist die Bedingung (Regex) nicht erfüllt, erfolgt kein Einschalten des Verbrauchers auch wenn die sonstigen Voraussetzungen wie Zeitplanung, on-Schlüssel, auto-Mode und aktuelle PV-Leistung gegeben sind. Es erfolgt somit eine &#039;&#039;&#039;UND-Verknüpfung&#039;&#039;&#039; des Schlüssels swoncond mit den Planungsdaten und weiteren Einschaltbedingungen.&lt;br /&gt;
&lt;br /&gt;
Der optionale Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; definiert eine &#039;&#039;&#039;vorrangige Ausschaltbedingung&#039;&#039;&#039; (Regex). Sobald diese Bedingung erfüllt ist, wird der Consumer ausgeschaltet auch wenn die geplante Endezeit (consumerXX_planned_stop) noch nicht erreicht ist (&#039;&#039;&#039;ODER-Verknüpfung&#039;&#039;&#039;). Weitere Bedingungen wie off-Schlüssel und auto-Mode müssen zum automatischen Ausschalten erfüllt sein.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; kann während der geplanten Einschaltzeit eine automatische Unterbrechung sowie Wiedereinschaltung des Verbrauchers vorgenommen werden. Der Verbraucher wird temporär ausgeschaltet (interrupted) und wieder eingeschaltet (continued) wenn die Interrupt-Bedingung nicht mehr vorliegt. Die verbleibende Laufzeit wird durch einen Interrupt nicht beeinflusst! &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;power&#039;&#039;&#039; gibt die nominale Leistungsaufnahme des Verbrauchers gemäß seines Datenblattes an. Dieser Wert wird verwendet um die Schaltzeiten des Verbrauchers zu planen und das Schalten in Abhängigkeit des tatsächlichen PV-Überschusses zum Einplanungszeitpunkt zu steuern. Ist &#039;&#039;&#039;power=0&#039;&#039;&#039; gesetzt, wird der Verbraucher unabhängig von einem zum Zeitpunkt des Zyklus-Start eventuell nicht ausreichend vorhandenem PV-Überschuss wie geplant eingeschaltet und somit der Zyklus gestartet.&lt;br /&gt;
&lt;br /&gt;
Durch die Schlüssel &#039;&#039;&#039;notbefore&#039;&#039;&#039; und &#039;&#039;&#039;notafter&#039;&#039;&#039; kann der Startzeitpunkt des Verbrauchers so gesteuert werden, dass der Start des Zyklus nicht vor bzw. nach der angegebenen Zeit eingeplant wird. Diese Steuerung bezieht sich auf die &#039;&#039;Planung&#039;&#039;, d.h. der eigentliche Start des Verbrauchers kann sich unter Umständen durch vorhandene Rahmenbedingungen verzögern. &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; legt die geplanten Einschaltzeit, d.h. die Laufzeit des Zyklus fest. Der Name &#039;&#039;&#039;mintime&#039;&#039;&#039; ist nicht als MInimum-Zeit zu deuten, sondern beschreibt die angegebene Zeit in Minuten die der Zyklus dauern soll.&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist optional, da sich die Standard-Laufzeit des Verbrauchers von dessen Typ abgeleitet wird. Diese Standard Laufzeiten sind:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|dryer&lt;br /&gt;
|90 Minten&lt;br /&gt;
|-&lt;br /&gt;
|dishwasher&lt;br /&gt;
|180 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|washingmachine&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|heater&lt;br /&gt;
|240 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|charger&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|other&lt;br /&gt;
|60 Minuten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Der Verbraucher wurde nicht gestartet obwohl die Startzeit der Einplanung erreicht wurde ===&lt;br /&gt;
&lt;br /&gt;
Wenn die Startzeit des Consumers entsprechend der Einplanung erreicht oder überschritten ist, wird der Consumer eingeschaltet wenn die weiteren Voraussetzungen wahr sind:&lt;br /&gt;
&lt;br /&gt;
* es ist aktuell ein PV-Überschuss vorhanden und der PV-Überschuss deckt die kalkulierten Leistungsaufnahme des Verbrauchers ab. Mit den Schlüsseln &#039;&#039;&#039;power&#039;&#039;&#039; und &#039;&#039;&#039;spignorecond&#039;&#039;&#039; kann die Einschaltung trotz fehlendem PV-Überschuss ermöglicht werden. &lt;br /&gt;
&lt;br /&gt;
* die Angabe im Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; ist wahr (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* das Schalten ist über den Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; freigegeben (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* im Schlüssel &#039;&#039;&#039;on&#039;&#039;&#039; ist ein valides Einschaltkommando hinterlegt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind diese zusätzlichen Bedingungen nicht erfüllt, erfolgt kein Start des eingeplanten Zyklus. Der Verbraucher verbleibt in diesem Fall weiterhin im Status &#039;&#039;planned&#039;&#039; oder &#039;&#039;suspended&#039;&#039;. Die Startbedingungen werden regelmäßig reviewed und der Consumer gestartet sobald alle Startbedingungen wahr sind bzw. Start verhindernde Bedingungen entfallen sind. &lt;br /&gt;
&lt;br /&gt;
Dieser Vorgang erfolgt bis das geplante Ende des Verbaucherzyklus erreicht ist oder die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; zutrifft. Sobald die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; wahr ist, wird der gesamte Planungszyklus des Consumers beendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Kann manuell / automatisiert in den Planungszyklus eines Verbrauchers eingegriffen werden? ===&lt;br /&gt;
&lt;br /&gt;
Die Einplanung und die darauf aufbauenden Schaltprozesse laufen gemäß den hinterlegten Schlüsseloptionen im Modul automatatisch ab ohne dass ein Eingriff durch den Anwender erfolgen muß.&lt;br /&gt;
&lt;br /&gt;
Dennoch kann es gewünscht sein eine Neuplanung oder eine Sofortplanung eines Consumers vorzunehmen weil der Bedarf dazu besteht. Zu diesem Zweck stehen die Set-Kommandos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* consumerNewPlanning &lt;br /&gt;
&lt;br /&gt;
* consumerImmediatePlanning &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
zur Verfügung. &lt;br /&gt;
Beide Befehle initiieren die Consumer-Neuplanung, wobei mit dem Befehl &#039;&#039;consumerImmediatePlanning&#039;&#039; die eventuell im consumerXX Attribut gesetzten Schlüssel notbefore, notafter bzw. mode werden nicht beachtet werden. Dagenen beachtet der Befehl &#039;&#039;consumerNewPlanning&#039;&#039; alle definierten Schlüsseloptionen und dient gewöhnlich dazu einen abgeschlossenen Verbraucherzyklus wiederholt ausführen zu lassen weil die aktuelle Witterungslage dazu geeignet ist. &lt;br /&gt;
&lt;br /&gt;
Ein Anwendungsbeispiel dafür ist zum Beispiel die Ausführung von mehreren Waschmaschinen-Zyklen an einem langen, sonnigen Sommertag.&lt;br /&gt;
Diese beiden Set-Befehle können zum Beispiel über ein auf einen Schalter/Taster reagierendes Notify oder DOIF Device ausgeführt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung eines Verbrauchers mit getrennten Geräten für Messung und Schalten ===&lt;br /&gt;
&lt;br /&gt;
Es existieren in FHEM Geräte, die über verschiedene Kanäle für unterschiedliche Aufgaben verfügen. Diese Kanäle werden jeweils in einem gesonderten Device abgebildet. HomeMatic oder readingsProxy sind Beispiele für solche Varianten.&lt;br /&gt;
&lt;br /&gt;
Um solche Verbraucher einzubinden gibt es im consumerXX Attribut den Schlüssel &#039;&#039;&#039;switchdev&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Bei der Registrierung gibt man als Consumerdevice das Gerät für die Messung an und im Schüssel switchdev das entsprechende FHEM-Device, welches für die Schaltvorgänge benutzt wird. &lt;br /&gt;
Ist switchdev angegeben, beziehen sich die weiteren Schlüssel on, off, swstate, auto und asynchron auf dieses Gerät.&lt;br /&gt;
&lt;br /&gt;
In dem nachfolgenden Beispiel (Homematic) ist &#039;&#039;eg.az.fridge_Pwr&#039;&#039; FHEM Device für die Energiemessung. Die Schlüssel &#039;&#039;pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; geben Readings in diesem Device an damit SolarForecast den Verbrauch und die Energiemengen auslesen kann. Demgegenüber ist im Schlüssel &#039;&#039;switchdev&#039;&#039; das zugehörige Schalter-Device der Kombination angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eg.az.fridge_Pwr&lt;br /&gt;
type=noSchedule switchdev=eg.az.fridge_Sw power=0 icon=fridge pcurr=power:W:5 etotal=energyCalc:Wh &lt;br /&gt;
swstate=state:on:off auto=automatic&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung von Verbrauchern ohne Zeitplanung und aktivem Schalten ===&lt;br /&gt;
Manchmal besteht der Wunsch, Verbraucher in SolarForecast zu integrieren um lediglich folgende Sachverhalte abzubilden:&lt;br /&gt;
&lt;br /&gt;
* Visualisierung des Schaltstatus in der Consumer Legende und/oder der Energieflußgrafik&lt;br /&gt;
* Darstellung des aktuellen Energieverbrauchs in der Energieflußgrafik&lt;br /&gt;
* Erfassung der (externen) Schaltzeiten, d.h. der Zeiten der Gerätenutzung sowie der Verbrauchsdaten um deren Einfluß bei den Planungszeiten anderer Geräte durch SolarForecast berücksichtigen zu lassen&lt;br /&gt;
&lt;br /&gt;
In solchen Fällen werden bei der Registrierung die Schlüssel &#039;&#039;swstate, pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; zur Erfassung der Schaltzustände und der Energieverbrauchs angegeben, jedoch zur Verhinderung der Zeitplanung durch SolarForecast der Schlüssel &#039;&#039;&#039;type=noSchedule&#039;&#039;&#039; gesetzt sowie die Schlüssel &#039;&#039;on&#039;&#039; und &#039;&#039;off&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt eine mögliche Registrierung eines Zwischensteckers (Shelly) zur Erfassung der Daten eines Gefrierschrankes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Shelly.shellyplug4&lt;br /&gt;
type=noSchedule power=65 asynchron=1&lt;br /&gt;
icon=gefrierschrank &lt;br /&gt;
swstate=state:.*on.*:.*off.* &lt;br /&gt;
pcurr=relay_0_power:W:5 etotal=relay_0_energy_Wh:Wh&lt;br /&gt;
&amp;lt;/pre&amp;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;
&lt;br /&gt;
 Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off&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;
&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;
&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. Alternativ kann die Berücksichtigung des zwangsweisen PV Überschuss mit dem Schlüssel &amp;quot;spignorecond&amp;quot; im Consumer-Attribut ausgesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== zusätzliche Readings bzw. Erzeugung von statistischen Readings ==&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den zahlreichen im Modul per Standard erzeugten Readings kann der Anwender weitere Readings generieren lassen.&lt;br /&gt;
Diese zusätzlichen Readings geben entweder einen bestimmten Sachverhalt (Laufzeit, Status der API-Abfragen, etc.) oder einen statistischen Wert, z.B. die Batterieentladung des aktuellen Tages, wieder.&lt;br /&gt;
&lt;br /&gt;
Die zusätzlich erstellten Readings sind durch den Präfix &#039;&#039;&#039;special_&#039;&#039;&#039; im Device gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Diese zusätzlichen Informationen können durch das Setzen einer oder mehrerer Kennzeichen im Attribut &#039;&#039;&#039;ctrlSpecialReadings&#039;&#039;&#039; erzeugt werden. Die mögliche Auswahl wird je nach Bedarf ausgebaut und umfasst zum aktuellen Zeitpunkt (07.02.2025) diese Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;BatPowerIn_Sum: 	die Summe der momentanen Batterieladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;BatPowerOut_Sum: 	die Summe der momentanen Batterieentladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;allStringsFullfilled: 	Erfüllungsstatus der fehlerfreien Generierung aller Strings&lt;br /&gt;
;conForecastTillNextSunrise: 	Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
;currentAPIinterval: 	das aktuelle Abrufintervall der gewählten Strahlungsdaten-API in Sekunden&lt;br /&gt;
;currentRunMtsConsumer_XX: 	die Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; seit dem letzten Einschalten. (letzter Laufzyklus)&lt;br /&gt;
;dayAfterTomorrowPVforecast: 	liefert die Vorhersage der PV Erzeugung für Übermorgen (sofern verfügbar) ohne Autokorrektur (Rohdaten).&lt;br /&gt;
;daysUntilBatteryCare_XX: 	Tage bis zur nächsten Batterie XX Pflege (Erreichen der Ladung &#039;maxSoC&#039; aus Attribut ctrlBatSocManagementXX)&lt;br /&gt;
;lastretrieval_time: 	der letzte Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;lastretrieval_timestamp: 	der Timestamp der letzen Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;response_message: 	die letzte Statusmeldung der gewählten Strahlungsdaten-API&lt;br /&gt;
;runTimeAvgDayConsumer_XX: 	die durchschnittliche Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; an einem Tag&lt;br /&gt;
;runTimeCentralTask: 	die Laufzeit des letzten SolarForecast Intervalls (Gesamtprozess) in Sekunden&lt;br /&gt;
;runTimeTrainAI: 	die Laufzeit des letzten KI Trainingszyklus in Sekunden&lt;br /&gt;
;runTimeLastAPIAnswer: 	die letzte Antwortzeit des Strahlungsdaten-API Abrufs auf einen Request in Sekunden&lt;br /&gt;
;runTimeLastAPIProc: 	die letzte Prozesszeit zur Verarbeitung der empfangenen Strahlungsdaten-API Daten&lt;br /&gt;
;SunMinutes_Remain: 	die verbleibenden Minuten bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;SunHours_Remain: 	die verbleibenden Stunden bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;todayConsumptionForecast: 	Verbrauchsprognose pro Stunde des aktuellen Tages (01-24)&lt;br /&gt;
;todayConForecastTillSunset: 	Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
;todayDoneAPIcalls: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Calls&lt;br /&gt;
;todayDoneAPIrequests: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Requests&lt;br /&gt;
;todayConsumption: 	der gesamte Energieverbrauch (Wh) des Hauses am aktuellen Tag&lt;br /&gt;
;todayGridConsumption: 	die aus dem öffentlichen Netz bezogene Energie am aktuellen Tag&lt;br /&gt;
;todayGridFeedIn: 	die in das öffentliche Netz eingespeiste PV Energie am aktuellen Tag&lt;br /&gt;
;todayMaxAPIcalls: 	die maximal mögliche Anzahl Strahlungsdaten-API Calls. Ein Call kann mehrere API Requests enthalten.&lt;br /&gt;
;todayRemainingAPIcalls: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Calls&lt;br /&gt;
;todayRemainingAPIrequests: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Requests&lt;br /&gt;
;todayBatIn_XX: 	die am aktuellen Tag in die Batterie XX geladene Energie&lt;br /&gt;
;todayBatInSum: 	Summe der am aktuellen Tag in alle Batterien geladene Energie&lt;br /&gt;
;todayBatOut_XX: 	die am aktuellen Tag aus der Batterie XX entnommene Energie&lt;br /&gt;
;todayBatOutSum: 	Summe der am aktuellen Tag aus allen Batterien entnommene Energie&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Manche Angaben sind im Setup des Moduls optional, d.h. sie müssen nicht zwingend beim Setup angegeben werden. Allerdings sind diese Angaben für die Erstellung eines zusätzlichen Readings unter Umständen Voraussetzung. Es empfiehlt sich deshalb bei Setup so viele Informationen wie möglich zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
So ist zum Beispiel für die sinnvolle Erstellung der Informationen &#039;&#039;&#039;todayBatInSum&#039;&#039;&#039; und &#039;&#039;&#039;todayBatOutSum&#039;&#039;&#039; (Readings special_todayBatInSum und special_todayBatOutSum) das Vorhandensein der Schlüssel &#039;&#039;intotal&#039;&#039; und &#039;&#039;outtotal&#039;&#039; im Attribut setupBatteryDevXX notwendig (Beispiel):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupBatteryDev01 MQTT2_cerboGX_c0619ab34e08_battery &lt;br /&gt;
                              pin=BatIn:W pout=BatOut:W charge=SOC_value intotal=BatInTotal:Wh outtotal=BatOutTotal:Wh &lt;br /&gt;
                              cap=InstalledCapacity_Wh:Wh asynchron=1 show=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Fehlersuche ==&lt;br /&gt;
Das Modul SolarForecast ist sehr komplex und es die verschiedensten Datenquellen ausgewertet, zusammengeführt und daraus Ergebnisse berechnet und/oder visualisiert. Wird etwas nicht wie erwartet durch das Modul geliefert, können die Ursachen vielfältig sein. Natürlich kann ein Fehler im Modulcode vorliegen, oftmals gibt es aber andere Ursachen.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgenden Hinweise sollen Hilfe zur Selbsthilfe geben und sind eine Zusammenfassung von realen Fällen die mit dem beschriebenen Wegen und Verfahren gelöst wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die erwartete erzeugte PV-Energie ist im Modul zu gering und wird im Balkendiagramm nicht angezeigt === &lt;br /&gt;
&lt;br /&gt;
Die erzeugte PV-Energie wird nicht richtig angezeigt: Am Vormittag sind keine Werte vorhanden und, wenn dann etwas kommt, ist die Anzeige zu gering. Für 13 und 14 Uhr wurden ca. 5.000Wh erwartet (im Vergleich mit den Daten aus einer anderen Auswertungsquelle). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lösungsweg:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Aus dem List des Devices wurden die für den Fall wesentlichen Readings herausgezogen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVforecast 152 Wh&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVforecast 1400 Wh&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVforecast 2500 Wh&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVforecast 4392 Wh&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVforecast 4000 Wh&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVreal 300 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVforecast 6415 Wh&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVreal 3200 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVforecast 5629 Wh&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVreal 2700 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVforecast 3958 Wh&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVreal 900 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVforecast 945 Wh&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVreal 500 Wh&lt;br /&gt;
   &lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour18_PVforecast 59 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man sieht dass bis 12:00 keine erzeugte Energie vom WR gemeldet wird. Deswegen wird in der Balkengrafik nichts dargestellt. Auch danach bleibt die registrierte PV-Energie hinter den Erwartungen zurück. Zuständig für die Lieferung der PV-Energie an das Modul ist das Reading im Schlüssel:&lt;br /&gt;
&lt;br /&gt;
 setupInverterDev01 SH10rt pv=Total_DC_Power:W &amp;lt;mark&amp;gt;etotal=Total_Export_Energy_from_PV:kWh&amp;lt;/mark&amp;gt; capacity=10000 strings=Hauptdach,Flachdach&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Welche Änderungen es zwischen den Stunden gab, sieht man mit einem &amp;quot;get ... pvHistory XX&amp;quot; (&amp;quot;XX&amp;quot; steht für das Datum, d.h. den Tag, z.B. 02). &amp;lt;br&amp;gt;&lt;br /&gt;
Hier ein Beispiel für die Stunden 10 (9:00 - 9:59) und 11 (10:00 - 10:59). &amp;lt;br&amp;gt;&lt;br /&gt;
Wichtig ist hier der Key etotali01 für den ersten Inverter. Die Differenz zwischen den Werten beider Stunden ist die in der Stunde erzeugte Energie (hier 380 Wh). Diese 380 Wh findest du auch im Key pvrl01 als PVReal für diese Stunde. Das Modul rechnet intern immer mit Wh, kWh werden vorher in Wh umgerechnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
10 =&amp;gt; pvfc: 365, pvrl: 530, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63364714&amp;lt;/mark&amp;gt;, etotali02: 3044110, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;pvrl01: 380&amp;lt;/mark&amp;gt;, pvrl02: 150, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 574, con: 518, gcons: 22, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 1, feedprice: 0.1269&lt;br /&gt;
&lt;br /&gt;
            DoN: 1, sunaz: 137, sunalt: 12&lt;br /&gt;
&lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
      11 =&amp;gt; pvfc: 2966, pvrl: 1862, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63365094&amp;lt;/mark&amp;gt;, etotali02: 3044260, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            pvrl01: 1392, pvrl02: 470, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 774, con: 609, gcons: 25, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 4, feedprice: 0.1269&lt;br /&gt;
           &lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
D.h. wenn zwischen den beiden Stunden keine Differenzen zu finden sind, liegt es sehr wahrscheinlich am Input des Readings:&lt;br /&gt;
&lt;br /&gt;
 etotal=Total_Export_Energy_from_PV:kWh&lt;br /&gt;
&lt;br /&gt;
welches sich in den ersten Stunden nicht ändert und danach auch nur wenig.&lt;br /&gt;
&lt;br /&gt;
Man kann mit dem Attribut:&lt;br /&gt;
&lt;br /&gt;
 ctrlDebug=collectData&lt;br /&gt;
&lt;br /&gt;
die Datensammlung verfolgen (leider entstehen viele Daten im Log). Man sieht welche Werte von dem Inverter/Reading geliefert werden:&lt;br /&gt;
 &lt;br /&gt;
 ....&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; collect Inverter 01 data - device: STP_5000, delivery: default =&amp;gt;&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; pv: 0 W, &amp;lt;mark&amp;gt;etotal: 63378810 Wh&amp;lt;/mark&amp;gt;&lt;br /&gt;
 ....&lt;br /&gt;
&lt;br /&gt;
Dieser Wert muß bei PV Erzeugung kontinuierlich hochzählen. Wenn nicht, muss das angegebene Reading, d.h. die Quelle überprüft werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ergebnis der Prüfung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tatsächlich wurde ein Reading benutzt, das ungeeignet war: Statt &amp;quot;Total_PV_Generation&amp;quot; wurde &amp;quot;Total_export_energy_from_PV&amp;quot; genutzt. In diesem Reading wurde immer die in die Batterie gespeicherte Energie von der gesamten erzeugten Energie abgezogen. Daher war auch vormittags alles 0, da in dieser Periode alle PV-Energie in die Batterie geladen wurde bzw. in weiteren Stunden ein Anteil der dann bei dem PV-Erzeugungswert fehlte.&lt;br /&gt;
&lt;br /&gt;
Nachdem die Ursache beseitigt war, zeigt SolarForecast wieder die erwarteten PV-Erzeugungswerte an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Konfigurationsbeispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Visualisierung solare Vorhersage und reale Erzeugung ===&lt;br /&gt;
&lt;br /&gt;
Zu Beginn jedes neuen Tages gegen 00:00 Uhr werden durch das SolarForecast Device Events für die initiale PV Prognose des kommenden Tages erstellt.&lt;br /&gt;
Der Readingteil dieser Events heißt&lt;br /&gt;
&lt;br /&gt;
 AllPVforecastsToEvent&lt;br /&gt;
&lt;br /&gt;
Die Uhrzeiten der Events sind so aufbereitet und können direkt geloggt werden um sie in einen SVG Plot zu integrieren.&lt;br /&gt;
Im SolarForecast Device ist dieses Reading nicht sichtbar, nur die Events werden erstellt.&lt;br /&gt;
&lt;br /&gt;
Die meteorologischen Bedingungen verändern sich über den Tag permanent. Je nach gewählter Strahlungsdatenquelle (eine API oder DWD Device) erfolgt eine mehr oder weniger dynamische Anpassung der Prognose an die sich verändernde Umwelt.&lt;br /&gt;
&lt;br /&gt;
Aktuelle Prognosedaten sowie die reale PV Erzeugung der vergangenen Stunde können über die Readings&lt;br /&gt;
&lt;br /&gt;
 LastHourPVforecast&lt;br /&gt;
 LastHourPVreal&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-10-20 134050.png|right|thumb|400px|Übersicht solare Vorhersage]]&lt;br /&gt;
geloggt werden. &lt;br /&gt;
&lt;br /&gt;
Werden alle drei Werte in einem SVG kombiniert, kann die Entwicklung der Prognose über den Tag und die Beziehung von Prognose zu realer PV Erzeugnung pro Stunde visualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Für das rechts abgebildete Beispiel des Plots aus einer Datenbank &amp;quot;LogDBShort&amp;quot; sieht das gplot-File wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Created by FHEM/98_SVG.pm, 2024-03-08 15:05:31&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;TL&amp;gt;&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid&lt;br /&gt;
set ylabel &amp;quot;Wh&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Wh&amp;quot;&lt;br /&gt;
set yrange [0:7500]&lt;br /&gt;
set y2range [0:7500]&lt;br /&gt;
&lt;br /&gt;
#LogDBShort SolCast:LastHourPVforecast:::&lt;br /&gt;
#LogDBShort SolCast:LastHourPVreal:::&lt;br /&gt;
#LogDBShort SolCast:AllPVforecastsToEvent:::&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;aktuelle PV Vorhersage&#039; ls l6fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;reale PV Erzeugung&#039; ls l2fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;initiale PV Vorhersage&#039; ls l4 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; In manchen Fällen werden die Vorhersagewerte im SVG-Plot nicht angezeigt wenn FileLog verwendet wird. Ein Setzen des Attribute &amp;quot;fixedrange=3days +1&amp;quot; im SVG löst das Problem. Die Definition des SVG-Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_LogDBShort_SolCast SVG LogDBShort:SVG_LogDBShort_SolCast:HISTORY&lt;br /&gt;
attr SVG_LogDBShort_SolCast fixedrange 3days +1&lt;br /&gt;
attr SVG_LogDBShort_SolCast room Energie-&amp;gt;SolarPrognose&lt;br /&gt;
attr SVG_LogDBShort_SolCast sortby 2&lt;br /&gt;
attr SVG_LogDBShort_SolCast title &amp;quot;Übersicht solare Vorhersage&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Technisch bedingt werden an einem Tag X kurz nach 00:00 Uhr die am Vortag für den Tag X erzeugten Events aktualisiert. Diese Daten erzeugen in der Datenbank einen zweiten Satz an Daten mit dem gleichen Timestamp was für die Anzeige unvorteilhaft ist. &lt;br /&gt;
Um nur die aktualisierten Events von &#039;&#039;&#039;AllPVforecastsToEvent&#039;&#039;&#039; in der Datenbank zu erhalten, bietet sich ein DbRep-Device an. Die nachfolgende Vorschlagsdefinition kann per at-Device jeden Tag kurz vor Mitternacht (z.B. 23:57:10) ausgeführt werden. Es werden immer die in der Vergangenheit geschriebenen (veralteten) Daten aus der Datenbank gelöscht, doppelte Datesätze vermieden und immer die aktuellste initiale Prognose gespeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.Del.AllPVforecastsToEvent DbRep LogDBShort&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent alias Löschen Readings AllPVforecastsToEvent des Folgetages&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent comment ermöglicht dass die Readings AllPVforecastsToEvent am Folgetag wieder neu und aktuell geschrieben werden können&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent devStateIcon initialized:control_3dot_hor_s connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent disable 0&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent event-on-update-reading state&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent icon edit_delete&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent showproctime 1&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent device TYPE=SolarForecast&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_begin next_day_begin&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_end next_day_end&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das angegebene DbLog-Device &#039;&#039;&#039;LogDBShort&#039;&#039;&#039; ist natürlich anzupassen.&lt;br /&gt;
&lt;br /&gt;
Das at-Device zum Starten der Datenbankbereinigung sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define At.Del.AllPVforecastsToEvent at *23:58:10 set Rep.Del.AllPVforecastsToEvent delEntries&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent alias Start Löschen Readings AllPVforecastsToEventn LogDBShort&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent icon clock&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich sind auch hier die eigenen Devicenamen entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
Ab SolarForecast Version 1.51.7 kann die Eventerzeugung für bestimmte SVG Plot-Typen optimiert werden. &amp;lt;br&amp;gt; &lt;br /&gt;
Die Aktivierung dieser Optimierungen ist in der Online Hilfe zum Attribut &#039;&#039;&#039;plantControl-&amp;gt;genPVforecastsToEvent&#039;&#039;&#039; beschrieben. Bei Nutzung des Attributes plantControl-&amp;gt;genPVforecastsToEvent ist ebenfalls das Attribut &#039;&#039;&#039;event-on-update-reading=AllPVforecastsToEvent&#039;&#039;&#039; zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispielkonfiguration 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;
Bitte dabei diese DWD-Version aus dem [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter Contrib] von DS_Starter dazu nutzen&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|55_DWD_OpenData.pm&lt;br /&gt;
|136.2 KB ​&lt;br /&gt;
|29260  &lt;br /&gt;
|DS_Starter&lt;br /&gt;
|55_DWD_OpenData: contrib 1.17.7&lt;br /&gt;
|}&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 downloadTimeout 120&lt;br /&gt;
attr DWD comment Im DWD Wetterdevice verwendet Solarforecast : \&lt;br /&gt;
TTT,Neff,RR1c,ww,SunUp,SunRise,SunSet \&lt;br /&gt;
zusätzlich ist jedoch auch noch Rad1h notwendig \&lt;br /&gt;
wenn dieses DWD-Device als Strahlungsdevice genutzt wird.\&lt;br /&gt;
Die Station 10418 (Lüdenscheid) überträgt aktuell am 09.03.2025 (noch) Rad1h.\&lt;br /&gt;
attr DWD downloadTimeout 120&lt;br /&gt;
attr DWD forecastDays 7&lt;br /&gt;
attr DWD forecastProperties SunUp, SunRise, SunSet, Rad1h, R101, RR1c, TTT, Tx, Tn, Tg, DD, FX1, RR6c, R600, RRhc, Rh00, ww, wwd, Neff&lt;br /&gt;
attr DWD forecastRefresh 1&lt;br /&gt;
attr DWD forecastResolution 1&lt;br /&gt;
attr DWD forecastStation 10418&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 fc_description  -(state fc_time)&lt;br /&gt;
attr DWD verbose 2&lt;br /&gt;
&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;
defmod InverterDummy dummy&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;
defmod 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 feedinPrice 0.08&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 powerCost 0.25&lt;br /&gt;
attr SMA_Energymeter room 015_Zaehler,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;
defmod 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;
attr BatteryDummy userReadings total_pac, power_out, power_in, chargestatus, bat_rated_capacity, bat_loadtotal, bat_unloadtotal&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;
defmod N.PV.TotalConsumption.Dum.Energy notify SMA_Energymeter:Saldo_Wirkleistung:.* {\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung_2 Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&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;MB_USRW610_004&amp;quot;,&amp;quot;Power_Sum__W&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;
fhem &amp;quot;setreading InverterDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(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;
#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;
 # Batterie-total_pac  InverterDummy\&lt;br /&gt;
my $wert7 = sprintf(&amp;quot;%.3f&amp;quot;,((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy bat_rated_capacity &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert7));;\&lt;br /&gt;
 # möglicher Aufruf einer Batterie-Bebladung-Routine....SMABatteryChargewithTibber();;\&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;
defmod Forecast SolarForecast&lt;br /&gt;
attr Forecast DbLogExclude .*&lt;br /&gt;
attr Forecast DbLogInclude Current_BatCharge999&lt;br /&gt;
attr Forecast affectBatteryPreferredCharge 30&lt;br /&gt;
attr Forecast affectConsForecastLastDays 31&lt;br /&gt;
attr Forecast affect70percentRule 0&lt;br /&gt;
attr Forecast comment &amp;quot;wget -qO ./FHEM/76_SolarForecast.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/76_SolarForecast.pm&amp;quot;\&lt;br /&gt;
&amp;quot;wget -qO ./FHEM/55_DWD_OpenData.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/55_DWD_OpenData.pm&amp;quot;\&lt;br /&gt;
&amp;quot;13.01.2025 mit der Version 76_SolarForecast.pm:v1.43.2-s29518/2025-01-12&amp;quot;&lt;br /&gt;
attr Forecast graphicHeaderOwnspec PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal Verbrauch&amp;amp;nbsp;;bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast  Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest FCU-Erzeugung&amp;amp;nbsp;;:Current_PP01\&lt;br /&gt;
attr Forecast consumer01 FBDECT_fbahahttp_11657_0127183 icon=scene_washing_machine@orange type=washingmachine power=10 swstate:state notbefore=09 notafter=20 pcurr=power:W:3 etotal=energy:Wh interruptable=1 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer02 FBDECT_fbahahttp_E8_DF_70_07_3E_57 icon=light_floor_lamp@orange type=other power=15 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer03 FBDECT_fbahahttp_E8_DF_70_07_42_0B icon=raspberrypi@orange type=other power=8 swstate:state pcurr=power:W:1 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer04 FBDECT_fbahahttp_11657_0067275 icon=springbrunnen_icon@orange type=other power=50 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer05 FBDECT_fbahahttp_34_31_C4_D4_31_37 icon=sani_domestic_waterworks@orange type=other power=10 swstate:state pcurr=power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer06 tuya_local_bf5037060f450bdbd4rl0q icon=scene_clothes_dryer@orange type=dryer power=10 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer07 tuya_local_bfac44fb487476efd1vhdu icon=weather_sunset@orange type=noSchedule power=5 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumerControl adviceIcon=light_light_dim_100@gold&lt;br /&gt;
attr Forecast consumerControl showLegend=icon_top&lt;br /&gt;
attr Forecast consumerControl detailLink=1&lt;br /&gt;
attr Forecast ctrlAIdataStorageDuration 1825&lt;br /&gt;
attr Forecast ctrlAIshiftTrainStart 2&lt;br /&gt;
attr Forecast ctrlBatSocManagement01 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlBatSocManagement02 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlDebug none&lt;br /&gt;
attr Forecast plantControl genPVdeviation=continuously&lt;br /&gt;
attr Forecast plantControl cycleInterval=15&lt;br /&gt;
attr Forecast ctrlNextDayForecastReadings 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24&lt;br /&gt;
attr Forecast ctrlNextHoursSoCForecastReadings 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23&lt;br /&gt;
attr Forecast ctrlSpecialReadings BatPowerIn_Sum,BatPowerOut_Sum,SunHours_Remain,SunMinutes_Remain,allStringsFullfilled,conForecastTillNextSunrise,currentAPIinterval,currentRunMtsConsumer_01,currentRunMtsConsumer_02,currentRunMtsConsumer_03,currentRunMtsConsumer_04,currentRunMtsConsumer_05,currentRunMtsConsumer_06,currentRunMtsConsumer_07,dayAfterTomorrowPVforecast,daysUntilBatteryCare_01,daysUntilBatteryCare_02,lastretrieval_time,lastretrieval_timestamp,response_message,runTimeAvgDayConsumer_01,runTimeAvgDayConsumer_02,runTimeAvgDayConsumer_03,runTimeAvgDayConsumer_04,runTimeAvgDayConsumer_05,runTimeAvgDayConsumer_06,runTimeAvgDayConsumer_07,runTimeCentralTask,runTimeLastAPIAnswer,runTimeLastAPIProc,runTimeTrainAI,todayBatIn_01,todayBatIn_02,todayBatOut_01,todayBatOut_02,todayConForecastTillSunset,todayConsumptionForecast,todayDoneAPIcalls,todayDoneAPIrequests,todayGridConsumption,todayGridFeedIn,todayMaxAPIcalls,todayRemainingAPIcalls,todayRemainingAPIrequests&lt;br /&gt;
attr Forecast disable 0&lt;br /&gt;
attr Forecast event-min-interval .*:1800&lt;br /&gt;
attr Forecast event-on-change-reading .*&lt;br /&gt;
attr Forecast flowGraphicControl animate=1 consumerdist=80 h2consumerdist=50 shiftx=0  shifty=0 showconsumer=1 showconsumerdummy=1 showconsumerpower=1 showconsumerremaintime=0 size=400 strokewidth=12&lt;br /&gt;
attr Forecast graphicBeam1Color 3C14FF&lt;br /&gt;
attr Forecast graphicBeam1Content pvReal&lt;br /&gt;
attr Forecast graphicBeam2Color 19FF29&lt;br /&gt;
attr Forecast graphicBeam2Content pvForecast&lt;br /&gt;
attr Forecast graphicBeam3Color D60924&lt;br /&gt;
attr Forecast graphicBeam3Content batsocforecast_02&lt;br /&gt;
attr Forecast graphicBeam3FontColor FFFF0D&lt;br /&gt;
attr Forecast graphicBeam4Color FFFF1F&lt;br /&gt;
attr Forecast graphicBeam4Content batsocforecast_01&lt;br /&gt;
attr Forecast graphicBeam4FontColor 000000&lt;br /&gt;
attr Forecast graphicBeamHeightLevel1 200&lt;br /&gt;
attr Forecast graphicBeamHeightLevel2 200&lt;br /&gt;
attr Forecast graphicHeaderDetail all&lt;br /&gt;
attr Forecast graphicHeaderOwnspec #PV\&lt;br /&gt;
PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal\&lt;br /&gt;
PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast\&lt;br /&gt;
PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast\&lt;br /&gt;
:\&lt;br /&gt;
#\&lt;br /&gt;
AutarkyRate:Current_AutarkyRate\&lt;br /&gt;
Überschuss:Current_Surplus\&lt;br /&gt;
aktueller&amp;amp;nbsp;;Netzbezug:Current_GridConsumption\&lt;br /&gt;
:\&lt;br /&gt;
#Verbrauch\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenuntergang:special_todayConForecastTillSunset\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie01\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_01\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_01\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_01\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_01\&lt;br /&gt;
#Batterie01_tmp\&lt;br /&gt;
Current_PowerBatIn_01:Current_PowerBatIn_01\&lt;br /&gt;
Current_PowerBatOut_01:Current_PowerBatOut_01\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie02\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_02\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_02\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_02\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_02\&lt;br /&gt;
#Batterie02_tmp\&lt;br /&gt;
Current_PowerBatIn_02:Current_PowerBatIn_02\&lt;br /&gt;
Current_PowerBatOut_02:Current_PowerBatOut_02\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Settings\&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto \&lt;br /&gt;
Wetter:graphicShowWeather\&lt;br /&gt;
History:graphicHistoryHour\&lt;br /&gt;
ShowNight:graphicShowNight\&lt;br /&gt;
Debug:ctrlDebug\&lt;br /&gt;
FCU-Modus:FCU-Betriebsmodus@FCU&lt;br /&gt;
attr Forecast graphicHistoryHour 4&lt;br /&gt;
attr Forecast graphicHourCount 24&lt;br /&gt;
attr Forecast graphicLayoutType double&lt;br /&gt;
attr Forecast graphicShowDiff top&lt;br /&gt;
attr Forecast graphicShowNight 1&lt;br /&gt;
attr Forecast graphicShowWeather 1&lt;br /&gt;
attr Forecast group Energy Meter&lt;br /&gt;
attr Forecast room 020_PV,Energie&lt;br /&gt;
attr Forecast setupBatteryDev01 SBS25 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupBatteryDev02 SBS25_2 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupInverterDev01 SB25 pv=total_pac:kW etotal=etotal:kWh capacity=2500 strings=GarageSE limit=70&lt;br /&gt;
attr Forecast setupInverterDev02 SB30 pv=total_pac:kW etotal=etotal:kWh capacity=3000 strings=GarageNW,HausNW limit=70&lt;br /&gt;
attr Forecast setupInverterDev03 SB40 pv=total_pac:kW etotal=etotal:kWh capacity=4000 strings=HausSE1,HausSE2,HausSW limit=70&lt;br /&gt;
attr Forecast setupInverterStrings GarageSE,GarageNW,HausNW,HausSW,HausSE1,HausSE2&lt;br /&gt;
attr Forecast setupMeterDev SMA_Energymeter gcon=Bezug_Wirkleistung:W contotal=Bezug_Wirkleistung_Zaehler:kWh gfeedin=Einspeisung_Wirkleistung:W feedtotal=Einspeisung_Wirkleistung_Zaehler:kWh conprice=0.25:€ feedprice=0.08123:€&lt;br /&gt;
attr Forecast setupOtherProducer01 icon=Heizung_FCU_green@red MB_USRW610_004 pcurr=Power_L1__W:W etotal=Energy_L1_import__kWh:kWh&lt;br /&gt;
attr Forecast setupRadiationAPI DWD&lt;br /&gt;
attr Forecast setupStringPeak GarageSE=2.75 GarageNW=3.200 HausNW=2.230 HausSW=2.230 HausSE1=2.200 HausSE2=2.200&lt;br /&gt;
attr Forecast setupWeatherDev1 DWD&lt;br /&gt;
attr Forecast stateFormat Current_PV&lt;br /&gt;
attr Forecast userReadings Current_BatCharge999 {((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))) / ( (ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0) * 1000)  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0)*1000))*100}&lt;br /&gt;
attr Forecast verbose 2&lt;br /&gt;
&lt;br /&gt;
setstate Forecast 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .FCU_FCU-Betriebsmodus 2&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_ctrlDebug none&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicHistoryHour 4&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowNight 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowWeather 1&lt;br /&gt;
setstate Forecast 2025-01-13 08:24:25 .associatedWith SMA_Energymeter FBDECT_fbahahttp_11657_0127183 FBDECT_fbahahttp_E8_DF_70_07_3E_57 FBDECT_fbahahttp_E8_DF_70_07_42_0B FBDECT_fbahahttp_11657_0067275 FBDECT_fbahahttp_34_31_C4_D4_31_37 tuya_local_bf5037060f450bdbd4rl0q tuya_local_bfac44fb487476efd1vhdu SBS25 SBS25_2 SB25 SB30 SB40 DWD MB_USRW610_004&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .lastupdateForecastValues 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .pvCorrectionFactor_Auto_Soll on_complex_ai&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .signaldone_01 done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .signaldone_02 done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .signaldone_03 done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .signaldone_04 done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .signaldone_05 done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .signaldone_06 done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .signaldone_07 done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .signaldone_08 done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .signaldone_09 done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .signaldone_10 done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .signaldone_11 done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .signaldone_12 done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .signaldone_13 done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .signaldone_14 done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .signaldone_15 done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .signaldone_16 done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .signaldone_17 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .signaldone_18 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_01 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_02 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_01 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_02 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_AutarkyRate 83 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 Current_BatCharge999 10&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_01 12 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_02 8 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Consumption 626 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridConsumption 2 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridFeedIn 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PP_01 746.0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PV 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_01 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_02 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_01 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_02 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumption 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumptionRate 0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Surplus 120 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourGridconsumptionReal 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_ConsumptionForecast 2944 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayConsumptionForecast 3609 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_01 272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PPreal_01 748 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PPreal_01 787 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_01 271 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PPreal_01 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PPreal_01 745 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_01 267 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PPreal_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_01 255 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PPreal_01 752 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_01 226 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_01 50 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PPreal_01 681 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_02 233 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_01 845 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridConsumption 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_01 37 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_02 90 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_01 351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_02 188 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridConsumption 447 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVforecast 127 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridConsumption 1650 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVforecast 478 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVreal 26 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridConsumption 513 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVforecast 868 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVreal 97 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridConsumption 576 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVforecast 1157 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVreal 320 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_01 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_02 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridConsumption 1272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridFeedIn 7 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVforecast 1238 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVreal 945 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_01 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_02 53 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridConsumption 955 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridFeedIn 31 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PPreal_01 562 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVforecast 1168 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVreal 1410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_01 703 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_02 500 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_01 22 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_02 18 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridConsumption 32 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridFeedIn 71 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PPreal_01 777 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVreal 1416 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_01 296 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_02 70 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_01 74 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_02 258 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridConsumption 13 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridFeedIn 17 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PPreal_01 732 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVforecast 880 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVreal 1051 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_01 47 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_02 126 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_01 102 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_02 75 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridConsumption 15 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridFeedIn 23 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PPreal_01 771 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVforecast 117 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVreal 86 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_02 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_02 67 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridConsumption 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridFeedIn 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PPreal_01 723 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_01 349 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_02 124 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_01 73 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_02 450 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridConsumption 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridFeedIn 6 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PPreal_01 671 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecastTime 2025-01-13 14:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVdeviation 30.17 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVforecast 7663 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVreal 5351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunRise 08:28&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunSet 16:46&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_ConsumptionForecast 17043 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour05_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour06_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour07_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour08_PVforecast 10 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour09_PVforecast 161 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour10_PVforecast 275 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour11_PVforecast 532 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour12_PVforecast 730 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour13_PVforecast 1252 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour14_PVforecast 818 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour15_PVforecast 1465 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour16_PVforecast 303 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour17_PVforecast 20 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour18_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour19_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour20_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour21_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour22_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour23_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour24_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_PVforecast 5566 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunRise 08:27&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunSet 16:47&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01 name=&#039;_Waschmaschine&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_start 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_stop 14.01.2025 11:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02 name=&#039;_Esszimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_currentPower 15.3 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03 name=&#039;_FCU&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_currentPower 7.15 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04 name=&#039;_Brunnen&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05 name=&#039;_Zisterne&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06 name=&#039;SW Trockner&#039; state=&#039;unknown&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_stop 14.01.2025 08:30:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07 name=&#039;SW Urlaubslicht-Wohnzimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;noSchedule&#039; info=&#039;von extern umgeschaltet&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 nextCycletime 18:54:09&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 pvCorrectionFactor_10 0.53 (automatic - old factor: 1.00, Sun Alt range: 5, Cloud range: 75, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 pvCorrectionFactor_11 0.56 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 70, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 pvCorrectionFactor_12 0.64 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 pvCorrectionFactor_13 0.88 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 pvCorrectionFactor_14 1.10 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 50, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 pvCorrectionFactor_15 1.01 (automatic - old factor: 1.06, Sun Alt range: 15, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 pvCorrectionFactor_16 1.09 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 45, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 pvCorrectionFactor_17 0.28 (automatic - old factor: 0.52, Sun Alt range: 0, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 pvCorrectionFactor_Auto on_complex_ai&lt;br /&gt;
setstate Forecast 2024-10-30 19:42:19 setupStringAzimuth GarageSE=-55 GarageNW=125 HausNW=125 HausSW=35 HausSE1=-55 HausSE2=-55&lt;br /&gt;
setstate Forecast 2024-10-30 19:37:38 setupStringDeclination GarageSE=40 GarageNW=40 HausNW=50 HausSW=50 HausSE1=50 HausSE2=50&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerIn_Sum 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerOut_Sum 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunHours_Remain 0.00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunMinutes_Remain 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_allStringsFullfilled 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_conForecastTillNextSunrise 9467 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentAPIinterval 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_01 132 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_02 184 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_03 329512 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_04 200 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_05 27 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_06 193 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_07 106 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_dayAfterTomorrowPVforecast 7344 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_01 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_02 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_time 2025-01-13 18:53:54&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_timestamp 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_response_message success&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_01 545.94 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_02 382.10 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_03 1430.13 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_04 262.05 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_05 28.80 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_06 622.63 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_07 276.51 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeCentralTask 0.3744&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIAnswer -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIProc -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeTrainAI 1.2529&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_01 3683.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_02 1617.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_01 2287.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_02 1057.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConForecastTillSunset 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 special_todayConsumptionForecast_01 509 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 special_todayConsumptionForecast_02 499 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 special_todayConsumptionForecast_03 501 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 special_todayConsumptionForecast_04 511 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 special_todayConsumptionForecast_05 503 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 special_todayConsumptionForecast_06 495 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 special_todayConsumptionForecast_07 504 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 special_todayConsumptionForecast_08 561 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 special_todayConsumptionForecast_09 768 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 special_todayConsumptionForecast_10 783 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 special_todayConsumptionForecast_11 692 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 special_todayConsumptionForecast_12 791 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 special_todayConsumptionForecast_13 910 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 special_todayConsumptionForecast_14 1022 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 special_todayConsumptionForecast_15 965 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 special_todayConsumptionForecast_16 812 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 special_todayConsumptionForecast_17 884 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 special_todayConsumptionForecast_18 928 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_19 874 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_20 763 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_21 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_22 765 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_23 643 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_24 601 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIcalls 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIrequests 4532&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridConsumption 5500.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridFeedIn 178.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayMaxAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIrequests n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 state updated&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So sollte es dann als Ergebnis aussehen:&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13.png|zentriert|mini|Ergebnis nach kompletter Einrichtung]]&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13 Teil II.png|alternativtext=Unterer Teil der Anzeige|zentriert|mini]]&lt;br /&gt;
&lt;br /&gt;
== Praxisbeispiele und Lösungsansätze für Steuerungen ==&lt;br /&gt;
=== Fallstudie: Trockner darf pausiert werden, wenn nicht genug PV-Überschuss vorhanden ist, soll aber nach spätestens X Stunden fertig sein ===&lt;br /&gt;
Für diese Aufgabenstellung sind mehrere Schlüssel essentiell wichtig, &#039;&#039;&#039;power&#039;&#039;&#039;, &#039;&#039;&#039;mintime&#039;&#039;&#039;, &#039;&#039;&#039;mode&#039;&#039;&#039; und &#039;&#039;&#039;interruptable&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Die Bedingung, dass der Trockner nach spätestens X Stunden fertig sein soll, steht in einem Widerspruch zu der Möglichkeit den Trockner bei zu wenig PV-Überschuss unterbrechen zu können. Im Extremfall könnte nach dem Start die gesamte Planungszeit ungenügender Überschuss vorliegen und der Trockner nicht arbeiten. Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; (in Minuten) wird nun wie folgt angesetzt:&lt;br /&gt;
&lt;br /&gt;
 mintime = 2,5 x &amp;lt;gewöhnliche Betriebszeit für einen Trockengang (mneed, z.B. 120)&amp;gt; = 300 Minuten&lt;br /&gt;
&lt;br /&gt;
Das bedeutet, der Trockner wird nach 300 Minuten Laufzeit abgeschaltet werden bzw. vom Netz getrennt. Der Trockenvorgang wird natürlich bereits nach 120 Minuten beendet sein, sofern nach Start keine Unterbrechnung des Vorganges erfolgte. Wurde der Vorgang unterbrochen, soll der Trockner innerhalb &lt;br /&gt;
&lt;br /&gt;
 X+120 bis X+300 &lt;br /&gt;
&lt;br /&gt;
fertig sein. &lt;br /&gt;
&lt;br /&gt;
Demnach ist die ausgeführte Laufzeit des Trockners permanent zu überwachen, zu summieren (rtsum) und die notwendige Restzeit (mneed - rtsum) mit der noch verbleibenden Restzeit (mrest) bis zur geplanten Abschaltung des Consumers zu vergleichen. Ist der Consumer gestartet, wird die Laufzeit in der pvHistory für jede Stunde des Tages im Schlüssel &#039;&#039;minutescsmXX&#039;&#039; (XX = Consumernummer) aufgezeichnet und kann darüber ausgewertet werden. Somit ist:&lt;br /&gt;
&lt;br /&gt;
 msum = for (01 .. 24) {Summe von minutescsmXX} des aktuellen Tages&lt;br /&gt;
&lt;br /&gt;
Solange die Bedingung &lt;br /&gt;
&lt;br /&gt;
 mrest &amp;gt;= (mneed - msum)&lt;br /&gt;
&lt;br /&gt;
zutrifft, darf der Trockner unterbrochen werden, anderenfalls darf er nicht mehr unterbrochen werden da die Restzeit evtl. nicht ausreichen könnte um den Vorgang abzuschließen. Für die Planung des Trockners wird der Consumer wie gewöhnlich nach dem Bedarf im Modul registriert. Für die Steuerung der Unterbrechbarkeit wird noch ein Code erstellt, welcher im Trockner-Device &#039;&#039;Dryerdev&#039;&#039; das Reading &#039;&#039;SF_Int&#039;&#039; zur Unterbrechnungssteuerung verwaltet. Dieses Reading wird dem Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; übergeben. Für das Beispiel wird der Consumer &#039;07&#039; verwendet, es kann natürlich jede andere freie Nummer verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Dryerdev:Trockner&lt;br /&gt;
                        icon=scene_cloves_dryer type=dryer power=2000 mode=must mintime=300 &lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic asynchron=1&lt;br /&gt;
                        interruptable=Dryerdev:SF_Int:1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Kombination &#039;&#039;&#039;auto=automatic&#039;&#039;&#039; eröffnet die Möglickeit, in der Consumer-Legende den Trockner-Start zusätzlich manuell freizugeben oder zu verbieten. &lt;br /&gt;
&lt;br /&gt;
Im nachfolgenden Code werden modulinterne Subroutinen verwendet. Diese sind inklusive dem Paket &#039;&#039;FHEM::SolarForecast::&#039;&#039; anzugeben. Die erstellte Subroutine wird in die 99_mySolarForecastUtils.pm eingefügt. Die Datei 99_mySolarForecastUtils.pm wird vorher von 99_myUtils.pm kopiert und enthält für die Übersichtlichkeit nur Routinen für SolarForecast.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Trocknersteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub dryControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # gewöhlich benötigte Zeit für &lt;br /&gt;
                                                                                  # einen Trockengang, z.B. 120 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $dryer     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename des Trockners&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Trockner-Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit des Trockners&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      my $dhash = $defs{$dryer};&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 1, 0);                        # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 0, 0);                        # keine Interrupt-Freigabe&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die gewöhnliche Laufzeit des Trockners für einen Trockenvorgang (120 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::dryControl ($name, &#039;07&#039;, 120);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Fallstudie: Umwälzpumpe Pool soll X Stunden am Tag laufen. Ist kein PV-Überschuß vorhanden, müssen die X Stunden/Tag trotzdem erreicht werden ===&lt;br /&gt;
&lt;br /&gt;
Die Vorgehensweise ähnelt der Fallstudie zuvor. Verändernd kommt hinzu, dass der Planungszeitraum bewusst sehr lang angesetzt wird mit der Option, den Zyklus des Consumers vorfristig zu beenden sobald die Laufzeit von X Stunden am Tag erreicht ist. &lt;br /&gt;
Im folgenden Beispiel soll die Pumpe 5 Stunden am Tag (300 Minuten) laufen und dabei mögliche PV-Überschüsse ausnutzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Pump:Zirkulationspumpe&lt;br /&gt;
                        icon=sani_pump type=other power=50 mode=must mintime=780 notafter=09&lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic &lt;br /&gt;
                        interruptable=1 swoffcond=Pump:SF_Abort:1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit dieser Registrierung wird die Pumpe ca. 09 Uhr täglich starten. Wenn kein bzw. ungenügender PV-Überschuß vorhanden ist, erfolgt eine Unterbrechung nach dem Start. Ist genügender PV-Überschuß (wieder) vorhanden, erfolgt keine Unterbrechnung (mehr). Zusätzlich wird über den Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; eine vorfristige Beendigung veranlasst, sobald die gewünschte Tageslaufzeit erreicht ist.&lt;br /&gt;
&lt;br /&gt;
Zur Verwaltung des Schlüssels &#039;&#039;interruptable&#039;&#039; und des Readings &#039;&#039;SF_Abort&#039;&#039; verwenden wir eine leicht veränderte Subroutine aus dem vorhergehenden Fallbeispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Pumpensteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub pumpControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # Soll-Pumpenzeit, z.B. 300 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $pump      = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename der Pumpe&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;);&lt;br /&gt;
  my $intbl     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;interruptable&#039;, 1); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
  my $dhash     = $defs{$pump};&lt;br /&gt;
&lt;br /&gt;
  readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 0, 0);                                # default keine Zyklusbeendigung&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Pumpen Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit der Pumpe&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
     &lt;br /&gt;
      if ($msum &amp;gt;= $mneed) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 1, 0);                       # vorfristige Zyklusbeendigung&lt;br /&gt;
          return;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=1&amp;quot;) if(!$intbl);  # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=0&amp;quot;) if($intbl);   # keine Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Befehl &#039;&#039;attrKeyVal&#039;&#039; setzt den Schlüssel &#039;&#039;interruptable&#039;&#039; im Attribut &#039;&#039;consumer07&#039;&#039; dynamisch. Diese Strukturänderung wird automatisch im System gespeichert, sofern &#039;&#039;global-&amp;gt;autosave=1&#039;&#039; gesetzt ist. Diese Einstellung ist der FHEM default.  &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die Mindestlaufzeit der Umwälzpumpe (300 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::pumpControl ($name, &#039;07&#039;, 300);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamische Ladestromsteuerung eines Victron MultiPlus II Chargers mit Pylontech Batterie ===&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;
&lt;br /&gt;
 set &amp;lt;Device&amp;gt; MaxChargeCurrent &amp;lt;Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
eingestellt bzw. variiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Modul bietet dem Nutzer die Möglichkeit in dem Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltene Code wird am Ende jedes Zyklus (siehe Attribut &#039;&#039;plantControl-&amp;gt;cycleInterval&#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;
&lt;br /&gt;
&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 $mppt1   = &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common&#039;;              # SmartLoader Device&lt;br /&gt;
  my $maxcspc = 105;                        # max. Ladesollstrom (A) nominal&lt;br /&gt;
  my $spcorr  = 0.9;                        # Korrekturfaktor Überschuss 90%&lt;br /&gt;
  my $sch     = 0.25;                       # Verkürzungsfaktor Zeit bis Vollladung vor Sunset             &lt;br /&gt;
  &lt;br /&gt;
  my $cclvl0  = 15;                         # Ladestrom Level 0 max. 5  A (240 W) pro WR  (720  W)&lt;br /&gt;
  my $cclvl1  = 27;                         # Ladestrom Level 1 max. 9  A (432 W) pro WR  (1296 W)&lt;br /&gt;
  my $cclvl2  = 54;                         # Ladestrom Level 2 max. 18 A (864 W) pro WR  (2592 W)&lt;br /&gt;
  my $cclvl3  = 81;                         # Ladestrom Level 3 max. 27 A (1296 W) pro WR (3888 W)&lt;br /&gt;
  ###############&lt;br /&gt;
  &lt;br /&gt;
  my $cofc   = ReadingsNum ($name,  &#039;special_todayConForecastTillSunset&#039;, 0);&lt;br /&gt;
  my $pvfc   = ReadingsNum ($name,  &#039;RestOfDayPVforecast&#039;, 0);&lt;br /&gt;
  my $cpv    = ReadingsNum ($name,  &#039;Current_PV&#039;,          0);&lt;br /&gt;
  my $mppt1c = ReadingsNum ($mppt1, &#039;DC_0_Current_value&#039;,  0);             # Load I MPPT1 (max. 44 A)&lt;br /&gt;
  my $ssts   = CurrentVal  ($hash,  &#039;sunsetTodayTs&#039;,        0);&lt;br /&gt;
  my $srts   = CurrentVal  ($hash,  &#039;sunriseTodayTs&#039;,       0);&lt;br /&gt;
  my $sdiff  = ($ssts - $srts) / 3600;                                     # Sonnengang heute in h &lt;br /&gt;
  &lt;br /&gt;
  my $solh   = ReadingsNum ($name, &#039;special_SunHours_Remain&#039;, 0);          # h bis SunSet&lt;br /&gt;
  $solh      = $solh - ($sdiff * $sch);                                    # h bis SunSet - X&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;              # Ah Bat bis SOC&lt;br /&gt;
  $ahrem     = sprintf &amp;quot;%.0f&amp;quot;, $ahrem;&lt;br /&gt;
  &lt;br /&gt;
  my $fcdiff = ($pvfc - $cofc) * $spcorr;     # Korrektur d. noch prognostizierten Überschussenergie &lt;br /&gt;
  $fcdiff    = $fcdiff &amp;lt; 0 ? 0 : $fcdiff;     # Wh&lt;br /&gt;
  &lt;br /&gt;
  my $loadcur = $maxcspc;&lt;br /&gt;
  &lt;br /&gt;
  if ($cpv &amp;amp;&amp;amp; $solh &amp;amp;&amp;amp; $ahrem &amp;amp;&amp;amp; $fcdiff &amp;gt; $ahrem) {  # Ladeanforderung und Überschuss übersteigt &lt;br /&gt;
                                                      # Lademenge&lt;br /&gt;
      my $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($ahrem / $solh);    # A = Ah / h -&amp;gt; A Soll Schätzung&lt;br /&gt;
&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Battery charging process should be completed }.&lt;br /&gt;
                      qq{in &amp;gt;$solh&amp;lt; hours});&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; raw Target charging current: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($cspc - $mppt1c);      # SmartLoader IST berücksichtigen&lt;br /&gt;
	  &lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Charge Current minus MPPT load Current &amp;gt;$mppt1c&amp;lt;: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $loadcur = $cspc &amp;lt;= 0       ? 0       :     # nur MPPT Ladung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl0 ? $cclvl0 :     # Übergangsbereich&lt;br /&gt;
                 $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;
	  Log3 ($name, 3, qq{$name - userFn -&amp;gt; MaxChargeCurrent calculated: $loadcur});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent&#039;,       $loadcur.&#039; A&#039;,          1);&lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_HoursUntilChargeFinish&#039;, sprintf (&amp;quot;%.2f&amp;quot;,$solh), 1);&lt;br /&gt;
  CommandSet           (undef, &amp;quot;$vebus MaxChargeCurrent $loadcur&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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. 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;special_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;special_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;Verkürzungsfaktor Zeit bis Vollladung vor Sunset&#039;&#039;) reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche mindest Ladestromstärke ermittelt.&lt;br /&gt;
&lt;br /&gt;
&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 auch während der MQTT Intergration 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;
=== Poolheizung in Abhängigkeit von vorhandenem Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren) ===&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;consumer01&#039;&#039; wird beispielhaft wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr Forecast consumer01 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;&lt;br /&gt;
&lt;br /&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. &lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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, einen 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 Überschuss 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;. &lt;br /&gt;
&lt;br /&gt;
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;
=== PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) ===&lt;br /&gt;
[https://evcc.io evcc] ist ein Energie-Management-System, mit dem u.a. Überschussladen von Elektroautos möglich ist. Hier ist beschreiben, wie die SolarForecast-Vorhersagedaten per API von evcc abgerufen werden.&lt;br /&gt;
Lege im SolarForecast-Device ein User-Reading mit dem Namen forecast_json an. Es wandelt die Forecast-Werte in JSON und ins UTC-Zeitformat um, so dass evcc die Daten verwenden kann:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
forecast_json {&lt;br /&gt;
&lt;br /&gt;
    use strict;&lt;br /&gt;
    use warnings;&lt;br /&gt;
    use JSON;&lt;br /&gt;
    use DateTime;&lt;br /&gt;
    use DateTime::Format::Strptime;&lt;br /&gt;
&lt;br /&gt;
    my $hour = 0;&lt;br /&gt;
    my @output;&lt;br /&gt;
&lt;br /&gt;
    # Parser für Datum mit CET/CEST&lt;br /&gt;
    my $parser = DateTime::Format::Strptime-&amp;gt;new(&lt;br /&gt;
        pattern   =&amp;gt; &#039;%Y-%m-%d %H:%M:%S&#039;,&lt;br /&gt;
        time_zone =&amp;gt; &#039;Europe/Berlin&#039;,&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    # Alle NextHour-Daten durchsuchen&lt;br /&gt;
    while ($hour &amp;lt; 100) {&lt;br /&gt;
        my $hour_str = sprintf(&#039;NextHour%02d&#039;, $hour);&lt;br /&gt;
        my $start_str = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;starttime&#039;, &#039;na&#039;); &lt;br /&gt;
        my $pvfc = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;pvfc&#039;, &#039;na&#039;);&lt;br /&gt;
&lt;br /&gt;
        # Schleife beenden, wenn keine Werte mehr vorhanden sind&lt;br /&gt;
        last if $start_str eq &#039;na&#039; or $pvfc eq &#039;na&#039;;&lt;br /&gt;
&lt;br /&gt;
        # parse und konvertiere Zeit&lt;br /&gt;
        my $start_dt = $parser-&amp;gt;parse_datetime($start_str);&lt;br /&gt;
        my $end_dt   = $start_dt-&amp;gt;clone-&amp;gt;add(hours =&amp;gt; 1);&lt;br /&gt;
&lt;br /&gt;
        # nach UTC konvertieren&lt;br /&gt;
        $start_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
        $end_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $start_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            end   =&amp;gt; $end_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            value =&amp;gt; 0 + $pvfc,&lt;br /&gt;
        };&lt;br /&gt;
        &lt;br /&gt;
        $hour++;&lt;br /&gt;
    }  &lt;br /&gt;
&lt;br /&gt;
    # Ausgabe als JSON&lt;br /&gt;
    my $json = JSON-&amp;gt;new-&amp;gt;utf8-&amp;gt;pretty-&amp;gt;encode(\@output);&lt;br /&gt;
    return $json;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Datei:Screenshot 2025-08-04 104835.png|right|thumb|300px|Darstellung der PV-Vorhersage in evcc auf Basis der SolarForecast-Daten]]&lt;br /&gt;
Die Kommunikation läuft über den integrierten FHEM-Webserver, der die JSON-Daten aus dem Reading forecast_json veröffentlicht. Dazu wird in FHEM eine separate Webinstanz auf einem neuen Port erstellt, die ohne [[CsrfToken-HowTo|CSFR-Token]] (Achtung, Auswirkungen auf die Sicherheit beachten!) und nur von localhost aufrufbar ist (Voraussetzung: evcc läuft auf derselben Maschine wie FHEM):&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
define WEBapi FHEMWEB 8089&lt;br /&gt;
attr WEBapi csrfToken none&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;In der [https://docs.evcc.io/docs/tariffs#pv-vorhersage evcc-Konfig unter tariffs] steht die Quelle für die Solar-Vorhersage. Der FHEM-Befehl {ReadingsVal(&#039;solarforecast_dev&#039;,&#039;forecast_json&#039;,&#039;[]&#039;)} wird encoded und in die uri eingetragen. Trage statt solarforecast_dev den passenden Namen deines SolarForecast-Device ein. evcc holt die Daten aus dem Reading forecast_json dann regelmäßig ab.&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
solar:&lt;br /&gt;
  type: custom&lt;br /&gt;
  interval: 20m    &lt;br /&gt;
  forecast:&lt;br /&gt;
    source: http&lt;br /&gt;
    uri: http://localhost:8089/fhem?cmd=%7BReadingsVal%28%27solarforecast_dev%27%2C%27forecast_json%27%2C%27%5B%5D%27%29%7D&amp;amp;XHR=1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Zur Verbesserung der Sicherheit kann das neue WEBapi Device auch ein [[CsrfToken-HowTo#csrfToken festlegen|festes CSFR-Token]] verwenden. Dieses Token muss dann in der evcc-Konfiguration an die uri mittels &amp;amp;fwcsrf=&amp;lt;festes token&amp;gt; angehängt werden.&lt;br /&gt;
&lt;br /&gt;
== weiterführende Links ==&lt;br /&gt;
* Forenthema &amp;quot;{{Link2Forum|Topic=137058|LinkText=76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support}}&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;
* Photovoltaik Ingenieurbüro Junge: https://www.ing-büro-junge.de/html/photovoltaik.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung&amp;diff=40307</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=40307"/>
		<updated>2025-08-04T15:57:45Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Hinweis|Die vorliegende Wiki-Seite befindet sich im Aufbau.}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Solarprognose und Verbrauchersteuerung&lt;br /&gt;
|ModType=d&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 Prognosewerte können die SolCast API, OpenMeteo API, Forecast.Solar API, Victron VRM Portal API oder alternativ DWD Stahlungswerte-Stationen verwendet werden&lt;br /&gt;
&lt;br /&gt;
::* optionale KI Unterstützung der PV-Prognose bei Verwendung von geeigneten Solar-API&#039;s&lt;br /&gt;
&lt;br /&gt;
::* es wird sowohl die Erzeugungsprognose als auch eine Verbrauchsprognose sowie SoC Prognose (bei Batterie-Integration) erstellt&lt;br /&gt;
&lt;br /&gt;
::* Wetterdaten werden über DWD Wetter-Stationen oder verschiedene API integriert. Es können verschiedene API zur Gewinnung von Solar- und Wetterdaten kombiniert werden. &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 FHEM-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 Integration von bis zu 4 Inverter und Smartloader (DC-DC Batterieladegeräte) ist möglich&lt;br /&gt;
&lt;br /&gt;
::* eine Integration von bis zu 3 nicht PV-Energieerzeugern wie BHKW, Windrädern oder Notstromaggregaten ist möglich&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;
::* Einbindung von bis zu drei Batteriespeichersystemen&lt;br /&gt;
&lt;br /&gt;
::* Bereitstellung von Leitwerten zur optimalen Einstellung/Steuerung von Batteriespeichersystemen&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 Benutzererlebnis 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;
Das Wiki gibt allgemeingültige und teilweise sehr spezifische bzw. tiefgehende Informationen und Handlungsempfehlungen zum SolarForecast Modul. Die dargestellten Informationen beziehen sich auf den zum Zeitpunkt der Wiki-Erstellung vorhandenen Entwicklungsstand des Moduls. Durch die stetige Weiterentwicklung können sich Abweichungen zum beschriebenen Inhalt ergeben oder zur Obsoleszenz dieser Inhalte führen. &lt;br /&gt;
&lt;br /&gt;
Vergleiche deshalb die Informationen immer mit der aktuellen Befehls-Referenz zum Modul!&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Ein SolarForecast Device wird mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 define &amp;lt;Name&amp;gt; SolarForecast &lt;br /&gt;
&lt;br /&gt;
angelegt. Nach der Definition wird der User durch einen Dialog geführt, der einige unerlässliche Einstellungen abfragt und in den entsprechenden Attributen und Readings persistiert. Alle Attribute und Readings die eine Einstellung der Anlage bewirken, sind mit dem Präfix &amp;quot;setup&amp;quot; versehen. &lt;br /&gt;
&lt;br /&gt;
Die Verwendung von setup-Readings gestattet es die Anlagenparameter dynamisch im Betrieb zu verändern. So kann mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringAzimuth   bzw.&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringDeclination &lt;br /&gt;
&lt;br /&gt;
die Ausrichtung und der Neigungswinkel der PV-Module ständig angepasst werden, was zum Beispiel bei einer dem Sonnenstand nachgeführten Anlage von Bedeutung ist.&lt;br /&gt;
&lt;br /&gt;
Die abgefragten Einstellungen während des Dialoges sind ausführlich in den entsprechenden Attributen bzw. Set-Kommandos erläutert. Die benötigten Informationen sind anhängig von der gewählten Prognose-API und können im Umfang variieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 213257.png|right|thumb|400px|Anlagenprüfung über Drucktaste in der Kopfgrafik]]&lt;br /&gt;
&lt;br /&gt;
Sobald alle verlangten Einstellungen vorgenommen sind, sollte eine Anlagenprüfung mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; plantConfiguration check&lt;br /&gt;
&lt;br /&gt;
oder über die angebotene Drucktaste in der Grafik durchgeführt werden. Es wird eine Plausibilitätsprüfung vorgenommen und das Ergebnis sowie eventuelle Hinweise bzw. Fehler ausgegeben.&lt;br /&gt;
Die Prüfung kann beliebig wiederholt werden und sollte sich bei jeder Einstellungsänderung der Anlage durchgeführt werden. Dadurch wird die Wahrscheinlichkeit von fehlerhaften Einstellungen minimiert.&lt;br /&gt;
&lt;br /&gt;
Neben den grundlegenden Einstellungen können im Device weitere sekundäre Anlagenkomponenten wie Batteriesystem(e) (Attribut setupBatteryDev1 - setupBatteryDev3), weitere Wetter-Devices (Attribut setupWeatherDev1 - setupWeatherDev3) oder sonstige Erzeuger (z.B. BHKW, Winderzeugung, Notstromaggregat) integriert werden (Attribut setupOtherProducer01 - setupOtherProducer03).&lt;br /&gt;
&lt;br /&gt;
Die verlangten Parameter der Anlage werden in der Online-Hilfe umfassend beschrieben und deren Funktion erschließt sich zum größten Teil selbst. Dennoch soll nachfolgend auf einige Punkte im Zusammenhang der Einrichtung eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Hinweise zur Struktur der Attribute ===&lt;br /&gt;
&lt;br /&gt;
Durch die umfangreichen Funktionen des Moduls würde bei Nutzung der im FHEM herkömmlich vorhandenen Attributstruktur die Anzahl der benötigten Attribute extrem stark steigen und nicht sinnvoll genutzt werden können. Deshalb gibt es neben den &#039;&#039;gewöhnlichen&#039;&#039; Attributen mit einfachen Werteauswahlmöglichkeiten oder Eingaben (z.B. ctrlDebug, ctrlSpecialReadings) sogenannte &#039;&#039;zusammengesetzte&#039;&#039; Attribute, deren Inhalt durch &#039;&#039;&#039;Schlüssel=Wert Paare&#039;&#039;&#039; gebildet wird und dadurch deutlich mehr Funktionen und Informationen transportieren als ein gewöhnliches Attribut.&lt;br /&gt;
&lt;br /&gt;
Für zusammengesetzte Attribute besteht die zusätzliche Möglichkeit, gewünschte Änderungen der Schlüssel=Wert Paare selektiv vornehmen zu können, ohne das gesamte Attribut aufrufen und ändern zu müssen. Die Vorgang, der vor allem für programmtechnische Manipulationen gedacht ist, kann durch eine Set-Funktion ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; attrKeyVal &amp;lt;Attribut&amp;gt; [&amp;lt;Gerät&amp;gt;] &amp;lt;Schlüssel=Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiele für zusammengesetzte Attribute sind:&lt;br /&gt;
&lt;br /&gt;
* aiControl&lt;br /&gt;
* plantControl&lt;br /&gt;
* setup* Attribute&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktionen der Attribute werden durch einen Präfix geclustert und so inhaltlich, aber vor allem auch in der Attribute Drop-Down Liste, strukturiert dargestellt.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der &#039;&#039;&#039;Präfixe&#039;&#039;&#039; sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ai&#039;&#039;&#039; - Steuerungsfunktionen für KI (z.B. aiControl)&lt;br /&gt;
* &#039;&#039;&#039;consumer&#039;&#039;&#039; - Registrierung und Einstellungen für Verbraucher (z.B. consumer02, consumerControl)&lt;br /&gt;
* &#039;&#039;&#039;ctrl&#039;&#039;&#039; - Steuerungsfunktion allgemeiner Art (z.B. ctrlDebug, ctrlSpecialReadings, ctrlUserExitFn)&lt;br /&gt;
* &#039;&#039;&#039;flowGraphic&#039;&#039;&#039; - Einstellungen für die Energieflußgrafik (z.B. flowGraphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphic&#039;&#039;&#039; - Einstellung für die Grafik allgemein (z.B. graphicSelect, graphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphicBeam&#039;&#039;&#039; -  Einstellungen bestimmte Balkeneigenschaften in der Balkengrafik (z.B. graphicBeamHeightLevel1)&lt;br /&gt;
* &#039;&#039;&#039;plant&#039;&#039;&#039; - übergreifende Einstellungen betreffend der gesamten PV-Anlage bzw. des SolarForecast-Devices (z.B. plantControl)&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039; - Registrierung von Geräten in der Gesamtanlage und Einstellung deren Eigenschaften (Inverter, Zähler, Batterien usw.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Einrichtung der Wechselrichter mit setupInverterDevXX ===&lt;br /&gt;
&lt;br /&gt;
Mit den Attributen setupInverterDev01 bis setupInverterDevXX werden die vorhandenen Wechselrichter der Anlage registriert.&lt;br /&gt;
Das Modul unterscheidet verschiedene Wechselrichter-Typen, die sich durch ihre Arbeitsweise innerhalb der Anlage unterscheiden. Die Schlüssel=Wert Paare in den Attributen können mehrzeilig organisiert werden. Das erleichtert die Übersicht wenn viele dieser Parameter eingegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;PV-Wechselrichter: Es ist der Standard Wechselrichter in einer PV-Anlage. An ihn sind die Solarzellen bzw. Strings angeschlossen. Die zugeordneten Strings können mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ohne diese Angabe werden diesem Gerät alle definierten Strings (siehe Attribut &#039;&#039;setupInverterStrings&#039;&#039;) zugeordnet. Der Wechselrichter liefert seine Energie in das Hausnetz. Alternativ kann mit der Angabe &#039;&#039;&#039;feed=grid&#039;&#039;&#039; die Funktion des Wechselrichters geändert werden. Diese Angabe sagt aus, dass dieser Wechselrichter ausschließlich in das öffentliche Netz einspeist.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel-Setup eines PV-Wechselrichters (SMA STP):&lt;br /&gt;
&lt;br /&gt;
 STP_5000 pvIn=string_1_pdc:kW pvOut=total_pac:kW etotal=etotal:kWh capacity=5000 strings=Süddach asynchron=1 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Solar-Ladegeräte: Solar-Ladegeräte sind DC-DC Wandler und liefern die Energie der angeschlossenen Solarzellen nicht in das Wechselstromnetz, sondern laden direkt eine Batterie bzw. versorgen einen Batteriewechselrichter auf der Gleichstromseite. Die Funktion als Solar-Ladegerät wird mit &#039;&#039;&#039;feed=bat&#039;&#039;&#039; aktiviert, die relevanten Strings können ebenfalls mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ein Beispiel eines Solar-Ladegerätes ist ein Victron SmartSolar MPPT. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel für das Setup eines Solar-Ladegeräts (SmartSolar Charger MPPT):&lt;br /&gt;
&lt;br /&gt;
 MQTT2_cerboGX_c0619ab34e08_solarcharger_Common pv=Yield_Power_value:W etotal=Yield_System_value:kWh capacity=2080 strings=Schleppdach feed=bat synchron=0 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Batterie-Wechselrichter: Dieses Gerät hat keine angeschlossenen Solarzellen und arbeitet als DC-AC bzw. AC-DC Wandler zwischen einer Batterie (=Gleichstromquelle) und dem Wechselstrom-Hausnetz. Die Funktion als Batterie-Wechselrichter wird mit der Angabe &#039;&#039;&#039;strings=none&#039;&#039;&#039; aktiviert. Die Schlüssel &#039;&#039;etotal&#039;&#039; und &#039;&#039;pv&#039;&#039; können bei einem Batterie-Wechselrichter ohne zugeordnete Solarzellen nicht gesetzt werden. Ein Beispiel eines Batterie-Wechselrichter ist der Victron MultiPlus II.&lt;br /&gt;
&lt;br /&gt;
Ein Setup-Beispiel für einen Batterie-Wechselrichter (Victron MultiPlus II):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dc2ac=DC_IN:W&lt;br /&gt;
ac2dc=DC_OUT:W&lt;br /&gt;
capacity=7200&lt;br /&gt;
strings=none&lt;br /&gt;
icon=inverter@darkorange:inverter@grey&lt;br /&gt;
asynchron=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Eigenschaften des Wechselrichters werden durch eine Reihe von &amp;lt;Schlüssel=Wert&amp;gt; Paaren festgelegt. Auf einige dieser Paramter soll hier eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Ausgewählte Schlüssel=Wert Paare ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;pvIn=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvIn&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell zugeführte PV-Leistung bereitstellt. Der Schlüssel ist optional und dient in erster Linie dazu den entsprechenden Input-Wert in der Flußgrafik anzuzeigen sofern man das Attribut flowGraphicControl-&amp;gt;showGenerators=1 setzt. Dadurch ist auch der Eigenverbrauch des Inverters bzw. dessen Wandlungsverlust visuell abschätzbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pvOut=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvOut&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell erzeugte Leistung als positiven Wert liefert. Für einen PV-Wechselrichter (DC-&amp;gt;AC) oder Solar-Ladegerät (DC-&amp;gt;DC) ist es die erzeugte PV-Leistung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ac2dc=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter vom Hausnetz in Richtung Batterie (AC-&amp;gt;DC) wandelt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;dc2ac=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter aus einer Gleichstromquelle, d.h. einer Batterie oder einem Solar-Ladegerät, in Richtung des Hausnetzes (AC) wandelt . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;capacity=&amp;lt;max. WR-Leistung&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In dem Schlüssel &#039;&#039;capacity&#039;&#039; wird die maximal mögliche Leistung in Watt (ohne Einheit) angegeben, die der Wechselrichter lt. seinem Datenblatt in der Lage ist zu leisten. &lt;br /&gt;
&lt;br /&gt;
Die Angabe &#039;&#039;capacity&#039;&#039; hat in erster Linie die Aufgabe, die max. mögliche PV-Leistung für die Prognose zu begrenzen. Oft sind die installierten Peak-Leistungen der PV-Module höher als die angeschlossene Wechselrichter-Leistung bzw. kommt es vor, dass die KI / (korrigierte) API-Prognose über der maximal möglichen Wechselrichter-Leistung liegt. In diesen Fällen wird die Prognose auf die angegebene &#039;&#039;capacity&#039;&#039; begrenzt.&lt;br /&gt;
&lt;br /&gt;
Der Wert in diesem Schlüssel kann, wie andere Schlüssel auch, dynamisch zur Laufzeit mit dem Set-Befehl &amp;quot;[[#Hinweise zur Struktur der Attribute|set &amp;lt;Name&amp;gt; attrKeyVal ...]]&amp;quot; geändert werden. Ein Beispiel zur Anwendung ergibt sich aus folgendem Szenario.&lt;br /&gt;
&lt;br /&gt;
Gegeben sei eine Anlage die aus Solarzellen (1300 W Peak) mit einem Solar-Ladegerät mit max. 1800 W Leistung, einer Batterie und einem Batterie-Wechselrichter besteht. Die Anlage versorgt nur das Hausnetz. Eine Netzeinspeisung ist nicht vorgesehen oder nicht erlaubt.  &lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, es ist ein Tag voller Sonnenschein prognostiziert und die Batterie ist zunächst entladen. Der Haushalt verbraucht 300 W. Dann würden die PV-Module Module ihre volle Leistung von 1300 W Peak leisten können, die sich auch in der Balken-Vorhersage niederschlägt. Die Leistung wird nicht begrenzt, weil:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* sie niedriger ist als die nominale und angegebene Wechselrichter Kapazität von &#039;&#039;capacity=1800&#039;&#039;&lt;br /&gt;
* die erzeugte Energie anteilig für die Verorgung des Hauses und die Aufladung der Batterie verwendet wird&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders verhält es sich wenn nach einer gewissen Zeit die Batterie voll ist und weiterhin volle PV Leistung zur Verfügung steht. In diesem Fall würde der Haushalt seine benötigte Leistung von 300 W abnehmen, aber das Solar-Ladegerät kann keine weitere Leistung mehr abgeben, da die Batterie bereits voll geladen ist, d.h. die Anlagensteuerung würde die PV-Anlage abregeln. In diesem Fall, wenn es einen längeren Zeitraum betrifft, muß auch die Prognose PV-Energie auf 300 Wh (bzw. den durchschnittlichen Energieverbrauch des Hauses pro Stunde) begrenzt werden, damit die PV-Prognose nach unten angepasst wird und so eine realitätsnahere Prognose ermöglicht wird. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;icon=&amp;lt;aktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;][:&amp;lt;inaktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Jeder Wechselrichter wird im Standard durch ein Icon getrennt nach Tag und Nacht, d.h. je nach Aktiv-Status und Inaktiv-Status, symbolisiert.&lt;br /&gt;
&lt;br /&gt;
;Tag bzw. Aktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Sonnensymbol im Standard verwendet. Batterie-Wechselrichter verwenden ein gefärbtes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
;Nacht bzw. Inaktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Symbol der aktuellen Mondphasen im Standard verwendet. Batterie-Wechselrichter verwenden ein ausgegrautes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie angegeben, kann man für Tag und Nacht jeweils ein Wunsch-Icon, wenn gewünscht mit einer alternativen Färbung, auswählen.&lt;br /&gt;
&lt;br /&gt;
 icon=inverter@darkorange:inverter@gray&lt;br /&gt;
&lt;br /&gt;
Soll nur das Icon für die Nacht bzw. Inaktivät geändert werden, kann dies in dieser Form angegeben werden:&lt;br /&gt;
&lt;br /&gt;
 icon=:inverter@gray  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(beachte den führenden &#039;:&#039;)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Der integrierte SolarForecast Grafikbereich ==&lt;br /&gt;
Das SolarForecast Modul beinhaltet eine Grafikdarstellung die sich in mehrere Bereiche gliedert. Diese Bereiche können über Attribute ein- bzw. ausgeblendet sowie die Inhalte festgelegt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 223545.png|right|thumb|400px|Bereiche der integrierten Grafik]]&lt;br /&gt;
&lt;br /&gt;
Der nebenstehende Screenshot gibt die Gliederung der Grafikbereiche wieder:&lt;br /&gt;
&lt;br /&gt;
 1 - der Kopfbereich (Graphic Header)&lt;br /&gt;
 2 - durch den Nutzer selbst definierbarer Inhalt (Graphic Header Own Specification) als Teil des Kopfbereiches&lt;br /&gt;
 3 - Bereich Verbraucherdarstellung (Consumer Legend)&lt;br /&gt;
 4 - Bereich Balkengrafik (Beam Graphic)&lt;br /&gt;
 5 - Energieflußgrafik (Flow Graphic)&lt;br /&gt;
&lt;br /&gt;
Jeder dieser Bereiche hat spezifische Steuerungsattribute zur Anpassung des Verhaltens und ggf. des Inhalts.&lt;br /&gt;
&lt;br /&gt;
=== 1 - Der Grafik Kopfbereich ===&lt;br /&gt;
Im Kopfbereich befinden sich fest verankerte Informationen zur verwendeten Vorhersage-API sowie deren Status, Informationen zum Sonnenaufgang und Sonnenuntergang, dem aktuellen Gesamtstatus des SolarForecast Devices, Abweichungskennzahlen der PV Vorhersage sowie weitere Kennzeichen zur Verfügung.&lt;br /&gt;
Über zwei Drucktasten kann eine Anlagenprüfung durchgeführt und in den Spportthread des Moduls im FHEM Forum abgesprungen werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;graphicHeaderShow&#039;&#039;&#039; kann der gesamte Kopfbereich 1 und 2 (nutzereigener Teilbereich) ausgeblendet werden. Wird der Kopbereich ausgeblendet, ist es hilfreich mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;showLink&#039;&#039;&#039; einen Link zur Detailgrafik einzufügen da der in der Kopfgrafik integrierte Link in diesem Fall nicht mehr zur Verfügung steht. &lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;graphicHeaderDetail&#039;&#039;&#039; definiert welche Bereiche des Grafikkopfes angezeigt werden sollen. Es kann die Anzeige des Energieverbrauches, der PV-Erzeugung und der vom Nutzer selbst definierte Inhalt miteinander frei kombiniert werden.&lt;br /&gt;
&lt;br /&gt;
=== 2 - Der Bereich mit selbst definierbarem Inhalt (Graphic Header Own Specification) ===&lt;br /&gt;
In diesem Bereich kann der User beliebige Readings, Set-Kommandos und Attribute des SolarForecast Devices oder anderer Devices, die sich im gleichen FHEM-System wie das SolarForecast Device befinden, anzeigen lassen.&lt;br /&gt;
&lt;br /&gt;
Dieser Bereich ist als Tabelle mit einer beliebigen Anzahl von Zeilen organisiert. Jede Zeile beinhaltet ein Kommentarfeld und vier Nutzfelder zur Darstellung ausgewähler Werte + Label. Der Bereich bzw. der Inhalt des Bereiches wird mit dem Attribut &#039;&#039;&#039;graphicHeaderOwnspec&#039;&#039;&#039; definiert.  &lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt ein real gesetztes graphicHeaderOwnspec Attribut. Die Leerzeilen sind nicht notwendig, erhöhen aber die Lesbarkeit der Struktur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
Autarkierate:Current_AutarkyRate&lt;br /&gt;
PV&amp;amp;nbsp;übermorgen:special_dayAfterTomorrowPVforecast&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;Sunset:special_todayConForecastTillSunset&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;nächsten&amp;amp;nbsp;Sunrise:special_conForecastTillNextSunrise&lt;br /&gt;
&lt;br /&gt;
#Batterie&lt;br /&gt;
BatteryLive&amp;amp;nbsp;Status:userFn_BatLive_State&lt;br /&gt;
SoC&amp;amp;nbsp;Limit:Settings_CGwacs_BatteryLife_MinimumSocLimit_value@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SoC&amp;amp;nbsp;Ist:SOC_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
SOC&amp;amp;nbsp;Optimum:Battery_OptimumTargetSoC&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
aktuelle&amp;amp;nbsp;Ladung:userFn_Bat_EnergyState&lt;br /&gt;
Verfügbar:userFn_BatLive_UsableEnergy&lt;br /&gt;
benötigte&amp;amp;nbsp;Ladeenergie:userFn_Bat_EnergyRemain&lt;br /&gt;
Ladefreigabe:Battery_ChargeRecommended&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
akt.&amp;amp;nbsp;DC&amp;amp;nbsp;Strom:DC_Current_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
Restladezeit&amp;amp;nbsp;Ziel:userFn_Bat_HoursUntilChargeFinish&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Soll:userFn_Bat_MaxChargeCurrent_set&lt;br /&gt;
:&lt;br /&gt;
&lt;br /&gt;
#Settings&lt;br /&gt;
Batterie&amp;amp;nbsp;Lademanagement:userFn_BatteryChargeManagement&lt;br /&gt;
SoC&amp;amp;nbsp;Management:userFn_BatterySoCManagement&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Ist:MaxChargeCurrent@MQTT2_cerboGX_c0619ab34e08_vebus&lt;br /&gt;
SmartSolar&amp;lt;br&amp;gt;Einspeisung:OvervoltageFeedIn@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
MPII&amp;amp;nbsp;Limit&amp;lt;br&amp;gt;Einspeisung&amp;amp;nbsp;(W):MaxFeedInPower@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SOC&amp;amp;nbsp;Limit&amp;amp;nbsp;Soll:MinimumSocLimit@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Verbr.&amp;amp;nbsp;Neuplanung:consumerNewPlanning&lt;br /&gt;
Wetteranzeige:graphicShowWeather &lt;br /&gt;
&lt;br /&gt;
Anzeige&amp;amp;nbsp;Nachtstunden:graphicShowNight&lt;br /&gt;
hist.&amp;amp;nbsp;Stunden:graphicHistoryHour&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto&lt;br /&gt;
Victron&amp;amp;nbsp;BatteryLife&amp;lt;br&amp;gt;(1=an,10=aus):BatteryLife@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Debug:ctrlDebu&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Kommentarfeld am Beginn einer Zeile wird durch ein &#039;&#039;&#039;#&#039;&#039;&#039; gekennzeichnet. Folgt dem # ein String, wird dieser String als Kommentarangabe gewertet und in der Grafik ausgegeben. Ein leeres Kommentarfeld wird lediglich durch ein # gefolgt von einem Leerzeichen oder NL beschrieben:&lt;br /&gt;
&lt;br /&gt;
 #:&amp;lt;Text&amp;gt;  (bzw nur # für einen &#039;leeren&#039; Titel)&lt;br /&gt;
&lt;br /&gt;
Ein Netzfeld bzw. ein Datensatz wird durch die Angabe von einem Label und dem darzustellenden Wert getrennt durch &#039;:&#039; definiert:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Label&amp;gt;:&amp;lt;Reading, Attribut oder Set-Kommando&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das System erkennt selbständig, ob es sich bei der Angabe um ein Reading, Attribut oder ein Set-Kommando handelt. Sollen Readings, Set-Kommandos und Attribute anderer Devices als dem SolarForecast-Device angezeigt werden, kann dies einfach durch Zusatz von&lt;br /&gt;
&lt;br /&gt;
 ....@&amp;lt;Device-Name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
an den Parameter erreicht werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-12-05 203916.png|right|thumb|400px|Darstellung eigener Grafikbereich]]&lt;br /&gt;
Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten &amp;quot;Wh&amp;quot; bzw. &amp;quot;kWh&amp;quot; werden entsprechend der Einstellung des Attributs &#039;&#039;&#039;graphicEnergyUnit&#039;&#039;&#039; umgerechnet. Im Label sind Leerzeichen durch &amp;quot;&amp;amp;amp;nbsp;&amp;quot; einzufügen, ein Zeilenumbruch durch &amp;quot;&amp;amp;lt;br&amp;amp;gt;&amp;quot;. Ein leeres Feld in einer Zeile wird durch &amp;quot;:&amp;quot; ohne eine weitere Angabe erzeugt.&lt;br /&gt;
&lt;br /&gt;
Die nebenstehende Abbildung zeigt die reale Darstellung der oben angegebenen Struktur im Attribut graphicHeaderOwnspec.&lt;br /&gt;
&lt;br /&gt;
==== Formatierung der Inhalte im Bereich &amp;quot;Graphic Header Own Specification&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
Die angezeigten Inhalte, wie z.B. Readingwerte, des User eigenen Bereiches (Attribut graphicHeaderOwnspec) können durch Spezifikationen im Attribut &#039;&#039;&#039;graphicHeaderOwnspecValForm&#039;&#039;&#039; manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
Die Online-Hilfe zum Attribut graphicHeaderOwnspecValForm erläutert die verfügbaren Möglichkeiten und Optionen.&lt;br /&gt;
Als Beispiel hier einige mögliche Notationen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &#039;userFn_Bat_HoursUntilChargeFinish&#039;                        =&amp;gt; &amp;quot;($VALUE).&#039; Stunden&#039;&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_battery.SOC_value&#039;             =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Settings_CGwacs_BatteryLife_MinimumSocLimit_value&#039;        =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Info_MaxChargeCurrent_value&#039;                              =&amp;gt; &amp;quot;($VALUE).&#039; A&#039;&amp;quot;,&lt;br /&gt;
  &#039;DC_Current_value&#039;                                         =&amp;gt; &amp;quot;%.0f A&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common.Regulated&#039; =&amp;gt; &amp;quot;($VALUE eq &#039;1&#039; ? &#039;Ja&#039; : &#039;Nein&#039;)&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine Besonderheit besteht bei darzustellenden Werten die die Einheiten &#039;Wh&#039; bzw. &#039;kWh&#039; besitzen. Diese Werte und Einheiten werden automatisch entsprechend des gesetzten Attributes graphicEnergyUnit umgerechnet und angezeigt.&lt;br /&gt;
&lt;br /&gt;
Soll in diesen Fällen eine automatische Formatierung umgangen werden, kann eine solche Notation verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &#039;Today_PVforecast&#039; =&amp;gt; &amp;quot;(sprintf &#039;%.1f &amp;amp;amp;nbsp;kWh&#039;, ($VALUE / 1000))&amp;quot;,&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Die Angabe von &amp;amp;amp;nbsp; vor &#039;kWh&#039; verhindert die Erkennung der Einheit und so auch die automatische Umsetzung durch das Modul. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 3 - Bereich Verbraucherdarstellung (Consumer Legend) ===&lt;br /&gt;
Dieser Grafikbereich zeigt die im Modul registrierten Verbraucher sowie deren Status und weitere Informationen an. Sind die Voraussetzungen gegeben, d.h. entsprechende Schlüssel in der ConsumerXX-Attributen gesetzt, können die Verbraucher über das Paneel manuell geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Zur Anpassung der Darstellung sind verschiedene Attribute verfügbar:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;consumerControl-&amp;gt;showLegend: Definiert die Lage bzw. Darstellungsweise der Verbraucherlegende sofern Verbraucher im SolarForecast Device registriert sind.&lt;br /&gt;
;consumerControl-&amp;gt;adviceIcon: Definiert die Art der Information über die geplanten Schaltzeiten eines Verbrauchers in der Verbraucherlegende. &lt;br /&gt;
;consumerControl-&amp;gt;detailLink: Wenn gesetzt, ist der jeweilige Verbraucher klickbar um direkt zur Detailansicht des jeweiligen Geräts auf einer neuen Browserseite zu gelangen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Standard wird das Verbraucherpaneel zwischen dem Kopfbereich und der ersten Balkengrafik Ebene dargestellt. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;showLegend&#039;&#039;&#039; und Argument &#039;&#039;&#039;icon_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_bottom&#039;&#039;&#039; kann das Verbraucherpaneel an das Ende des Grafikbereiches verschoben werden.&lt;br /&gt;
Die Verwendung von &#039;&#039;&#039;text_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_top&#039;&#039;&#039; blendet die Icon-Spalte im Verbraucherpaneel aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Screenshot 2025-02-08 093239.png|Darstellung mit consumerControl showLegend=icon_top (default)&lt;br /&gt;
File:Screenshot 2025-02-08 093646.png|Darstellung mit consumerControl showLegend=icon_bottom&lt;br /&gt;
File:Screenshot 2025-02-08 152018.png|Darstellung mit consumerControl showLegend=text_top bzw. text_bottom&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 213634.png|right|thumb|400px|]]&lt;br /&gt;
Ein Mouse-Over über das Uhrensymbol zeigt nähere Informationen zum Status, den Planungsdaten, Modus und weitere Daten des Verbrauchers. Der Schalter &amp;quot;Aus/Ein&amp;quot; visualisiert den Schaltzustand des Verbrauchers und können auch zum manuellen Schalten des Verbrauchers dienen. Voraussetzung ist, dass im consumer-Attribut die Schlüssel &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; mit den Set-Kommandos zum Schalten des Verbrauchers defininiert sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 222210.png|right|thumb|300px|]]&lt;br /&gt;
Der Auto-Schieberegler zeigt einerseits den Freigabestatus zum Schalten des Verbrauchers durch das SolarForecast Modul und kann andererseits manuell betätigt werden. Der Status des Reglers korrespondiert mit dem im zugehörigen Consumer Attribut vorhandenen Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; angegebenen Reading-Wert.&lt;br /&gt;
&lt;br /&gt;
Die Verbraucherbezeichnungen in dem Paneel können in der Standardkonfiguration angeklickt werden um direkt zur Detailansicht des Devices zu gelangen. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;detailLink&#039;&#039;&#039; kann der Link zur Detailansicht deaktiviert werden.&lt;br /&gt;
&lt;br /&gt;
Das Uhrensymbol kann mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;adviceIcon&#039;&#039;&#039; geändert und/oder dessen Farbe angepasst, sowie einen Informationstext statt eines Icons angezeigt werden. &lt;br /&gt;
&lt;br /&gt;
=== 4 - Bereich Balkengrafik (Beam Graphic) ===&lt;br /&gt;
&lt;br /&gt;
Die Balkengrafik des Moduls ist ein wesentliches Visualisierungshilfsmittel. Im Auslieferungszustand existiert eine Balkengrafikebene, die &#039;&#039;&#039;Ebene 1&#039;&#039;&#039;.&lt;br /&gt;
Jede Ebene kann zwei Balkendiagramme mit auswählbaren Inhalten, Farben und einstellbarem LayoutTyp darstellen. In Ebene 1 kann die Wettervorhersage eingebettet oder, bei Vorhandensein von Batteriegeräten, die zukünftigen Zeiten mit empfohlener Ladefreigabe und SoC-Prognose eingeblendet werden. &lt;br /&gt;
&lt;br /&gt;
Welche Daten in welchen Zeiträumen dargestellt werden sollen, die Bestimmung des Layouts, die Gestaltung der Balken und einiges mehr wird durch Attribute gesteuert. Ein Teil dieser Einstellungen wird über das zusammengesetzete Attribut &#039;&#039;&#039;graphicControl-&amp;gt;&#039;Schlüssel&#039;=&#039;Wert&#039;&#039;&#039;&#039; eingestellt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;grundsätzliche Layout Definitionen&#039;&#039;&#039;&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204342.png|right|thumb|400px|Standardanzeige mit Wetter-Icons, gesetzen Attributen graphicBeam1Color=D4C177, graphicHistoryHour=11]]&lt;br /&gt;
&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingTop:Legt den Platz in px im Balkendiagramm fest, der zwischen dem oberen Rand der jeweiligen Balkengrafik Ebene und der ersten Text- oder Iconreihe dieser Ebene eingefügt wird.&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingBottom:Legt den Platz in px im Balkendiagramm fest, der zwischen der letzten Text- oder Iconreihe der jeweiligen Balkengrafik Ebene und dem unteren Rand dieser Ebene eingefügt wird. &lt;br /&gt;
;graphicControl-&amp;gt;layoutType:Layout-Optionen zur grundlegenden Gestaltung der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourStyle:Format der Zeitangabe in der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourCount:Anzahl der darzustellenden Balken/Stunden in der Balkengrafk&lt;br /&gt;
[[Datei:Screenshot Screenshot 2025-05-21 153613.png|right|thumb|400px|Erweiterung des oberen und unteren Abstandes mit den Attributen graphicControl-&amp;gt;beamPaddingTop und graphicControl-&amp;gt;beamPaddingBottom]]&lt;br /&gt;
;graphicControl-&amp;gt;energyUnit:definiert die Einheit zur Anzeige der elektrischen Leistung in der Grafik&lt;br /&gt;
;graphicHistoryHour:Anzahl der vorangegangenen Stunden die in der Balkengrafik dargestellt werden&lt;br /&gt;
;graphicControl-&amp;gt;beamWidth:Vorgabe Breite der Balken der Balkengrafik in px (sonst automatische Bestimmung) &lt;br /&gt;
;graphicBeamHeightLevel1:Multiplikator zur Festlegung der maximalen Balkenhöhe der jeweiligen Ebene (hier Ebene 1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;Definition der Inhalte und Balkeneigenschaften&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204756.png|right|thumb|400px|Wie oben aber mit gesetzem Attribut graphicShowNight=1]]&lt;br /&gt;
;graphicBeam1Color:Farbauswahl des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2Color:Farbauswahl des sekundären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam1Content:Legt den darzustellenden Inhalt des primären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam2Content:Legt den darzustellenden Inhalt des sekundären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam1FontColor:Auswahl der Schriftfarbe des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2FontColor:Auswahl der Schriftfarbe des sekundären Balkens (Ebene 1)&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 205024.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=0 (ohne Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;zusätzliche Optionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;graphicShowNight:Anzeigen oder Verbergen der Nachtstunden in der Balkengrafik&lt;br /&gt;
;graphicShowWeather:Wettericons in der Balkengrafik anzeigen/verbergen (nur Ebene 1)&lt;br /&gt;
;graphicWeatherColor:Farbe der Wetter-Icons für die Tagesstunden&lt;br /&gt;
;graphicWeatherColorNight:Farbe der Wetter-Icons für die Nachtstunden&lt;br /&gt;
;graphicShowDiff:Zusätzliche Anzeige der Differenz &amp;quot;&amp;lt;primärer Balkeninhalt&amp;gt; - &amp;lt;sekundärer Balkeninhalt&amp;gt;&amp;quot; im Kopf- oder Fußbereich der Balkengrafik&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die genaue Beschreibung und deren Optionen sind der aktuellen Online-Hilfe zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Für alle Ebenen gilt:&#039;&#039;&#039; Ein Attribut mit einer ungeraden Balkennummer (z.B. graphicBeam1Content) bezieht sich immer auf den primären Balken, ein Attribut mit einer geraden Balkennummer (z.B. graphicBeam2Content) bezieht sich immer auf den sekundären Balken.&lt;br /&gt;
&lt;br /&gt;
Die Balken haben, wie die meisten Elemente in der Balkengrafik, eine Mouse-Over Eigenschaft welche relevante Informationen zu den dargestellten Werten anzeigt. &lt;br /&gt;
&lt;br /&gt;
Sind die Nachtunden mit &#039;&#039;&#039;graphicShowNight&#039;&#039;&#039; ausgeblendet, werden keine Balken angezeigt sofern es keine Werte anzuzeigen gibt. Sollten dennoch Werte ungleich 0 anzuzeigen sein, werden diese Werte auch trotz ausgeblendeter Nachstunden angezeigt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 2 ====&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 211741.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=01 (mit Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 2&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam3Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam4Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 4 für Balken 4) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wetter-Icons können nur in Ebene 1 integriert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 2 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 2 gibt, eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgende Ebene.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 3 ====&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 3&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam5Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam6Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 5 für Balken 5) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 3 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 3 gibt, ist eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgenden Ebenen, d.h. auch auf die Ebene 3.&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 5 - Die Energieflußgrafik (Flow Graphic) ===&lt;br /&gt;
[[Datei:Screenshot 2025-02-13 213424.png|right|thumb|400px|Energieflußgrafik mit Verbrauchern in der Nachtdarstellung (Mondphasen) nach Sonnenuntergang]]&lt;br /&gt;
&lt;br /&gt;
Die Energieflußgrafik stellt die registrierten Erzeuger, Batterien, Netzzugänge und Verbraucher strukturiert in mehreren Ebenen dar:&lt;br /&gt;
&lt;br /&gt;
;Ebene 1: In der oberen Ebene befinden sich die PV-Generatoren, Smart-Loader sowie sonstigen Erzeuger &lt;br /&gt;
;Ebene 2: Die mittlere Ebene organisiert den Zugang zum öffentlichen Netz, dem Hausknoten, dem Batterieknoten sowie einem Dummy-Verbraucher (Lampensymbol) für den Energieverbrauch des Hauses der keinem der registrierten Verbraucher zugeordnet werden kann.&lt;br /&gt;
;Ebene 3: In der unteren Ebene werden die registrierten Verbraucher dargestellt. Unterhalb der Verbrauchersymbole werden der aktuelle Verbrauch (bzw. der On/Off-Zustand) sowie darunter die Restlaufzeit (Minuten) des Verbrauchers, sofern er durch das Modul geplant und gestartet wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Position und Gestaltung der Grafikelemente ist umfangreich über das Attribut &#039;&#039;&#039;flowGraphicControl&#039;&#039;&#039; und den darin verfügbaren Schlüsseln einstellbar.&lt;br /&gt;
Die Bedeutung der Schlüssel ist in der Online-Hilfe zum Attribut mit einem Beispiel beschrieben. &lt;br /&gt;
&lt;br /&gt;
Darüber hinaus enthalten die Setup-Attribute &#039;&#039;&#039;setupInverterDevXX&#039;&#039;&#039;, &#039;&#039;&#039;setupOtherProducerXX&#039;&#039;&#039; und &#039;&#039;&#039;consumerXX&#039;&#039;&#039; weitere Einstellungsmöglichkeiten um deren Icons und Färbungen in der Flußgrafik individuell einstellen zu können. So sind zum Beispiel die Icons der PV-Inverter und deren Färbung mit dem Schlüssel &#039;&#039;&#039;icon&#039;&#039;&#039; der setupInverterDevXX-Attribute in Abhängigkeit von Tag und Nacht separat definierbar.&lt;br /&gt;
&lt;br /&gt;
In den Verbraucher-Attributen ist mit dem Schlüssel &#039;&#039;&#039;noshow&#039;&#039;&#039; die Sichtbarkeit in der Flußgrafik definierbar.&lt;br /&gt;
&lt;br /&gt;
Generell steuert das Attribut &#039;&#039;&#039;graphicSelect&#039;&#039;&#039; die Ein- bzw. Ausblendung der gesamten Flußgrafik.&lt;br /&gt;
&lt;br /&gt;
== Die Verbrauchsprognose ==&lt;br /&gt;
Im Gegensatz zu der PV Prognose gibt es keine API oder andere externen Datenquellen die für die Verbrauchsprognose herangezogen werden könnten.&lt;br /&gt;
&lt;br /&gt;
Zum Zweck der Verbrauchsermittlung verwendet das Modul die Meterdaten aus dem Attribut &#039;&#039;setupMeterDev&#039;&#039; sowie den weiteren setup-Attributen &#039;&#039;setupInverterDevXX&#039;&#039;. &lt;br /&gt;
Sind auch andere Erzeuger (BHKW, Windanlagen, etc.) bzw. eine Batterie vorhanden, sind ebenfalls die Attribute &#039;&#039;setupOtherProducerXX&#039;&#039; bzw. &#039;&#039;setupBatteryDev&#039;&#039; für die Berechnung des Hausverbrauchs relevant. In diesen Attributen gibt es die Schlüssel &#039;&#039;*total&#039;&#039; die teilweise optional sind. Für die Verbrauchsprognose bilden sie jedoch die Berechnungsgrundlage und sind deswegen für diese Funktionalität wichtig anzugeben.&lt;br /&gt;
&lt;br /&gt;
Die Verbrauchswerte werden stundengenau erfasst und im Datenspeicher &#039;&#039;pvHistory&#039;&#039; für 31 Tage, sowie im Datenspeicher &#039;&#039;pvCircular&#039;&#039; 210 Tage gespeichert. Die beiden Datenspeicher übernehmen unterschiedliche Aufgaben im Rahmen der Prognoseerstellung. Auf Grundlage der gespeicherten und somit historischen Verbrauchswerte erstellt das Modul eine Prognose für die kommende Zeit.&lt;br /&gt;
&lt;br /&gt;
Mit dem Kommando &lt;br /&gt;
&lt;br /&gt;
   &amp;quot;get ... pvHistory [Tag]&amp;quot; &lt;br /&gt;
&lt;br /&gt;
wird der Inhalt aufgelistet. Die Schlüssel &#039;&#039;confc&#039;&#039;, &#039;&#039;con&#039;&#039; und &#039;&#039;gcon&#039;&#039; zeigen die Verbrauchsprognose, den Verbrauch und den Netzbezug der jeweiligen Stunde des gewählten Tages.&lt;br /&gt;
Die Stunde &amp;quot;99&amp;quot; zeigt die Summen dieser Schlüsssel für den Tag:&lt;br /&gt;
&lt;br /&gt;
      99 =&amp;gt; etotal: , pvfc: 782, pvrl: 0, rad1h: -&lt;br /&gt;
            confc: 14540, con: 13873, gcon: 13873, gfeedin: 0&lt;br /&gt;
            batintotal: , batin: 0, batouttotal: , batout: 0&lt;br /&gt;
            batmaxsoc: -, batsetsoc: -&lt;br /&gt;
            wid: , wcc: , wrp: , pvcorrf: , dayname: So&lt;br /&gt;
            cyclescsm01: 0&lt;br /&gt;
            cyclescsm02: 0&lt;br /&gt;
            cyclescsm03: 0&lt;br /&gt;
            cyclescsm04: 1, hourscsme04: 0.00&lt;br /&gt;
            cyclescsm05: 0&lt;br /&gt;
            cyclescsm06: 0&lt;br /&gt;
            cyclescsm07: 1, hourscsme07: 0.00&lt;br /&gt;
            cyclescsm08: 1, hourscsme08: 0.00&lt;br /&gt;
            cyclescsm09: 1, hourscsme09: 0.03 &lt;br /&gt;
&lt;br /&gt;
In dem Beispiel wurden für den Tag 14540 Wh Verbrauch prognostiziert, 13873 Wh tatsächlich verbraucht und davon 13873 Wh aus dem Netz bezogen. Leider war an diesem Tag keinerlei PV Ertrag vorhanden, was man auch an dem Schlüssel &#039;&#039;pvrl&#039;&#039; erkennen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Inhalt des pvCircular-Speichers kann mit dem Befehl  &lt;br /&gt;
&lt;br /&gt;
     &amp;quot;get ... pvCircular [Tag]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Das nachfolgende Beispiel zeigt die Ausgabe für die Tagesstunde 23:&lt;br /&gt;
&lt;br /&gt;
 23 =&amp;gt; pvapifc: 0, pvaifc: -, pvfc: 0, aihit: 0, pvrl: 0&lt;br /&gt;
       batin01: 0, batin02: -, batin03: -&lt;br /&gt;
       batout01: 619, batout02: -, batout03: -&lt;br /&gt;
       confc: 650, gcon: 23, gfeedin: 0, wcc: 40, rr1c: 0.00&lt;br /&gt;
       temp: -6.00, wid: 100, wtxt: Bewölkungsentwicklung nicht beobachtet&lt;br /&gt;
       pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
       ... &lt;br /&gt;
       con_all =&amp;gt; Sa  @ 617 762&lt;br /&gt;
                  Di  @ 693 645&lt;br /&gt;
                  Mo  @ 620 679&lt;br /&gt;
                  So  @ 669 666 636&lt;br /&gt;
                  Mi  @ 701 626&lt;br /&gt;
                  Do  @ 612 642&lt;br /&gt;
                  Fr  @ 615 606&lt;br /&gt;
&lt;br /&gt;
Der Schüssel &#039;&#039;con_all&#039;&#039; enthält einen Hash aus Arrays die für jeden Wochentag (Mo..So) bis zu 30 Verbrauchswerte (in Wh) für die angezeigte Stunde speichern. Wie hier erkennbar ist, wurden an den drei vergangenen Sonntagen jweils 669 Wh, 666 Wh bzw. 636 Wh in der Stunde 23 (22:00-22:59) verbraucht.&lt;br /&gt;
Der Median aus diesen Werten geht in die Verbrauchsprognose ein. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wochentagsnamen Mo..So sind von den installierten Locales auf Betriebsystemebene abhängig. Ist keine deutsche locale installiert, werden die englischen Wochentagsnamen Mon..Sun verwendet. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Wie wird der Verbrauch des Hauses ermittelt und gespeichert? ===&lt;br /&gt;
Die Verbrauchsdaten des Hauses werden auf Stundenbasis ermittelt und gespeichert. Das &amp;quot;Haus&amp;quot; steht als Synonym aller im Kontext des Solarforecast Devices zusammengeführten Inverter (setupInverterDevXX), sonstigen Erzeuger (setupOtherProducerXX), Netzanschlüsse (setupMeterDev), Verbraucher (consumerXX) und Batterien (setupBatteryDev).&lt;br /&gt;
&lt;br /&gt;
Alle diese Daten werden durch das Modul mit jedem ausgeführten Zyklus (Attribut plantControl-&amp;gt;cycleInterval) und, wenn ein Event eines als &#039;asynchron&#039; definierten Devices auftritt, gesammelt und daraus permanent ein aktualisierter Verbrauch berechnet. Die Berechnung beschreibt folgende Formel:&lt;br /&gt;
&lt;br /&gt;
 PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung - Verbrauch = 0&lt;br /&gt;
&lt;br /&gt;
bzw.&lt;br /&gt;
 &lt;br /&gt;
 Verbrauch (Wh) = PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung&lt;br /&gt;
            con = PV           + PP                 - GridIn          + GridCon   - BatIn          + BatOut&lt;br /&gt;
&lt;br /&gt;
Die PV-Erzeugung beinhaltet die Summe aller durch die angegebnen Inverter (setupInverterDev01 .. setupInverterDevXX) erzeugten Energien. Die &amp;quot;sonstige Erzeugung&amp;quot; summiert sich aus den Werten aller angegebenen Producer (setupOtherProducer01 .. setupOtherProducerXX). Der Verbrauch wird durch die registrierten Geräte consumerXX teilweise direkt erfasst, ist aber grundsätzlich unvollständig da nicht alle Verbrauchswerte im &amp;quot;Haus&amp;quot; gemessen und durch das Modul erfasst werden können.&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel zeigt das Ergebnis bei 300 Wh PV-Erzeugung und gleichzeitige 500 Wh Netzbezug:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 300 + 0 - 0 + 500 - 0 + 0 = 800 Wh&lt;br /&gt;
&lt;br /&gt;
Bei 1300Wh PV-Erzeugung, 100 Wh Netzeinspeisung sowie 200 Wh Batterieladung ergibt sich der Verbrauch zu:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 1300 + 0 - 100 + 0 - 200 + 0 = 1000 Wh&lt;br /&gt;
&lt;br /&gt;
Ohne Erzeugung, aber mit der Energielieferung von 500 Wh aus der Batterie, 800 Wh Netzbezug (mit einem Anteil Batterienachladung aus dem Netz von 200 Wh) sieht die Verbrauchsrechnung wie folgt aus: &lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 0 + 0 - 0 + 800 - 200 + 500 = 1100 Wh&lt;br /&gt;
&lt;br /&gt;
Der so ermittelte Verbrauchsert wird mit jedem Zyklus in der pvHistory im Schlüssel &amp;quot;con&amp;quot; gespeichert. Man kann sich die gespeicherten Werte mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;name&amp;gt; pvHistory [&amp;lt;Tag&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Nachfolgendes Beispiel zeigt einen Datensatz für die Stunde 8 eines Tages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      08 =&amp;gt; pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotali01: 62940734, etotali02: 2928860, etotali03: -&lt;br /&gt;
            pvrl01: 0, pvrl02: 0, pvrl03: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 630, con: 962, gcons: 962, conprice: 0.2958&lt;br /&gt;
            gfeedin: 0, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 120, sunalt: -3&lt;br /&gt;
            batintotal: 3713815.07742543, batouttotal: 3604468.26993988, batin: 0, batout: 0&lt;br /&gt;
            wid: 161, wcc: 89, rr1c: 0.00, pvcorrf: 0.27/0.00 temp: 7.40, &lt;br /&gt;
            csmt01: 110996.12, csme01: 32.1399999999994, minutescsm01: 30&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 2513.67, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1581293.6, csme04: 136.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 1662.17, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 90.53, csme06: 0, minutescsm06: 0&lt;br /&gt;
            csmt07: 39.75, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 38050, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 131627, csme09: 33.2000000000116, minutescsm09: 39&lt;br /&gt;
            minutescsm10: 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Schlüssel &amp;quot;con&amp;quot; ist der gespeicherte Verbrauch von 962 Wh ersichtlich.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit bekommt man mit dem Attribut &#039;&#039;ctrlDebug=collectData&#039;&#039; einen Einblick in die Verbrauchsermittlung bei jedem Zyklus und kann so die Eingangswerte und das daraus resultierende Ergebnis im FHEM Log nachverfolgen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
2024.11.28 11:38:20.080 1: SolCast DEBUG&amp;gt; EnergyConsumption input -&amp;gt; PV: 96, PP: 0, GridIn: 0, GridCon: 582, BatIn: 5, BatOut: 0&lt;br /&gt;
2024.11.28 11:38:20.081 1: SolCast DEBUG&amp;gt; EnergyConsumption result -&amp;gt; 673 Wh&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie wird die Verbrauchsprognose erstellt? ===&lt;br /&gt;
&lt;br /&gt;
Aus den gespeicherten con-Werten (Verbrauchsdaten) der pvCircular (Schlüssel con_all) sowie Einträgen der pvHistory wird der Median der historischen Tage ermittelt und für den kommenden Tag bzw. die kommen Stunden zur Prognose angewendet. Dabei geht per default jeder verfügbare historische Tag gleichberechtigt in die Prognose ein. Mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039; kann festgelegt werden, dass nur gleiche Wochentage (Mo..So) für die Prognose verwendet werden. Hierbei spielt die Vermutung, dass das Verbrauchsverhalten eine gewisse Korrelation zum Wochentag hat, eine Rolle. &lt;br /&gt;
&lt;br /&gt;
Verwendet man die Einstellung consForecastIdentWeekdays=1, hat es sich als vorteilhaft erwiesen, das Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays&#039;&#039;&#039; auf einen niedrigeren Wert als den Default zu setzen. Eine Einstellung auf &#039;8&#039; zum Beispiel verwendet den Median der gleichen Wochentage der vergangenenen 8 Wochen. Dadurch wird nicht zu weit in die Vergangenheit verzweigt und so eine langsame Veränderung des Verbrauchsmedian, zum Beispiel hervorgerufen durch den Übergang vom Winter in das Frühjahr hinein, abgebildet.&lt;br /&gt;
&lt;br /&gt;
Weiteren Einfluß auf die Verbrauchsprognose kann mit dem Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; im Consumerattribut genommen werden. Insbesondere bei der unregelmäßigen Nutzung von Verbrauchern mit hoher Leistung kann die Projektion der aufgezeichneten historischen Werte in die Prognose zu unverhältnismäßig hohen Verbrauchswerwartunden führen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Möglicherweise führt in Fällen die Verwendung eine der nachfolgenden Optionen zu einem besseren Ergebnis:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;1 -&#039;&#039;&#039; die allgemeine Verbrauchsprognose wird um die gespeicherten Energieverbrauchsanteile reduziert.&lt;br /&gt;
* &#039;&#039;&#039;2 -&#039;&#039;&#039; wie bei &#039;1&#039;, jedoch gehen die Planungsdaten des Verbrauchers bei der Prognose der kommenden Stunden wieder mit ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;&#039;exconfc&#039;&#039;&#039; in einem der Consumer verwendet, sollte&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays=4&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
eingestellt werden. Hintergrund ist, dass die Verbrauchsanteile der jeweiligen Verbraucher nur maximal 31 Tage in der pvHistory verfügbar sind. Für längere Zeiträume stehen nur Gesamtsummen des Verbrauchs in der pvCircular zu Verfügung.  &lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=1&#039;&#039;&#039; werden die in der Historie aufgezeichneten Verbrauchsbestandteile aus einer Prognose herausgerechnet. Konkret werden die in der pvHistory aufgezeichneten Verbrauchsbestandteile für die relevante Stunde ermittelt und daraus ein Durchschnitt gebildet der vom Prognosewert subtrahiert wird. Mit dem Attributwert plantControl-&amp;gt;consForecastIdentWeekdays=1 werden wiederum nur identische Wochentage (Mo .. So) zusammengefasst.&lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=2&#039;&#039;&#039; erfolgt ebenso die Eliminierung des Verbrauchsanteils, es wird jedoch auf die Planungsdaten für diesen Verbraucher zugegriffen und die geplanten Energieanteile wiederum der Verbrauchsprognose für die kommenden Stunden hinzugerechnet.&lt;br /&gt;
&lt;br /&gt;
In beiden Anwendungsfällen ist es notwendig, dass dem Modul durch die Angabe entsprechender Readings der Energieverbrauch im Setup des Consumers bekannt gemacht wird damit diese Energieanteile registriert werden können. Allgemein funktioniert die Verbrauchsprognose gut wenn Verbrauchsprozesse regelmäßig in einem wiederkehrenden Zeitraster ablaufen, der Verbrauch durch persönliche Rituale bestimmt ist. So zum Beispiel könnte am Dienstag und Samstag gewöhnlich die Waschmaschine laufen, das E-Auto täglich aufgeladen werden und gebügelt wird oft am Sonntag Nachmittag.&lt;br /&gt;
&lt;br /&gt;
Unregelmäßige Nutzung, vor allem vom Großverbrauchern, lässt sich nur sehr schwer und ungenügend auf zukünftige Verbrauchsprognosen projizieren.&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis der Prognose wird im Kopf der Grafik in der Zeile &#039;&#039;Verbrauch&#039;&#039; sowie in diversen Readings wie &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RestOfDayConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den Rest des Tages)&lt;br /&gt;
* &#039;&#039;&#039;NextHours_Sum04_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für die nächsten 4 Stunden)&lt;br /&gt;
* &#039;&#039;&#039;Tomorrow_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den kommenden Tag)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
angezeigt.&lt;br /&gt;
&lt;br /&gt;
Weitere Aggregationen kann man sich über das Attribut &#039;&#039;&#039;ctrlStatisticReadings&#039;&#039;&#039; bei Bedarf zuschalten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;conForecastTillNextSunrise&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
* &#039;&#039;&#039;todayConForecastTillSunset&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
* &#039;&#039;&#039;todayConsumptionForecast&#039;&#039;&#039; - Verbrauchsprognose aufgesplittet pro Stunde des aktuellen Tages (01-24) &lt;br /&gt;
 &lt;br /&gt;
==== Debugging der Verbrauchsprognose ====&lt;br /&gt;
Um sich einen Einblick über die Erstellung der Verbrauchsprognose zu verschaffen, bietet sich die Einschaltung von:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
an. Mit diesem gesetzten Attribut wird die Erstellung der Prognose im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; ################### Start Consumption forecast ###################&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; Basics - installed locale: de_DE.UTF-8, used scheme: DE&lt;br /&gt;
2025.02.27 19:52:00.064 1: SolCast DEBUG&amp;gt; process Today dayname: Do, Tomorrow dayname: Fr&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 01 - 74.43 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 10 - 290.77 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 24 - 660.70 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 20, hod: 07 - 459.93 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;07&#039; register for exclude day 20, hod: 02 - 0.33 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 30, hod: 08 - 264.78 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next Hours (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; excl. hist 74 Wh for Hour 01, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; estimated cons of Hour 01: 436 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; excl. hist 0 Wh for Hour 02, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 02: 428 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 03: 458 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 04: 503 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 05: 489 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 06: 482 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; excl. hist 460 Wh for Hour 07, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 07: 274 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 265 Wh for Hour 08, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 08: 441 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 09: 558 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 291 Wh for Hour 10, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 10: 443 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 11: 881 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 12: 794 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 13: 840 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 14: 660 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 15: 812 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 16: 752 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 17: 597 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 18: 652 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 19: 634 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 20: 628 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 21: 713 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 22: 596 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 23: 629 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; excl. hist 661 Wh for Hour 24, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons of Hour 24: 660 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons Tomorrow: 16848 Wh, Individual hourly values considered: 72, exclude: 0 Wh (avg of 0 entities)&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Store Consumption forecast values (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour00&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;20&#039; confc: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour01&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;21&#039; confc: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour02&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;22&#039; confc: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour03&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;23&#039; confc: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store &#039;NextHour04&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;24&#039; confc: 660&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour05&#039; hod &#039;01&#039; confc: 436, confcEx: 436&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour06&#039; hod &#039;02&#039; confc: 428, confcEx: 428&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour07&#039; hod &#039;03&#039; confc: 458, confcEx: 458&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour08&#039; hod &#039;04&#039; confc: 503, confcEx: 503&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour09&#039; hod &#039;05&#039; confc: 489, confcEx: 489&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour10&#039; hod &#039;06&#039; confc: 482, confcEx: 482&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour11&#039; hod &#039;07&#039; confc: 274, confcEx: 274&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour12&#039; hod &#039;08&#039; confc: 441, confcEx: 441&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour13&#039; hod &#039;09&#039; confc: 558, confcEx: 558&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour14&#039; hod &#039;10&#039; confc: 443, confcEx: 443&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour15&#039; hod &#039;11&#039; confc: 881, confcEx: 881&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour16&#039; hod &#039;12&#039; confc: 794, confcEx: 794&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour17&#039; hod &#039;13&#039; confc: 840, confcEx: 840&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour18&#039; hod &#039;14&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour19&#039; hod &#039;15&#039; confc: 812, confcEx: 812&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour20&#039; hod &#039;16&#039; confc: 752, confcEx: 752&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour21&#039; hod &#039;17&#039; confc: 597, confcEx: 597&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour22&#039; hod &#039;18&#039; confc: 652, confcEx: 652&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour23&#039; hod &#039;19&#039; confc: 634, confcEx: 634&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour24&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour25&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour26&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour27&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour28&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; consumption calculated - day: 27, hod: 20, con: 574 Wh&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; write pvCircular consumption - hod: 99, todayConsumption: 11210 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe startet mit &#039;&#039;&amp;quot;Start Consumption forecast&#039;&#039;&amp;quot;, es werden die zu exkludierenden historischen Daten für jeden Consumer bzgl. jedem Tag (day) und Stunde des Tages (hod) getrennt registriert. Diese Werte werden durch die gespeicherte Einträge in der pvHistory (max. 31 historische Tage) geliefert. &lt;br /&gt;
&lt;br /&gt;
Im nächsten Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next Hours (new median)&amp;quot;&#039;&#039; werden die Prognosen für die nächsten Stunden kalkuliert und die zuvor registrierten Excludes angewendet. Die Prognose für den kommenden Tag ist im Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next day (new median)&amp;quot;&#039;&#039; protokolliert. Die Prognose für den kommenden Tag ist nicht einfach die Summe der Prognose der nächsten Stunden, denn in den kommenden Stunden werden auch die verfügbaren Planungen der Consumer einbezogen. Für den kommenden Tag können diese Werte unter Umständen nicht einbezogen werden da sie zum Zeitpunkt X noch nicht verfügbar sind.&lt;br /&gt;
&lt;br /&gt;
Im Abschnitt &#039;&#039;&amp;quot;Store Consumption forecast values (new median)&amp;quot;&#039;&#039; erscheinen die effektiv gespeicherten Werte. Diese sind die Grandlage für die grafische Darstellung sowie weiteren Kalkulationen.&lt;br /&gt;
&lt;br /&gt;
=== Wie kann eine fehlerhafte Verbrauchsprognose korrigiert werden? ===&lt;br /&gt;
Wie im vorherigen Abschnitt beschrieben, wird die Prognose aus den gespeicherten &amp;quot;con&amp;quot;-Werten der vergangenen Tage (bzw. Stunden) abgeleitet. &lt;br /&gt;
Grundsätzlich muß zunächst sichergestellt werden, dass die auszulesenden Readings der angegebenen Energiezähler sowie deren Einheiten! korrekt eingestellt sind. Das gilt ebenfalls für die registrierten Verbraucher im Modul.&lt;br /&gt;
&lt;br /&gt;
Für einen ersten Überblick bietet sich das Debug Attribut an zu setzen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
Beispielausgabe des Debug:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2024.09.21 13:28:27.041 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day ###################&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;01&amp;lt; considering possible exclusions: 14082&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;08&amp;lt; considering possible exclusions: 16446&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;15&amp;lt; considering possible exclusions: 14568&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;25&amp;lt; considering possible exclusions: 15522&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; estimated Consumption for tomorrow: 15154, days for avg: 4&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next hours ###################&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 14 -&amp;gt; 850 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 14 -&amp;gt; 643 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 14 -&amp;gt; 590 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 14 -&amp;gt; 522 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 13:00:00, confc: 651, days for avg: 4, hist. consumption registered consumers: 560.97&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 15 -&amp;gt; 720 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 15 -&amp;gt; 743 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 15 -&amp;gt; 897 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 15 -&amp;gt; 557 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 14:00:00, confc: 729, days for avg: 4, hist. consumption registered consumers: 620.97&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 16 -&amp;gt; 676 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 16 -&amp;gt; 790 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 16 -&amp;gt; 785 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 16 -&amp;gt; 581 Wh&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 15:00:00, confc: 708, days for avg: 4, hist. consumption registered consumers: 647.29&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 17 -&amp;gt; 622 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 17 -&amp;gt; 639 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 17 -&amp;gt; 646 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 17 -&amp;gt; 572 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 16:00:00, confc: 619, days for avg: 4, hist. consumption registered consumers: 618.30&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 18 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 18 -&amp;gt; 614 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 18 -&amp;gt; 580 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 18 -&amp;gt; 480 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 17:00:00, confc: 567, days for avg: 4, hist. consumption registered consumers: 583.41&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 19 -&amp;gt; 615 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 19 -&amp;gt; 1659 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 19 -&amp;gt; 597 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 19 -&amp;gt; 618 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 18:00:00, confc: 872, days for avg: 4, hist. consumption registered consumers: 636.97&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 20 -&amp;gt; 611 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 20 -&amp;gt; 1124 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 20 -&amp;gt; 546 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 20 -&amp;gt; 479 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 19:00:00, confc: 690, days for avg: 4, hist. consumption registered consumers: 578.87&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 21 -&amp;gt; 1474 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 21 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 21 -&amp;gt; 619 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 21 -&amp;gt; 433 Wh&lt;br /&gt;
2024.09.21 13:28:27.058 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Im ersten Teil wird die erwartete Consumption für den nächsten Tag unter Berücksichtigung möglicher Ausschlüsse von Verbrauchern ausgegeben. Ausschlüsse von Verbrauchern ergeben sich wenn in dem Verbraucherattribut der Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; gesetzt ist. Er besagt, dass die Verbrauchswerte des Verbrauchers in eine zukünftige Prognose nicht eingehen sollen. Zum Beispiel wenn ein Verbraucher mit sehr hohen Verbrauchswerten nur sporadisch eingesetzt wird und dadurch die Prognose stark verfälschen würde. Es ist auch zu sehen, dass bedingt durch das Attribut &#039;&#039;&#039;affectConsForecastIdentWeekdays = 1&#039;&#039;&#039; nur die historischen Tage 01, 08, 15 und 25 berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Teil wird die berechnete Erwartung für die nächsten Stunden ausgegeben. &lt;br /&gt;
Zur Beschreibung der Fehlersuche gehen wir davon aus, dass die Prognose von 780 Wh am 2024-09-21 20:00:00 zu hoch erscheint weil am Tag &amp;quot;07&amp;quot; ein Wert von 1474 Wh gespeichert ist:&lt;br /&gt;
&lt;br /&gt;
 SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt geben wir die historischen Werte für den Tag 07 aus:&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;Name&amp;gt; pvHistory 07&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz interessiert die Stunde 21. Sie resultiert aus der obigen Angabe &amp;quot;starttime: xxxx-xx-xx 20:00:00&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      21 =&amp;gt; etotal: 64354660, pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 496, con: 1474, gcons: 23, conprice: 0.2958&lt;br /&gt;
            gfeedin: 5, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 289, sunalt: -8&lt;br /&gt;
            batintotal: 3064096.92456668, batouttotal: 2958021.37946804, batin: 0, batout: 1460&lt;br /&gt;
            wid: 101, wcc: 20, rr1c: 0.00, pvcorrf: 1.00/-temp: 26.00, &lt;br /&gt;
            csmt01: 64262.43, csme01: 28.8099999999977, minutescsm01: 25&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 0, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1389417.4, csme04: 94.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 0, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 290.15, csme06: 6.66999999999996, minutescsm06: 54&lt;br /&gt;
            csmt07: 0, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 32800, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 103987.8, csme09: 38, minutescsm09: 43&lt;br /&gt;
            csmt10: 9151.24999999783, csme10: 3.99999999997999, minutescsm10: 60&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz sind die Energieverbrauchsanteile der im Device registrierten Verbraucher mit dem Schlüssel &amp;quot;csmeXX&amp;quot; gespeichert. Dabei ist &amp;quot;XX&amp;quot; die Verbrauchernummer. In dem Beispiel existieren die Anteile csme01 und csme03 - csme10. Keiner dieser Verbraucher hat einen auffälligen Verbrauchswert gespeichert, d.h. die Messung der Verbraucher scheidet als Problemquelle aus. Wäre ein unverhältmismäßig hoher Verbrauch bei einem der Verbraucher feststellbar, müssten die Schlüssel &#039;&#039;&#039;pcurr&#039;&#039;&#039; und &#039;&#039;&#039;etotal&#039;&#039;&#039; im consumerXX-Attribut geprüft, sowie die Datenlieferung des Consumerdevices selbst geprüft werden.  &lt;br /&gt;
&lt;br /&gt;
Es wurde offensichtlich ein hoher Verbrauch von einem nicht registrierten Verbraucher verursacht oder durch die Übertragung eines Meßfehlers des Devices, angegeben im Attribut &#039;&#039;&#039;setupMeterDev&#039;&#039;&#039;, in das SolarForecast Device übertragen. Eine weitere Analyse ist an dieser Stelle nicht möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Behebung des falschen Wertes kann ein Reset der gespeicherten Consumption der relevanten Stunde durchgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; reset consumptionHistory 07 21&lt;br /&gt;
&lt;br /&gt;
== Modulinterne Datenstrukturen ==&lt;br /&gt;
Das Modul speichert die verschiedenen historischen und aktuellen Daten wie PV-Prognose, Witterungsdaten (Regen, Bewölkung), Strahlungsdaten, Einspeisung, Bezug, reale Erzeugungsdaten und vieles mehr zur Laufzeit im Arbeitsspeicher. Dadurch ist die Verarbeitung dieser Daten im Vergleich zu Lesevorgängen aus dem Filesystem bzw. einer Datenbank sehr performant. Allerdings würden diese Daten bei einem FHEM Absturz bzw. bei einem regulären Shutdown verlorengehen.&lt;br /&gt;
&lt;br /&gt;
Deswegen werden die relevanten Daten regelmäßig in Dateien gesichert und bei Bedarf wiederhergestellt. Diese Dateien befinden sich im Verzeichnis &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; und heißen &#039;&#039;&#039;.*_SolarForecast_.*&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Die Daten werden in jedem Zyklus der Zentralschleife (CentralTask) gesammelt bzw. berechnet. Der Zyklus wird mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;cycleInterval&#039;&#039;&#039; eingestellt.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit können diese Daten über get-Kommandos abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvHistory [Tag]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der pvHistory Datenspeicher enthält die vergangenen Kennwerte der letzten 31 Tage mit einer Genauigkeit von einer Stunde. Es werden die Prognosewerte für Erzeugung und Verbrauch, die realen Werte für Erzeugung und Verbrauch sowie ebenso die Laufzeiten jedes einzelnen Verbrauchers (Consumer) festgehalten. Für jeden Tag gibt es die Stunde &amp;quot;99&amp;quot; die eine Summierung der Stundenwerte des Tages bzw. Sonderschlüssel enthält.&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf lässt sich mit dem Befehl &amp;quot;set ... reset pvHistory&amp;quot; der gesamte Inhalt des Speichers löschen (nicht empfohlen). Selektiver funktioniert die Datenlöschung mit &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt;&amp;quot; (Daten eines bestimmten Tages löschen) bzw. &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt; &amp;lt;Stunde&amp;gt;&amp;quot; (Daten der Stunde  eines bestimmten Tages löschen). Die letzten beiden Kommandos müssen über die Kommandozeile im Browser ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvCircular &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Ringspeicher enthält Daten der letzten 24 Stunden sowie fortwährend berechnete Werte wie Korrekturfaktoren der PV-Erzeugung und Prognosequalität.&lt;br /&gt;
Neue Stundenwerte des Tages überschreiben die gespeicherten Schüssel des vorangegangenen Tages sofern es sich nicht um fortwährend berechnete Werte handelt. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... nextHours&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Speicher enthält sämtliche Prognosewerte der kommenden Stunden beginnend mit der aktuellen Stunde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... radiationApiData&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Abhängig von der ausgewählten Strahlungsdaten API enthält dieser Speicher die von der API gelieferten Rohdaten sowie evtl. weitere für die Funktion benötigte Daten wie API-Keys, Response Messages, Anzahl der API Abruf und weitere.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valCurrent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Struktur wird nicht regelmäßig im Filesystem gespeichert und enthält immer aktuell gesammelte oder berechnete/gelieferte Daten wie z.B. die Autarkierate, letze Laufzeit der Zentralschleife (CentralTask), Zeit des Sonnenauf- und untergangs sowie weitere Betriebsdaten. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valConsumerMaster [XX]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zeigt die Daten der aktuell im SolarForecast Device registrierten Verbraucher. Mit der Nummer &#039;&#039;&#039;XX&#039;&#039;&#039; kann ein bestimmter Verbraucher angesprungen werden. Die Nummer korrespondiert mit dem entsprechenden &#039;&#039;&#039;consumerXX&#039;&#039;&#039; Attribut.&lt;br /&gt;
Neben anderen Betriebs- und Energiedaten werden insbesondere folgende Daten ermittelt, die für die zukünftige Planung der Verbraucherschaltzeiten relevant sind:&lt;br /&gt;
&lt;br /&gt;
* epieces - prognostizierte Energiescheiben pro Betriebsstunde &lt;br /&gt;
&lt;br /&gt;
Ausgehend von gespeicherten historischen Verbrauchsdaten des Verbrauchers wird der Energieverbrauch des Verbrauchers in seiner ersten Betriebsstunde prognostiziert, was insbesondere für die Planung der optimalen Startzeit des Verbrauchers in Bezug zu der prognostizierten PV Energie und den Verbrauchswerten weiterer vorhandener bzw. zu planender Verbraucher Berücksichtigung findet. Weitere Informationen zur Verbrauchersteuerung in diesem  [[#Verbrauchersteuerung_-_Registrieren_und_visualisieren_von_Verbrauchern|Abschnitt]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Schnittstelle für Modulautoren bzw. eigenen Code ===&lt;br /&gt;
&lt;br /&gt;
Die im vorherigen Artikel beschriebenen internen Datenstrukturen können durch externen Code abgefragt und ausgewertet werden.&lt;br /&gt;
Dazu stehen die folgenden Funktionen zur Verfügung. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]BatteryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Bn&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valBattery&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CurrentVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valCurrent&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]InverterVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valInverter&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ProducerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valProducer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]HistoryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Day&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvHistory&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CircularVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvCircular&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]NexthoursVal (&#039;&amp;lt;Name&amp;gt;&#039;, &amp;lt;nhr&amp;gt;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... nextHours&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ConsumerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valConsumerMaster&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]RadiationAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;DateTime&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... radiationApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]WeatherAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;TimeCode&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... weatherApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StatusAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;QTag&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... statusApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StringVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valStrings&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Angabe des Packages (FHEM::SolarForecast::) ist nur notwendig wenn die Funktionen von außerhalb des SolarForecast-Devices aufgerufen werden. Innerhalb des Devices (Code-Ausführung im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039;) kann darauf verzichtet werden.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der Platzhalter sind:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     &amp;lt;Name&amp;gt;     - Name des SolarForecast Devices&lt;br /&gt;
     &amp;lt;Day&amp;gt;      - abzufragender Tag (01 - 31)&lt;br /&gt;
     &amp;lt;Bn&amp;gt;       - Batterie Nummer (01, 02, ...)&lt;br /&gt;
     &amp;lt;DateTime&amp;gt; - Startzeit der Form YYYY-MM-DD hh:00:00&lt;br /&gt;
     &amp;lt;TimeCode&amp;gt; - Zeitwert der Form fcX_XX (z.B. fc1_19)&lt;br /&gt;
     &amp;lt;APIname&amp;gt;  - Hauptname der API gemäß setupWeatherDev1 (z.B. OpenMeteo)&lt;br /&gt;
     &amp;lt;String&amp;gt;   - Name des PV-Modulstrings wie im Attribut &#039;setupInverterStrings&#039;&lt;br /&gt;
     &amp;lt;QTag&amp;gt;     - Question Tag, z.B. &#039;?All&#039;&lt;br /&gt;
     &amp;lt;Nr&amp;gt;       - laufende Nummer des Verbrauchers / Gerätes (01, 02, 03, 04,...)&lt;br /&gt;
     &amp;lt;HoD&amp;gt;      - abzufragende Stunde (01 - 24, 99)&lt;br /&gt;
     &amp;lt;nhr&amp;gt;      - nächste Stunde (NextHour00, NextHour01,...)&lt;br /&gt;
     &amp;lt;Key&amp;gt;      - der abzufragende Schlüssel &lt;br /&gt;
     &amp;lt;default&amp;gt;  - def default-Rückgabewert&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Auswerten von internen Arrays ===&lt;br /&gt;
&lt;br /&gt;
Die meisten der internen Datenstrukturen liefern bei der Abfrage einen einfachen String oder numerischen Wert der ausgewertet werden kann. Es gibt allerdings auch intern gespeicherte Wertelisten. Werden die Listenstrukturen mit den oben beschriebenen Befehlen abgefragt, wird eine Referenz auf die Liste geliefert sofern sie vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
Um auf die Werte einer solchen Liste zuzugreifen, ist am Beispiel des Arrays &#039;&#039;surplusslidereg&#039;&#039; aus dem Current-Speicher (get ... valCurrent) dargestellt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
my $splref = CurrentVal ($name, &#039;surplusslidereg&#039;, &#039;.&#039;);&lt;br /&gt;
my $spser  = ref $splref eq &#039;ARRAY&#039; ? join &#039; &#039;, @{$splref} : undef;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Variable $spser enthält bei Vorhandensein der Liste einen String, der die Listenelemente von &#039;surplusslidereg&#039; durch Leerzeichen getrennt enthält.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backup und Wiederherstellung der Moduldaten ==&lt;br /&gt;
Neben der Datenhaltung in den Attributen und Readings des SolarForecast Devices, erzeugt jedes SolarForecast Device Dateien im Verzeichnis  &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; mit folgenden Inhalten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PVH_SolarForecast_&amp;lt;name&amp;gt;        - PV History&lt;br /&gt;
PVC_SolarForecast_&amp;lt;name&amp;gt;        - PV Circular&lt;br /&gt;
PVCfg_SolarForecast_&amp;lt;name&amp;gt;      - PV Anlagenkonfiguration&lt;br /&gt;
PVCsm_SolarForecast_&amp;lt;name&amp;gt;      - Consumer Status&lt;br /&gt;
ScApi_SolarForecast_&amp;lt;name&amp;gt;      - Strahlungswerte aus verwendeter API&lt;br /&gt;
StatApi_SolarForecast_&amp;lt;name&amp;gt;    - Statusdaten der verwendeten API&#039;s&lt;br /&gt;
WeatherApi_SolarForecast_&amp;lt;name&amp;gt; - Wetterdaten der gewählten Wetter-API (außer DWD-Device)&lt;br /&gt;
AItra_SolarForecast_&amp;lt;name&amp;gt;      - KI Entscheidungsquelle (trainierte Daten)&lt;br /&gt;
AIraw_SolarForecast_&amp;lt;name&amp;gt;      - KI Input Daten = Raw Trainigsdaten&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nach Ausprägung und eingesetzten Features des SolarForecast Devices sind alle oder nur ein Teil dieser Dateien vorhanden. Dabei ist &#039;&#039;&#039;&amp;lt;name&amp;gt;&#039;&#039;&#039; der Name des SolarForecast Devices.&lt;br /&gt;
&lt;br /&gt;
Bei einem Filebackup des FHEM-Servers ist darauf zu achten, dass diese Dateien in dem Backup enthalten sind. Der Inhalt der Dateien ist nicht statisch, sondern kann sich dynamisch aktualisieren. Um im Bedarfsfall einen aktuellen Datenstand zu haben, ist mindestens ein tägliches Backup dieser Dateien empfehlenswert. Eventuell auch öfter mit Hilfe einer Versionierung welche z.B. immer die letzten 3 Versionen aufbewahrt.&lt;br /&gt;
&lt;br /&gt;
Beim Start von FHEM werden bestimmte Dateien automatisch gelesen und in das SolarForecast Device importiert. &lt;br /&gt;
Der Vorgang ist mit verbose=3 im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2023.10.02 09:57:07.967 3: SolCast6 - cached data &amp;quot;pvHistory&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.969 3: SolCast6 - cached data &amp;quot;pvCircular&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;consumerMaster&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;radiationApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;statusApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;weatherApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.974 3: SolCast6 - cached data &amp;quot;aiTrainedData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.976 3: SolCast6 - cached data &amp;quot;aiRawData&amp;quot; restored&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bestimmte Betriebsdaten, wie z.B. die witterungsabhängigen Korrekturfaktoren (circular) oder die KI-Daten (aitrained/airaw), bauen sich über die Zeit immer granularer auf und stellen einen wertvollen Datenbestand dar.&lt;br /&gt;
&lt;br /&gt;
Wird das SolarForecast Device gelöscht und anschließend wieder neu mit dem gleichen Namen definiert, können die bisher verfügbaren Daten sehr einfach wiederhergestellt werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. starten von FHEM (bestimmte Daten werden automatisch importiert)&lt;br /&gt;
* 5. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Soll das neue SolarForecast Device mit einem anderen Namen oder weitere SolarForecast Devices erstellt werden, welche die Betriebsdaten des primären Devices verwenden sollen, ist wie folgt vorzugehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. umbenenen der Dateien, wobei &amp;lt;name&amp;gt; durch den Namen des neuen SolarForecast Devices ersetzt wird&lt;br /&gt;
* 5. starten von FHEM (die Daten werden automatisch importiert)&lt;br /&gt;
* 6. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn sich die SolarForecast Devices hinsichtlich ihres Models oder der integrierten Consumer unterscheiden, sind die Dateien &amp;quot;PVCsm_SolarForecast_&amp;lt;name&amp;gt; &amp;quot; , &amp;quot;ScApi_SolarForecast_&amp;lt;name&amp;gt;&amp;quot; von dem Verfahren auszuschließen.&lt;br /&gt;
&lt;br /&gt;
== Batterieintegration und -steuerung ==&lt;br /&gt;
&lt;br /&gt;
=== Wie eine Batterie eingebunden wird ===&lt;br /&gt;
Wie immer muß die Batterieanlage zunächst mit einem für die Batterie spezifischen FHEM-Device in FHEM definiert sein.&lt;br /&gt;
In diesem Device werden Readings erwartet die folgende Werte bereitstellen:&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieentladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die installierte Batteriekapazität liefert (&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; dieser Schlüssel ist für die Aktivierung des Batterie SOC-Managements und die grafische Anzeige des SOC wesentlich!)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Lade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Entlade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* Reading welches den aktuellen Ladezustand (SOC in Prozent) liefert (optional)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Batterie, bzw. das Batteriedevice wird mit dem Attribut &#039;&#039;&#039;setupBatteryDev&#039;&#039;&#039; im SolarForecast Device registriert. Die Syntax des Attributes ist in  der Online-Hilfe zum Attribut umfassend erläutert. &lt;br /&gt;
Auch wenn manche Readings optional sind, wird empfohlen alle Werte bereitzustellen um alle Batterie-Funktionen im Modul nutzen zu können. Durch die Weiterentwicklung des Moduls können optionale Readings später auch obligatorisch werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Visualisierung der Batterie in der Balkengrafik ====&lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;setupBatteryDevXX&#039;&#039;&#039; verfügt über den Schlüssel &#039;&#039;&#039;show&#039;&#039;&#039;, mit dem die Einblendung des bzw. der Batteriesymbole in den Ebenen der Balkengrafik gesteuert werden kann:&lt;br /&gt;
[[Datei:Screenshot 2025-02-23 192002.png|right|thumb|400px|Einblendung der Batterieleiste und Darstellung des Batterie-SoC als Balkencontent in der zweiten Ebene]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 0 - keine Anzeige des Gerätes (default)&lt;br /&gt;
* 1 - Anzeige des Gerätes in der Balkengrafik Ebene 1&lt;br /&gt;
* 2 - Anzeige des Gerätes in der Balkengrafik Ebene 2 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Symbole und die Farbgebung der Batterie(n) können mittels des Schlüssels &#039;&#039;&#039;icon&#039;&#039;&#039; verändert werden. Die Online-Hilfe gibt weitere Informationen zur Ausgestaltung. &lt;br /&gt;
&lt;br /&gt;
In der Batteriedarstellung wird das Symbol der aktuellen Stunde hervorgehoben. Ein Mouse-Over zeigt wesentliche Betriebszustände der Batterie. Die Batteriesymbole vergangener Stunden zeigen mit einem Mouse-Over die erreichten SoC (State of Charge) Stände. Die kommenden Stunden visualisieren die folgenden Prognosen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der prognostizierte SoC unter Berücksichtigung der PV-Prognose und der [[#Aktivierung_des_Batterie_SOC-Managements|Batteriesteuerung]] sofern sie im Modul aktiviert ist.&lt;br /&gt;
* eine Freigabe bzw. Empfehlung der Batterieladung zur [[#Unterstützung_eines_netzdienlichen_Verhaltens|Unterstützung eines netzdienlichen Verhaltens]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Neben der Einblendung der Batterieleiste über der Balkengrafik selbst können bestimmte Batteriekennwerte als Balkeninhalt dargestellt werden. Die Auswahl erfolgt über das Attribut &#039;&#039;&#039;graphicBeamXContent&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Aktivierung des Batterie SOC- und Lade-Managements ===&lt;br /&gt;
Das integrierte SOC- und Lade-Management verfolgt insbesondere zwei Ziele: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* den Ladezustand der Batterie(n) zu optmimieren, was besonders in den Monaten mit geringerer PV-Erzeugung einen wertvollen Beitrag zur Erhöhung der Autarkierate und Batteriepflege leisten kann&lt;br /&gt;
 &lt;br /&gt;
* eine PV-Prognose und Verbrauch optimierte Beladungssteuerung, die in den Monaten mit hoher PV-Erzeugung hilft eine evtl. Abregelung der Anlage zu verhindern, die Batterie ausgewogen über den Tag zu laden und ein netzdienliches Verhalten zu unterstützen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese beiden Aspekte der Batteriesteuerung werden in den folgenden Abschnitten beschrieben. Sind mehrere Batterien installiert, kann die Steuerung getrennt für jede einzelne Batterie aktiviert und eingestellt werden. Dabei ist zu beachten, dass vom Modul nur Signale und Readings bereitgestellt werden, die durch eine entsprechende Routine ausgewertet werden können um spezifische Befehle zur Umsetzung der Steuerung an das Batteriesystem zu senden. &lt;br /&gt;
 &lt;br /&gt;
Für eine Aktivierung des Managements muß zunächst das Batterie-Device wie im vorigen Abschnitt im SolarForecast Device registriert werden.&lt;br /&gt;
Das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; aktiviert die im Modul integrierte SOC- und Lade-Management Routine: &lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; ctrlBatSocManagement01 lowSoc=&amp;lt;Wert&amp;gt; upSoC=&amp;lt;Wert&amp;gt; [maxSoC=&amp;lt;Wert&amp;gt;] [careCycle=&amp;lt;Wert&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
Die einzelnen Schlüssel werden der Kalkulationsroutine als Steuerungsparameter übergeben und bedeuten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;lowSoc:unterer Mindest-SoC, die Batterie wird nicht tiefer als dieser Wert entladen (muß &amp;gt; 0 sein). Dieser Wert kann zum Beispiel dazu dienen, stets eine Mindestenergiemenge für den Fall eines Stromausfalls im öffentlichen Netz in den Batterien vorzuhalten.&lt;br /&gt;
&lt;br /&gt;
;upSoC:oberer Mindest-SoC, Der übliche Wert des optimalen SoC bewegt sich in Perioden mit hohen PV-Überschuß tendenziell zwischen &#039;lowSoC&#039; und &#039;upSoC&#039;, in Perioden mit geringer PV-Ausbeute bzw. geringem PV Energieüberschuß bewegt sich der optimale SoC tendenziell zwischen &#039;upSoC&#039; und &#039;maxSoC&#039;. Die Einstellung von upSoC=50 für ein ausgewogenes Verhalten kann als guter Startwert dienen.&lt;br /&gt;
&lt;br /&gt;
;maxSoC:maximaler Mindest-SoC, d.h. der SoC Wert der mindestens im Abstand von &#039;careCycle&#039; Tagen erreicht werden muß um den Ladungsausgleich im Speicherverbund auszuführen. Die Angabe ist optional (muß &amp;lt;= 100 sein, default: 95)&lt;br /&gt;
&lt;br /&gt;
;careCycle:maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens &#039;maxSoC&#039; auftreten darf. Die Angabe ist optional. (default: 20)&lt;br /&gt;
&lt;br /&gt;
;loadAbort: definiert eine vom Anwender gewünnschte Bedingung für einen generellen Ladeabbruch und Wiederfreigabe der Lademöglichkeit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle Werte sind ganze Zahlen in %. Dabei gilt: &lt;br /&gt;
&lt;br /&gt;
 lowSoc &amp;lt; upSoC &amp;lt; maxSoC&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====  Erläuterung der Batterie-Steuerungsreadings ==== &lt;br /&gt;
&lt;br /&gt;
Für die Steuerung des Batteriesystems gibt es im SolarForecast einen Satz an Readings, die unterschiedliche Zustände signalisieren und für entsprechende Steuerungsaufgaben bezüglich der Batteriesysteme eingesetzt werden können. In den nachfolgenden Abschnitten werden diese Zusammenhänge noch dataillierter beschrieben.&lt;br /&gt;
&lt;br /&gt;
;Hinweis: SolarForecast stellt lediglich Steuerungsinformationen zur Verfügung. Die Umsetzung des Eingriffs in das Batteriesystem erfolgt durch den Anwender selbst über entsprechende Skripte. In den thematischen Abschnitten werden Beispiele für solche Steuerungsskripte vorgestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle erstellten Readings gelten für ein Batteriesystem, es können mehrere Batteriesysteme in SolarForecast integriert sein. Die Endung &#039;&#039;XX&#039;&#039; der Readings beschreibt die Nummer des Batteriesystems und korrespondiert mit der Endung des entsprechenden Attributes &#039;&#039;ctrlBatSocManagementXX&#039;&#039; bzw. &#039;&#039;setupBatteryDevXX&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Battery_OptimumTargetSoC_XX: Mit den im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; hinterlegten Parametern unter Berücksichtigung von PV- und Verbrauchsprognosen wird ein optimaler SOC-Wert errechnet. Dieser Wert dient zur Einstellung des unteren SOC des Batteriesystems.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeRequest_XX: Dieses Reading signalisiert mit 1 eine Anforderung zur Zwangsladung der Batterie um die Batterie vor Schäden zu schützen (wenn der SOC unter ctrlBatSocManagementXX-&amp;gt;lowSoc gefallen ist) oder wenn der aktuelle SOC unter den berechneten Mindest-SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeUnrestricted_XX: Dieses Reading kann den Wert &#039;&#039;&#039;0&#039;&#039;&#039; oder &#039;&#039;&#039;1&#039;&#039;&#039; einnehmen. Ist der Inhalt 0, sollte die Batterie nur geladen werden, wenn der im Attribut &#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039; definierte Wert überschritten wird. Ist der Inhalt 1, sollte die Batterie mit der vollen zur Verfügung stehenden Ladeleistung angesteuert werden, um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeAbort_XX: Im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; kann mit dem Schlüssel &#039;&#039;loadAbort&#039;&#039; eine Bedingung definiert werden, bei deren Eintritt die Ladung der Batterie abgebrochen werden soll. In diesem Fall wird &#039;&#039;Battery_ChargeAbort_XX=1&#039;&#039; gesetzt. Mit einem entsprechenden Befehl kann der Anwender das Batteriesystem anweisen den Ladevorgang abzubrechen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Nutzung des Batterie SOC-Management ====&lt;br /&gt;
&lt;br /&gt;
Oftmals wird durch die Anlagenhersteller ein hoher statischer SOC eingestellt bzw. empfohlen, der eine längere Verharrungszeit auf einem tiefen SOC-Wert verhindern soll. Allerdings wechseln sich in auch in den Herbst-, Frühlings- und Wintermonaten Zeiten mit wenig PV-Erzeugung mit Phasen stärkerer Solarstrahlung bei klarem Himmel und Sonnenschein ab.&lt;br /&gt;
&lt;br /&gt;
Ein statischer SOC würde dazu führen, dass in den erwähnten Phasen zuviel Energie in das öffentliche Netz eingespeist wird. Dies soll verhindert werden da die wertvolle Energie besser im eigenen Netz gespeichert und in Dunkelphasen verwendet werden kann. Andererseits soll die Batterie nicht zu lange auf einem tiefen SOC verbleiben und außerdem in gewissen Abständen auf einen so hohen SOC geladen werden der den internen Zellausgleich ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Die SOC Kalkulationsroutine des Moduls errechnet unter Berücksichtigung des prognostizierten PV-Ertrages der kommenden Tage, des aktuellen SOC und der im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; (nachfolgend beschrieben) angegebenen Steuerparameter den Vorschlag für eine optimale SOC-Einstellung. Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert.&lt;br /&gt;
&lt;br /&gt;
Durch das Modul selbst findet keine Steuerung der Batterie statt. Es stellt entsprechende Readings zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen SoC.&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SoC unter den optimalen SoC gefallen ist. In diesem Fall sollte die Batterie, unter Umständen mit Netzstrom, zwangsgeladen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Readings können zur Steuerung des SoC (State of Charge) sowie zur Steuerung des verwendeten Ladestroms der Batterie verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ermittlung des optimalen SOC erfolgt nach folgender Logik:&lt;br /&gt;
&lt;br /&gt;
# 	Ausgehend von &#039;lowSoc&#039; wird der Mindest-SoC kurz vor Sonnenuntergang um 5% inkrementiert sofern am laufenden Tag &#039;maxSoC&#039; nicht erreicht wurde und die PV-Prognose keinen hinreichenden Ertrag des kommenden Tages vorhersagt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Wird &#039;maxSoC&#039; (wieder) erreicht, wird Mindest-SoC um 5%, aber nicht tiefer als &#039;lowSoc&#039;, verringert. Ist der berechnete Mindest-SoC größer als &#039;upSoc&#039;, wird der Mindest-SoC auf &#039;upSoc&#039; gesetzt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#   Mindest-SoC wird soweit verringert, dass die prognostizierte PV Energie des aktuellen bzw. des folgenden Tages von der Batterie aufgenommen werden kann. Mindest-SoC wird typisch auf &#039;upSoc&#039; und nicht tiefer als &#039;lowSoc&#039; verringert.  &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Das Modul erfasst den letzten Zeitpunkt am &#039;maxSoC&#039;-Level, um eine Ladung auf &#039;maxSoC&#039; mindestens alle &#039;careCycle&#039; Tage zu realisieren. Zu diesem Zweck wird der optimierte SoC in Abhängigkeit der Resttage bis zum nächsten &#039;careCycle&#039; Zeitpunkt derart verändert, dass durch eine tägliche 5% SoC-Steigerung &#039;maxSoC&#039; am &#039;careCycle&#039; Zeitpunkt rechnerisch erreicht wird. Wird zwischenzeitlich &#039;maxSoC&#039; erreicht, beginnt der &#039;careCycle&#039; Zeitraum erneut. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im fünften Schritt werden die Grenzen &#039;lowSoc&#039; und &#039;upSoc&#039; berücksichtigt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im letzten Schritt erfolgt Generierung des Readings &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; zur Signalisierung einer eventuell empfohlenen Zwangsladung auf den berechneten Min-SoC. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei sehr wenig Erzeugungungsprognose, d.h. wenn sich der berechnete Min-SoC oberhalb von &#039;upSoC&#039; bewegt, wird &#039;upSoC&#039; eingestellt. Liegt der berechnete Min-SoC unterhalb von &#039;upSoC&#039;, ist jedoch größer als &#039;lowSoC&#039;, wird der berechnete SOC im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; eingestellt. Somit eignet sich die Angabe im Schlüssel &#039;upSoC&#039; um in Zeiten geringer Solarenergieerzeugung die Batterie für eine Notstromerzeugung auf mindestens diesem Wert zu halten. Sollte die PV-Prognose kurzfristig einen größeren Ertrag vorhersagen als die Batterie durch die Einhaltung von &#039;upSoC&#039; aufnehmen kann, wird der Min-SoC unter &#039;upSoC&#039; abgesenkt um möglichst allen PV-Überschuß in der Batterie zu speichern und somit dem Eigenverbrauch zuzuführen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der berechnete Mindest-SoC ist immer nur ein unterer Grenzwert. Die Batterie kann durch Ladevorgänge natürlich jederzeit einen höheren als den im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; dargestellten optimalen SoC haben. Der optimale SoC sollte nicht unterschritten werden um die oben genannten Zusammenhänge abbilden zu können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Die dynamische SOC Steuerung mit Umsetzungsbeispiel =====&lt;br /&gt;
Das Modul bietet eine Unterstützung zur automatisierten Einstellung eines optimalen SoC Wertes.&lt;br /&gt;
&lt;br /&gt;
Ziel ist es, den Minimum SoC in Abhängigkeit der zu erwartenden Solarerträge des aktuellen und des folgenden Tages so einzustellen, dass der prognostizierte Solarertrag von der Batterie aufgenommen werden kann. Die Einspeisung in das öffentliche Netz soll minimiert werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin soll ein unterer SoC nicht unterschritten, sowie ein oberer Minimum SoC im Normalfall nicht überschritten werden. Der obere Grenzwert stellt sicher, dass die Batterie mindestens bis zu diesem Wert wieder entladen werden kann. Dadurch bleibt innerhalb der Batterie immer genügend Kapazität verfügbar um unvorhergesehene PV Energie aufnehmen zu können.&lt;br /&gt;
&lt;br /&gt;
Aktiviert wird die Unterstützung der Batteriesteuerung durch das Setzen des Attributes &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; z.B. mit diesen Angaben:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagementXX lowSoc=x upSoC=x maxSoC=x careCycle=x &lt;br /&gt;
&lt;br /&gt;
so zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=98 careCycle=20&lt;br /&gt;
&lt;br /&gt;
Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert. &lt;br /&gt;
Ist dieses Attribut gesetzt, werden Steuerungs-Readings erstellt, die der Nutzer auswerten und seine Batterieanlage z.B. via notify oder DOIF steuern kann. &amp;lt;bR&amp;gt;&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen Mindest-SoC.&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SOC unter den optimalen SOC bzw. minimalen SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
Die Schlüssel &#039;&#039;&#039;lowSoc&#039;&#039;&#039; und &#039;&#039;&#039;upSoC&#039;&#039;&#039; sind die unteren und oberen Grenzen, zwischen denen sich der Minimum SoC im normalen Betrieb bewegen soll.&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;maxSoC&#039;&#039;&#039; stellt eine Ladungsgrenze dar, die mindestens alle X (careCycle) Tage erreicht werden soll. Zu diesem Zweck errechnet das Modul die Anzahl der nötigen Erhöhungen der Minimum Batterieladung von 5% pro Tag um ausgehend vom aktuellen SoC-Level. Der resultierende Minimum SoC Wert wird entsprechend angepasst. Wurde der einstellte maxSoC Level erreicht, startet der Wartungszyklus (careCycle) erneut. &amp;lt;br&amp;gt;&lt;br /&gt;
Der maxSoC in Verbindung mit dem durch &#039;&#039;&#039;careCycle&#039;&#039;&#039; definierten Zyklus soll sicherstellen, dass der Batterieverbund in regelmäßigen Abständen einen Ladungsausgleich vollziehen kann. &lt;br /&gt;
&lt;br /&gt;
Durch die Modullogik erfolgt eine 5 protentige Anhebung des Minimum SoC wenn am Vortag maxSoC nicht erreicht wurde. Die Anhebung erfolgt aber nicht über upSoC. upSoC ist die obere Grenze des Minimum SoC. Wird am Vortag mindestens die maxSoC Ladung erreicht, verringert sich der Minimum SoC wieder schrittweise um 5%, aber nicht tiefer als lowSoc.&lt;br /&gt;
&lt;br /&gt;
Ergänzt wird die Logik noch um die PV Vorhersage. Dabei wird die obige Minimum SoC Berechnung um die Erwartung der PV Erwartung am aktuellen und folgenden Tag korrigiert. Das bedeutet, dass der Minimum SoC z.B. von heute 50% auf 10% abgesenkt und dadurch die gespeicherte Energie dem Haushalt zugeführt wird, wenn am heutigen oder kommenden Tag eine entsprechende PV Energie zu erwarten ist um die Batterie wieder vollständig zu zuladen.&lt;br /&gt;
Dadurch ist immer genügend &amp;quot;Freiplatz&amp;quot; in der Batterie und andererseits hat die Batterie in langen Dunkelphasen eine Reserve für einen eventuellen Stromausfall (falls der abgesichert werden soll) und wird vor einem dauerhaften tiefen SoC geschützt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Umsetzungsbeispiel =====&lt;br /&gt;
&lt;br /&gt;
Wie das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; genutzt werden kann, wird am Beispiel einer Victron Batterieanlage gezeigt. Die Anlage wird durch Cerbo GX Gerät gesteuert. Der Cerbo GX ist per MQTT2 in FHEM eingebunden. Umgesetzt ist die Steuerung der Batterie &#039;01&#039;, d.h. die Angabe &#039;XX&#039; ist durch &#039;01&#039; ersetzt.&lt;br /&gt;
&lt;br /&gt;
Die folgende kleine Logik ist in einem &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; File eingebaut und wird regelmäßig mit&lt;br /&gt;
&lt;br /&gt;
 batSocChargeMgmnt (&#039;&amp;lt;Name SolarForecast Device&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
aufgerufen. Der Aufruf erfolgt durch Angabe der Routine im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; des SolarForecast Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
  # Hinweis: die Zeichen &#039;::&#039; vor der Routine sind durch das SolarForecast Package bedingt&lt;br /&gt;
  ::batSocChargeMgmnt ($name);&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Routine wird dadurch automatisch am Ende jedes Zyklus (siehe Attribut plantControl-&amp;gt;cycleInterval) ausgeführt.&lt;br /&gt;
Um die SOC Managementfunktion nach Bedarf ein- bzw. ausschalten zu können wird zunächst im SolarForecast Device ein userattr zur Steuerung der SOC-Logik angelegt:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; userattr userFn_BatterySoCManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
Die Perl Routine &#039;&#039;&#039;batSocChargeMgmnt&#039;&#039;&#039; ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#  Batterie SOC und Max. Ladestrom Management&lt;br /&gt;
############################################################################&lt;br /&gt;
sub batSocChargeMgmnt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vebus   = &#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;;                            # Victron Vebus Device&lt;br /&gt;
  my $vicsets = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                         # Victron Einstellungen&lt;br /&gt;
&lt;br /&gt;
  my $maxcspc = 105;                                                           # max. Ladestrom (A) Victron MPII Verbund&lt;br /&gt;
  my $actmcc  = ReadingsNum ($vebus, &#039;MaxChargeCurrent&#039;, undef);               # akt. Ladestromeinstellung&lt;br /&gt;
  my $load    = $actmcc // $maxcspc;                                           # Soll-Ladestrom (A)&lt;br /&gt;
&lt;br /&gt;
  ## Battery SoC Management&lt;br /&gt;
  ###########################&lt;br /&gt;
  my $ubsm = AttrVal ($name, &#039;userFn_BatterySoCManagement&#039;, &#039;aus&#039;); &lt;br /&gt;
  &lt;br /&gt;
  if ($ubsm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name,    &#039;Battery_ChargeRequest_01&#039;,     0);&lt;br /&gt;
    my $csoc = ReadingsNum ($vicsets, &#039;MinimumSocLimit&#039;,             10);      # akt. SoC&lt;br /&gt;
    my $osoc = ReadingsNum ($name,    &#039;Battery_OptimumTargetSoC_01&#039;, 10);      # Soll-SoC&lt;br /&gt;
    my $surp = ReadingsNum ($name,    &#039;Current_Surplus&#039;,              0);      # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if ($csoc != $osoc) {&lt;br /&gt;
      CommandSet (undef, &amp;quot;$vicsets MinimumSocLimit $osoc&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn SoCMgmnt -&amp;gt; MinimumSocLimit in $vicsets set to $osoc %});&lt;br /&gt;
    }&lt;br /&gt;
	                                           &lt;br /&gt;
    if ($bcrq &amp;amp;&amp;amp; $surp &amp;lt; 1000) {                                              # max. Strom b. Battery_ChargeRequest &lt;br /&gt;
      $load = 21;&lt;br /&gt;
    }&lt;br /&gt;
	else {&lt;br /&gt;
	  $load = $maxcspc;&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Batterie Einstellung MaxChargeCurrent&lt;br /&gt;
  ##########################################&lt;br /&gt;
  if ($load != $actmcc) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$vebus MaxChargeCurrent $load&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
    Log3 ($name, 3, qq{$name - userFn ChargeMgmnt -&amp;gt; MaxChargeCurrent in $vebus set }.&lt;br /&gt;
                    qq{from old $actmcc A to $load A});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent_set&#039;, $load, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist im SolarForecast Device das Reading  &#039;&#039;&#039;Battery_ChargeRequest_01&#039;&#039;&#039; gesetzt, ist der aktuelle SOC kleiner als der optimale SOC und die Batterie wird (eventuell aus dem öffentlichen Netz) geladen. Das kann automatisch durch den Cerbo GX bzw. in anderen Anlagen durch einen entsprechenden Befehl erfolgen.&lt;br /&gt;
Damit die Netzbeladung nicht mit der vollen Ladestromstärke geschieht, wird der Ladestrom auf den gewünschten Wert (hier 21 A -&amp;gt; ca. 1000 W bei einem 48V System) reduziert sofern kein oder zu wenig PV-Überschuß vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== weitere mögliche Aspekte der SOC- und Batterieladesteuerung ====&lt;br /&gt;
&lt;br /&gt;
SolarForecast liefert durch seine internen Logiken bereits sehr hilfreiche Signale zur Steuerung von Batteriesystemen in Form von Readings an. Abhängig von den individuellen Möglichkeiten der vorhandenen Anlage käme zum Beispiel zusätzlich zu einer Steurung des optimalen SOC oder der Zeitfenster für die Batterieaufladung auch eine Steuerung des Ladestroms bzw. der verwendeten Ladeleistung in Betracht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hintergründe:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Das Laden eines Akkus mit möglichst gleichbleibender und geringer Leistung wirkt sich positiv auf dessen Langlebigkeit aus, was u.a. auch daran liegt, dass der Temperaturstreß im Akku bei langsamer Energiezuführung nur gering ist.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom führt zu einem geringen Absacken der Akkuspannung beim (ggf, temporären) Abschalten des Ladestroms, was sich positiv auf die SOC-Schätzung auswirkt.&lt;br /&gt;
    &lt;br /&gt;
* Ein geringer Ladestrom führt, insb. bei Nutzung passiver Balancer (sind in den Akku-Systemen üblicherweise verbaut), zu einer geringen Differenz zwischen den einzelnen Zellspannungen und damit zu einer besseren Kapazitätsausnutzung eins Akkus.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom kann zu einem zeitlich punktgenauen Zielfüllstand (im Winter 100%, ansonsten natürlich weniger) am Ende des Tages führen.&lt;br /&gt;
    &lt;br /&gt;
* Eine geringer Ladestrom führt auch zu geringen Leitungsverlusten, da der Strom quadratisch zu den Leitungsverlusten beiträgt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann auch die Verweildauer oder die Begrenzung des SOC, auf den die Batterie maximal geladen werden soll, Gegenstand von Optimierungen sein.&lt;br /&gt;
&lt;br /&gt;
Die häufig zu findende Empfehlung, Akkus nicht zu lange bei einem SOC von 100% verweilen zu lassen, liegt weniger an dem SOC als solchem, sondern daran, dass &#039;&#039;SOC=100%&#039;&#039; üblicherweise dadurch ermittelt wird, dass eine Zelle im Akku einen Spannungsschwellenwert überschreitet, der – würde dieser Schwellenwert zeitlich länger überschritten sein – zu einer Schädigung des Akkus führen könnte. Schädlich sind insbesondere häufige Nachladevorgänge bei Werten um die 100% SOC, da Zellen dann ja häufiger und damit - integral gesehen - auch länger den o.g. Schwellenwert überschreiten.&lt;br /&gt;
&lt;br /&gt;
Einige Akku-Hersteller, z.B. BYD, haben auf o.g, Grund in der (neueren) Firmware Ihrer Systeme einen SOC-Threshold (bei BYD liegt dieser bei 95%) eingebaut. Dieser Wert muss nach einem erreichten SOC von 100% unterschritten  werden, bevor überhaupt eine weitere Ladung erfolgt. Insbesondere in der dunklen Jahreszeit kann es daher sinnvoll sein, den Akku unter Verwendung von PV-Leistung so zu füllen, dass dieser möglichst nur einmal vor Einbruch der Dunkelheit auf &#039;&#039;SOC=100%&#039;&#039; geladen wird. Hierbei sollte darauf geachtet werden, dass der Ladeschlussstrom des jeweiligen Systems nicht unterschritten wird. &lt;br /&gt;
&lt;br /&gt;
SolarForecast unterstützt die oben betrachtete Batteriesteuerung durch die optionale Angabe von &#039;&#039;&#039;loadAbort&#039;&#039;&#039; im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039;. Das in diesem Kontext erstellte Reading &#039;&#039;&#039;Battery_ChargeAbort_XX&#039;&#039;&#039; stellt die auswertbaren Steuerungsinformationen zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== PV-Prognose und Verbrauch optimierte Beladungssteuerung unter Berücksichtigung einer Wirkleistungsbegrenzung ====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-04-25 143910.png|right|thumb|400px|Batterie Popup &amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Batterie geladen. sobald PV-Überschuß vorhanden ist ohne eine Prognose zu berücksichtigen. Dadurch sind die Batterien im Sommer unter Umständen schon um 10-12 Uhr voll geladen und die Anlage liefert ihre mehr oder weniger volle Energie (je nach Ausrichtung) in das öffentliche Netz. Dann könnte es zu einer Begrenzung der PV-Leistung durch einen Schwellenwert (z.B. 70%-Regelung) oder eventuell Zwangsabregelung durch den Netzbetreiber kommen.&lt;br /&gt;
&lt;br /&gt;
Hintergrund dieser Erweiterung ist das Bestreben, eine optimale Unterstützung bei der Maximierung des Eigenverbrauchs zu geben und einen Beitrag zur Netzstabilität zu leisten.&lt;br /&gt;
Das Ziel der Beladungssteuerung der Batterie ist es, die Ladung der Batterie über den Tag verteilt so zu steuern, dass die Batterie erst dann geladen wird, wenn durch den PV-Überschuß eine Netzeinspeisung erfolgen würde bzw. ein Grenzwert erreicht werden würde, der zu einer Abregelung der PV-Anlage führen könnte.&lt;br /&gt;
Es kann auch zu einer Zwangsabregelung durch den Netzbetreiber führen, was vermieden werden soll.&lt;br /&gt;
 &lt;br /&gt;
Die interne Kalkulationslogik erstellt zu diesem Zweck ein Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039;.&lt;br /&gt;
Dieses Reading gibt dem User ein Signal, ob zu der aktuellen Stunde der Ladevorgang der Batterie freigegeben (1) oder nicht freigegeben werden sollte (0). Die Freigabe zur Ladung bedeutet dass:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; die Batterie mit ihrer vollen Ladeleistung angesteuert werden sollte um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=0&#039;&#039;&#039; die Batterie nur geladen werden sollte wenn der im Attribut plantControl-&amp;gt;feedinPowerLimit definierte Wert überschritten wird&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ist keine Freigabe zur Ladung vorhanden, kann bzw. sollte dennoch eine Ladung der Batterie vorgenommen werden, sofern eine über dem im &amp;lt;br&amp;gt;&lt;br /&gt;
Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limit liegende Einspeiseleistung vorhanden ist. In diesem Status sollte die Batterie nur mit der Differenzleistung von vorhandener Einspeiseleistung und dem gesetzen Einspeiselimit geladen werden und damit das gesetzte Einspeiselimit einhalten ohne die Anlage abzuregeln. Ist die Batterie in einer Balkengrafikebene dargestellt, wird im Mouse-Over Popup die Battrie mit &#039;&#039;&amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;&#039;&#039; gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Möglichkeiten der Batteriesteuerung sind stark von der individuellen Anlage abhängig und können hier nicht beschrieben werden. Ein Umsetzungsbeispiel mit einer Victron-Anlage mit Pylontech Batterie ist weiter unten dargestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Aktivierung und Arbeitsweise =====&lt;br /&gt;
&lt;br /&gt;
Die implementierte Logik zur optimierten Batterie Beladungssteuerung wird aktiviert, wenn folgende Kriterien erfüllt sind: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;capacity&#039;&#039;&#039; in den setupInverterDevXX Atributen ist gesetzt&lt;br /&gt;
* das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; für die jeweilige Batterie ist gesetzt&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;cap&#039;&#039;&#039; im Attribut setupBatteryDevXX der jeweiligen Batterie ist gesetzt&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Die Logik arbeitet wie folgt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Der resultierende Schwellenwert der Wirkleistungsbegrenzung: der Gesamtanlage wird durch die Auswertung der in den Inverter-Attributen setupInverterDevXX  gesetzen Schlüssel limit (optional) und capacity ermittelt. Inverter mit gesetztem Schlüssel feed = grid (deren Energie wird ausschließlich in das öffentlich Netz eingespeist) werden von der Betrachtung in diesem Kontext ausgeschlossen.&lt;br /&gt;
&lt;br /&gt;
;Die benötigte Beladung bis zu maxSoC (im Attribut setupBatteryDevXX) : wird ermittelt und mit der zu erwartenden PV Tagesprognose in Beziehung gesetzt. Sofern die PV-Erzeugung abzgl. Verbrauch noch nicht das Wirkleistungbegrenzungs-Limit erreicht UND noch genügend PV-Überschuß für eine Ladung auf &#039;&#039;maxSoC&#039;&#039; im Laufe der kommenden Stunden des Tages zu erwarten ist, bleibt das Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 0&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
;Wird das Wirkleistungbegrenzungs-Limit erreicht/überschritten und/oder die PV-Überschußprognose: zzgl. eines Sicherheitspuffers unterschritten, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 1&#039;&#039;&#039; gesetzt. Der User kann darauf reagieren und den Batterie Ladevorgang aktivieren. Die Möglichkeiten der Aktivierung sind natürlich von der installierten Anlage abhängig. Das SolarForecast Device greift nicht in die Batteriesteuerung direkt ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders ausgedrückt erfolgt immer dann eine Ladefreigabe, wenn einer der nachfolgenden Sachverhalte &#039;&#039;wahr&#039;&#039; ist:&lt;br /&gt;
&lt;br /&gt;
- die benötigte Ladeenergie (aller installierten Batterien) &amp;gt;= PV-Restüberschuß des Tages (Reading RestOfDayPVforecast) zzgl. Sicherheitsaufschlag&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- der Zeitpunkt des PV-Erzeugungszenit des laufenden Tages überschritten ist (Reading Today_MaxPVforecastTime)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn die aktuelle PV Leistung &amp;gt;= einer eventuellen Wechselrichter-Leistungsbegrenzung ist (Summe aller WR-Begrenzungen)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn das BatSoc-Management _nicht_ aktiviert ist (nicht alle oben genannten Aktivierungskriterien erfüllt sind)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind mehrere Batterien installiert und durch das Management einer Batterie die Einhaltung der genannten Kriterien bzw. Sachverhalte erwirkt wird, bleiben die weiteren Batterien im Modus Ladefreigabe (Battery_ChargeUnrestricted_XX=1).  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Umsetzungsbeispiel Batterie Ladesteuerung mit Victron GX Venus über den Grid Setpoint =====&lt;br /&gt;
&lt;br /&gt;
Ziel der Steuerung ist es abhängig vom Wert des Readings Battery_ChargeUnrestricted_XX (z.B. Battery_ChargeUnrestricted_01) die Ladung des angeschlossenen Batteriesystems zu aktivieren bzw. zu deaktivieren.&lt;br /&gt;
Das vorliegende Beispiel soll umzusetzen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 0 -&amp;gt; Batterie nicht aufladen bzw. nur laden wenn Einspeiselimit überschritten (Attribut plantControl-&amp;gt;feedinPowerLimit)&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 1 -&amp;gt; Batterie aufladen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Grid Setpoint ist ein Parameter in den Victron Systemeinstellungen. Das Victron System wird den eingestellten Grid Setpoint versuchen einzuhalten und bei einem positiven Wert Energie aus dem Netz beziehen bzw. bei einem negativen Grid Setpoint Energie in das Netz einspeisen.&lt;br /&gt;
&lt;br /&gt;
Normalerweise wird das Victron System die erzeugte PV Energie zunächst zur Deckung des Hausverbrauchs verwenden, ist dann noch ein PV Überschuß vorhanden, die Batterien aufladen und bei weiter vohandenen PV Überschuß diese Energie in das öffentliche Netz einspeisen sofern dem System eine Einspeisung erlaubt ist. Anderenfalls werden die Wechselrichter oder MPPT Smartloader heruntergeregelt bzw. limitiert. &lt;br /&gt;
&lt;br /&gt;
In der Standardeinstellung ist beim Victron System ein Grid Setpoint von ca. 20 bis 50 Watt, d.h. das System strebt danach diese Vorgabe zu erfüllen zieht ständig Energie in diesem Bereich aus dem öffentlich Netz von einem gelegentlichen Überschwingen der Regelung abgesehen. Damit ein eventueller PV Überschuß nicht zum Laden der Batterie verwendet, sondern statt dessen in das öffentliche Netz eingespeist wird, muß der Grid Setpoint um diesen Betrag abgesenkt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-24 114403.png|right|thumb|400px|Integration des Grid Setpoint-Managements in den Own_Spec-Bereich]]&lt;br /&gt;
&lt;br /&gt;
Damit man später per Attribut bzw. über den [[#Formatierung_der_Inhalte_im_Bereich_&amp;quot;Graphic_Header_Own_Specification&amp;quot;|Own_Spec-Bereich]] die automatische Ladesteuerung über den Grid Setpoint ein- bzw. ausschalten kann, legen wir ein userattr an:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 userattr &amp;lt;Name&amp;gt; userFn_GridSetpointManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin sind einige Vorbereitungen im Device MQTT2_cerboGX_c0619ab34e08_settings vorzunehmen. Dieses Device ist im vorliegenden Beispiel ein in FHEM vorhandenes MQTT2_DEVICE, über das die Victron CerboGX Einstellungen zugreifbar sowie einstellbar sind. Die Vorgehensweise zur Erstellung des MQTT2_DEVICE ist hier nicht beschrieben und wird vorausgesetzt.&lt;br /&gt;
&lt;br /&gt;
Damit ein entsprechender Set-Befehl zur Einstellung des Grid Setpoints vorhanden ist, werden folgende Attribute gesetzt:&lt;br /&gt;
&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings jsonMap Settings_CGwacs_AcPowerSetPoint_value:GridSetpoint&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings setList GridSetpoint W/c0619ab34e08/settings/0/Settings/CGwacs/AcPowerSetPoint {&amp;quot;value&amp;quot;:$EVTPART1}&lt;br /&gt;
&lt;br /&gt;
Nach dieser Attributierung kann mit einem &amp;quot;&#039;&#039;set MQTT2_cerboGX_c0619ab34e08_settings GridSetpoint &amp;lt;Wert&amp;gt;&#039;&#039;&amp;quot; der Grid Setpoint eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Das Attribut userFn_GridSetpointManagement kann nun im Perl Code ausgewertet werden um das Grid Setpoint-Management ein- bzw. auszuschalten.&lt;br /&gt;
Der nachfolgende Code wird in die Datei &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; eingefügt. Ist diese Datei nicht vorhanden, legen wir sie vorab als Kopie der ausgelieferten 99_myUtils.pm an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Steuerung Start/Stop der Batterieladung über den Victron Grid Setpoint&lt;br /&gt;
############################################################################&lt;br /&gt;
sub gridSetpointMgmt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vicsets   = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                               # Device Victron Einstellungen&lt;br /&gt;
  my $gspdef    = 20;                                                                  # Default Einstellung des Grid Setpoint&lt;br /&gt;
  my $targetgsp = $gspdef;                                                             # Voreinstellung Grid Setpoint&lt;br /&gt;
  my $neggspmax = FHEM::SolarForecast::CurrentVal ($name, &#039;feedinPowerLimit&#039;, 5000);   # max. gewünschte Einspeiseleistung in Watt&lt;br /&gt;
  $neggspmax    = $neggspmax * -1;&lt;br /&gt;
  my $gspm      = AttrVal ($name, &#039;userFn_GridSetpointManagement&#039;, &#039;aus&#039;);             # Freischaltung des Grid Setpoint-Managements&lt;br /&gt;
  my $curgsp    = ReadingsNum ($vicsets, &#039;GridSetpoint&#039;,         $gspdef);             # aktuelle Einstellung Grid Setpoint&lt;br /&gt;
  &lt;br /&gt;
  if ($gspm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name, &#039;Battery_ChargeUnrestricted_01&#039;, 0);         # Ladefreigabe (1 -&amp;gt; Bat Ladefreigabe)&lt;br /&gt;
    my $surp = ReadingsNum ($name, &#039;Current_Surplus&#039;,               0);         # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if (!$bcrq) {                                                               # Grid Setpoint absenken wenn keine .. &lt;br /&gt;
        $targetgsp = $gspdef - $surp;                                           # ..Batterie Ladefreigabe&lt;br /&gt;
        $targetgsp = $neggspmax if($targetgsp &amp;lt; $neggspmax);                    # Begrenzung der Einspeiseleistung&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($curgsp != $targetgsp) {&lt;br /&gt;
	  fhem (&amp;quot;set $vicsets GridSetpoint $targetgsp&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn gridSetpointMgmt -&amp;gt; GridSetpoint in $vicsets set to $targetgsp});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Victron_GridSetpoint_set&#039;, $targetgsp, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Vergleich des Setpoints mit der Vorgabe von &#039;&#039;$neggspmax&#039;&#039; dient dazu die maximale Einspeiseleistung in das öffentliche Netz zu begrenzen. Ist diese Grenze erreicht, wird der noch verbleibende Überschuß in die Batterie geladen. Dadurch wird eine Abregelung der Anlage vermieden wenn der Schwellenwert &#039;&#039;$neggspmax&#039;&#039;erreicht ist sofern die Batterie aufnahmefähig ist und nicht voll geladen ist. &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::gridSetpointMgmt  ($name);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zum Management des automatischen Grid Setpoint und der Anzeige des eingestellten Wertes wird das Attribut und die Readinganzeige in den Own_Spec-Bereich eingebunden, z.B.:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; graphicHeaderOwnspec  #Settings&lt;br /&gt;
                                   SetPoint&amp;amp;nbsp;Management:userFn_GridSetpointManagement&lt;br /&gt;
                                   Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Unterstützung eines netzdienlichen Verhaltens ====&lt;br /&gt;
&lt;br /&gt;
Der Steuerungsprozess der Batterieanlage leistet insgesamt einen kleinen Beitrag zur Netzstabilität, indem die Speicherladung in den Zeitraum der meisten prognostizierten Überschußeinspeisung gelegt wird. Im Sommer kann sich dieser Zeitraum in die Zeit nach dem Maxmimum des prognostizierten PV-Überschusses verlagern, wenn auch danach noch genügend Überschußenergie zu Volladung der Batterie prognostiziert wird. In dem Zusammenhang sollte im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; ein Einspeiselimit gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zur Verdeutlichung soll das Beispiel dienen:&lt;br /&gt;
&lt;br /&gt;
* die Batterie ist zu 60% geladen &lt;br /&gt;
* der User hat upSoC=40 eingestellt&lt;br /&gt;
* der User hat maxSoC=90 eingestellt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Am Vormittag ist genügend Sonne vohanden, das Maximumum der Energie über die Zeit wird aber noch erwartet. &lt;br /&gt;
Zu diesem Zeitpunkt wird das Reading  &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039; auf den Wert &amp;quot;0&amp;quot; gesetzt. Durch den Nutzer erfolgt daraufhin, zum Beipiel über ein Notify, ein anlagenspezifischer Befehl &amp;quot;Ladestop&amp;quot; an die Batterieanlage. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ab diesem Moment wird:&lt;br /&gt;
&lt;br /&gt;
# die Batterie nicht geladen&lt;br /&gt;
# die erzeugte PV-Energie dem Haushalt zur Verfügung gestellt bzw. der verbleibende Überschuß eingespeist, sofern der Überschuß unterhalb des im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limits liegt.&lt;br /&gt;
# ein eventuell über dem Limit &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; vorhandener Überschuß in die Batterie geladen und so die Netzlast verringert sowie die Batterie schonend geladen. (dieser Punkt trifft in den Monaten mit wenig PV-Erzeugung eher nicht zu)  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig liefert die Batterie Energie an das Hausnetz und wird von 60% bis maximal einem SoC-Wert entladen, der durch die [[#Die_dynamische_SOC_Steuerung_mit_Umsetzungsbeispiel|dynamische SOC Steuerung]] bestimmt wird. Dazu muß diese Steuerung natürlich implementiert sein. Sofern der berechnete SoC größer als upSoC ist, wird der maximale Entladungs-SoC auf upSoC gesetzt. &lt;br /&gt;
&lt;br /&gt;
Zusätzlich überprüft das Modul permanent bei jedem Zyklus die Differenz des aktuell vorhandenen SoC zum eingestellten maxSoC.&lt;br /&gt;
Sie soll nicht größer sein um mit dem (noch) zu erwartenden PV-überschuß des Tages der eingestellte maxSoC bzw. dessen Nähe wahrscheinlich erreicht werden kann. &lt;br /&gt;
Sollte der Differenz-Grenzwert erreicht sein, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; gesetzt und der Nutzer sollte dann über einen geeigneten Befehl seine Anlage in den Modus &amp;quot;Laden&amp;quot; umschalten.&lt;br /&gt;
Dieser Vorgang kann beliebig oft während des Tages alternieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Nutzung von batteryTrigger ===&lt;br /&gt;
Ergänzt werden die Möglichkeiten durch das set-Kommando: &lt;br /&gt;
&lt;br /&gt;
 batteryTrigger &amp;lt;1on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;1off&amp;gt;=&amp;lt;Wert&amp;gt; [&amp;lt;2on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;2off&amp;gt;=&amp;lt;Wert&amp;gt; ...] &lt;br /&gt;
&lt;br /&gt;
Das Kommando setzt Triggerpunkte bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %).&lt;br /&gt;
&lt;br /&gt;
Der verwendete SoC wird als resultierender SoC als Summe der aktuellen Ladung aller registrierten Batterie-Geräte im Verhältnis zur installierten Gesamtkapazität gebildet. Das bedeutet, dass alle einzelnen Batterie-Geräte als ein gemeinsamer Cluster betrachtet werden. &lt;br /&gt;
&lt;br /&gt;
Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise definiert werden.&lt;br /&gt;
Überschreiten die letzten drei SoC-Messungen eine definierte Xon-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = on&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
Unterschreiten die letzten drei SoC-Messungen eine definierte Xoff-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = off&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
&lt;br /&gt;
Der Inhalt der Readings kann durch ein User-Programm oder, bei Erzeugung von entsprechenden Events, mittels notify-Device ausgewertet werden um bei Eintreten eines definierten Ereignisses entsprechende Reaktionen auszulösen. Das kann zum Beispiel die Freigabe eines Heizstabes oberhalb eines bestimmten SOC sein oder ein Entladeverbot der Batterie unterhalb eines SOC-Wertes um Reserven für einen eventuellen Stromausfall zu behalten.&lt;br /&gt;
&lt;br /&gt;
Damit die Batterietrigger dynamisch geändert werden können, ist die Einstellung als Set-Kommando und nicht als Attribut ausgeführt.   &lt;br /&gt;
&lt;br /&gt;
Alle Triggerpunkte können mit dem set-Befehl:&lt;br /&gt;
&lt;br /&gt;
 reset batteryTriggerSet&lt;br /&gt;
&lt;br /&gt;
wieder gelöscht werden.&lt;br /&gt;
&lt;br /&gt;
== Verbrauchersteuerung - Registrieren und visualisieren 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;
Die Eigenschaften und das Schaltverhalten wird durch die Angabe der verfügbaren Schlüssel gesteuert. Die Möglichkeiten sind sehr umfangreich. Die nachfolgenden Abschnitte beschreiben die Verwendung am Beispiel oft vorkommender bzw. nachgefragter Sachverhalte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die Phasen der Verbrauchersteuerung ===&lt;br /&gt;
&lt;br /&gt;
Jeder Zyklus eines Verbrauchers durchläuft im Modul die folgenden Phasen:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Planung&#039;&#039;&#039; der Aktivzeiten des Verbrauchers, d.h. wann der Verbraucher geplant eingeschaltet sowie geplant ausgeschaltet wird und damit der Zyklus beendet wird.&lt;br /&gt;
# &#039;&#039;&#039;Start&#039;&#039;&#039; des Zyklus, d.h. Einschalten des Verbrauchers entsprechend der Planungsdaten sofern weitere, in den Consumer-Schlüsseln definierbare Rahmenbedingungen das Einschalten nicht verhindern (z.B. kein oder zu wenig PV-Energieerzeugung / PV-Überschuss)&lt;br /&gt;
# &#039;&#039;&#039;Permanente Überprüfung von&#039;&#039;&#039; eventuell vorhandenen &#039;&#039;&#039;Interruptbedingungen&#039;&#039;&#039; die den Verbraucher temporär ausschalten und, sofern die Interruptbedingung nicht mehr vorliegt, den Verbraucher wieder einschalten und so den gestarteten Zyklus fortsetzen.&lt;br /&gt;
#  &#039;&#039;&#039;Beendigung&#039;&#039;&#039; der Zyklus. Die Beendigung erfolgt entweder (normalerweise) wenn die geplante Endezeit der Zyklus erreicht ist oder eine optionale Endebedingung erfüllt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Steuerung der Phasen ====&lt;br /&gt;
Der Ablauf der Phasen kann durch verschiedene Schlüssel-Wert Paare beeinflusst und gesteuert werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; kann eine &#039;&#039;&#039;zusätzliche externe Bedingung&#039;&#039;&#039; definiert werden um den Einschaltvorgang des Consumers freizugeben. Ist die Bedingung (Regex) nicht erfüllt, erfolgt kein Einschalten des Verbrauchers auch wenn die sonstigen Voraussetzungen wie Zeitplanung, on-Schlüssel, auto-Mode und aktuelle PV-Leistung gegeben sind. Es erfolgt somit eine &#039;&#039;&#039;UND-Verknüpfung&#039;&#039;&#039; des Schlüssels swoncond mit den Planungsdaten und weiteren Einschaltbedingungen.&lt;br /&gt;
&lt;br /&gt;
Der optionale Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; definiert eine &#039;&#039;&#039;vorrangige Ausschaltbedingung&#039;&#039;&#039; (Regex). Sobald diese Bedingung erfüllt ist, wird der Consumer ausgeschaltet auch wenn die geplante Endezeit (consumerXX_planned_stop) noch nicht erreicht ist (&#039;&#039;&#039;ODER-Verknüpfung&#039;&#039;&#039;). Weitere Bedingungen wie off-Schlüssel und auto-Mode müssen zum automatischen Ausschalten erfüllt sein.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; kann während der geplanten Einschaltzeit eine automatische Unterbrechung sowie Wiedereinschaltung des Verbrauchers vorgenommen werden. Der Verbraucher wird temporär ausgeschaltet (interrupted) und wieder eingeschaltet (continued) wenn die Interrupt-Bedingung nicht mehr vorliegt. Die verbleibende Laufzeit wird durch einen Interrupt nicht beeinflusst! &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;power&#039;&#039;&#039; gibt die nominale Leistungsaufnahme des Verbrauchers gemäß seines Datenblattes an. Dieser Wert wird verwendet um die Schaltzeiten des Verbrauchers zu planen und das Schalten in Abhängigkeit des tatsächlichen PV-Überschusses zum Einplanungszeitpunkt zu steuern. Ist &#039;&#039;&#039;power=0&#039;&#039;&#039; gesetzt, wird der Verbraucher unabhängig von einem zum Zeitpunkt des Zyklus-Start eventuell nicht ausreichend vorhandenem PV-Überschuss wie geplant eingeschaltet und somit der Zyklus gestartet.&lt;br /&gt;
&lt;br /&gt;
Durch die Schlüssel &#039;&#039;&#039;notbefore&#039;&#039;&#039; und &#039;&#039;&#039;notafter&#039;&#039;&#039; kann der Startzeitpunkt des Verbrauchers so gesteuert werden, dass der Start des Zyklus nicht vor bzw. nach der angegebenen Zeit eingeplant wird. Diese Steuerung bezieht sich auf die &#039;&#039;Planung&#039;&#039;, d.h. der eigentliche Start des Verbrauchers kann sich unter Umständen durch vorhandene Rahmenbedingungen verzögern. &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; legt die geplanten Einschaltzeit, d.h. die Laufzeit des Zyklus fest. Der Name &#039;&#039;&#039;mintime&#039;&#039;&#039; ist nicht als MInimum-Zeit zu deuten, sondern beschreibt die angegebene Zeit in Minuten die der Zyklus dauern soll.&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist optional, da sich die Standard-Laufzeit des Verbrauchers von dessen Typ abgeleitet wird. Diese Standard Laufzeiten sind:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|dryer&lt;br /&gt;
|90 Minten&lt;br /&gt;
|-&lt;br /&gt;
|dishwasher&lt;br /&gt;
|180 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|washingmachine&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|heater&lt;br /&gt;
|240 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|charger&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|other&lt;br /&gt;
|60 Minuten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Der Verbraucher wurde nicht gestartet obwohl die Startzeit der Einplanung erreicht wurde ===&lt;br /&gt;
&lt;br /&gt;
Wenn die Startzeit des Consumers entsprechend der Einplanung erreicht oder überschritten ist, wird der Consumer eingeschaltet wenn die weiteren Voraussetzungen wahr sind:&lt;br /&gt;
&lt;br /&gt;
* es ist aktuell ein PV-Überschuss vorhanden und der PV-Überschuss deckt die kalkulierten Leistungsaufnahme des Verbrauchers ab. Mit den Schlüsseln &#039;&#039;&#039;power&#039;&#039;&#039; und &#039;&#039;&#039;spignorecond&#039;&#039;&#039; kann die Einschaltung trotz fehlendem PV-Überschuss ermöglicht werden. &lt;br /&gt;
&lt;br /&gt;
* die Angabe im Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; ist wahr (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* das Schalten ist über den Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; freigegeben (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* im Schlüssel &#039;&#039;&#039;on&#039;&#039;&#039; ist ein valides Einschaltkommando hinterlegt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind diese zusätzlichen Bedingungen nicht erfüllt, erfolgt kein Start des eingeplanten Zyklus. Der Verbraucher verbleibt in diesem Fall weiterhin im Status &#039;&#039;planned&#039;&#039; oder &#039;&#039;suspended&#039;&#039;. Die Startbedingungen werden regelmäßig reviewed und der Consumer gestartet sobald alle Startbedingungen wahr sind bzw. Start verhindernde Bedingungen entfallen sind. &lt;br /&gt;
&lt;br /&gt;
Dieser Vorgang erfolgt bis das geplante Ende des Verbaucherzyklus erreicht ist oder die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; zutrifft. Sobald die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; wahr ist, wird der gesamte Planungszyklus des Consumers beendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Kann manuell / automatisiert in den Planungszyklus eines Verbrauchers eingegriffen werden? ===&lt;br /&gt;
&lt;br /&gt;
Die Einplanung und die darauf aufbauenden Schaltprozesse laufen gemäß den hinterlegten Schlüsseloptionen im Modul automatatisch ab ohne dass ein Eingriff durch den Anwender erfolgen muß.&lt;br /&gt;
&lt;br /&gt;
Dennoch kann es gewünscht sein eine Neuplanung oder eine Sofortplanung eines Consumers vorzunehmen weil der Bedarf dazu besteht. Zu diesem Zweck stehen die Set-Kommandos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* consumerNewPlanning &lt;br /&gt;
&lt;br /&gt;
* consumerImmediatePlanning &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
zur Verfügung. &lt;br /&gt;
Beide Befehle initiieren die Consumer-Neuplanung, wobei mit dem Befehl &#039;&#039;consumerImmediatePlanning&#039;&#039; die eventuell im consumerXX Attribut gesetzten Schlüssel notbefore, notafter bzw. mode werden nicht beachtet werden. Dagenen beachtet der Befehl &#039;&#039;consumerNewPlanning&#039;&#039; alle definierten Schlüsseloptionen und dient gewöhnlich dazu einen abgeschlossenen Verbraucherzyklus wiederholt ausführen zu lassen weil die aktuelle Witterungslage dazu geeignet ist. &lt;br /&gt;
&lt;br /&gt;
Ein Anwendungsbeispiel dafür ist zum Beispiel die Ausführung von mehreren Waschmaschinen-Zyklen an einem langen, sonnigen Sommertag.&lt;br /&gt;
Diese beiden Set-Befehle können zum Beispiel über ein auf einen Schalter/Taster reagierendes Notify oder DOIF Device ausgeführt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung eines Verbrauchers mit getrennten Geräten für Messung und Schalten ===&lt;br /&gt;
&lt;br /&gt;
Es existieren in FHEM Geräte, die über verschiedene Kanäle für unterschiedliche Aufgaben verfügen. Diese Kanäle werden jeweils in einem gesonderten Device abgebildet. HomeMatic oder readingsProxy sind Beispiele für solche Varianten.&lt;br /&gt;
&lt;br /&gt;
Um solche Verbraucher einzubinden gibt es im consumerXX Attribut den Schlüssel &#039;&#039;&#039;switchdev&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Bei der Registrierung gibt man als Consumerdevice das Gerät für die Messung an und im Schüssel switchdev das entsprechende FHEM-Device, welches für die Schaltvorgänge benutzt wird. &lt;br /&gt;
Ist switchdev angegeben, beziehen sich die weiteren Schlüssel on, off, swstate, auto und asynchron auf dieses Gerät.&lt;br /&gt;
&lt;br /&gt;
In dem nachfolgenden Beispiel (Homematic) ist &#039;&#039;eg.az.fridge_Pwr&#039;&#039; FHEM Device für die Energiemessung. Die Schlüssel &#039;&#039;pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; geben Readings in diesem Device an damit SolarForecast den Verbrauch und die Energiemengen auslesen kann. Demgegenüber ist im Schlüssel &#039;&#039;switchdev&#039;&#039; das zugehörige Schalter-Device der Kombination angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eg.az.fridge_Pwr&lt;br /&gt;
type=noSchedule switchdev=eg.az.fridge_Sw power=0 icon=fridge pcurr=power:W:5 etotal=energyCalc:Wh &lt;br /&gt;
swstate=state:on:off auto=automatic&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung von Verbrauchern ohne Zeitplanung und aktivem Schalten ===&lt;br /&gt;
Manchmal besteht der Wunsch, Verbraucher in SolarForecast zu integrieren um lediglich folgende Sachverhalte abzubilden:&lt;br /&gt;
&lt;br /&gt;
* Visualisierung des Schaltstatus in der Consumer Legende und/oder der Energieflußgrafik&lt;br /&gt;
* Darstellung des aktuellen Energieverbrauchs in der Energieflußgrafik&lt;br /&gt;
* Erfassung der (externen) Schaltzeiten, d.h. der Zeiten der Gerätenutzung sowie der Verbrauchsdaten um deren Einfluß bei den Planungszeiten anderer Geräte durch SolarForecast berücksichtigen zu lassen&lt;br /&gt;
&lt;br /&gt;
In solchen Fällen werden bei der Registrierung die Schlüssel &#039;&#039;swstate, pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; zur Erfassung der Schaltzustände und der Energieverbrauchs angegeben, jedoch zur Verhinderung der Zeitplanung durch SolarForecast der Schlüssel &#039;&#039;&#039;type=noSchedule&#039;&#039;&#039; gesetzt sowie die Schlüssel &#039;&#039;on&#039;&#039; und &#039;&#039;off&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt eine mögliche Registrierung eines Zwischensteckers (Shelly) zur Erfassung der Daten eines Gefrierschrankes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Shelly.shellyplug4&lt;br /&gt;
type=noSchedule power=65 asynchron=1&lt;br /&gt;
icon=gefrierschrank &lt;br /&gt;
swstate=state:.*on.*:.*off.* &lt;br /&gt;
pcurr=relay_0_power:W:5 etotal=relay_0_energy_Wh:Wh&lt;br /&gt;
&amp;lt;/pre&amp;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;
&lt;br /&gt;
 Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off&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;
&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;
&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. Alternativ kann die Berücksichtigung des zwangsweisen PV Überschuss mit dem Schlüssel &amp;quot;spignorecond&amp;quot; im Consumer-Attribut ausgesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== zusätzliche Readings bzw. Erzeugung von statistischen Readings ==&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den zahlreichen im Modul per Standard erzeugten Readings kann der Anwender weitere Readings generieren lassen.&lt;br /&gt;
Diese zusätzlichen Readings geben entweder einen bestimmten Sachverhalt (Laufzeit, Status der API-Abfragen, etc.) oder einen statistischen Wert, z.B. die Batterieentladung des aktuellen Tages, wieder.&lt;br /&gt;
&lt;br /&gt;
Die zusätzlich erstellten Readings sind durch den Präfix &#039;&#039;&#039;special_&#039;&#039;&#039; im Device gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Diese zusätzlichen Informationen können durch das Setzen einer oder mehrerer Kennzeichen im Attribut &#039;&#039;&#039;ctrlSpecialReadings&#039;&#039;&#039; erzeugt werden. Die mögliche Auswahl wird je nach Bedarf ausgebaut und umfasst zum aktuellen Zeitpunkt (07.02.2025) diese Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;BatPowerIn_Sum: 	die Summe der momentanen Batterieladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;BatPowerOut_Sum: 	die Summe der momentanen Batterieentladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;allStringsFullfilled: 	Erfüllungsstatus der fehlerfreien Generierung aller Strings&lt;br /&gt;
;conForecastTillNextSunrise: 	Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
;currentAPIinterval: 	das aktuelle Abrufintervall der gewählten Strahlungsdaten-API in Sekunden&lt;br /&gt;
;currentRunMtsConsumer_XX: 	die Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; seit dem letzten Einschalten. (letzter Laufzyklus)&lt;br /&gt;
;dayAfterTomorrowPVforecast: 	liefert die Vorhersage der PV Erzeugung für Übermorgen (sofern verfügbar) ohne Autokorrektur (Rohdaten).&lt;br /&gt;
;daysUntilBatteryCare_XX: 	Tage bis zur nächsten Batterie XX Pflege (Erreichen der Ladung &#039;maxSoC&#039; aus Attribut ctrlBatSocManagementXX)&lt;br /&gt;
;lastretrieval_time: 	der letzte Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;lastretrieval_timestamp: 	der Timestamp der letzen Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;response_message: 	die letzte Statusmeldung der gewählten Strahlungsdaten-API&lt;br /&gt;
;runTimeAvgDayConsumer_XX: 	die durchschnittliche Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; an einem Tag&lt;br /&gt;
;runTimeCentralTask: 	die Laufzeit des letzten SolarForecast Intervalls (Gesamtprozess) in Sekunden&lt;br /&gt;
;runTimeTrainAI: 	die Laufzeit des letzten KI Trainingszyklus in Sekunden&lt;br /&gt;
;runTimeLastAPIAnswer: 	die letzte Antwortzeit des Strahlungsdaten-API Abrufs auf einen Request in Sekunden&lt;br /&gt;
;runTimeLastAPIProc: 	die letzte Prozesszeit zur Verarbeitung der empfangenen Strahlungsdaten-API Daten&lt;br /&gt;
;SunMinutes_Remain: 	die verbleibenden Minuten bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;SunHours_Remain: 	die verbleibenden Stunden bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;todayConsumptionForecast: 	Verbrauchsprognose pro Stunde des aktuellen Tages (01-24)&lt;br /&gt;
;todayConForecastTillSunset: 	Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
;todayDoneAPIcalls: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Calls&lt;br /&gt;
;todayDoneAPIrequests: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Requests&lt;br /&gt;
;todayConsumption: 	der gesamte Energieverbrauch (Wh) des Hauses am aktuellen Tag&lt;br /&gt;
;todayGridConsumption: 	die aus dem öffentlichen Netz bezogene Energie am aktuellen Tag&lt;br /&gt;
;todayGridFeedIn: 	die in das öffentliche Netz eingespeiste PV Energie am aktuellen Tag&lt;br /&gt;
;todayMaxAPIcalls: 	die maximal mögliche Anzahl Strahlungsdaten-API Calls. Ein Call kann mehrere API Requests enthalten.&lt;br /&gt;
;todayRemainingAPIcalls: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Calls&lt;br /&gt;
;todayRemainingAPIrequests: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Requests&lt;br /&gt;
;todayBatIn_XX: 	die am aktuellen Tag in die Batterie XX geladene Energie&lt;br /&gt;
;todayBatInSum: 	Summe der am aktuellen Tag in alle Batterien geladene Energie&lt;br /&gt;
;todayBatOut_XX: 	die am aktuellen Tag aus der Batterie XX entnommene Energie&lt;br /&gt;
;todayBatOutSum: 	Summe der am aktuellen Tag aus allen Batterien entnommene Energie&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Manche Angaben sind im Setup des Moduls optional, d.h. sie müssen nicht zwingend beim Setup angegeben werden. Allerdings sind diese Angaben für die Erstellung eines zusätzlichen Readings unter Umständen Voraussetzung. Es empfiehlt sich deshalb bei Setup so viele Informationen wie möglich zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
So ist zum Beispiel für die sinnvolle Erstellung der Informationen &#039;&#039;&#039;todayBatInSum&#039;&#039;&#039; und &#039;&#039;&#039;todayBatOutSum&#039;&#039;&#039; (Readings special_todayBatInSum und special_todayBatOutSum) das Vorhandensein der Schlüssel &#039;&#039;intotal&#039;&#039; und &#039;&#039;outtotal&#039;&#039; im Attribut setupBatteryDevXX notwendig (Beispiel):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupBatteryDev01 MQTT2_cerboGX_c0619ab34e08_battery &lt;br /&gt;
                              pin=BatIn:W pout=BatOut:W charge=SOC_value intotal=BatInTotal:Wh outtotal=BatOutTotal:Wh &lt;br /&gt;
                              cap=InstalledCapacity_Wh:Wh asynchron=1 show=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Fehlersuche ==&lt;br /&gt;
Das Modul SolarForecast ist sehr komplex und es die verschiedensten Datenquellen ausgewertet, zusammengeführt und daraus Ergebnisse berechnet und/oder visualisiert. Wird etwas nicht wie erwartet durch das Modul geliefert, können die Ursachen vielfältig sein. Natürlich kann ein Fehler im Modulcode vorliegen, oftmals gibt es aber andere Ursachen.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgenden Hinweise sollen Hilfe zur Selbsthilfe geben und sind eine Zusammenfassung von realen Fällen die mit dem beschriebenen Wegen und Verfahren gelöst wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die erwartete erzeugte PV-Energie ist im Modul zu gering und wird im Balkendiagramm nicht angezeigt === &lt;br /&gt;
&lt;br /&gt;
Die erzeugte PV-Energie wird nicht richtig angezeigt: Am Vormittag sind keine Werte vorhanden und, wenn dann etwas kommt, ist die Anzeige zu gering. Für 13 und 14 Uhr wurden ca. 5.000Wh erwartet (im Vergleich mit den Daten aus einer anderen Auswertungsquelle). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lösungsweg:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Aus dem List des Devices wurden die für den Fall wesentlichen Readings herausgezogen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVforecast 152 Wh&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVforecast 1400 Wh&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVforecast 2500 Wh&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVforecast 4392 Wh&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVforecast 4000 Wh&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVreal 300 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVforecast 6415 Wh&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVreal 3200 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVforecast 5629 Wh&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVreal 2700 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVforecast 3958 Wh&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVreal 900 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVforecast 945 Wh&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVreal 500 Wh&lt;br /&gt;
   &lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour18_PVforecast 59 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man sieht dass bis 12:00 keine erzeugte Energie vom WR gemeldet wird. Deswegen wird in der Balkengrafik nichts dargestellt. Auch danach bleibt die registrierte PV-Energie hinter den Erwartungen zurück. Zuständig für die Lieferung der PV-Energie an das Modul ist das Reading im Schlüssel:&lt;br /&gt;
&lt;br /&gt;
 setupInverterDev01 SH10rt pv=Total_DC_Power:W &amp;lt;mark&amp;gt;etotal=Total_Export_Energy_from_PV:kWh&amp;lt;/mark&amp;gt; capacity=10000 strings=Hauptdach,Flachdach&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Welche Änderungen es zwischen den Stunden gab, sieht man mit einem &amp;quot;get ... pvHistory XX&amp;quot; (&amp;quot;XX&amp;quot; steht für das Datum, d.h. den Tag, z.B. 02). &amp;lt;br&amp;gt;&lt;br /&gt;
Hier ein Beispiel für die Stunden 10 (9:00 - 9:59) und 11 (10:00 - 10:59). &amp;lt;br&amp;gt;&lt;br /&gt;
Wichtig ist hier der Key etotali01 für den ersten Inverter. Die Differenz zwischen den Werten beider Stunden ist die in der Stunde erzeugte Energie (hier 380 Wh). Diese 380 Wh findest du auch im Key pvrl01 als PVReal für diese Stunde. Das Modul rechnet intern immer mit Wh, kWh werden vorher in Wh umgerechnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
10 =&amp;gt; pvfc: 365, pvrl: 530, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63364714&amp;lt;/mark&amp;gt;, etotali02: 3044110, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;pvrl01: 380&amp;lt;/mark&amp;gt;, pvrl02: 150, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 574, con: 518, gcons: 22, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 1, feedprice: 0.1269&lt;br /&gt;
&lt;br /&gt;
            DoN: 1, sunaz: 137, sunalt: 12&lt;br /&gt;
&lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
      11 =&amp;gt; pvfc: 2966, pvrl: 1862, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63365094&amp;lt;/mark&amp;gt;, etotali02: 3044260, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            pvrl01: 1392, pvrl02: 470, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 774, con: 609, gcons: 25, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 4, feedprice: 0.1269&lt;br /&gt;
           &lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
D.h. wenn zwischen den beiden Stunden keine Differenzen zu finden sind, liegt es sehr wahrscheinlich am Input des Readings:&lt;br /&gt;
&lt;br /&gt;
 etotal=Total_Export_Energy_from_PV:kWh&lt;br /&gt;
&lt;br /&gt;
welches sich in den ersten Stunden nicht ändert und danach auch nur wenig.&lt;br /&gt;
&lt;br /&gt;
Man kann mit dem Attribut:&lt;br /&gt;
&lt;br /&gt;
 ctrlDebug=collectData&lt;br /&gt;
&lt;br /&gt;
die Datensammlung verfolgen (leider entstehen viele Daten im Log). Man sieht welche Werte von dem Inverter/Reading geliefert werden:&lt;br /&gt;
 &lt;br /&gt;
 ....&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; collect Inverter 01 data - device: STP_5000, delivery: default =&amp;gt;&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; pv: 0 W, &amp;lt;mark&amp;gt;etotal: 63378810 Wh&amp;lt;/mark&amp;gt;&lt;br /&gt;
 ....&lt;br /&gt;
&lt;br /&gt;
Dieser Wert muß bei PV Erzeugung kontinuierlich hochzählen. Wenn nicht, muss das angegebene Reading, d.h. die Quelle überprüft werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ergebnis der Prüfung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tatsächlich wurde ein Reading benutzt, das ungeeignet war: Statt &amp;quot;Total_PV_Generation&amp;quot; wurde &amp;quot;Total_export_energy_from_PV&amp;quot; genutzt. In diesem Reading wurde immer die in die Batterie gespeicherte Energie von der gesamten erzeugten Energie abgezogen. Daher war auch vormittags alles 0, da in dieser Periode alle PV-Energie in die Batterie geladen wurde bzw. in weiteren Stunden ein Anteil der dann bei dem PV-Erzeugungswert fehlte.&lt;br /&gt;
&lt;br /&gt;
Nachdem die Ursache beseitigt war, zeigt SolarForecast wieder die erwarteten PV-Erzeugungswerte an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Konfigurationsbeispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Visualisierung solare Vorhersage und reale Erzeugung ===&lt;br /&gt;
&lt;br /&gt;
Zu Beginn jedes neuen Tages gegen 00:00 Uhr werden durch das SolarForecast Device Events für die initiale PV Prognose des kommenden Tages erstellt.&lt;br /&gt;
Der Readingteil dieser Events heißt&lt;br /&gt;
&lt;br /&gt;
 AllPVforecastsToEvent&lt;br /&gt;
&lt;br /&gt;
Die Uhrzeiten der Events sind so aufbereitet und können direkt geloggt werden um sie in einen SVG Plot zu integrieren.&lt;br /&gt;
Im SolarForecast Device ist dieses Reading nicht sichtbar, nur die Events werden erstellt.&lt;br /&gt;
&lt;br /&gt;
Die meteorologischen Bedingungen verändern sich über den Tag permanent. Je nach gewählter Strahlungsdatenquelle (eine API oder DWD Device) erfolgt eine mehr oder weniger dynamische Anpassung der Prognose an die sich verändernde Umwelt.&lt;br /&gt;
&lt;br /&gt;
Aktuelle Prognosedaten sowie die reale PV Erzeugung der vergangenen Stunde können über die Readings&lt;br /&gt;
&lt;br /&gt;
 LastHourPVforecast&lt;br /&gt;
 LastHourPVreal&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-10-20 134050.png|right|thumb|400px|Übersicht solare Vorhersage]]&lt;br /&gt;
geloggt werden. &lt;br /&gt;
&lt;br /&gt;
Werden alle drei Werte in einem SVG kombiniert, kann die Entwicklung der Prognose über den Tag und die Beziehung von Prognose zu realer PV Erzeugnung pro Stunde visualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Für das rechts abgebildete Beispiel des Plots aus einer Datenbank &amp;quot;LogDBShort&amp;quot; sieht das gplot-File wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Created by FHEM/98_SVG.pm, 2024-03-08 15:05:31&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;TL&amp;gt;&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid&lt;br /&gt;
set ylabel &amp;quot;Wh&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Wh&amp;quot;&lt;br /&gt;
set yrange [0:7500]&lt;br /&gt;
set y2range [0:7500]&lt;br /&gt;
&lt;br /&gt;
#LogDBShort SolCast:LastHourPVforecast:::&lt;br /&gt;
#LogDBShort SolCast:LastHourPVreal:::&lt;br /&gt;
#LogDBShort SolCast:AllPVforecastsToEvent:::&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;aktuelle PV Vorhersage&#039; ls l6fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;reale PV Erzeugung&#039; ls l2fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;initiale PV Vorhersage&#039; ls l4 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; In manchen Fällen werden die Vorhersagewerte im SVG-Plot nicht angezeigt wenn FileLog verwendet wird. Ein Setzen des Attribute &amp;quot;fixedrange=3days +1&amp;quot; im SVG löst das Problem. Die Definition des SVG-Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_LogDBShort_SolCast SVG LogDBShort:SVG_LogDBShort_SolCast:HISTORY&lt;br /&gt;
attr SVG_LogDBShort_SolCast fixedrange 3days +1&lt;br /&gt;
attr SVG_LogDBShort_SolCast room Energie-&amp;gt;SolarPrognose&lt;br /&gt;
attr SVG_LogDBShort_SolCast sortby 2&lt;br /&gt;
attr SVG_LogDBShort_SolCast title &amp;quot;Übersicht solare Vorhersage&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Technisch bedingt werden an einem Tag X kurz nach 00:00 Uhr die am Vortag für den Tag X erzeugten Events aktualisiert. Diese Daten erzeugen in der Datenbank einen zweiten Satz an Daten mit dem gleichen Timestamp was für die Anzeige unvorteilhaft ist. &lt;br /&gt;
Um nur die aktualisierten Events von &#039;&#039;&#039;AllPVforecastsToEvent&#039;&#039;&#039; in der Datenbank zu erhalten, bietet sich ein DbRep-Device an. Die nachfolgende Vorschlagsdefinition kann per at-Device jeden Tag kurz vor Mitternacht (z.B. 23:57:10) ausgeführt werden. Es werden immer die in der Vergangenheit geschriebenen (veralteten) Daten aus der Datenbank gelöscht, doppelte Datesätze vermieden und immer die aktuellste initiale Prognose gespeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.Del.AllPVforecastsToEvent DbRep LogDBShort&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent alias Löschen Readings AllPVforecastsToEvent des Folgetages&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent comment ermöglicht dass die Readings AllPVforecastsToEvent am Folgetag wieder neu und aktuell geschrieben werden können&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent devStateIcon initialized:control_3dot_hor_s connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent disable 0&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent event-on-update-reading state&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent icon edit_delete&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent showproctime 1&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent device TYPE=SolarForecast&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_begin next_day_begin&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_end next_day_end&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das angegebene DbLog-Device &#039;&#039;&#039;LogDBShort&#039;&#039;&#039; ist natürlich anzupassen.&lt;br /&gt;
&lt;br /&gt;
Das at-Device zum Starten der Datenbankbereinigung sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define At.Del.AllPVforecastsToEvent at *23:58:10 set Rep.Del.AllPVforecastsToEvent delEntries&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent alias Start Löschen Readings AllPVforecastsToEventn LogDBShort&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent icon clock&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich sind auch hier die eigenen Devicenamen entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
Ab SolarForecast Version 1.51.7 kann die Eventerzeugung für bestimmte SVG Plot-Typen optimiert werden. &amp;lt;br&amp;gt; &lt;br /&gt;
Die Aktivierung dieser Optimierungen ist in der Online Hilfe zum Attribut &#039;&#039;&#039;plantControl-&amp;gt;genPVforecastsToEvent&#039;&#039;&#039; beschrieben. Bei Nutzung des Attributes plantControl-&amp;gt;genPVforecastsToEvent ist ebenfalls das Attribut &#039;&#039;&#039;event-on-update-reading=AllPVforecastsToEvent&#039;&#039;&#039; zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispielkonfiguration 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;
Bitte dabei diese DWD-Version aus dem [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter Contrib] von DS_Starter dazu nutzen&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|55_DWD_OpenData.pm&lt;br /&gt;
|136.2 KB ​&lt;br /&gt;
|29260  &lt;br /&gt;
|DS_Starter&lt;br /&gt;
|55_DWD_OpenData: contrib 1.17.7&lt;br /&gt;
|}&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 downloadTimeout 120&lt;br /&gt;
attr DWD comment Im DWD Wetterdevice verwendet Solarforecast : \&lt;br /&gt;
TTT,Neff,RR1c,ww,SunUp,SunRise,SunSet \&lt;br /&gt;
zusätzlich ist jedoch auch noch Rad1h notwendig \&lt;br /&gt;
wenn dieses DWD-Device als Strahlungsdevice genutzt wird.\&lt;br /&gt;
Die Station 10418 (Lüdenscheid) überträgt aktuell am 09.03.2025 (noch) Rad1h.\&lt;br /&gt;
attr DWD downloadTimeout 120&lt;br /&gt;
attr DWD forecastDays 7&lt;br /&gt;
attr DWD forecastProperties SunUp, SunRise, SunSet, Rad1h, R101, RR1c, TTT, Tx, Tn, Tg, DD, FX1, RR6c, R600, RRhc, Rh00, ww, wwd, Neff&lt;br /&gt;
attr DWD forecastRefresh 1&lt;br /&gt;
attr DWD forecastResolution 1&lt;br /&gt;
attr DWD forecastStation 10418&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 fc_description  -(state fc_time)&lt;br /&gt;
attr DWD verbose 2&lt;br /&gt;
&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;
defmod InverterDummy dummy&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;
defmod 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 feedinPrice 0.08&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 powerCost 0.25&lt;br /&gt;
attr SMA_Energymeter room 015_Zaehler,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;
defmod 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;
attr BatteryDummy userReadings total_pac, power_out, power_in, chargestatus, bat_rated_capacity, bat_loadtotal, bat_unloadtotal&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;
defmod N.PV.TotalConsumption.Dum.Energy notify SMA_Energymeter:Saldo_Wirkleistung:.* {\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung_2 Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&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;MB_USRW610_004&amp;quot;,&amp;quot;Power_Sum__W&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;
fhem &amp;quot;setreading InverterDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(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;
#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;
 # Batterie-total_pac  InverterDummy\&lt;br /&gt;
my $wert7 = sprintf(&amp;quot;%.3f&amp;quot;,((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy bat_rated_capacity &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert7));;\&lt;br /&gt;
 # möglicher Aufruf einer Batterie-Bebladung-Routine....SMABatteryChargewithTibber();;\&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;
defmod Forecast SolarForecast&lt;br /&gt;
attr Forecast DbLogExclude .*&lt;br /&gt;
attr Forecast DbLogInclude Current_BatCharge999&lt;br /&gt;
attr Forecast affectBatteryPreferredCharge 30&lt;br /&gt;
attr Forecast affectConsForecastLastDays 31&lt;br /&gt;
attr Forecast affect70percentRule 0&lt;br /&gt;
attr Forecast comment &amp;quot;wget -qO ./FHEM/76_SolarForecast.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/76_SolarForecast.pm&amp;quot;\&lt;br /&gt;
&amp;quot;wget -qO ./FHEM/55_DWD_OpenData.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/55_DWD_OpenData.pm&amp;quot;\&lt;br /&gt;
&amp;quot;13.01.2025 mit der Version 76_SolarForecast.pm:v1.43.2-s29518/2025-01-12&amp;quot;&lt;br /&gt;
attr Forecast graphicHeaderOwnspec PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal Verbrauch&amp;amp;nbsp;;bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast  Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest FCU-Erzeugung&amp;amp;nbsp;;:Current_PP01\&lt;br /&gt;
attr Forecast consumer01 FBDECT_fbahahttp_11657_0127183 icon=scene_washing_machine@orange type=washingmachine power=10 swstate:state notbefore=09 notafter=20 pcurr=power:W:3 etotal=energy:Wh interruptable=1 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer02 FBDECT_fbahahttp_E8_DF_70_07_3E_57 icon=light_floor_lamp@orange type=other power=15 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer03 FBDECT_fbahahttp_E8_DF_70_07_42_0B icon=raspberrypi@orange type=other power=8 swstate:state pcurr=power:W:1 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer04 FBDECT_fbahahttp_11657_0067275 icon=springbrunnen_icon@orange type=other power=50 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer05 FBDECT_fbahahttp_34_31_C4_D4_31_37 icon=sani_domestic_waterworks@orange type=other power=10 swstate:state pcurr=power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer06 tuya_local_bf5037060f450bdbd4rl0q icon=scene_clothes_dryer@orange type=dryer power=10 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer07 tuya_local_bfac44fb487476efd1vhdu icon=weather_sunset@orange type=noSchedule power=5 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumerControl adviceIcon=light_light_dim_100@gold&lt;br /&gt;
attr Forecast consumerControl showLegend=icon_top&lt;br /&gt;
attr Forecast consumerControl detailLink=1&lt;br /&gt;
attr Forecast ctrlAIdataStorageDuration 1825&lt;br /&gt;
attr Forecast ctrlAIshiftTrainStart 2&lt;br /&gt;
attr Forecast ctrlBatSocManagement01 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlBatSocManagement02 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlDebug none&lt;br /&gt;
attr Forecast plantControl genPVdeviation=continuously&lt;br /&gt;
attr Forecast plantControl cycleInterval=15&lt;br /&gt;
attr Forecast ctrlNextDayForecastReadings 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24&lt;br /&gt;
attr Forecast ctrlNextHoursSoCForecastReadings 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23&lt;br /&gt;
attr Forecast ctrlSpecialReadings BatPowerIn_Sum,BatPowerOut_Sum,SunHours_Remain,SunMinutes_Remain,allStringsFullfilled,conForecastTillNextSunrise,currentAPIinterval,currentRunMtsConsumer_01,currentRunMtsConsumer_02,currentRunMtsConsumer_03,currentRunMtsConsumer_04,currentRunMtsConsumer_05,currentRunMtsConsumer_06,currentRunMtsConsumer_07,dayAfterTomorrowPVforecast,daysUntilBatteryCare_01,daysUntilBatteryCare_02,lastretrieval_time,lastretrieval_timestamp,response_message,runTimeAvgDayConsumer_01,runTimeAvgDayConsumer_02,runTimeAvgDayConsumer_03,runTimeAvgDayConsumer_04,runTimeAvgDayConsumer_05,runTimeAvgDayConsumer_06,runTimeAvgDayConsumer_07,runTimeCentralTask,runTimeLastAPIAnswer,runTimeLastAPIProc,runTimeTrainAI,todayBatIn_01,todayBatIn_02,todayBatOut_01,todayBatOut_02,todayConForecastTillSunset,todayConsumptionForecast,todayDoneAPIcalls,todayDoneAPIrequests,todayGridConsumption,todayGridFeedIn,todayMaxAPIcalls,todayRemainingAPIcalls,todayRemainingAPIrequests&lt;br /&gt;
attr Forecast disable 0&lt;br /&gt;
attr Forecast event-min-interval .*:1800&lt;br /&gt;
attr Forecast event-on-change-reading .*&lt;br /&gt;
attr Forecast flowGraphicControl animate=1 consumerdist=80 h2consumerdist=50 shiftx=0  shifty=0 showconsumer=1 showconsumerdummy=1 showconsumerpower=1 showconsumerremaintime=0 size=400 strokewidth=12&lt;br /&gt;
attr Forecast graphicBeam1Color 3C14FF&lt;br /&gt;
attr Forecast graphicBeam1Content pvReal&lt;br /&gt;
attr Forecast graphicBeam2Color 19FF29&lt;br /&gt;
attr Forecast graphicBeam2Content pvForecast&lt;br /&gt;
attr Forecast graphicBeam3Color D60924&lt;br /&gt;
attr Forecast graphicBeam3Content batsocforecast_02&lt;br /&gt;
attr Forecast graphicBeam3FontColor FFFF0D&lt;br /&gt;
attr Forecast graphicBeam4Color FFFF1F&lt;br /&gt;
attr Forecast graphicBeam4Content batsocforecast_01&lt;br /&gt;
attr Forecast graphicBeam4FontColor 000000&lt;br /&gt;
attr Forecast graphicBeamHeightLevel1 200&lt;br /&gt;
attr Forecast graphicBeamHeightLevel2 200&lt;br /&gt;
attr Forecast graphicHeaderDetail all&lt;br /&gt;
attr Forecast graphicHeaderOwnspec #PV\&lt;br /&gt;
PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal\&lt;br /&gt;
PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast\&lt;br /&gt;
PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast\&lt;br /&gt;
:\&lt;br /&gt;
#\&lt;br /&gt;
AutarkyRate:Current_AutarkyRate\&lt;br /&gt;
Überschuss:Current_Surplus\&lt;br /&gt;
aktueller&amp;amp;nbsp;;Netzbezug:Current_GridConsumption\&lt;br /&gt;
:\&lt;br /&gt;
#Verbrauch\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenuntergang:special_todayConForecastTillSunset\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie01\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_01\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_01\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_01\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_01\&lt;br /&gt;
#Batterie01_tmp\&lt;br /&gt;
Current_PowerBatIn_01:Current_PowerBatIn_01\&lt;br /&gt;
Current_PowerBatOut_01:Current_PowerBatOut_01\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie02\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_02\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_02\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_02\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_02\&lt;br /&gt;
#Batterie02_tmp\&lt;br /&gt;
Current_PowerBatIn_02:Current_PowerBatIn_02\&lt;br /&gt;
Current_PowerBatOut_02:Current_PowerBatOut_02\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Settings\&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto \&lt;br /&gt;
Wetter:graphicShowWeather\&lt;br /&gt;
History:graphicHistoryHour\&lt;br /&gt;
ShowNight:graphicShowNight\&lt;br /&gt;
Debug:ctrlDebug\&lt;br /&gt;
FCU-Modus:FCU-Betriebsmodus@FCU&lt;br /&gt;
attr Forecast graphicHistoryHour 4&lt;br /&gt;
attr Forecast graphicHourCount 24&lt;br /&gt;
attr Forecast graphicLayoutType double&lt;br /&gt;
attr Forecast graphicShowDiff top&lt;br /&gt;
attr Forecast graphicShowNight 1&lt;br /&gt;
attr Forecast graphicShowWeather 1&lt;br /&gt;
attr Forecast group Energy Meter&lt;br /&gt;
attr Forecast room 020_PV,Energie&lt;br /&gt;
attr Forecast setupBatteryDev01 SBS25 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupBatteryDev02 SBS25_2 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupInverterDev01 SB25 pv=total_pac:kW etotal=etotal:kWh capacity=2500 strings=GarageSE limit=70&lt;br /&gt;
attr Forecast setupInverterDev02 SB30 pv=total_pac:kW etotal=etotal:kWh capacity=3000 strings=GarageNW,HausNW limit=70&lt;br /&gt;
attr Forecast setupInverterDev03 SB40 pv=total_pac:kW etotal=etotal:kWh capacity=4000 strings=HausSE1,HausSE2,HausSW limit=70&lt;br /&gt;
attr Forecast setupInverterStrings GarageSE,GarageNW,HausNW,HausSW,HausSE1,HausSE2&lt;br /&gt;
attr Forecast setupMeterDev SMA_Energymeter gcon=Bezug_Wirkleistung:W contotal=Bezug_Wirkleistung_Zaehler:kWh gfeedin=Einspeisung_Wirkleistung:W feedtotal=Einspeisung_Wirkleistung_Zaehler:kWh conprice=0.25:€ feedprice=0.08123:€&lt;br /&gt;
attr Forecast setupOtherProducer01 icon=Heizung_FCU_green@red MB_USRW610_004 pcurr=Power_L1__W:W etotal=Energy_L1_import__kWh:kWh&lt;br /&gt;
attr Forecast setupRadiationAPI DWD&lt;br /&gt;
attr Forecast setupStringPeak GarageSE=2.75 GarageNW=3.200 HausNW=2.230 HausSW=2.230 HausSE1=2.200 HausSE2=2.200&lt;br /&gt;
attr Forecast setupWeatherDev1 DWD&lt;br /&gt;
attr Forecast stateFormat Current_PV&lt;br /&gt;
attr Forecast userReadings Current_BatCharge999 {((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))) / ( (ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0) * 1000)  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0)*1000))*100}&lt;br /&gt;
attr Forecast verbose 2&lt;br /&gt;
&lt;br /&gt;
setstate Forecast 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .FCU_FCU-Betriebsmodus 2&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_ctrlDebug none&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicHistoryHour 4&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowNight 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowWeather 1&lt;br /&gt;
setstate Forecast 2025-01-13 08:24:25 .associatedWith SMA_Energymeter FBDECT_fbahahttp_11657_0127183 FBDECT_fbahahttp_E8_DF_70_07_3E_57 FBDECT_fbahahttp_E8_DF_70_07_42_0B FBDECT_fbahahttp_11657_0067275 FBDECT_fbahahttp_34_31_C4_D4_31_37 tuya_local_bf5037060f450bdbd4rl0q tuya_local_bfac44fb487476efd1vhdu SBS25 SBS25_2 SB25 SB30 SB40 DWD MB_USRW610_004&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .lastupdateForecastValues 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .pvCorrectionFactor_Auto_Soll on_complex_ai&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .signaldone_01 done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .signaldone_02 done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .signaldone_03 done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .signaldone_04 done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .signaldone_05 done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .signaldone_06 done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .signaldone_07 done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .signaldone_08 done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .signaldone_09 done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .signaldone_10 done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .signaldone_11 done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .signaldone_12 done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .signaldone_13 done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .signaldone_14 done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .signaldone_15 done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .signaldone_16 done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .signaldone_17 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .signaldone_18 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_01 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_02 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_01 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_02 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_AutarkyRate 83 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 Current_BatCharge999 10&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_01 12 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_02 8 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Consumption 626 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridConsumption 2 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridFeedIn 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PP_01 746.0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PV 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_01 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_02 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_01 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_02 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumption 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumptionRate 0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Surplus 120 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourGridconsumptionReal 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_ConsumptionForecast 2944 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayConsumptionForecast 3609 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_01 272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PPreal_01 748 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PPreal_01 787 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_01 271 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PPreal_01 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PPreal_01 745 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_01 267 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PPreal_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_01 255 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PPreal_01 752 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_01 226 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_01 50 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PPreal_01 681 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_02 233 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_01 845 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridConsumption 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_01 37 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_02 90 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_01 351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_02 188 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridConsumption 447 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVforecast 127 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridConsumption 1650 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVforecast 478 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVreal 26 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridConsumption 513 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVforecast 868 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVreal 97 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridConsumption 576 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVforecast 1157 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVreal 320 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_01 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_02 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridConsumption 1272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridFeedIn 7 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVforecast 1238 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVreal 945 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_01 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_02 53 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridConsumption 955 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridFeedIn 31 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PPreal_01 562 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVforecast 1168 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVreal 1410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_01 703 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_02 500 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_01 22 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_02 18 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridConsumption 32 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridFeedIn 71 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PPreal_01 777 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVreal 1416 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_01 296 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_02 70 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_01 74 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_02 258 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridConsumption 13 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridFeedIn 17 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PPreal_01 732 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVforecast 880 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVreal 1051 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_01 47 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_02 126 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_01 102 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_02 75 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridConsumption 15 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridFeedIn 23 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PPreal_01 771 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVforecast 117 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVreal 86 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_02 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_02 67 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridConsumption 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridFeedIn 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PPreal_01 723 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_01 349 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_02 124 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_01 73 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_02 450 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridConsumption 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridFeedIn 6 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PPreal_01 671 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecastTime 2025-01-13 14:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVdeviation 30.17 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVforecast 7663 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVreal 5351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunRise 08:28&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunSet 16:46&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_ConsumptionForecast 17043 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour05_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour06_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour07_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour08_PVforecast 10 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour09_PVforecast 161 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour10_PVforecast 275 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour11_PVforecast 532 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour12_PVforecast 730 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour13_PVforecast 1252 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour14_PVforecast 818 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour15_PVforecast 1465 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour16_PVforecast 303 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour17_PVforecast 20 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour18_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour19_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour20_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour21_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour22_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour23_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour24_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_PVforecast 5566 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunRise 08:27&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunSet 16:47&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01 name=&#039;_Waschmaschine&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_start 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_stop 14.01.2025 11:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02 name=&#039;_Esszimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_currentPower 15.3 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03 name=&#039;_FCU&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_currentPower 7.15 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04 name=&#039;_Brunnen&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05 name=&#039;_Zisterne&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06 name=&#039;SW Trockner&#039; state=&#039;unknown&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_stop 14.01.2025 08:30:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07 name=&#039;SW Urlaubslicht-Wohnzimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;noSchedule&#039; info=&#039;von extern umgeschaltet&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 nextCycletime 18:54:09&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 pvCorrectionFactor_10 0.53 (automatic - old factor: 1.00, Sun Alt range: 5, Cloud range: 75, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 pvCorrectionFactor_11 0.56 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 70, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 pvCorrectionFactor_12 0.64 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 pvCorrectionFactor_13 0.88 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 pvCorrectionFactor_14 1.10 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 50, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 pvCorrectionFactor_15 1.01 (automatic - old factor: 1.06, Sun Alt range: 15, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 pvCorrectionFactor_16 1.09 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 45, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 pvCorrectionFactor_17 0.28 (automatic - old factor: 0.52, Sun Alt range: 0, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 pvCorrectionFactor_Auto on_complex_ai&lt;br /&gt;
setstate Forecast 2024-10-30 19:42:19 setupStringAzimuth GarageSE=-55 GarageNW=125 HausNW=125 HausSW=35 HausSE1=-55 HausSE2=-55&lt;br /&gt;
setstate Forecast 2024-10-30 19:37:38 setupStringDeclination GarageSE=40 GarageNW=40 HausNW=50 HausSW=50 HausSE1=50 HausSE2=50&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerIn_Sum 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerOut_Sum 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunHours_Remain 0.00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunMinutes_Remain 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_allStringsFullfilled 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_conForecastTillNextSunrise 9467 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentAPIinterval 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_01 132 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_02 184 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_03 329512 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_04 200 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_05 27 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_06 193 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_07 106 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_dayAfterTomorrowPVforecast 7344 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_01 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_02 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_time 2025-01-13 18:53:54&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_timestamp 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_response_message success&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_01 545.94 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_02 382.10 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_03 1430.13 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_04 262.05 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_05 28.80 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_06 622.63 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_07 276.51 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeCentralTask 0.3744&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIAnswer -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIProc -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeTrainAI 1.2529&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_01 3683.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_02 1617.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_01 2287.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_02 1057.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConForecastTillSunset 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 special_todayConsumptionForecast_01 509 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 special_todayConsumptionForecast_02 499 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 special_todayConsumptionForecast_03 501 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 special_todayConsumptionForecast_04 511 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 special_todayConsumptionForecast_05 503 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 special_todayConsumptionForecast_06 495 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 special_todayConsumptionForecast_07 504 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 special_todayConsumptionForecast_08 561 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 special_todayConsumptionForecast_09 768 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 special_todayConsumptionForecast_10 783 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 special_todayConsumptionForecast_11 692 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 special_todayConsumptionForecast_12 791 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 special_todayConsumptionForecast_13 910 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 special_todayConsumptionForecast_14 1022 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 special_todayConsumptionForecast_15 965 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 special_todayConsumptionForecast_16 812 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 special_todayConsumptionForecast_17 884 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 special_todayConsumptionForecast_18 928 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_19 874 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_20 763 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_21 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_22 765 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_23 643 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_24 601 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIcalls 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIrequests 4532&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridConsumption 5500.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridFeedIn 178.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayMaxAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIrequests n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 state updated&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So sollte es dann als Ergebnis aussehen:&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13.png|zentriert|mini|Ergebnis nach kompletter Einrichtung]]&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13 Teil II.png|alternativtext=Unterer Teil der Anzeige|zentriert|mini]]&lt;br /&gt;
&lt;br /&gt;
== Praxisbeispiele und Lösungsansätze für Steuerungen ==&lt;br /&gt;
=== Fallstudie: Trockner darf pausiert werden, wenn nicht genug PV-Überschuss vorhanden ist, soll aber nach spätestens X Stunden fertig sein ===&lt;br /&gt;
Für diese Aufgabenstellung sind mehrere Schlüssel essentiell wichtig, &#039;&#039;&#039;power&#039;&#039;&#039;, &#039;&#039;&#039;mintime&#039;&#039;&#039;, &#039;&#039;&#039;mode&#039;&#039;&#039; und &#039;&#039;&#039;interruptable&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Die Bedingung, dass der Trockner nach spätestens X Stunden fertig sein soll, steht in einem Widerspruch zu der Möglichkeit den Trockner bei zu wenig PV-Überschuss unterbrechen zu können. Im Extremfall könnte nach dem Start die gesamte Planungszeit ungenügender Überschuss vorliegen und der Trockner nicht arbeiten. Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; (in Minuten) wird nun wie folgt angesetzt:&lt;br /&gt;
&lt;br /&gt;
 mintime = 2,5 x &amp;lt;gewöhnliche Betriebszeit für einen Trockengang (mneed, z.B. 120)&amp;gt; = 300 Minuten&lt;br /&gt;
&lt;br /&gt;
Das bedeutet, der Trockner wird nach 300 Minuten Laufzeit abgeschaltet werden bzw. vom Netz getrennt. Der Trockenvorgang wird natürlich bereits nach 120 Minuten beendet sein, sofern nach Start keine Unterbrechnung des Vorganges erfolgte. Wurde der Vorgang unterbrochen, soll der Trockner innerhalb &lt;br /&gt;
&lt;br /&gt;
 X+120 bis X+300 &lt;br /&gt;
&lt;br /&gt;
fertig sein. &lt;br /&gt;
&lt;br /&gt;
Demnach ist die ausgeführte Laufzeit des Trockners permanent zu überwachen, zu summieren (rtsum) und die notwendige Restzeit (mneed - rtsum) mit der noch verbleibenden Restzeit (mrest) bis zur geplanten Abschaltung des Consumers zu vergleichen. Ist der Consumer gestartet, wird die Laufzeit in der pvHistory für jede Stunde des Tages im Schlüssel &#039;&#039;minutescsmXX&#039;&#039; (XX = Consumernummer) aufgezeichnet und kann darüber ausgewertet werden. Somit ist:&lt;br /&gt;
&lt;br /&gt;
 msum = for (01 .. 24) {Summe von minutescsmXX} des aktuellen Tages&lt;br /&gt;
&lt;br /&gt;
Solange die Bedingung &lt;br /&gt;
&lt;br /&gt;
 mrest &amp;gt;= (mneed - msum)&lt;br /&gt;
&lt;br /&gt;
zutrifft, darf der Trockner unterbrochen werden, anderenfalls darf er nicht mehr unterbrochen werden da die Restzeit evtl. nicht ausreichen könnte um den Vorgang abzuschließen. Für die Planung des Trockners wird der Consumer wie gewöhnlich nach dem Bedarf im Modul registriert. Für die Steuerung der Unterbrechbarkeit wird noch ein Code erstellt, welcher im Trockner-Device &#039;&#039;Dryerdev&#039;&#039; das Reading &#039;&#039;SF_Int&#039;&#039; zur Unterbrechnungssteuerung verwaltet. Dieses Reading wird dem Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; übergeben. Für das Beispiel wird der Consumer &#039;07&#039; verwendet, es kann natürlich jede andere freie Nummer verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Dryerdev:Trockner&lt;br /&gt;
                        icon=scene_cloves_dryer type=dryer power=2000 mode=must mintime=300 &lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic asynchron=1&lt;br /&gt;
                        interruptable=Dryerdev:SF_Int:1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Kombination &#039;&#039;&#039;auto=automatic&#039;&#039;&#039; eröffnet die Möglickeit, in der Consumer-Legende den Trockner-Start zusätzlich manuell freizugeben oder zu verbieten. &lt;br /&gt;
&lt;br /&gt;
Im nachfolgenden Code werden modulinterne Subroutinen verwendet. Diese sind inklusive dem Paket &#039;&#039;FHEM::SolarForecast::&#039;&#039; anzugeben. Die erstellte Subroutine wird in die 99_mySolarForecastUtils.pm eingefügt. Die Datei 99_mySolarForecastUtils.pm wird vorher von 99_myUtils.pm kopiert und enthält für die Übersichtlichkeit nur Routinen für SolarForecast.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Trocknersteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub dryControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # gewöhlich benötigte Zeit für &lt;br /&gt;
                                                                                  # einen Trockengang, z.B. 120 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $dryer     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename des Trockners&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Trockner-Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit des Trockners&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      my $dhash = $defs{$dryer};&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 1, 0);                        # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 0, 0);                        # keine Interrupt-Freigabe&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die gewöhnliche Laufzeit des Trockners für einen Trockenvorgang (120 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::dryControl ($name, &#039;07&#039;, 120);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Fallstudie: Umwälzpumpe Pool soll X Stunden am Tag laufen. Ist kein PV-Überschuß vorhanden, müssen die X Stunden/Tag trotzdem erreicht werden ===&lt;br /&gt;
&lt;br /&gt;
Die Vorgehensweise ähnelt der Fallstudie zuvor. Verändernd kommt hinzu, dass der Planungszeitraum bewusst sehr lang angesetzt wird mit der Option, den Zyklus des Consumers vorfristig zu beenden sobald die Laufzeit von X Stunden am Tag erreicht ist. &lt;br /&gt;
Im folgenden Beispiel soll die Pumpe 5 Stunden am Tag (300 Minuten) laufen und dabei mögliche PV-Überschüsse ausnutzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Pump:Zirkulationspumpe&lt;br /&gt;
                        icon=sani_pump type=other power=50 mode=must mintime=780 notafter=09&lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic &lt;br /&gt;
                        interruptable=1 swoffcond=Pump:SF_Abort:1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit dieser Registrierung wird die Pumpe ca. 09 Uhr täglich starten. Wenn kein bzw. ungenügender PV-Überschuß vorhanden ist, erfolgt eine Unterbrechung nach dem Start. Ist genügender PV-Überschuß (wieder) vorhanden, erfolgt keine Unterbrechnung (mehr). Zusätzlich wird über den Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; eine vorfristige Beendigung veranlasst, sobald die gewünschte Tageslaufzeit erreicht ist.&lt;br /&gt;
&lt;br /&gt;
Zur Verwaltung des Schlüssels &#039;&#039;interruptable&#039;&#039; und des Readings &#039;&#039;SF_Abort&#039;&#039; verwenden wir eine leicht veränderte Subroutine aus dem vorhergehenden Fallbeispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Pumpensteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub pumpControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # Soll-Pumpenzeit, z.B. 300 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $pump      = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename der Pumpe&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;);&lt;br /&gt;
  my $intbl     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;interruptable&#039;, 1); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
  my $dhash     = $defs{$pump};&lt;br /&gt;
&lt;br /&gt;
  readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 0, 0);                                # default keine Zyklusbeendigung&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Pumpen Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit der Pumpe&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
     &lt;br /&gt;
      if ($msum &amp;gt;= $mneed) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 1, 0);                       # vorfristige Zyklusbeendigung&lt;br /&gt;
          return;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=1&amp;quot;) if(!$intbl);  # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=0&amp;quot;) if($intbl);   # keine Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Befehl &#039;&#039;attrKeyVal&#039;&#039; setzt den Schlüssel &#039;&#039;interruptable&#039;&#039; im Attribut &#039;&#039;consumer07&#039;&#039; dynamisch. Diese Strukturänderung wird automatisch im System gespeichert, sofern &#039;&#039;global-&amp;gt;autosave=1&#039;&#039; gesetzt ist. Diese Einstellung ist der FHEM default.  &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die Mindestlaufzeit der Umwälzpumpe (300 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::pumpControl ($name, &#039;07&#039;, 300);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamische Ladestromsteuerung eines Victron MultiPlus II Chargers mit Pylontech Batterie ===&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;
&lt;br /&gt;
 set &amp;lt;Device&amp;gt; MaxChargeCurrent &amp;lt;Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
eingestellt bzw. variiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Modul bietet dem Nutzer die Möglichkeit in dem Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltene Code wird am Ende jedes Zyklus (siehe Attribut &#039;&#039;plantControl-&amp;gt;cycleInterval&#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;
&lt;br /&gt;
&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 $mppt1   = &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common&#039;;              # SmartLoader Device&lt;br /&gt;
  my $maxcspc = 105;                        # max. Ladesollstrom (A) nominal&lt;br /&gt;
  my $spcorr  = 0.9;                        # Korrekturfaktor Überschuss 90%&lt;br /&gt;
  my $sch     = 0.25;                       # Verkürzungsfaktor Zeit bis Vollladung vor Sunset             &lt;br /&gt;
  &lt;br /&gt;
  my $cclvl0  = 15;                         # Ladestrom Level 0 max. 5  A (240 W) pro WR  (720  W)&lt;br /&gt;
  my $cclvl1  = 27;                         # Ladestrom Level 1 max. 9  A (432 W) pro WR  (1296 W)&lt;br /&gt;
  my $cclvl2  = 54;                         # Ladestrom Level 2 max. 18 A (864 W) pro WR  (2592 W)&lt;br /&gt;
  my $cclvl3  = 81;                         # Ladestrom Level 3 max. 27 A (1296 W) pro WR (3888 W)&lt;br /&gt;
  ###############&lt;br /&gt;
  &lt;br /&gt;
  my $cofc   = ReadingsNum ($name,  &#039;special_todayConForecastTillSunset&#039;, 0);&lt;br /&gt;
  my $pvfc   = ReadingsNum ($name,  &#039;RestOfDayPVforecast&#039;, 0);&lt;br /&gt;
  my $cpv    = ReadingsNum ($name,  &#039;Current_PV&#039;,          0);&lt;br /&gt;
  my $mppt1c = ReadingsNum ($mppt1, &#039;DC_0_Current_value&#039;,  0);             # Load I MPPT1 (max. 44 A)&lt;br /&gt;
  my $ssts   = CurrentVal  ($hash,  &#039;sunsetTodayTs&#039;,        0);&lt;br /&gt;
  my $srts   = CurrentVal  ($hash,  &#039;sunriseTodayTs&#039;,       0);&lt;br /&gt;
  my $sdiff  = ($ssts - $srts) / 3600;                                     # Sonnengang heute in h &lt;br /&gt;
  &lt;br /&gt;
  my $solh   = ReadingsNum ($name, &#039;special_SunHours_Remain&#039;, 0);          # h bis SunSet&lt;br /&gt;
  $solh      = $solh - ($sdiff * $sch);                                    # h bis SunSet - X&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;              # Ah Bat bis SOC&lt;br /&gt;
  $ahrem     = sprintf &amp;quot;%.0f&amp;quot;, $ahrem;&lt;br /&gt;
  &lt;br /&gt;
  my $fcdiff = ($pvfc - $cofc) * $spcorr;     # Korrektur d. noch prognostizierten Überschussenergie &lt;br /&gt;
  $fcdiff    = $fcdiff &amp;lt; 0 ? 0 : $fcdiff;     # Wh&lt;br /&gt;
  &lt;br /&gt;
  my $loadcur = $maxcspc;&lt;br /&gt;
  &lt;br /&gt;
  if ($cpv &amp;amp;&amp;amp; $solh &amp;amp;&amp;amp; $ahrem &amp;amp;&amp;amp; $fcdiff &amp;gt; $ahrem) {  # Ladeanforderung und Überschuss übersteigt &lt;br /&gt;
                                                      # Lademenge&lt;br /&gt;
      my $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($ahrem / $solh);    # A = Ah / h -&amp;gt; A Soll Schätzung&lt;br /&gt;
&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Battery charging process should be completed }.&lt;br /&gt;
                      qq{in &amp;gt;$solh&amp;lt; hours});&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; raw Target charging current: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($cspc - $mppt1c);      # SmartLoader IST berücksichtigen&lt;br /&gt;
	  &lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Charge Current minus MPPT load Current &amp;gt;$mppt1c&amp;lt;: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $loadcur = $cspc &amp;lt;= 0       ? 0       :     # nur MPPT Ladung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl0 ? $cclvl0 :     # Übergangsbereich&lt;br /&gt;
                 $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;
	  Log3 ($name, 3, qq{$name - userFn -&amp;gt; MaxChargeCurrent calculated: $loadcur});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent&#039;,       $loadcur.&#039; A&#039;,          1);&lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_HoursUntilChargeFinish&#039;, sprintf (&amp;quot;%.2f&amp;quot;,$solh), 1);&lt;br /&gt;
  CommandSet           (undef, &amp;quot;$vebus MaxChargeCurrent $loadcur&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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. 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;special_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;special_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;Verkürzungsfaktor Zeit bis Vollladung vor Sunset&#039;&#039;) reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche mindest Ladestromstärke ermittelt.&lt;br /&gt;
&lt;br /&gt;
&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 auch während der MQTT Intergration 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;
=== Poolheizung in Abhängigkeit von vorhandenem Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren) ===&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;consumer01&#039;&#039; wird beispielhaft wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr Forecast consumer01 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;&lt;br /&gt;
&lt;br /&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. &lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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, einen 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 Überschuss 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;. &lt;br /&gt;
&lt;br /&gt;
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;
=== PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) ===&lt;br /&gt;
[https://evcc.io evcc] ist ein Energie-Management-System, mit dem u.a. Überschussladen von Elektroautos möglich ist. Hier ist beschreiben, wie die SolarForecast-Vorhersagedaten per API von evcc abgerufen werden.&lt;br /&gt;
Lege im SolarForecast-Device ein User-Reading mit dem Namen forecast_json an. Es wandelt die Forecast-Werte in JSON und ins UTC-Zeitformat um, so dass evcc die Daten verwenden kann:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
forecast_json {&lt;br /&gt;
&lt;br /&gt;
    use strict;&lt;br /&gt;
    use warnings;&lt;br /&gt;
    use JSON;&lt;br /&gt;
    use DateTime;&lt;br /&gt;
    use DateTime::Format::Strptime;&lt;br /&gt;
&lt;br /&gt;
    my $hour = 0;&lt;br /&gt;
    my @output;&lt;br /&gt;
&lt;br /&gt;
    # Parser für Datum mit CET/CEST&lt;br /&gt;
    my $parser = DateTime::Format::Strptime-&amp;gt;new(&lt;br /&gt;
        pattern   =&amp;gt; &#039;%Y-%m-%d %H:%M:%S&#039;,&lt;br /&gt;
        time_zone =&amp;gt; &#039;Europe/Berlin&#039;,&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    # Alle NextHour-Daten durchsuchen&lt;br /&gt;
    while ($hour &amp;lt; 100) {&lt;br /&gt;
        my $hour_str = sprintf(&#039;NextHour%02d&#039;, $hour);&lt;br /&gt;
        my $start_str = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;starttime&#039;, &#039;na&#039;); &lt;br /&gt;
        my $pvfc = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;pvfc&#039;, &#039;na&#039;);&lt;br /&gt;
&lt;br /&gt;
        # Schleife beenden, wenn keine Werte mehr vorhanden sind&lt;br /&gt;
        last if $start_str eq &#039;na&#039; or $pvfc eq &#039;na&#039;;&lt;br /&gt;
&lt;br /&gt;
        # parse und konvertiere Zeit&lt;br /&gt;
        my $start_dt = $parser-&amp;gt;parse_datetime($start_str);&lt;br /&gt;
        my $end_dt   = $start_dt-&amp;gt;clone-&amp;gt;add(hours =&amp;gt; 1);&lt;br /&gt;
&lt;br /&gt;
        # nach UTC konvertieren&lt;br /&gt;
        $start_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
        $end_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $start_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            end   =&amp;gt; $end_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            value =&amp;gt; 0 + $pvfc,&lt;br /&gt;
        };&lt;br /&gt;
        &lt;br /&gt;
        $hour++;&lt;br /&gt;
    }  &lt;br /&gt;
&lt;br /&gt;
    # Ausgabe als JSON&lt;br /&gt;
    my $json = JSON-&amp;gt;new-&amp;gt;utf8-&amp;gt;pretty-&amp;gt;encode(\@output);&lt;br /&gt;
    return $json;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Datei:Screenshot 2025-08-04 104835.png|right|thumb|300px|Darstellung der PV-Vorhersage in evcc auf Basis der SolarForecast-Daten]]&lt;br /&gt;
Die Kommunikation läuft über den integrierten FHEM-Webserver, der die JSON-Daten aus dem Reading forecast_json veröffentlicht. Dazu wird in FHEM eine separate Webinstanz auf einem neuen Port erstellt, die ohne [[CsrfToken-HowTo|CSFR-Token]] (Achtung, Auswirkungen auf die Sicherheit beachten!) und nur von localhost aufrufbar ist (Voraussetzung: evcc läuft auf derselben Maschine wie FHEM):&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
defmod WEBapi FHEMWEB 8089&lt;br /&gt;
attr WEBapi csrfToken none&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;In der [https://docs.evcc.io/docs/tariffs#pv-vorhersage evcc-Konfig unter tariffs] steht die Quelle für die Solar-Vorhersage. Der FHEM-Befehl {ReadingsVal(&#039;solarforecast_dev&#039;,&#039;forecast_json&#039;,&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;)} wird encoded und in die uri eingetragen. Trage statt solarforecast_dev den passenden Namen deines SolarForecast-Device ein. evcc holt die Daten aus dem Reading forecast_json dann regelmäßig ab.&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
solar:&lt;br /&gt;
  type: custom&lt;br /&gt;
  interval: 20m    &lt;br /&gt;
  forecast:&lt;br /&gt;
    source: http&lt;br /&gt;
    uri: http://localhost:8089/fhem?cmd=%7BReadingsVal%28%27solarforecast_dev%27%2C%27forecast_json%27%2C%27%27%29%7D&amp;amp;XHR=1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Zur Verbesserung der Sicherheit kann das neue WEBapi Device auch ein [[CsrfToken-HowTo#csrfToken festlegen|festes CSFR-Token]] verwenden. Dieses Token muss dann in der evcc-Konfiguration an die uri mittels &amp;amp;fwcsrf=&amp;lt;festes token&amp;gt; angehängt werden.&lt;br /&gt;
&lt;br /&gt;
== weiterführende Links ==&lt;br /&gt;
* Forenthema &amp;quot;{{Link2Forum|Topic=137058|LinkText=76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support}}&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;
* Photovoltaik Ingenieurbüro Junge: https://www.ing-büro-junge.de/html/photovoltaik.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung&amp;diff=40306</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=40306"/>
		<updated>2025-08-04T15:47:14Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Hinweis|Die vorliegende Wiki-Seite befindet sich im Aufbau.}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Solarprognose und Verbrauchersteuerung&lt;br /&gt;
|ModType=d&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 Prognosewerte können die SolCast API, OpenMeteo API, Forecast.Solar API, Victron VRM Portal API oder alternativ DWD Stahlungswerte-Stationen verwendet werden&lt;br /&gt;
&lt;br /&gt;
::* optionale KI Unterstützung der PV-Prognose bei Verwendung von geeigneten Solar-API&#039;s&lt;br /&gt;
&lt;br /&gt;
::* es wird sowohl die Erzeugungsprognose als auch eine Verbrauchsprognose sowie SoC Prognose (bei Batterie-Integration) erstellt&lt;br /&gt;
&lt;br /&gt;
::* Wetterdaten werden über DWD Wetter-Stationen oder verschiedene API integriert. Es können verschiedene API zur Gewinnung von Solar- und Wetterdaten kombiniert werden. &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 FHEM-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 Integration von bis zu 4 Inverter und Smartloader (DC-DC Batterieladegeräte) ist möglich&lt;br /&gt;
&lt;br /&gt;
::* eine Integration von bis zu 3 nicht PV-Energieerzeugern wie BHKW, Windrädern oder Notstromaggregaten ist möglich&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;
::* Einbindung von bis zu drei Batteriespeichersystemen&lt;br /&gt;
&lt;br /&gt;
::* Bereitstellung von Leitwerten zur optimalen Einstellung/Steuerung von Batteriespeichersystemen&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 Benutzererlebnis 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;
Das Wiki gibt allgemeingültige und teilweise sehr spezifische bzw. tiefgehende Informationen und Handlungsempfehlungen zum SolarForecast Modul. Die dargestellten Informationen beziehen sich auf den zum Zeitpunkt der Wiki-Erstellung vorhandenen Entwicklungsstand des Moduls. Durch die stetige Weiterentwicklung können sich Abweichungen zum beschriebenen Inhalt ergeben oder zur Obsoleszenz dieser Inhalte führen. &lt;br /&gt;
&lt;br /&gt;
Vergleiche deshalb die Informationen immer mit der aktuellen Befehls-Referenz zum Modul!&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Ein SolarForecast Device wird mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 define &amp;lt;Name&amp;gt; SolarForecast &lt;br /&gt;
&lt;br /&gt;
angelegt. Nach der Definition wird der User durch einen Dialog geführt, der einige unerlässliche Einstellungen abfragt und in den entsprechenden Attributen und Readings persistiert. Alle Attribute und Readings die eine Einstellung der Anlage bewirken, sind mit dem Präfix &amp;quot;setup&amp;quot; versehen. &lt;br /&gt;
&lt;br /&gt;
Die Verwendung von setup-Readings gestattet es die Anlagenparameter dynamisch im Betrieb zu verändern. So kann mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringAzimuth   bzw.&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringDeclination &lt;br /&gt;
&lt;br /&gt;
die Ausrichtung und der Neigungswinkel der PV-Module ständig angepasst werden, was zum Beispiel bei einer dem Sonnenstand nachgeführten Anlage von Bedeutung ist.&lt;br /&gt;
&lt;br /&gt;
Die abgefragten Einstellungen während des Dialoges sind ausführlich in den entsprechenden Attributen bzw. Set-Kommandos erläutert. Die benötigten Informationen sind anhängig von der gewählten Prognose-API und können im Umfang variieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 213257.png|right|thumb|400px|Anlagenprüfung über Drucktaste in der Kopfgrafik]]&lt;br /&gt;
&lt;br /&gt;
Sobald alle verlangten Einstellungen vorgenommen sind, sollte eine Anlagenprüfung mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; plantConfiguration check&lt;br /&gt;
&lt;br /&gt;
oder über die angebotene Drucktaste in der Grafik durchgeführt werden. Es wird eine Plausibilitätsprüfung vorgenommen und das Ergebnis sowie eventuelle Hinweise bzw. Fehler ausgegeben.&lt;br /&gt;
Die Prüfung kann beliebig wiederholt werden und sollte sich bei jeder Einstellungsänderung der Anlage durchgeführt werden. Dadurch wird die Wahrscheinlichkeit von fehlerhaften Einstellungen minimiert.&lt;br /&gt;
&lt;br /&gt;
Neben den grundlegenden Einstellungen können im Device weitere sekundäre Anlagenkomponenten wie Batteriesystem(e) (Attribut setupBatteryDev1 - setupBatteryDev3), weitere Wetter-Devices (Attribut setupWeatherDev1 - setupWeatherDev3) oder sonstige Erzeuger (z.B. BHKW, Winderzeugung, Notstromaggregat) integriert werden (Attribut setupOtherProducer01 - setupOtherProducer03).&lt;br /&gt;
&lt;br /&gt;
Die verlangten Parameter der Anlage werden in der Online-Hilfe umfassend beschrieben und deren Funktion erschließt sich zum größten Teil selbst. Dennoch soll nachfolgend auf einige Punkte im Zusammenhang der Einrichtung eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Hinweise zur Struktur der Attribute ===&lt;br /&gt;
&lt;br /&gt;
Durch die umfangreichen Funktionen des Moduls würde bei Nutzung der im FHEM herkömmlich vorhandenen Attributstruktur die Anzahl der benötigten Attribute extrem stark steigen und nicht sinnvoll genutzt werden können. Deshalb gibt es neben den &#039;&#039;gewöhnlichen&#039;&#039; Attributen mit einfachen Werteauswahlmöglichkeiten oder Eingaben (z.B. ctrlDebug, ctrlSpecialReadings) sogenannte &#039;&#039;zusammengesetzte&#039;&#039; Attribute, deren Inhalt durch &#039;&#039;&#039;Schlüssel=Wert Paare&#039;&#039;&#039; gebildet wird und dadurch deutlich mehr Funktionen und Informationen transportieren als ein gewöhnliches Attribut.&lt;br /&gt;
&lt;br /&gt;
Für zusammengesetzte Attribute besteht die zusätzliche Möglichkeit, gewünschte Änderungen der Schlüssel=Wert Paare selektiv vornehmen zu können, ohne das gesamte Attribut aufrufen und ändern zu müssen. Die Vorgang, der vor allem für programmtechnische Manipulationen gedacht ist, kann durch eine Set-Funktion ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; attrKeyVal &amp;lt;Attribut&amp;gt; [&amp;lt;Gerät&amp;gt;] &amp;lt;Schlüssel=Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiele für zusammengesetzte Attribute sind:&lt;br /&gt;
&lt;br /&gt;
* aiControl&lt;br /&gt;
* plantControl&lt;br /&gt;
* setup* Attribute&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktionen der Attribute werden durch einen Präfix geclustert und so inhaltlich, aber vor allem auch in der Attribute Drop-Down Liste, strukturiert dargestellt.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der &#039;&#039;&#039;Präfixe&#039;&#039;&#039; sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ai&#039;&#039;&#039; - Steuerungsfunktionen für KI (z.B. aiControl)&lt;br /&gt;
* &#039;&#039;&#039;consumer&#039;&#039;&#039; - Registrierung und Einstellungen für Verbraucher (z.B. consumer02, consumerControl)&lt;br /&gt;
* &#039;&#039;&#039;ctrl&#039;&#039;&#039; - Steuerungsfunktion allgemeiner Art (z.B. ctrlDebug, ctrlSpecialReadings, ctrlUserExitFn)&lt;br /&gt;
* &#039;&#039;&#039;flowGraphic&#039;&#039;&#039; - Einstellungen für die Energieflußgrafik (z.B. flowGraphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphic&#039;&#039;&#039; - Einstellung für die Grafik allgemein (z.B. graphicSelect, graphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphicBeam&#039;&#039;&#039; -  Einstellungen bestimmte Balkeneigenschaften in der Balkengrafik (z.B. graphicBeamHeightLevel1)&lt;br /&gt;
* &#039;&#039;&#039;plant&#039;&#039;&#039; - übergreifende Einstellungen betreffend der gesamten PV-Anlage bzw. des SolarForecast-Devices (z.B. plantControl)&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039; - Registrierung von Geräten in der Gesamtanlage und Einstellung deren Eigenschaften (Inverter, Zähler, Batterien usw.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Einrichtung der Wechselrichter mit setupInverterDevXX ===&lt;br /&gt;
&lt;br /&gt;
Mit den Attributen setupInverterDev01 bis setupInverterDevXX werden die vorhandenen Wechselrichter der Anlage registriert.&lt;br /&gt;
Das Modul unterscheidet verschiedene Wechselrichter-Typen, die sich durch ihre Arbeitsweise innerhalb der Anlage unterscheiden. Die Schlüssel=Wert Paare in den Attributen können mehrzeilig organisiert werden. Das erleichtert die Übersicht wenn viele dieser Parameter eingegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;PV-Wechselrichter: Es ist der Standard Wechselrichter in einer PV-Anlage. An ihn sind die Solarzellen bzw. Strings angeschlossen. Die zugeordneten Strings können mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ohne diese Angabe werden diesem Gerät alle definierten Strings (siehe Attribut &#039;&#039;setupInverterStrings&#039;&#039;) zugeordnet. Der Wechselrichter liefert seine Energie in das Hausnetz. Alternativ kann mit der Angabe &#039;&#039;&#039;feed=grid&#039;&#039;&#039; die Funktion des Wechselrichters geändert werden. Diese Angabe sagt aus, dass dieser Wechselrichter ausschließlich in das öffentliche Netz einspeist.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel-Setup eines PV-Wechselrichters (SMA STP):&lt;br /&gt;
&lt;br /&gt;
 STP_5000 pvIn=string_1_pdc:kW pvOut=total_pac:kW etotal=etotal:kWh capacity=5000 strings=Süddach asynchron=1 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Solar-Ladegeräte: Solar-Ladegeräte sind DC-DC Wandler und liefern die Energie der angeschlossenen Solarzellen nicht in das Wechselstromnetz, sondern laden direkt eine Batterie bzw. versorgen einen Batteriewechselrichter auf der Gleichstromseite. Die Funktion als Solar-Ladegerät wird mit &#039;&#039;&#039;feed=bat&#039;&#039;&#039; aktiviert, die relevanten Strings können ebenfalls mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ein Beispiel eines Solar-Ladegerätes ist ein Victron SmartSolar MPPT. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel für das Setup eines Solar-Ladegeräts (SmartSolar Charger MPPT):&lt;br /&gt;
&lt;br /&gt;
 MQTT2_cerboGX_c0619ab34e08_solarcharger_Common pv=Yield_Power_value:W etotal=Yield_System_value:kWh capacity=2080 strings=Schleppdach feed=bat synchron=0 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Batterie-Wechselrichter: Dieses Gerät hat keine angeschlossenen Solarzellen und arbeitet als DC-AC bzw. AC-DC Wandler zwischen einer Batterie (=Gleichstromquelle) und dem Wechselstrom-Hausnetz. Die Funktion als Batterie-Wechselrichter wird mit der Angabe &#039;&#039;&#039;strings=none&#039;&#039;&#039; aktiviert. Die Schlüssel &#039;&#039;etotal&#039;&#039; und &#039;&#039;pv&#039;&#039; können bei einem Batterie-Wechselrichter ohne zugeordnete Solarzellen nicht gesetzt werden. Ein Beispiel eines Batterie-Wechselrichter ist der Victron MultiPlus II.&lt;br /&gt;
&lt;br /&gt;
Ein Setup-Beispiel für einen Batterie-Wechselrichter (Victron MultiPlus II):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dc2ac=DC_IN:W&lt;br /&gt;
ac2dc=DC_OUT:W&lt;br /&gt;
capacity=7200&lt;br /&gt;
strings=none&lt;br /&gt;
icon=inverter@darkorange:inverter@grey&lt;br /&gt;
asynchron=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Eigenschaften des Wechselrichters werden durch eine Reihe von &amp;lt;Schlüssel=Wert&amp;gt; Paaren festgelegt. Auf einige dieser Paramter soll hier eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Ausgewählte Schlüssel=Wert Paare ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;pvIn=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvIn&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell zugeführte PV-Leistung bereitstellt. Der Schlüssel ist optional und dient in erster Linie dazu den entsprechenden Input-Wert in der Flußgrafik anzuzeigen sofern man das Attribut flowGraphicControl-&amp;gt;showGenerators=1 setzt. Dadurch ist auch der Eigenverbrauch des Inverters bzw. dessen Wandlungsverlust visuell abschätzbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pvOut=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvOut&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell erzeugte Leistung als positiven Wert liefert. Für einen PV-Wechselrichter (DC-&amp;gt;AC) oder Solar-Ladegerät (DC-&amp;gt;DC) ist es die erzeugte PV-Leistung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ac2dc=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter vom Hausnetz in Richtung Batterie (AC-&amp;gt;DC) wandelt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;dc2ac=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter aus einer Gleichstromquelle, d.h. einer Batterie oder einem Solar-Ladegerät, in Richtung des Hausnetzes (AC) wandelt . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;capacity=&amp;lt;max. WR-Leistung&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In dem Schlüssel &#039;&#039;capacity&#039;&#039; wird die maximal mögliche Leistung in Watt (ohne Einheit) angegeben, die der Wechselrichter lt. seinem Datenblatt in der Lage ist zu leisten. &lt;br /&gt;
&lt;br /&gt;
Die Angabe &#039;&#039;capacity&#039;&#039; hat in erster Linie die Aufgabe, die max. mögliche PV-Leistung für die Prognose zu begrenzen. Oft sind die installierten Peak-Leistungen der PV-Module höher als die angeschlossene Wechselrichter-Leistung bzw. kommt es vor, dass die KI / (korrigierte) API-Prognose über der maximal möglichen Wechselrichter-Leistung liegt. In diesen Fällen wird die Prognose auf die angegebene &#039;&#039;capacity&#039;&#039; begrenzt.&lt;br /&gt;
&lt;br /&gt;
Der Wert in diesem Schlüssel kann, wie andere Schlüssel auch, dynamisch zur Laufzeit mit dem Set-Befehl &amp;quot;[[#Hinweise zur Struktur der Attribute|set &amp;lt;Name&amp;gt; attrKeyVal ...]]&amp;quot; geändert werden. Ein Beispiel zur Anwendung ergibt sich aus folgendem Szenario.&lt;br /&gt;
&lt;br /&gt;
Gegeben sei eine Anlage die aus Solarzellen (1300 W Peak) mit einem Solar-Ladegerät mit max. 1800 W Leistung, einer Batterie und einem Batterie-Wechselrichter besteht. Die Anlage versorgt nur das Hausnetz. Eine Netzeinspeisung ist nicht vorgesehen oder nicht erlaubt.  &lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, es ist ein Tag voller Sonnenschein prognostiziert und die Batterie ist zunächst entladen. Der Haushalt verbraucht 300 W. Dann würden die PV-Module Module ihre volle Leistung von 1300 W Peak leisten können, die sich auch in der Balken-Vorhersage niederschlägt. Die Leistung wird nicht begrenzt, weil:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* sie niedriger ist als die nominale und angegebene Wechselrichter Kapazität von &#039;&#039;capacity=1800&#039;&#039;&lt;br /&gt;
* die erzeugte Energie anteilig für die Verorgung des Hauses und die Aufladung der Batterie verwendet wird&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders verhält es sich wenn nach einer gewissen Zeit die Batterie voll ist und weiterhin volle PV Leistung zur Verfügung steht. In diesem Fall würde der Haushalt seine benötigte Leistung von 300 W abnehmen, aber das Solar-Ladegerät kann keine weitere Leistung mehr abgeben, da die Batterie bereits voll geladen ist, d.h. die Anlagensteuerung würde die PV-Anlage abregeln. In diesem Fall, wenn es einen längeren Zeitraum betrifft, muß auch die Prognose PV-Energie auf 300 Wh (bzw. den durchschnittlichen Energieverbrauch des Hauses pro Stunde) begrenzt werden, damit die PV-Prognose nach unten angepasst wird und so eine realitätsnahere Prognose ermöglicht wird. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;icon=&amp;lt;aktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;][:&amp;lt;inaktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Jeder Wechselrichter wird im Standard durch ein Icon getrennt nach Tag und Nacht, d.h. je nach Aktiv-Status und Inaktiv-Status, symbolisiert.&lt;br /&gt;
&lt;br /&gt;
;Tag bzw. Aktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Sonnensymbol im Standard verwendet. Batterie-Wechselrichter verwenden ein gefärbtes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
;Nacht bzw. Inaktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Symbol der aktuellen Mondphasen im Standard verwendet. Batterie-Wechselrichter verwenden ein ausgegrautes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie angegeben, kann man für Tag und Nacht jeweils ein Wunsch-Icon, wenn gewünscht mit einer alternativen Färbung, auswählen.&lt;br /&gt;
&lt;br /&gt;
 icon=inverter@darkorange:inverter@gray&lt;br /&gt;
&lt;br /&gt;
Soll nur das Icon für die Nacht bzw. Inaktivät geändert werden, kann dies in dieser Form angegeben werden:&lt;br /&gt;
&lt;br /&gt;
 icon=:inverter@gray  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(beachte den führenden &#039;:&#039;)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Der integrierte SolarForecast Grafikbereich ==&lt;br /&gt;
Das SolarForecast Modul beinhaltet eine Grafikdarstellung die sich in mehrere Bereiche gliedert. Diese Bereiche können über Attribute ein- bzw. ausgeblendet sowie die Inhalte festgelegt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 223545.png|right|thumb|400px|Bereiche der integrierten Grafik]]&lt;br /&gt;
&lt;br /&gt;
Der nebenstehende Screenshot gibt die Gliederung der Grafikbereiche wieder:&lt;br /&gt;
&lt;br /&gt;
 1 - der Kopfbereich (Graphic Header)&lt;br /&gt;
 2 - durch den Nutzer selbst definierbarer Inhalt (Graphic Header Own Specification) als Teil des Kopfbereiches&lt;br /&gt;
 3 - Bereich Verbraucherdarstellung (Consumer Legend)&lt;br /&gt;
 4 - Bereich Balkengrafik (Beam Graphic)&lt;br /&gt;
 5 - Energieflußgrafik (Flow Graphic)&lt;br /&gt;
&lt;br /&gt;
Jeder dieser Bereiche hat spezifische Steuerungsattribute zur Anpassung des Verhaltens und ggf. des Inhalts.&lt;br /&gt;
&lt;br /&gt;
=== 1 - Der Grafik Kopfbereich ===&lt;br /&gt;
Im Kopfbereich befinden sich fest verankerte Informationen zur verwendeten Vorhersage-API sowie deren Status, Informationen zum Sonnenaufgang und Sonnenuntergang, dem aktuellen Gesamtstatus des SolarForecast Devices, Abweichungskennzahlen der PV Vorhersage sowie weitere Kennzeichen zur Verfügung.&lt;br /&gt;
Über zwei Drucktasten kann eine Anlagenprüfung durchgeführt und in den Spportthread des Moduls im FHEM Forum abgesprungen werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;graphicHeaderShow&#039;&#039;&#039; kann der gesamte Kopfbereich 1 und 2 (nutzereigener Teilbereich) ausgeblendet werden. Wird der Kopbereich ausgeblendet, ist es hilfreich mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;showLink&#039;&#039;&#039; einen Link zur Detailgrafik einzufügen da der in der Kopfgrafik integrierte Link in diesem Fall nicht mehr zur Verfügung steht. &lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;graphicHeaderDetail&#039;&#039;&#039; definiert welche Bereiche des Grafikkopfes angezeigt werden sollen. Es kann die Anzeige des Energieverbrauches, der PV-Erzeugung und der vom Nutzer selbst definierte Inhalt miteinander frei kombiniert werden.&lt;br /&gt;
&lt;br /&gt;
=== 2 - Der Bereich mit selbst definierbarem Inhalt (Graphic Header Own Specification) ===&lt;br /&gt;
In diesem Bereich kann der User beliebige Readings, Set-Kommandos und Attribute des SolarForecast Devices oder anderer Devices, die sich im gleichen FHEM-System wie das SolarForecast Device befinden, anzeigen lassen.&lt;br /&gt;
&lt;br /&gt;
Dieser Bereich ist als Tabelle mit einer beliebigen Anzahl von Zeilen organisiert. Jede Zeile beinhaltet ein Kommentarfeld und vier Nutzfelder zur Darstellung ausgewähler Werte + Label. Der Bereich bzw. der Inhalt des Bereiches wird mit dem Attribut &#039;&#039;&#039;graphicHeaderOwnspec&#039;&#039;&#039; definiert.  &lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt ein real gesetztes graphicHeaderOwnspec Attribut. Die Leerzeilen sind nicht notwendig, erhöhen aber die Lesbarkeit der Struktur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
Autarkierate:Current_AutarkyRate&lt;br /&gt;
PV&amp;amp;nbsp;übermorgen:special_dayAfterTomorrowPVforecast&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;Sunset:special_todayConForecastTillSunset&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;nächsten&amp;amp;nbsp;Sunrise:special_conForecastTillNextSunrise&lt;br /&gt;
&lt;br /&gt;
#Batterie&lt;br /&gt;
BatteryLive&amp;amp;nbsp;Status:userFn_BatLive_State&lt;br /&gt;
SoC&amp;amp;nbsp;Limit:Settings_CGwacs_BatteryLife_MinimumSocLimit_value@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SoC&amp;amp;nbsp;Ist:SOC_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
SOC&amp;amp;nbsp;Optimum:Battery_OptimumTargetSoC&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
aktuelle&amp;amp;nbsp;Ladung:userFn_Bat_EnergyState&lt;br /&gt;
Verfügbar:userFn_BatLive_UsableEnergy&lt;br /&gt;
benötigte&amp;amp;nbsp;Ladeenergie:userFn_Bat_EnergyRemain&lt;br /&gt;
Ladefreigabe:Battery_ChargeRecommended&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
akt.&amp;amp;nbsp;DC&amp;amp;nbsp;Strom:DC_Current_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
Restladezeit&amp;amp;nbsp;Ziel:userFn_Bat_HoursUntilChargeFinish&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Soll:userFn_Bat_MaxChargeCurrent_set&lt;br /&gt;
:&lt;br /&gt;
&lt;br /&gt;
#Settings&lt;br /&gt;
Batterie&amp;amp;nbsp;Lademanagement:userFn_BatteryChargeManagement&lt;br /&gt;
SoC&amp;amp;nbsp;Management:userFn_BatterySoCManagement&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Ist:MaxChargeCurrent@MQTT2_cerboGX_c0619ab34e08_vebus&lt;br /&gt;
SmartSolar&amp;lt;br&amp;gt;Einspeisung:OvervoltageFeedIn@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
MPII&amp;amp;nbsp;Limit&amp;lt;br&amp;gt;Einspeisung&amp;amp;nbsp;(W):MaxFeedInPower@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SOC&amp;amp;nbsp;Limit&amp;amp;nbsp;Soll:MinimumSocLimit@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Verbr.&amp;amp;nbsp;Neuplanung:consumerNewPlanning&lt;br /&gt;
Wetteranzeige:graphicShowWeather &lt;br /&gt;
&lt;br /&gt;
Anzeige&amp;amp;nbsp;Nachtstunden:graphicShowNight&lt;br /&gt;
hist.&amp;amp;nbsp;Stunden:graphicHistoryHour&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto&lt;br /&gt;
Victron&amp;amp;nbsp;BatteryLife&amp;lt;br&amp;gt;(1=an,10=aus):BatteryLife@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Debug:ctrlDebu&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Kommentarfeld am Beginn einer Zeile wird durch ein &#039;&#039;&#039;#&#039;&#039;&#039; gekennzeichnet. Folgt dem # ein String, wird dieser String als Kommentarangabe gewertet und in der Grafik ausgegeben. Ein leeres Kommentarfeld wird lediglich durch ein # gefolgt von einem Leerzeichen oder NL beschrieben:&lt;br /&gt;
&lt;br /&gt;
 #:&amp;lt;Text&amp;gt;  (bzw nur # für einen &#039;leeren&#039; Titel)&lt;br /&gt;
&lt;br /&gt;
Ein Netzfeld bzw. ein Datensatz wird durch die Angabe von einem Label und dem darzustellenden Wert getrennt durch &#039;:&#039; definiert:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Label&amp;gt;:&amp;lt;Reading, Attribut oder Set-Kommando&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das System erkennt selbständig, ob es sich bei der Angabe um ein Reading, Attribut oder ein Set-Kommando handelt. Sollen Readings, Set-Kommandos und Attribute anderer Devices als dem SolarForecast-Device angezeigt werden, kann dies einfach durch Zusatz von&lt;br /&gt;
&lt;br /&gt;
 ....@&amp;lt;Device-Name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
an den Parameter erreicht werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-12-05 203916.png|right|thumb|400px|Darstellung eigener Grafikbereich]]&lt;br /&gt;
Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten &amp;quot;Wh&amp;quot; bzw. &amp;quot;kWh&amp;quot; werden entsprechend der Einstellung des Attributs &#039;&#039;&#039;graphicEnergyUnit&#039;&#039;&#039; umgerechnet. Im Label sind Leerzeichen durch &amp;quot;&amp;amp;amp;nbsp;&amp;quot; einzufügen, ein Zeilenumbruch durch &amp;quot;&amp;amp;lt;br&amp;amp;gt;&amp;quot;. Ein leeres Feld in einer Zeile wird durch &amp;quot;:&amp;quot; ohne eine weitere Angabe erzeugt.&lt;br /&gt;
&lt;br /&gt;
Die nebenstehende Abbildung zeigt die reale Darstellung der oben angegebenen Struktur im Attribut graphicHeaderOwnspec.&lt;br /&gt;
&lt;br /&gt;
==== Formatierung der Inhalte im Bereich &amp;quot;Graphic Header Own Specification&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
Die angezeigten Inhalte, wie z.B. Readingwerte, des User eigenen Bereiches (Attribut graphicHeaderOwnspec) können durch Spezifikationen im Attribut &#039;&#039;&#039;graphicHeaderOwnspecValForm&#039;&#039;&#039; manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
Die Online-Hilfe zum Attribut graphicHeaderOwnspecValForm erläutert die verfügbaren Möglichkeiten und Optionen.&lt;br /&gt;
Als Beispiel hier einige mögliche Notationen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &#039;userFn_Bat_HoursUntilChargeFinish&#039;                        =&amp;gt; &amp;quot;($VALUE).&#039; Stunden&#039;&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_battery.SOC_value&#039;             =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Settings_CGwacs_BatteryLife_MinimumSocLimit_value&#039;        =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Info_MaxChargeCurrent_value&#039;                              =&amp;gt; &amp;quot;($VALUE).&#039; A&#039;&amp;quot;,&lt;br /&gt;
  &#039;DC_Current_value&#039;                                         =&amp;gt; &amp;quot;%.0f A&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common.Regulated&#039; =&amp;gt; &amp;quot;($VALUE eq &#039;1&#039; ? &#039;Ja&#039; : &#039;Nein&#039;)&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine Besonderheit besteht bei darzustellenden Werten die die Einheiten &#039;Wh&#039; bzw. &#039;kWh&#039; besitzen. Diese Werte und Einheiten werden automatisch entsprechend des gesetzten Attributes graphicEnergyUnit umgerechnet und angezeigt.&lt;br /&gt;
&lt;br /&gt;
Soll in diesen Fällen eine automatische Formatierung umgangen werden, kann eine solche Notation verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &#039;Today_PVforecast&#039; =&amp;gt; &amp;quot;(sprintf &#039;%.1f &amp;amp;amp;nbsp;kWh&#039;, ($VALUE / 1000))&amp;quot;,&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Die Angabe von &amp;amp;amp;nbsp; vor &#039;kWh&#039; verhindert die Erkennung der Einheit und so auch die automatische Umsetzung durch das Modul. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 3 - Bereich Verbraucherdarstellung (Consumer Legend) ===&lt;br /&gt;
Dieser Grafikbereich zeigt die im Modul registrierten Verbraucher sowie deren Status und weitere Informationen an. Sind die Voraussetzungen gegeben, d.h. entsprechende Schlüssel in der ConsumerXX-Attributen gesetzt, können die Verbraucher über das Paneel manuell geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Zur Anpassung der Darstellung sind verschiedene Attribute verfügbar:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;consumerControl-&amp;gt;showLegend: Definiert die Lage bzw. Darstellungsweise der Verbraucherlegende sofern Verbraucher im SolarForecast Device registriert sind.&lt;br /&gt;
;consumerControl-&amp;gt;adviceIcon: Definiert die Art der Information über die geplanten Schaltzeiten eines Verbrauchers in der Verbraucherlegende. &lt;br /&gt;
;consumerControl-&amp;gt;detailLink: Wenn gesetzt, ist der jeweilige Verbraucher klickbar um direkt zur Detailansicht des jeweiligen Geräts auf einer neuen Browserseite zu gelangen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Standard wird das Verbraucherpaneel zwischen dem Kopfbereich und der ersten Balkengrafik Ebene dargestellt. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;showLegend&#039;&#039;&#039; und Argument &#039;&#039;&#039;icon_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_bottom&#039;&#039;&#039; kann das Verbraucherpaneel an das Ende des Grafikbereiches verschoben werden.&lt;br /&gt;
Die Verwendung von &#039;&#039;&#039;text_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_top&#039;&#039;&#039; blendet die Icon-Spalte im Verbraucherpaneel aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Screenshot 2025-02-08 093239.png|Darstellung mit consumerControl showLegend=icon_top (default)&lt;br /&gt;
File:Screenshot 2025-02-08 093646.png|Darstellung mit consumerControl showLegend=icon_bottom&lt;br /&gt;
File:Screenshot 2025-02-08 152018.png|Darstellung mit consumerControl showLegend=text_top bzw. text_bottom&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 213634.png|right|thumb|400px|]]&lt;br /&gt;
Ein Mouse-Over über das Uhrensymbol zeigt nähere Informationen zum Status, den Planungsdaten, Modus und weitere Daten des Verbrauchers. Der Schalter &amp;quot;Aus/Ein&amp;quot; visualisiert den Schaltzustand des Verbrauchers und können auch zum manuellen Schalten des Verbrauchers dienen. Voraussetzung ist, dass im consumer-Attribut die Schlüssel &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; mit den Set-Kommandos zum Schalten des Verbrauchers defininiert sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 222210.png|right|thumb|300px|]]&lt;br /&gt;
Der Auto-Schieberegler zeigt einerseits den Freigabestatus zum Schalten des Verbrauchers durch das SolarForecast Modul und kann andererseits manuell betätigt werden. Der Status des Reglers korrespondiert mit dem im zugehörigen Consumer Attribut vorhandenen Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; angegebenen Reading-Wert.&lt;br /&gt;
&lt;br /&gt;
Die Verbraucherbezeichnungen in dem Paneel können in der Standardkonfiguration angeklickt werden um direkt zur Detailansicht des Devices zu gelangen. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;detailLink&#039;&#039;&#039; kann der Link zur Detailansicht deaktiviert werden.&lt;br /&gt;
&lt;br /&gt;
Das Uhrensymbol kann mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;adviceIcon&#039;&#039;&#039; geändert und/oder dessen Farbe angepasst, sowie einen Informationstext statt eines Icons angezeigt werden. &lt;br /&gt;
&lt;br /&gt;
=== 4 - Bereich Balkengrafik (Beam Graphic) ===&lt;br /&gt;
&lt;br /&gt;
Die Balkengrafik des Moduls ist ein wesentliches Visualisierungshilfsmittel. Im Auslieferungszustand existiert eine Balkengrafikebene, die &#039;&#039;&#039;Ebene 1&#039;&#039;&#039;.&lt;br /&gt;
Jede Ebene kann zwei Balkendiagramme mit auswählbaren Inhalten, Farben und einstellbarem LayoutTyp darstellen. In Ebene 1 kann die Wettervorhersage eingebettet oder, bei Vorhandensein von Batteriegeräten, die zukünftigen Zeiten mit empfohlener Ladefreigabe und SoC-Prognose eingeblendet werden. &lt;br /&gt;
&lt;br /&gt;
Welche Daten in welchen Zeiträumen dargestellt werden sollen, die Bestimmung des Layouts, die Gestaltung der Balken und einiges mehr wird durch Attribute gesteuert. Ein Teil dieser Einstellungen wird über das zusammengesetzete Attribut &#039;&#039;&#039;graphicControl-&amp;gt;&#039;Schlüssel&#039;=&#039;Wert&#039;&#039;&#039;&#039; eingestellt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;grundsätzliche Layout Definitionen&#039;&#039;&#039;&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204342.png|right|thumb|400px|Standardanzeige mit Wetter-Icons, gesetzen Attributen graphicBeam1Color=D4C177, graphicHistoryHour=11]]&lt;br /&gt;
&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingTop:Legt den Platz in px im Balkendiagramm fest, der zwischen dem oberen Rand der jeweiligen Balkengrafik Ebene und der ersten Text- oder Iconreihe dieser Ebene eingefügt wird.&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingBottom:Legt den Platz in px im Balkendiagramm fest, der zwischen der letzten Text- oder Iconreihe der jeweiligen Balkengrafik Ebene und dem unteren Rand dieser Ebene eingefügt wird. &lt;br /&gt;
;graphicControl-&amp;gt;layoutType:Layout-Optionen zur grundlegenden Gestaltung der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourStyle:Format der Zeitangabe in der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourCount:Anzahl der darzustellenden Balken/Stunden in der Balkengrafk&lt;br /&gt;
[[Datei:Screenshot Screenshot 2025-05-21 153613.png|right|thumb|400px|Erweiterung des oberen und unteren Abstandes mit den Attributen graphicControl-&amp;gt;beamPaddingTop und graphicControl-&amp;gt;beamPaddingBottom]]&lt;br /&gt;
;graphicControl-&amp;gt;energyUnit:definiert die Einheit zur Anzeige der elektrischen Leistung in der Grafik&lt;br /&gt;
;graphicHistoryHour:Anzahl der vorangegangenen Stunden die in der Balkengrafik dargestellt werden&lt;br /&gt;
;graphicControl-&amp;gt;beamWidth:Vorgabe Breite der Balken der Balkengrafik in px (sonst automatische Bestimmung) &lt;br /&gt;
;graphicBeamHeightLevel1:Multiplikator zur Festlegung der maximalen Balkenhöhe der jeweiligen Ebene (hier Ebene 1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;Definition der Inhalte und Balkeneigenschaften&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204756.png|right|thumb|400px|Wie oben aber mit gesetzem Attribut graphicShowNight=1]]&lt;br /&gt;
;graphicBeam1Color:Farbauswahl des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2Color:Farbauswahl des sekundären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam1Content:Legt den darzustellenden Inhalt des primären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam2Content:Legt den darzustellenden Inhalt des sekundären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam1FontColor:Auswahl der Schriftfarbe des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2FontColor:Auswahl der Schriftfarbe des sekundären Balkens (Ebene 1)&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 205024.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=0 (ohne Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;zusätzliche Optionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;graphicShowNight:Anzeigen oder Verbergen der Nachtstunden in der Balkengrafik&lt;br /&gt;
;graphicShowWeather:Wettericons in der Balkengrafik anzeigen/verbergen (nur Ebene 1)&lt;br /&gt;
;graphicWeatherColor:Farbe der Wetter-Icons für die Tagesstunden&lt;br /&gt;
;graphicWeatherColorNight:Farbe der Wetter-Icons für die Nachtstunden&lt;br /&gt;
;graphicShowDiff:Zusätzliche Anzeige der Differenz &amp;quot;&amp;lt;primärer Balkeninhalt&amp;gt; - &amp;lt;sekundärer Balkeninhalt&amp;gt;&amp;quot; im Kopf- oder Fußbereich der Balkengrafik&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die genaue Beschreibung und deren Optionen sind der aktuellen Online-Hilfe zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Für alle Ebenen gilt:&#039;&#039;&#039; Ein Attribut mit einer ungeraden Balkennummer (z.B. graphicBeam1Content) bezieht sich immer auf den primären Balken, ein Attribut mit einer geraden Balkennummer (z.B. graphicBeam2Content) bezieht sich immer auf den sekundären Balken.&lt;br /&gt;
&lt;br /&gt;
Die Balken haben, wie die meisten Elemente in der Balkengrafik, eine Mouse-Over Eigenschaft welche relevante Informationen zu den dargestellten Werten anzeigt. &lt;br /&gt;
&lt;br /&gt;
Sind die Nachtunden mit &#039;&#039;&#039;graphicShowNight&#039;&#039;&#039; ausgeblendet, werden keine Balken angezeigt sofern es keine Werte anzuzeigen gibt. Sollten dennoch Werte ungleich 0 anzuzeigen sein, werden diese Werte auch trotz ausgeblendeter Nachstunden angezeigt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 2 ====&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 211741.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=01 (mit Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 2&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam3Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam4Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 4 für Balken 4) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wetter-Icons können nur in Ebene 1 integriert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 2 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 2 gibt, eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgende Ebene.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 3 ====&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 3&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam5Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam6Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 5 für Balken 5) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 3 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 3 gibt, ist eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgenden Ebenen, d.h. auch auf die Ebene 3.&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 5 - Die Energieflußgrafik (Flow Graphic) ===&lt;br /&gt;
[[Datei:Screenshot 2025-02-13 213424.png|right|thumb|400px|Energieflußgrafik mit Verbrauchern in der Nachtdarstellung (Mondphasen) nach Sonnenuntergang]]&lt;br /&gt;
&lt;br /&gt;
Die Energieflußgrafik stellt die registrierten Erzeuger, Batterien, Netzzugänge und Verbraucher strukturiert in mehreren Ebenen dar:&lt;br /&gt;
&lt;br /&gt;
;Ebene 1: In der oberen Ebene befinden sich die PV-Generatoren, Smart-Loader sowie sonstigen Erzeuger &lt;br /&gt;
;Ebene 2: Die mittlere Ebene organisiert den Zugang zum öffentlichen Netz, dem Hausknoten, dem Batterieknoten sowie einem Dummy-Verbraucher (Lampensymbol) für den Energieverbrauch des Hauses der keinem der registrierten Verbraucher zugeordnet werden kann.&lt;br /&gt;
;Ebene 3: In der unteren Ebene werden die registrierten Verbraucher dargestellt. Unterhalb der Verbrauchersymbole werden der aktuelle Verbrauch (bzw. der On/Off-Zustand) sowie darunter die Restlaufzeit (Minuten) des Verbrauchers, sofern er durch das Modul geplant und gestartet wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Position und Gestaltung der Grafikelemente ist umfangreich über das Attribut &#039;&#039;&#039;flowGraphicControl&#039;&#039;&#039; und den darin verfügbaren Schlüsseln einstellbar.&lt;br /&gt;
Die Bedeutung der Schlüssel ist in der Online-Hilfe zum Attribut mit einem Beispiel beschrieben. &lt;br /&gt;
&lt;br /&gt;
Darüber hinaus enthalten die Setup-Attribute &#039;&#039;&#039;setupInverterDevXX&#039;&#039;&#039;, &#039;&#039;&#039;setupOtherProducerXX&#039;&#039;&#039; und &#039;&#039;&#039;consumerXX&#039;&#039;&#039; weitere Einstellungsmöglichkeiten um deren Icons und Färbungen in der Flußgrafik individuell einstellen zu können. So sind zum Beispiel die Icons der PV-Inverter und deren Färbung mit dem Schlüssel &#039;&#039;&#039;icon&#039;&#039;&#039; der setupInverterDevXX-Attribute in Abhängigkeit von Tag und Nacht separat definierbar.&lt;br /&gt;
&lt;br /&gt;
In den Verbraucher-Attributen ist mit dem Schlüssel &#039;&#039;&#039;noshow&#039;&#039;&#039; die Sichtbarkeit in der Flußgrafik definierbar.&lt;br /&gt;
&lt;br /&gt;
Generell steuert das Attribut &#039;&#039;&#039;graphicSelect&#039;&#039;&#039; die Ein- bzw. Ausblendung der gesamten Flußgrafik.&lt;br /&gt;
&lt;br /&gt;
== Die Verbrauchsprognose ==&lt;br /&gt;
Im Gegensatz zu der PV Prognose gibt es keine API oder andere externen Datenquellen die für die Verbrauchsprognose herangezogen werden könnten.&lt;br /&gt;
&lt;br /&gt;
Zum Zweck der Verbrauchsermittlung verwendet das Modul die Meterdaten aus dem Attribut &#039;&#039;setupMeterDev&#039;&#039; sowie den weiteren setup-Attributen &#039;&#039;setupInverterDevXX&#039;&#039;. &lt;br /&gt;
Sind auch andere Erzeuger (BHKW, Windanlagen, etc.) bzw. eine Batterie vorhanden, sind ebenfalls die Attribute &#039;&#039;setupOtherProducerXX&#039;&#039; bzw. &#039;&#039;setupBatteryDev&#039;&#039; für die Berechnung des Hausverbrauchs relevant. In diesen Attributen gibt es die Schlüssel &#039;&#039;*total&#039;&#039; die teilweise optional sind. Für die Verbrauchsprognose bilden sie jedoch die Berechnungsgrundlage und sind deswegen für diese Funktionalität wichtig anzugeben.&lt;br /&gt;
&lt;br /&gt;
Die Verbrauchswerte werden stundengenau erfasst und im Datenspeicher &#039;&#039;pvHistory&#039;&#039; für 31 Tage, sowie im Datenspeicher &#039;&#039;pvCircular&#039;&#039; 210 Tage gespeichert. Die beiden Datenspeicher übernehmen unterschiedliche Aufgaben im Rahmen der Prognoseerstellung. Auf Grundlage der gespeicherten und somit historischen Verbrauchswerte erstellt das Modul eine Prognose für die kommende Zeit.&lt;br /&gt;
&lt;br /&gt;
Mit dem Kommando &lt;br /&gt;
&lt;br /&gt;
   &amp;quot;get ... pvHistory [Tag]&amp;quot; &lt;br /&gt;
&lt;br /&gt;
wird der Inhalt aufgelistet. Die Schlüssel &#039;&#039;confc&#039;&#039;, &#039;&#039;con&#039;&#039; und &#039;&#039;gcon&#039;&#039; zeigen die Verbrauchsprognose, den Verbrauch und den Netzbezug der jeweiligen Stunde des gewählten Tages.&lt;br /&gt;
Die Stunde &amp;quot;99&amp;quot; zeigt die Summen dieser Schlüsssel für den Tag:&lt;br /&gt;
&lt;br /&gt;
      99 =&amp;gt; etotal: , pvfc: 782, pvrl: 0, rad1h: -&lt;br /&gt;
            confc: 14540, con: 13873, gcon: 13873, gfeedin: 0&lt;br /&gt;
            batintotal: , batin: 0, batouttotal: , batout: 0&lt;br /&gt;
            batmaxsoc: -, batsetsoc: -&lt;br /&gt;
            wid: , wcc: , wrp: , pvcorrf: , dayname: So&lt;br /&gt;
            cyclescsm01: 0&lt;br /&gt;
            cyclescsm02: 0&lt;br /&gt;
            cyclescsm03: 0&lt;br /&gt;
            cyclescsm04: 1, hourscsme04: 0.00&lt;br /&gt;
            cyclescsm05: 0&lt;br /&gt;
            cyclescsm06: 0&lt;br /&gt;
            cyclescsm07: 1, hourscsme07: 0.00&lt;br /&gt;
            cyclescsm08: 1, hourscsme08: 0.00&lt;br /&gt;
            cyclescsm09: 1, hourscsme09: 0.03 &lt;br /&gt;
&lt;br /&gt;
In dem Beispiel wurden für den Tag 14540 Wh Verbrauch prognostiziert, 13873 Wh tatsächlich verbraucht und davon 13873 Wh aus dem Netz bezogen. Leider war an diesem Tag keinerlei PV Ertrag vorhanden, was man auch an dem Schlüssel &#039;&#039;pvrl&#039;&#039; erkennen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Inhalt des pvCircular-Speichers kann mit dem Befehl  &lt;br /&gt;
&lt;br /&gt;
     &amp;quot;get ... pvCircular [Tag]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Das nachfolgende Beispiel zeigt die Ausgabe für die Tagesstunde 23:&lt;br /&gt;
&lt;br /&gt;
 23 =&amp;gt; pvapifc: 0, pvaifc: -, pvfc: 0, aihit: 0, pvrl: 0&lt;br /&gt;
       batin01: 0, batin02: -, batin03: -&lt;br /&gt;
       batout01: 619, batout02: -, batout03: -&lt;br /&gt;
       confc: 650, gcon: 23, gfeedin: 0, wcc: 40, rr1c: 0.00&lt;br /&gt;
       temp: -6.00, wid: 100, wtxt: Bewölkungsentwicklung nicht beobachtet&lt;br /&gt;
       pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
       ... &lt;br /&gt;
       con_all =&amp;gt; Sa  @ 617 762&lt;br /&gt;
                  Di  @ 693 645&lt;br /&gt;
                  Mo  @ 620 679&lt;br /&gt;
                  So  @ 669 666 636&lt;br /&gt;
                  Mi  @ 701 626&lt;br /&gt;
                  Do  @ 612 642&lt;br /&gt;
                  Fr  @ 615 606&lt;br /&gt;
&lt;br /&gt;
Der Schüssel &#039;&#039;con_all&#039;&#039; enthält einen Hash aus Arrays die für jeden Wochentag (Mo..So) bis zu 30 Verbrauchswerte (in Wh) für die angezeigte Stunde speichern. Wie hier erkennbar ist, wurden an den drei vergangenen Sonntagen jweils 669 Wh, 666 Wh bzw. 636 Wh in der Stunde 23 (22:00-22:59) verbraucht.&lt;br /&gt;
Der Median aus diesen Werten geht in die Verbrauchsprognose ein. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wochentagsnamen Mo..So sind von den installierten Locales auf Betriebsystemebene abhängig. Ist keine deutsche locale installiert, werden die englischen Wochentagsnamen Mon..Sun verwendet. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Wie wird der Verbrauch des Hauses ermittelt und gespeichert? ===&lt;br /&gt;
Die Verbrauchsdaten des Hauses werden auf Stundenbasis ermittelt und gespeichert. Das &amp;quot;Haus&amp;quot; steht als Synonym aller im Kontext des Solarforecast Devices zusammengeführten Inverter (setupInverterDevXX), sonstigen Erzeuger (setupOtherProducerXX), Netzanschlüsse (setupMeterDev), Verbraucher (consumerXX) und Batterien (setupBatteryDev).&lt;br /&gt;
&lt;br /&gt;
Alle diese Daten werden durch das Modul mit jedem ausgeführten Zyklus (Attribut plantControl-&amp;gt;cycleInterval) und, wenn ein Event eines als &#039;asynchron&#039; definierten Devices auftritt, gesammelt und daraus permanent ein aktualisierter Verbrauch berechnet. Die Berechnung beschreibt folgende Formel:&lt;br /&gt;
&lt;br /&gt;
 PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung - Verbrauch = 0&lt;br /&gt;
&lt;br /&gt;
bzw.&lt;br /&gt;
 &lt;br /&gt;
 Verbrauch (Wh) = PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung&lt;br /&gt;
            con = PV           + PP                 - GridIn          + GridCon   - BatIn          + BatOut&lt;br /&gt;
&lt;br /&gt;
Die PV-Erzeugung beinhaltet die Summe aller durch die angegebnen Inverter (setupInverterDev01 .. setupInverterDevXX) erzeugten Energien. Die &amp;quot;sonstige Erzeugung&amp;quot; summiert sich aus den Werten aller angegebenen Producer (setupOtherProducer01 .. setupOtherProducerXX). Der Verbrauch wird durch die registrierten Geräte consumerXX teilweise direkt erfasst, ist aber grundsätzlich unvollständig da nicht alle Verbrauchswerte im &amp;quot;Haus&amp;quot; gemessen und durch das Modul erfasst werden können.&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel zeigt das Ergebnis bei 300 Wh PV-Erzeugung und gleichzeitige 500 Wh Netzbezug:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 300 + 0 - 0 + 500 - 0 + 0 = 800 Wh&lt;br /&gt;
&lt;br /&gt;
Bei 1300Wh PV-Erzeugung, 100 Wh Netzeinspeisung sowie 200 Wh Batterieladung ergibt sich der Verbrauch zu:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 1300 + 0 - 100 + 0 - 200 + 0 = 1000 Wh&lt;br /&gt;
&lt;br /&gt;
Ohne Erzeugung, aber mit der Energielieferung von 500 Wh aus der Batterie, 800 Wh Netzbezug (mit einem Anteil Batterienachladung aus dem Netz von 200 Wh) sieht die Verbrauchsrechnung wie folgt aus: &lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 0 + 0 - 0 + 800 - 200 + 500 = 1100 Wh&lt;br /&gt;
&lt;br /&gt;
Der so ermittelte Verbrauchsert wird mit jedem Zyklus in der pvHistory im Schlüssel &amp;quot;con&amp;quot; gespeichert. Man kann sich die gespeicherten Werte mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;name&amp;gt; pvHistory [&amp;lt;Tag&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Nachfolgendes Beispiel zeigt einen Datensatz für die Stunde 8 eines Tages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      08 =&amp;gt; pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotali01: 62940734, etotali02: 2928860, etotali03: -&lt;br /&gt;
            pvrl01: 0, pvrl02: 0, pvrl03: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 630, con: 962, gcons: 962, conprice: 0.2958&lt;br /&gt;
            gfeedin: 0, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 120, sunalt: -3&lt;br /&gt;
            batintotal: 3713815.07742543, batouttotal: 3604468.26993988, batin: 0, batout: 0&lt;br /&gt;
            wid: 161, wcc: 89, rr1c: 0.00, pvcorrf: 0.27/0.00 temp: 7.40, &lt;br /&gt;
            csmt01: 110996.12, csme01: 32.1399999999994, minutescsm01: 30&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 2513.67, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1581293.6, csme04: 136.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 1662.17, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 90.53, csme06: 0, minutescsm06: 0&lt;br /&gt;
            csmt07: 39.75, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 38050, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 131627, csme09: 33.2000000000116, minutescsm09: 39&lt;br /&gt;
            minutescsm10: 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Schlüssel &amp;quot;con&amp;quot; ist der gespeicherte Verbrauch von 962 Wh ersichtlich.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit bekommt man mit dem Attribut &#039;&#039;ctrlDebug=collectData&#039;&#039; einen Einblick in die Verbrauchsermittlung bei jedem Zyklus und kann so die Eingangswerte und das daraus resultierende Ergebnis im FHEM Log nachverfolgen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
2024.11.28 11:38:20.080 1: SolCast DEBUG&amp;gt; EnergyConsumption input -&amp;gt; PV: 96, PP: 0, GridIn: 0, GridCon: 582, BatIn: 5, BatOut: 0&lt;br /&gt;
2024.11.28 11:38:20.081 1: SolCast DEBUG&amp;gt; EnergyConsumption result -&amp;gt; 673 Wh&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie wird die Verbrauchsprognose erstellt? ===&lt;br /&gt;
&lt;br /&gt;
Aus den gespeicherten con-Werten (Verbrauchsdaten) der pvCircular (Schlüssel con_all) sowie Einträgen der pvHistory wird der Median der historischen Tage ermittelt und für den kommenden Tag bzw. die kommen Stunden zur Prognose angewendet. Dabei geht per default jeder verfügbare historische Tag gleichberechtigt in die Prognose ein. Mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039; kann festgelegt werden, dass nur gleiche Wochentage (Mo..So) für die Prognose verwendet werden. Hierbei spielt die Vermutung, dass das Verbrauchsverhalten eine gewisse Korrelation zum Wochentag hat, eine Rolle. &lt;br /&gt;
&lt;br /&gt;
Verwendet man die Einstellung consForecastIdentWeekdays=1, hat es sich als vorteilhaft erwiesen, das Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays&#039;&#039;&#039; auf einen niedrigeren Wert als den Default zu setzen. Eine Einstellung auf &#039;8&#039; zum Beispiel verwendet den Median der gleichen Wochentage der vergangenenen 8 Wochen. Dadurch wird nicht zu weit in die Vergangenheit verzweigt und so eine langsame Veränderung des Verbrauchsmedian, zum Beispiel hervorgerufen durch den Übergang vom Winter in das Frühjahr hinein, abgebildet.&lt;br /&gt;
&lt;br /&gt;
Weiteren Einfluß auf die Verbrauchsprognose kann mit dem Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; im Consumerattribut genommen werden. Insbesondere bei der unregelmäßigen Nutzung von Verbrauchern mit hoher Leistung kann die Projektion der aufgezeichneten historischen Werte in die Prognose zu unverhältnismäßig hohen Verbrauchswerwartunden führen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Möglicherweise führt in Fällen die Verwendung eine der nachfolgenden Optionen zu einem besseren Ergebnis:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;1 -&#039;&#039;&#039; die allgemeine Verbrauchsprognose wird um die gespeicherten Energieverbrauchsanteile reduziert.&lt;br /&gt;
* &#039;&#039;&#039;2 -&#039;&#039;&#039; wie bei &#039;1&#039;, jedoch gehen die Planungsdaten des Verbrauchers bei der Prognose der kommenden Stunden wieder mit ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;&#039;exconfc&#039;&#039;&#039; in einem der Consumer verwendet, sollte&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays=4&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
eingestellt werden. Hintergrund ist, dass die Verbrauchsanteile der jeweiligen Verbraucher nur maximal 31 Tage in der pvHistory verfügbar sind. Für längere Zeiträume stehen nur Gesamtsummen des Verbrauchs in der pvCircular zu Verfügung.  &lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=1&#039;&#039;&#039; werden die in der Historie aufgezeichneten Verbrauchsbestandteile aus einer Prognose herausgerechnet. Konkret werden die in der pvHistory aufgezeichneten Verbrauchsbestandteile für die relevante Stunde ermittelt und daraus ein Durchschnitt gebildet der vom Prognosewert subtrahiert wird. Mit dem Attributwert plantControl-&amp;gt;consForecastIdentWeekdays=1 werden wiederum nur identische Wochentage (Mo .. So) zusammengefasst.&lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=2&#039;&#039;&#039; erfolgt ebenso die Eliminierung des Verbrauchsanteils, es wird jedoch auf die Planungsdaten für diesen Verbraucher zugegriffen und die geplanten Energieanteile wiederum der Verbrauchsprognose für die kommenden Stunden hinzugerechnet.&lt;br /&gt;
&lt;br /&gt;
In beiden Anwendungsfällen ist es notwendig, dass dem Modul durch die Angabe entsprechender Readings der Energieverbrauch im Setup des Consumers bekannt gemacht wird damit diese Energieanteile registriert werden können. Allgemein funktioniert die Verbrauchsprognose gut wenn Verbrauchsprozesse regelmäßig in einem wiederkehrenden Zeitraster ablaufen, der Verbrauch durch persönliche Rituale bestimmt ist. So zum Beispiel könnte am Dienstag und Samstag gewöhnlich die Waschmaschine laufen, das E-Auto täglich aufgeladen werden und gebügelt wird oft am Sonntag Nachmittag.&lt;br /&gt;
&lt;br /&gt;
Unregelmäßige Nutzung, vor allem vom Großverbrauchern, lässt sich nur sehr schwer und ungenügend auf zukünftige Verbrauchsprognosen projizieren.&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis der Prognose wird im Kopf der Grafik in der Zeile &#039;&#039;Verbrauch&#039;&#039; sowie in diversen Readings wie &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RestOfDayConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den Rest des Tages)&lt;br /&gt;
* &#039;&#039;&#039;NextHours_Sum04_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für die nächsten 4 Stunden)&lt;br /&gt;
* &#039;&#039;&#039;Tomorrow_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den kommenden Tag)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
angezeigt.&lt;br /&gt;
&lt;br /&gt;
Weitere Aggregationen kann man sich über das Attribut &#039;&#039;&#039;ctrlStatisticReadings&#039;&#039;&#039; bei Bedarf zuschalten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;conForecastTillNextSunrise&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
* &#039;&#039;&#039;todayConForecastTillSunset&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
* &#039;&#039;&#039;todayConsumptionForecast&#039;&#039;&#039; - Verbrauchsprognose aufgesplittet pro Stunde des aktuellen Tages (01-24) &lt;br /&gt;
 &lt;br /&gt;
==== Debugging der Verbrauchsprognose ====&lt;br /&gt;
Um sich einen Einblick über die Erstellung der Verbrauchsprognose zu verschaffen, bietet sich die Einschaltung von:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
an. Mit diesem gesetzten Attribut wird die Erstellung der Prognose im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; ################### Start Consumption forecast ###################&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; Basics - installed locale: de_DE.UTF-8, used scheme: DE&lt;br /&gt;
2025.02.27 19:52:00.064 1: SolCast DEBUG&amp;gt; process Today dayname: Do, Tomorrow dayname: Fr&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 01 - 74.43 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 10 - 290.77 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 24 - 660.70 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 20, hod: 07 - 459.93 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;07&#039; register for exclude day 20, hod: 02 - 0.33 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 30, hod: 08 - 264.78 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next Hours (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; excl. hist 74 Wh for Hour 01, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; estimated cons of Hour 01: 436 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; excl. hist 0 Wh for Hour 02, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 02: 428 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 03: 458 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 04: 503 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 05: 489 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 06: 482 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; excl. hist 460 Wh for Hour 07, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 07: 274 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 265 Wh for Hour 08, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 08: 441 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 09: 558 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 291 Wh for Hour 10, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 10: 443 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 11: 881 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 12: 794 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 13: 840 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 14: 660 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 15: 812 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 16: 752 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 17: 597 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 18: 652 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 19: 634 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 20: 628 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 21: 713 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 22: 596 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 23: 629 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; excl. hist 661 Wh for Hour 24, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons of Hour 24: 660 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons Tomorrow: 16848 Wh, Individual hourly values considered: 72, exclude: 0 Wh (avg of 0 entities)&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Store Consumption forecast values (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour00&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;20&#039; confc: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour01&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;21&#039; confc: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour02&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;22&#039; confc: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour03&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;23&#039; confc: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store &#039;NextHour04&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;24&#039; confc: 660&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour05&#039; hod &#039;01&#039; confc: 436, confcEx: 436&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour06&#039; hod &#039;02&#039; confc: 428, confcEx: 428&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour07&#039; hod &#039;03&#039; confc: 458, confcEx: 458&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour08&#039; hod &#039;04&#039; confc: 503, confcEx: 503&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour09&#039; hod &#039;05&#039; confc: 489, confcEx: 489&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour10&#039; hod &#039;06&#039; confc: 482, confcEx: 482&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour11&#039; hod &#039;07&#039; confc: 274, confcEx: 274&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour12&#039; hod &#039;08&#039; confc: 441, confcEx: 441&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour13&#039; hod &#039;09&#039; confc: 558, confcEx: 558&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour14&#039; hod &#039;10&#039; confc: 443, confcEx: 443&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour15&#039; hod &#039;11&#039; confc: 881, confcEx: 881&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour16&#039; hod &#039;12&#039; confc: 794, confcEx: 794&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour17&#039; hod &#039;13&#039; confc: 840, confcEx: 840&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour18&#039; hod &#039;14&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour19&#039; hod &#039;15&#039; confc: 812, confcEx: 812&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour20&#039; hod &#039;16&#039; confc: 752, confcEx: 752&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour21&#039; hod &#039;17&#039; confc: 597, confcEx: 597&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour22&#039; hod &#039;18&#039; confc: 652, confcEx: 652&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour23&#039; hod &#039;19&#039; confc: 634, confcEx: 634&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour24&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour25&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour26&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour27&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour28&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; consumption calculated - day: 27, hod: 20, con: 574 Wh&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; write pvCircular consumption - hod: 99, todayConsumption: 11210 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe startet mit &#039;&#039;&amp;quot;Start Consumption forecast&#039;&#039;&amp;quot;, es werden die zu exkludierenden historischen Daten für jeden Consumer bzgl. jedem Tag (day) und Stunde des Tages (hod) getrennt registriert. Diese Werte werden durch die gespeicherte Einträge in der pvHistory (max. 31 historische Tage) geliefert. &lt;br /&gt;
&lt;br /&gt;
Im nächsten Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next Hours (new median)&amp;quot;&#039;&#039; werden die Prognosen für die nächsten Stunden kalkuliert und die zuvor registrierten Excludes angewendet. Die Prognose für den kommenden Tag ist im Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next day (new median)&amp;quot;&#039;&#039; protokolliert. Die Prognose für den kommenden Tag ist nicht einfach die Summe der Prognose der nächsten Stunden, denn in den kommenden Stunden werden auch die verfügbaren Planungen der Consumer einbezogen. Für den kommenden Tag können diese Werte unter Umständen nicht einbezogen werden da sie zum Zeitpunkt X noch nicht verfügbar sind.&lt;br /&gt;
&lt;br /&gt;
Im Abschnitt &#039;&#039;&amp;quot;Store Consumption forecast values (new median)&amp;quot;&#039;&#039; erscheinen die effektiv gespeicherten Werte. Diese sind die Grandlage für die grafische Darstellung sowie weiteren Kalkulationen.&lt;br /&gt;
&lt;br /&gt;
=== Wie kann eine fehlerhafte Verbrauchsprognose korrigiert werden? ===&lt;br /&gt;
Wie im vorherigen Abschnitt beschrieben, wird die Prognose aus den gespeicherten &amp;quot;con&amp;quot;-Werten der vergangenen Tage (bzw. Stunden) abgeleitet. &lt;br /&gt;
Grundsätzlich muß zunächst sichergestellt werden, dass die auszulesenden Readings der angegebenen Energiezähler sowie deren Einheiten! korrekt eingestellt sind. Das gilt ebenfalls für die registrierten Verbraucher im Modul.&lt;br /&gt;
&lt;br /&gt;
Für einen ersten Überblick bietet sich das Debug Attribut an zu setzen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
Beispielausgabe des Debug:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2024.09.21 13:28:27.041 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day ###################&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;01&amp;lt; considering possible exclusions: 14082&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;08&amp;lt; considering possible exclusions: 16446&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;15&amp;lt; considering possible exclusions: 14568&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;25&amp;lt; considering possible exclusions: 15522&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; estimated Consumption for tomorrow: 15154, days for avg: 4&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next hours ###################&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 14 -&amp;gt; 850 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 14 -&amp;gt; 643 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 14 -&amp;gt; 590 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 14 -&amp;gt; 522 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 13:00:00, confc: 651, days for avg: 4, hist. consumption registered consumers: 560.97&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 15 -&amp;gt; 720 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 15 -&amp;gt; 743 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 15 -&amp;gt; 897 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 15 -&amp;gt; 557 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 14:00:00, confc: 729, days for avg: 4, hist. consumption registered consumers: 620.97&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 16 -&amp;gt; 676 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 16 -&amp;gt; 790 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 16 -&amp;gt; 785 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 16 -&amp;gt; 581 Wh&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 15:00:00, confc: 708, days for avg: 4, hist. consumption registered consumers: 647.29&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 17 -&amp;gt; 622 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 17 -&amp;gt; 639 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 17 -&amp;gt; 646 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 17 -&amp;gt; 572 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 16:00:00, confc: 619, days for avg: 4, hist. consumption registered consumers: 618.30&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 18 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 18 -&amp;gt; 614 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 18 -&amp;gt; 580 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 18 -&amp;gt; 480 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 17:00:00, confc: 567, days for avg: 4, hist. consumption registered consumers: 583.41&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 19 -&amp;gt; 615 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 19 -&amp;gt; 1659 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 19 -&amp;gt; 597 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 19 -&amp;gt; 618 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 18:00:00, confc: 872, days for avg: 4, hist. consumption registered consumers: 636.97&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 20 -&amp;gt; 611 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 20 -&amp;gt; 1124 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 20 -&amp;gt; 546 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 20 -&amp;gt; 479 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 19:00:00, confc: 690, days for avg: 4, hist. consumption registered consumers: 578.87&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 21 -&amp;gt; 1474 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 21 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 21 -&amp;gt; 619 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 21 -&amp;gt; 433 Wh&lt;br /&gt;
2024.09.21 13:28:27.058 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Im ersten Teil wird die erwartete Consumption für den nächsten Tag unter Berücksichtigung möglicher Ausschlüsse von Verbrauchern ausgegeben. Ausschlüsse von Verbrauchern ergeben sich wenn in dem Verbraucherattribut der Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; gesetzt ist. Er besagt, dass die Verbrauchswerte des Verbrauchers in eine zukünftige Prognose nicht eingehen sollen. Zum Beispiel wenn ein Verbraucher mit sehr hohen Verbrauchswerten nur sporadisch eingesetzt wird und dadurch die Prognose stark verfälschen würde. Es ist auch zu sehen, dass bedingt durch das Attribut &#039;&#039;&#039;affectConsForecastIdentWeekdays = 1&#039;&#039;&#039; nur die historischen Tage 01, 08, 15 und 25 berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Teil wird die berechnete Erwartung für die nächsten Stunden ausgegeben. &lt;br /&gt;
Zur Beschreibung der Fehlersuche gehen wir davon aus, dass die Prognose von 780 Wh am 2024-09-21 20:00:00 zu hoch erscheint weil am Tag &amp;quot;07&amp;quot; ein Wert von 1474 Wh gespeichert ist:&lt;br /&gt;
&lt;br /&gt;
 SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt geben wir die historischen Werte für den Tag 07 aus:&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;Name&amp;gt; pvHistory 07&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz interessiert die Stunde 21. Sie resultiert aus der obigen Angabe &amp;quot;starttime: xxxx-xx-xx 20:00:00&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      21 =&amp;gt; etotal: 64354660, pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 496, con: 1474, gcons: 23, conprice: 0.2958&lt;br /&gt;
            gfeedin: 5, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 289, sunalt: -8&lt;br /&gt;
            batintotal: 3064096.92456668, batouttotal: 2958021.37946804, batin: 0, batout: 1460&lt;br /&gt;
            wid: 101, wcc: 20, rr1c: 0.00, pvcorrf: 1.00/-temp: 26.00, &lt;br /&gt;
            csmt01: 64262.43, csme01: 28.8099999999977, minutescsm01: 25&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 0, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1389417.4, csme04: 94.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 0, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 290.15, csme06: 6.66999999999996, minutescsm06: 54&lt;br /&gt;
            csmt07: 0, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 32800, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 103987.8, csme09: 38, minutescsm09: 43&lt;br /&gt;
            csmt10: 9151.24999999783, csme10: 3.99999999997999, minutescsm10: 60&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz sind die Energieverbrauchsanteile der im Device registrierten Verbraucher mit dem Schlüssel &amp;quot;csmeXX&amp;quot; gespeichert. Dabei ist &amp;quot;XX&amp;quot; die Verbrauchernummer. In dem Beispiel existieren die Anteile csme01 und csme03 - csme10. Keiner dieser Verbraucher hat einen auffälligen Verbrauchswert gespeichert, d.h. die Messung der Verbraucher scheidet als Problemquelle aus. Wäre ein unverhältmismäßig hoher Verbrauch bei einem der Verbraucher feststellbar, müssten die Schlüssel &#039;&#039;&#039;pcurr&#039;&#039;&#039; und &#039;&#039;&#039;etotal&#039;&#039;&#039; im consumerXX-Attribut geprüft, sowie die Datenlieferung des Consumerdevices selbst geprüft werden.  &lt;br /&gt;
&lt;br /&gt;
Es wurde offensichtlich ein hoher Verbrauch von einem nicht registrierten Verbraucher verursacht oder durch die Übertragung eines Meßfehlers des Devices, angegeben im Attribut &#039;&#039;&#039;setupMeterDev&#039;&#039;&#039;, in das SolarForecast Device übertragen. Eine weitere Analyse ist an dieser Stelle nicht möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Behebung des falschen Wertes kann ein Reset der gespeicherten Consumption der relevanten Stunde durchgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; reset consumptionHistory 07 21&lt;br /&gt;
&lt;br /&gt;
== Modulinterne Datenstrukturen ==&lt;br /&gt;
Das Modul speichert die verschiedenen historischen und aktuellen Daten wie PV-Prognose, Witterungsdaten (Regen, Bewölkung), Strahlungsdaten, Einspeisung, Bezug, reale Erzeugungsdaten und vieles mehr zur Laufzeit im Arbeitsspeicher. Dadurch ist die Verarbeitung dieser Daten im Vergleich zu Lesevorgängen aus dem Filesystem bzw. einer Datenbank sehr performant. Allerdings würden diese Daten bei einem FHEM Absturz bzw. bei einem regulären Shutdown verlorengehen.&lt;br /&gt;
&lt;br /&gt;
Deswegen werden die relevanten Daten regelmäßig in Dateien gesichert und bei Bedarf wiederhergestellt. Diese Dateien befinden sich im Verzeichnis &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; und heißen &#039;&#039;&#039;.*_SolarForecast_.*&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Die Daten werden in jedem Zyklus der Zentralschleife (CentralTask) gesammelt bzw. berechnet. Der Zyklus wird mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;cycleInterval&#039;&#039;&#039; eingestellt.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit können diese Daten über get-Kommandos abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvHistory [Tag]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der pvHistory Datenspeicher enthält die vergangenen Kennwerte der letzten 31 Tage mit einer Genauigkeit von einer Stunde. Es werden die Prognosewerte für Erzeugung und Verbrauch, die realen Werte für Erzeugung und Verbrauch sowie ebenso die Laufzeiten jedes einzelnen Verbrauchers (Consumer) festgehalten. Für jeden Tag gibt es die Stunde &amp;quot;99&amp;quot; die eine Summierung der Stundenwerte des Tages bzw. Sonderschlüssel enthält.&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf lässt sich mit dem Befehl &amp;quot;set ... reset pvHistory&amp;quot; der gesamte Inhalt des Speichers löschen (nicht empfohlen). Selektiver funktioniert die Datenlöschung mit &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt;&amp;quot; (Daten eines bestimmten Tages löschen) bzw. &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt; &amp;lt;Stunde&amp;gt;&amp;quot; (Daten der Stunde  eines bestimmten Tages löschen). Die letzten beiden Kommandos müssen über die Kommandozeile im Browser ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvCircular &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Ringspeicher enthält Daten der letzten 24 Stunden sowie fortwährend berechnete Werte wie Korrekturfaktoren der PV-Erzeugung und Prognosequalität.&lt;br /&gt;
Neue Stundenwerte des Tages überschreiben die gespeicherten Schüssel des vorangegangenen Tages sofern es sich nicht um fortwährend berechnete Werte handelt. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... nextHours&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Speicher enthält sämtliche Prognosewerte der kommenden Stunden beginnend mit der aktuellen Stunde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... radiationApiData&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Abhängig von der ausgewählten Strahlungsdaten API enthält dieser Speicher die von der API gelieferten Rohdaten sowie evtl. weitere für die Funktion benötigte Daten wie API-Keys, Response Messages, Anzahl der API Abruf und weitere.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valCurrent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Struktur wird nicht regelmäßig im Filesystem gespeichert und enthält immer aktuell gesammelte oder berechnete/gelieferte Daten wie z.B. die Autarkierate, letze Laufzeit der Zentralschleife (CentralTask), Zeit des Sonnenauf- und untergangs sowie weitere Betriebsdaten. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valConsumerMaster [XX]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zeigt die Daten der aktuell im SolarForecast Device registrierten Verbraucher. Mit der Nummer &#039;&#039;&#039;XX&#039;&#039;&#039; kann ein bestimmter Verbraucher angesprungen werden. Die Nummer korrespondiert mit dem entsprechenden &#039;&#039;&#039;consumerXX&#039;&#039;&#039; Attribut.&lt;br /&gt;
Neben anderen Betriebs- und Energiedaten werden insbesondere folgende Daten ermittelt, die für die zukünftige Planung der Verbraucherschaltzeiten relevant sind:&lt;br /&gt;
&lt;br /&gt;
* epieces - prognostizierte Energiescheiben pro Betriebsstunde &lt;br /&gt;
&lt;br /&gt;
Ausgehend von gespeicherten historischen Verbrauchsdaten des Verbrauchers wird der Energieverbrauch des Verbrauchers in seiner ersten Betriebsstunde prognostiziert, was insbesondere für die Planung der optimalen Startzeit des Verbrauchers in Bezug zu der prognostizierten PV Energie und den Verbrauchswerten weiterer vorhandener bzw. zu planender Verbraucher Berücksichtigung findet. Weitere Informationen zur Verbrauchersteuerung in diesem  [[#Verbrauchersteuerung_-_Registrieren_und_visualisieren_von_Verbrauchern|Abschnitt]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Schnittstelle für Modulautoren bzw. eigenen Code ===&lt;br /&gt;
&lt;br /&gt;
Die im vorherigen Artikel beschriebenen internen Datenstrukturen können durch externen Code abgefragt und ausgewertet werden.&lt;br /&gt;
Dazu stehen die folgenden Funktionen zur Verfügung. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]BatteryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Bn&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valBattery&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CurrentVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valCurrent&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]InverterVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valInverter&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ProducerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valProducer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]HistoryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Day&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvHistory&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CircularVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvCircular&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]NexthoursVal (&#039;&amp;lt;Name&amp;gt;&#039;, &amp;lt;nhr&amp;gt;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... nextHours&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ConsumerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valConsumerMaster&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]RadiationAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;DateTime&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... radiationApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]WeatherAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;TimeCode&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... weatherApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StatusAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;QTag&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... statusApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StringVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valStrings&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Angabe des Packages (FHEM::SolarForecast::) ist nur notwendig wenn die Funktionen von außerhalb des SolarForecast-Devices aufgerufen werden. Innerhalb des Devices (Code-Ausführung im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039;) kann darauf verzichtet werden.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der Platzhalter sind:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     &amp;lt;Name&amp;gt;     - Name des SolarForecast Devices&lt;br /&gt;
     &amp;lt;Day&amp;gt;      - abzufragender Tag (01 - 31)&lt;br /&gt;
     &amp;lt;Bn&amp;gt;       - Batterie Nummer (01, 02, ...)&lt;br /&gt;
     &amp;lt;DateTime&amp;gt; - Startzeit der Form YYYY-MM-DD hh:00:00&lt;br /&gt;
     &amp;lt;TimeCode&amp;gt; - Zeitwert der Form fcX_XX (z.B. fc1_19)&lt;br /&gt;
     &amp;lt;APIname&amp;gt;  - Hauptname der API gemäß setupWeatherDev1 (z.B. OpenMeteo)&lt;br /&gt;
     &amp;lt;String&amp;gt;   - Name des PV-Modulstrings wie im Attribut &#039;setupInverterStrings&#039;&lt;br /&gt;
     &amp;lt;QTag&amp;gt;     - Question Tag, z.B. &#039;?All&#039;&lt;br /&gt;
     &amp;lt;Nr&amp;gt;       - laufende Nummer des Verbrauchers / Gerätes (01, 02, 03, 04,...)&lt;br /&gt;
     &amp;lt;HoD&amp;gt;      - abzufragende Stunde (01 - 24, 99)&lt;br /&gt;
     &amp;lt;nhr&amp;gt;      - nächste Stunde (NextHour00, NextHour01,...)&lt;br /&gt;
     &amp;lt;Key&amp;gt;      - der abzufragende Schlüssel &lt;br /&gt;
     &amp;lt;default&amp;gt;  - def default-Rückgabewert&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Auswerten von internen Arrays ===&lt;br /&gt;
&lt;br /&gt;
Die meisten der internen Datenstrukturen liefern bei der Abfrage einen einfachen String oder numerischen Wert der ausgewertet werden kann. Es gibt allerdings auch intern gespeicherte Wertelisten. Werden die Listenstrukturen mit den oben beschriebenen Befehlen abgefragt, wird eine Referenz auf die Liste geliefert sofern sie vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
Um auf die Werte einer solchen Liste zuzugreifen, ist am Beispiel des Arrays &#039;&#039;surplusslidereg&#039;&#039; aus dem Current-Speicher (get ... valCurrent) dargestellt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
my $splref = CurrentVal ($name, &#039;surplusslidereg&#039;, &#039;.&#039;);&lt;br /&gt;
my $spser  = ref $splref eq &#039;ARRAY&#039; ? join &#039; &#039;, @{$splref} : undef;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Variable $spser enthält bei Vorhandensein der Liste einen String, der die Listenelemente von &#039;surplusslidereg&#039; durch Leerzeichen getrennt enthält.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backup und Wiederherstellung der Moduldaten ==&lt;br /&gt;
Neben der Datenhaltung in den Attributen und Readings des SolarForecast Devices, erzeugt jedes SolarForecast Device Dateien im Verzeichnis  &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; mit folgenden Inhalten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PVH_SolarForecast_&amp;lt;name&amp;gt;        - PV History&lt;br /&gt;
PVC_SolarForecast_&amp;lt;name&amp;gt;        - PV Circular&lt;br /&gt;
PVCfg_SolarForecast_&amp;lt;name&amp;gt;      - PV Anlagenkonfiguration&lt;br /&gt;
PVCsm_SolarForecast_&amp;lt;name&amp;gt;      - Consumer Status&lt;br /&gt;
ScApi_SolarForecast_&amp;lt;name&amp;gt;      - Strahlungswerte aus verwendeter API&lt;br /&gt;
StatApi_SolarForecast_&amp;lt;name&amp;gt;    - Statusdaten der verwendeten API&#039;s&lt;br /&gt;
WeatherApi_SolarForecast_&amp;lt;name&amp;gt; - Wetterdaten der gewählten Wetter-API (außer DWD-Device)&lt;br /&gt;
AItra_SolarForecast_&amp;lt;name&amp;gt;      - KI Entscheidungsquelle (trainierte Daten)&lt;br /&gt;
AIraw_SolarForecast_&amp;lt;name&amp;gt;      - KI Input Daten = Raw Trainigsdaten&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nach Ausprägung und eingesetzten Features des SolarForecast Devices sind alle oder nur ein Teil dieser Dateien vorhanden. Dabei ist &#039;&#039;&#039;&amp;lt;name&amp;gt;&#039;&#039;&#039; der Name des SolarForecast Devices.&lt;br /&gt;
&lt;br /&gt;
Bei einem Filebackup des FHEM-Servers ist darauf zu achten, dass diese Dateien in dem Backup enthalten sind. Der Inhalt der Dateien ist nicht statisch, sondern kann sich dynamisch aktualisieren. Um im Bedarfsfall einen aktuellen Datenstand zu haben, ist mindestens ein tägliches Backup dieser Dateien empfehlenswert. Eventuell auch öfter mit Hilfe einer Versionierung welche z.B. immer die letzten 3 Versionen aufbewahrt.&lt;br /&gt;
&lt;br /&gt;
Beim Start von FHEM werden bestimmte Dateien automatisch gelesen und in das SolarForecast Device importiert. &lt;br /&gt;
Der Vorgang ist mit verbose=3 im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2023.10.02 09:57:07.967 3: SolCast6 - cached data &amp;quot;pvHistory&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.969 3: SolCast6 - cached data &amp;quot;pvCircular&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;consumerMaster&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;radiationApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;statusApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;weatherApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.974 3: SolCast6 - cached data &amp;quot;aiTrainedData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.976 3: SolCast6 - cached data &amp;quot;aiRawData&amp;quot; restored&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bestimmte Betriebsdaten, wie z.B. die witterungsabhängigen Korrekturfaktoren (circular) oder die KI-Daten (aitrained/airaw), bauen sich über die Zeit immer granularer auf und stellen einen wertvollen Datenbestand dar.&lt;br /&gt;
&lt;br /&gt;
Wird das SolarForecast Device gelöscht und anschließend wieder neu mit dem gleichen Namen definiert, können die bisher verfügbaren Daten sehr einfach wiederhergestellt werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. starten von FHEM (bestimmte Daten werden automatisch importiert)&lt;br /&gt;
* 5. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Soll das neue SolarForecast Device mit einem anderen Namen oder weitere SolarForecast Devices erstellt werden, welche die Betriebsdaten des primären Devices verwenden sollen, ist wie folgt vorzugehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. umbenenen der Dateien, wobei &amp;lt;name&amp;gt; durch den Namen des neuen SolarForecast Devices ersetzt wird&lt;br /&gt;
* 5. starten von FHEM (die Daten werden automatisch importiert)&lt;br /&gt;
* 6. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn sich die SolarForecast Devices hinsichtlich ihres Models oder der integrierten Consumer unterscheiden, sind die Dateien &amp;quot;PVCsm_SolarForecast_&amp;lt;name&amp;gt; &amp;quot; , &amp;quot;ScApi_SolarForecast_&amp;lt;name&amp;gt;&amp;quot; von dem Verfahren auszuschließen.&lt;br /&gt;
&lt;br /&gt;
== Batterieintegration und -steuerung ==&lt;br /&gt;
&lt;br /&gt;
=== Wie eine Batterie eingebunden wird ===&lt;br /&gt;
Wie immer muß die Batterieanlage zunächst mit einem für die Batterie spezifischen FHEM-Device in FHEM definiert sein.&lt;br /&gt;
In diesem Device werden Readings erwartet die folgende Werte bereitstellen:&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieentladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die installierte Batteriekapazität liefert (&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; dieser Schlüssel ist für die Aktivierung des Batterie SOC-Managements und die grafische Anzeige des SOC wesentlich!)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Lade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Entlade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* Reading welches den aktuellen Ladezustand (SOC in Prozent) liefert (optional)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Batterie, bzw. das Batteriedevice wird mit dem Attribut &#039;&#039;&#039;setupBatteryDev&#039;&#039;&#039; im SolarForecast Device registriert. Die Syntax des Attributes ist in  der Online-Hilfe zum Attribut umfassend erläutert. &lt;br /&gt;
Auch wenn manche Readings optional sind, wird empfohlen alle Werte bereitzustellen um alle Batterie-Funktionen im Modul nutzen zu können. Durch die Weiterentwicklung des Moduls können optionale Readings später auch obligatorisch werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Visualisierung der Batterie in der Balkengrafik ====&lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;setupBatteryDevXX&#039;&#039;&#039; verfügt über den Schlüssel &#039;&#039;&#039;show&#039;&#039;&#039;, mit dem die Einblendung des bzw. der Batteriesymbole in den Ebenen der Balkengrafik gesteuert werden kann:&lt;br /&gt;
[[Datei:Screenshot 2025-02-23 192002.png|right|thumb|400px|Einblendung der Batterieleiste und Darstellung des Batterie-SoC als Balkencontent in der zweiten Ebene]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 0 - keine Anzeige des Gerätes (default)&lt;br /&gt;
* 1 - Anzeige des Gerätes in der Balkengrafik Ebene 1&lt;br /&gt;
* 2 - Anzeige des Gerätes in der Balkengrafik Ebene 2 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Symbole und die Farbgebung der Batterie(n) können mittels des Schlüssels &#039;&#039;&#039;icon&#039;&#039;&#039; verändert werden. Die Online-Hilfe gibt weitere Informationen zur Ausgestaltung. &lt;br /&gt;
&lt;br /&gt;
In der Batteriedarstellung wird das Symbol der aktuellen Stunde hervorgehoben. Ein Mouse-Over zeigt wesentliche Betriebszustände der Batterie. Die Batteriesymbole vergangener Stunden zeigen mit einem Mouse-Over die erreichten SoC (State of Charge) Stände. Die kommenden Stunden visualisieren die folgenden Prognosen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der prognostizierte SoC unter Berücksichtigung der PV-Prognose und der [[#Aktivierung_des_Batterie_SOC-Managements|Batteriesteuerung]] sofern sie im Modul aktiviert ist.&lt;br /&gt;
* eine Freigabe bzw. Empfehlung der Batterieladung zur [[#Unterstützung_eines_netzdienlichen_Verhaltens|Unterstützung eines netzdienlichen Verhaltens]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Neben der Einblendung der Batterieleiste über der Balkengrafik selbst können bestimmte Batteriekennwerte als Balkeninhalt dargestellt werden. Die Auswahl erfolgt über das Attribut &#039;&#039;&#039;graphicBeamXContent&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Aktivierung des Batterie SOC- und Lade-Managements ===&lt;br /&gt;
Das integrierte SOC- und Lade-Management verfolgt insbesondere zwei Ziele: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* den Ladezustand der Batterie(n) zu optmimieren, was besonders in den Monaten mit geringerer PV-Erzeugung einen wertvollen Beitrag zur Erhöhung der Autarkierate und Batteriepflege leisten kann&lt;br /&gt;
 &lt;br /&gt;
* eine PV-Prognose und Verbrauch optimierte Beladungssteuerung, die in den Monaten mit hoher PV-Erzeugung hilft eine evtl. Abregelung der Anlage zu verhindern, die Batterie ausgewogen über den Tag zu laden und ein netzdienliches Verhalten zu unterstützen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese beiden Aspekte der Batteriesteuerung werden in den folgenden Abschnitten beschrieben. Sind mehrere Batterien installiert, kann die Steuerung getrennt für jede einzelne Batterie aktiviert und eingestellt werden. Dabei ist zu beachten, dass vom Modul nur Signale und Readings bereitgestellt werden, die durch eine entsprechende Routine ausgewertet werden können um spezifische Befehle zur Umsetzung der Steuerung an das Batteriesystem zu senden. &lt;br /&gt;
 &lt;br /&gt;
Für eine Aktivierung des Managements muß zunächst das Batterie-Device wie im vorigen Abschnitt im SolarForecast Device registriert werden.&lt;br /&gt;
Das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; aktiviert die im Modul integrierte SOC- und Lade-Management Routine: &lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; ctrlBatSocManagement01 lowSoc=&amp;lt;Wert&amp;gt; upSoC=&amp;lt;Wert&amp;gt; [maxSoC=&amp;lt;Wert&amp;gt;] [careCycle=&amp;lt;Wert&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
Die einzelnen Schlüssel werden der Kalkulationsroutine als Steuerungsparameter übergeben und bedeuten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;lowSoc:unterer Mindest-SoC, die Batterie wird nicht tiefer als dieser Wert entladen (muß &amp;gt; 0 sein). Dieser Wert kann zum Beispiel dazu dienen, stets eine Mindestenergiemenge für den Fall eines Stromausfalls im öffentlichen Netz in den Batterien vorzuhalten.&lt;br /&gt;
&lt;br /&gt;
;upSoC:oberer Mindest-SoC, Der übliche Wert des optimalen SoC bewegt sich in Perioden mit hohen PV-Überschuß tendenziell zwischen &#039;lowSoC&#039; und &#039;upSoC&#039;, in Perioden mit geringer PV-Ausbeute bzw. geringem PV Energieüberschuß bewegt sich der optimale SoC tendenziell zwischen &#039;upSoC&#039; und &#039;maxSoC&#039;. Die Einstellung von upSoC=50 für ein ausgewogenes Verhalten kann als guter Startwert dienen.&lt;br /&gt;
&lt;br /&gt;
;maxSoC:maximaler Mindest-SoC, d.h. der SoC Wert der mindestens im Abstand von &#039;careCycle&#039; Tagen erreicht werden muß um den Ladungsausgleich im Speicherverbund auszuführen. Die Angabe ist optional (muß &amp;lt;= 100 sein, default: 95)&lt;br /&gt;
&lt;br /&gt;
;careCycle:maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens &#039;maxSoC&#039; auftreten darf. Die Angabe ist optional. (default: 20)&lt;br /&gt;
&lt;br /&gt;
;loadAbort: definiert eine vom Anwender gewünnschte Bedingung für einen generellen Ladeabbruch und Wiederfreigabe der Lademöglichkeit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle Werte sind ganze Zahlen in %. Dabei gilt: &lt;br /&gt;
&lt;br /&gt;
 lowSoc &amp;lt; upSoC &amp;lt; maxSoC&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====  Erläuterung der Batterie-Steuerungsreadings ==== &lt;br /&gt;
&lt;br /&gt;
Für die Steuerung des Batteriesystems gibt es im SolarForecast einen Satz an Readings, die unterschiedliche Zustände signalisieren und für entsprechende Steuerungsaufgaben bezüglich der Batteriesysteme eingesetzt werden können. In den nachfolgenden Abschnitten werden diese Zusammenhänge noch dataillierter beschrieben.&lt;br /&gt;
&lt;br /&gt;
;Hinweis: SolarForecast stellt lediglich Steuerungsinformationen zur Verfügung. Die Umsetzung des Eingriffs in das Batteriesystem erfolgt durch den Anwender selbst über entsprechende Skripte. In den thematischen Abschnitten werden Beispiele für solche Steuerungsskripte vorgestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle erstellten Readings gelten für ein Batteriesystem, es können mehrere Batteriesysteme in SolarForecast integriert sein. Die Endung &#039;&#039;XX&#039;&#039; der Readings beschreibt die Nummer des Batteriesystems und korrespondiert mit der Endung des entsprechenden Attributes &#039;&#039;ctrlBatSocManagementXX&#039;&#039; bzw. &#039;&#039;setupBatteryDevXX&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Battery_OptimumTargetSoC_XX: Mit den im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; hinterlegten Parametern unter Berücksichtigung von PV- und Verbrauchsprognosen wird ein optimaler SOC-Wert errechnet. Dieser Wert dient zur Einstellung des unteren SOC des Batteriesystems.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeRequest_XX: Dieses Reading signalisiert mit 1 eine Anforderung zur Zwangsladung der Batterie um die Batterie vor Schäden zu schützen (wenn der SOC unter ctrlBatSocManagementXX-&amp;gt;lowSoc gefallen ist) oder wenn der aktuelle SOC unter den berechneten Mindest-SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeUnrestricted_XX: Dieses Reading kann den Wert &#039;&#039;&#039;0&#039;&#039;&#039; oder &#039;&#039;&#039;1&#039;&#039;&#039; einnehmen. Ist der Inhalt 0, sollte die Batterie nur geladen werden, wenn der im Attribut &#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039; definierte Wert überschritten wird. Ist der Inhalt 1, sollte die Batterie mit der vollen zur Verfügung stehenden Ladeleistung angesteuert werden, um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeAbort_XX: Im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; kann mit dem Schlüssel &#039;&#039;loadAbort&#039;&#039; eine Bedingung definiert werden, bei deren Eintritt die Ladung der Batterie abgebrochen werden soll. In diesem Fall wird &#039;&#039;Battery_ChargeAbort_XX=1&#039;&#039; gesetzt. Mit einem entsprechenden Befehl kann der Anwender das Batteriesystem anweisen den Ladevorgang abzubrechen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Nutzung des Batterie SOC-Management ====&lt;br /&gt;
&lt;br /&gt;
Oftmals wird durch die Anlagenhersteller ein hoher statischer SOC eingestellt bzw. empfohlen, der eine längere Verharrungszeit auf einem tiefen SOC-Wert verhindern soll. Allerdings wechseln sich in auch in den Herbst-, Frühlings- und Wintermonaten Zeiten mit wenig PV-Erzeugung mit Phasen stärkerer Solarstrahlung bei klarem Himmel und Sonnenschein ab.&lt;br /&gt;
&lt;br /&gt;
Ein statischer SOC würde dazu führen, dass in den erwähnten Phasen zuviel Energie in das öffentliche Netz eingespeist wird. Dies soll verhindert werden da die wertvolle Energie besser im eigenen Netz gespeichert und in Dunkelphasen verwendet werden kann. Andererseits soll die Batterie nicht zu lange auf einem tiefen SOC verbleiben und außerdem in gewissen Abständen auf einen so hohen SOC geladen werden der den internen Zellausgleich ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Die SOC Kalkulationsroutine des Moduls errechnet unter Berücksichtigung des prognostizierten PV-Ertrages der kommenden Tage, des aktuellen SOC und der im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; (nachfolgend beschrieben) angegebenen Steuerparameter den Vorschlag für eine optimale SOC-Einstellung. Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert.&lt;br /&gt;
&lt;br /&gt;
Durch das Modul selbst findet keine Steuerung der Batterie statt. Es stellt entsprechende Readings zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen SoC.&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SoC unter den optimalen SoC gefallen ist. In diesem Fall sollte die Batterie, unter Umständen mit Netzstrom, zwangsgeladen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Readings können zur Steuerung des SoC (State of Charge) sowie zur Steuerung des verwendeten Ladestroms der Batterie verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ermittlung des optimalen SOC erfolgt nach folgender Logik:&lt;br /&gt;
&lt;br /&gt;
# 	Ausgehend von &#039;lowSoc&#039; wird der Mindest-SoC kurz vor Sonnenuntergang um 5% inkrementiert sofern am laufenden Tag &#039;maxSoC&#039; nicht erreicht wurde und die PV-Prognose keinen hinreichenden Ertrag des kommenden Tages vorhersagt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Wird &#039;maxSoC&#039; (wieder) erreicht, wird Mindest-SoC um 5%, aber nicht tiefer als &#039;lowSoc&#039;, verringert. Ist der berechnete Mindest-SoC größer als &#039;upSoc&#039;, wird der Mindest-SoC auf &#039;upSoc&#039; gesetzt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#   Mindest-SoC wird soweit verringert, dass die prognostizierte PV Energie des aktuellen bzw. des folgenden Tages von der Batterie aufgenommen werden kann. Mindest-SoC wird typisch auf &#039;upSoc&#039; und nicht tiefer als &#039;lowSoc&#039; verringert.  &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Das Modul erfasst den letzten Zeitpunkt am &#039;maxSoC&#039;-Level, um eine Ladung auf &#039;maxSoC&#039; mindestens alle &#039;careCycle&#039; Tage zu realisieren. Zu diesem Zweck wird der optimierte SoC in Abhängigkeit der Resttage bis zum nächsten &#039;careCycle&#039; Zeitpunkt derart verändert, dass durch eine tägliche 5% SoC-Steigerung &#039;maxSoC&#039; am &#039;careCycle&#039; Zeitpunkt rechnerisch erreicht wird. Wird zwischenzeitlich &#039;maxSoC&#039; erreicht, beginnt der &#039;careCycle&#039; Zeitraum erneut. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im fünften Schritt werden die Grenzen &#039;lowSoc&#039; und &#039;upSoc&#039; berücksichtigt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im letzten Schritt erfolgt Generierung des Readings &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; zur Signalisierung einer eventuell empfohlenen Zwangsladung auf den berechneten Min-SoC. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei sehr wenig Erzeugungungsprognose, d.h. wenn sich der berechnete Min-SoC oberhalb von &#039;upSoC&#039; bewegt, wird &#039;upSoC&#039; eingestellt. Liegt der berechnete Min-SoC unterhalb von &#039;upSoC&#039;, ist jedoch größer als &#039;lowSoC&#039;, wird der berechnete SOC im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; eingestellt. Somit eignet sich die Angabe im Schlüssel &#039;upSoC&#039; um in Zeiten geringer Solarenergieerzeugung die Batterie für eine Notstromerzeugung auf mindestens diesem Wert zu halten. Sollte die PV-Prognose kurzfristig einen größeren Ertrag vorhersagen als die Batterie durch die Einhaltung von &#039;upSoC&#039; aufnehmen kann, wird der Min-SoC unter &#039;upSoC&#039; abgesenkt um möglichst allen PV-Überschuß in der Batterie zu speichern und somit dem Eigenverbrauch zuzuführen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der berechnete Mindest-SoC ist immer nur ein unterer Grenzwert. Die Batterie kann durch Ladevorgänge natürlich jederzeit einen höheren als den im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; dargestellten optimalen SoC haben. Der optimale SoC sollte nicht unterschritten werden um die oben genannten Zusammenhänge abbilden zu können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Die dynamische SOC Steuerung mit Umsetzungsbeispiel =====&lt;br /&gt;
Das Modul bietet eine Unterstützung zur automatisierten Einstellung eines optimalen SoC Wertes.&lt;br /&gt;
&lt;br /&gt;
Ziel ist es, den Minimum SoC in Abhängigkeit der zu erwartenden Solarerträge des aktuellen und des folgenden Tages so einzustellen, dass der prognostizierte Solarertrag von der Batterie aufgenommen werden kann. Die Einspeisung in das öffentliche Netz soll minimiert werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin soll ein unterer SoC nicht unterschritten, sowie ein oberer Minimum SoC im Normalfall nicht überschritten werden. Der obere Grenzwert stellt sicher, dass die Batterie mindestens bis zu diesem Wert wieder entladen werden kann. Dadurch bleibt innerhalb der Batterie immer genügend Kapazität verfügbar um unvorhergesehene PV Energie aufnehmen zu können.&lt;br /&gt;
&lt;br /&gt;
Aktiviert wird die Unterstützung der Batteriesteuerung durch das Setzen des Attributes &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; z.B. mit diesen Angaben:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagementXX lowSoc=x upSoC=x maxSoC=x careCycle=x &lt;br /&gt;
&lt;br /&gt;
so zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=98 careCycle=20&lt;br /&gt;
&lt;br /&gt;
Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert. &lt;br /&gt;
Ist dieses Attribut gesetzt, werden Steuerungs-Readings erstellt, die der Nutzer auswerten und seine Batterieanlage z.B. via notify oder DOIF steuern kann. &amp;lt;bR&amp;gt;&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen Mindest-SoC.&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SOC unter den optimalen SOC bzw. minimalen SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
Die Schlüssel &#039;&#039;&#039;lowSoc&#039;&#039;&#039; und &#039;&#039;&#039;upSoC&#039;&#039;&#039; sind die unteren und oberen Grenzen, zwischen denen sich der Minimum SoC im normalen Betrieb bewegen soll.&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;maxSoC&#039;&#039;&#039; stellt eine Ladungsgrenze dar, die mindestens alle X (careCycle) Tage erreicht werden soll. Zu diesem Zweck errechnet das Modul die Anzahl der nötigen Erhöhungen der Minimum Batterieladung von 5% pro Tag um ausgehend vom aktuellen SoC-Level. Der resultierende Minimum SoC Wert wird entsprechend angepasst. Wurde der einstellte maxSoC Level erreicht, startet der Wartungszyklus (careCycle) erneut. &amp;lt;br&amp;gt;&lt;br /&gt;
Der maxSoC in Verbindung mit dem durch &#039;&#039;&#039;careCycle&#039;&#039;&#039; definierten Zyklus soll sicherstellen, dass der Batterieverbund in regelmäßigen Abständen einen Ladungsausgleich vollziehen kann. &lt;br /&gt;
&lt;br /&gt;
Durch die Modullogik erfolgt eine 5 protentige Anhebung des Minimum SoC wenn am Vortag maxSoC nicht erreicht wurde. Die Anhebung erfolgt aber nicht über upSoC. upSoC ist die obere Grenze des Minimum SoC. Wird am Vortag mindestens die maxSoC Ladung erreicht, verringert sich der Minimum SoC wieder schrittweise um 5%, aber nicht tiefer als lowSoc.&lt;br /&gt;
&lt;br /&gt;
Ergänzt wird die Logik noch um die PV Vorhersage. Dabei wird die obige Minimum SoC Berechnung um die Erwartung der PV Erwartung am aktuellen und folgenden Tag korrigiert. Das bedeutet, dass der Minimum SoC z.B. von heute 50% auf 10% abgesenkt und dadurch die gespeicherte Energie dem Haushalt zugeführt wird, wenn am heutigen oder kommenden Tag eine entsprechende PV Energie zu erwarten ist um die Batterie wieder vollständig zu zuladen.&lt;br /&gt;
Dadurch ist immer genügend &amp;quot;Freiplatz&amp;quot; in der Batterie und andererseits hat die Batterie in langen Dunkelphasen eine Reserve für einen eventuellen Stromausfall (falls der abgesichert werden soll) und wird vor einem dauerhaften tiefen SoC geschützt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Umsetzungsbeispiel =====&lt;br /&gt;
&lt;br /&gt;
Wie das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; genutzt werden kann, wird am Beispiel einer Victron Batterieanlage gezeigt. Die Anlage wird durch Cerbo GX Gerät gesteuert. Der Cerbo GX ist per MQTT2 in FHEM eingebunden. Umgesetzt ist die Steuerung der Batterie &#039;01&#039;, d.h. die Angabe &#039;XX&#039; ist durch &#039;01&#039; ersetzt.&lt;br /&gt;
&lt;br /&gt;
Die folgende kleine Logik ist in einem &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; File eingebaut und wird regelmäßig mit&lt;br /&gt;
&lt;br /&gt;
 batSocChargeMgmnt (&#039;&amp;lt;Name SolarForecast Device&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
aufgerufen. Der Aufruf erfolgt durch Angabe der Routine im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; des SolarForecast Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
  # Hinweis: die Zeichen &#039;::&#039; vor der Routine sind durch das SolarForecast Package bedingt&lt;br /&gt;
  ::batSocChargeMgmnt ($name);&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Routine wird dadurch automatisch am Ende jedes Zyklus (siehe Attribut plantControl-&amp;gt;cycleInterval) ausgeführt.&lt;br /&gt;
Um die SOC Managementfunktion nach Bedarf ein- bzw. ausschalten zu können wird zunächst im SolarForecast Device ein userattr zur Steuerung der SOC-Logik angelegt:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; userattr userFn_BatterySoCManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
Die Perl Routine &#039;&#039;&#039;batSocChargeMgmnt&#039;&#039;&#039; ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#  Batterie SOC und Max. Ladestrom Management&lt;br /&gt;
############################################################################&lt;br /&gt;
sub batSocChargeMgmnt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vebus   = &#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;;                            # Victron Vebus Device&lt;br /&gt;
  my $vicsets = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                         # Victron Einstellungen&lt;br /&gt;
&lt;br /&gt;
  my $maxcspc = 105;                                                           # max. Ladestrom (A) Victron MPII Verbund&lt;br /&gt;
  my $actmcc  = ReadingsNum ($vebus, &#039;MaxChargeCurrent&#039;, undef);               # akt. Ladestromeinstellung&lt;br /&gt;
  my $load    = $actmcc // $maxcspc;                                           # Soll-Ladestrom (A)&lt;br /&gt;
&lt;br /&gt;
  ## Battery SoC Management&lt;br /&gt;
  ###########################&lt;br /&gt;
  my $ubsm = AttrVal ($name, &#039;userFn_BatterySoCManagement&#039;, &#039;aus&#039;); &lt;br /&gt;
  &lt;br /&gt;
  if ($ubsm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name,    &#039;Battery_ChargeRequest_01&#039;,     0);&lt;br /&gt;
    my $csoc = ReadingsNum ($vicsets, &#039;MinimumSocLimit&#039;,             10);      # akt. SoC&lt;br /&gt;
    my $osoc = ReadingsNum ($name,    &#039;Battery_OptimumTargetSoC_01&#039;, 10);      # Soll-SoC&lt;br /&gt;
    my $surp = ReadingsNum ($name,    &#039;Current_Surplus&#039;,              0);      # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if ($csoc != $osoc) {&lt;br /&gt;
      CommandSet (undef, &amp;quot;$vicsets MinimumSocLimit $osoc&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn SoCMgmnt -&amp;gt; MinimumSocLimit in $vicsets set to $osoc %});&lt;br /&gt;
    }&lt;br /&gt;
	                                           &lt;br /&gt;
    if ($bcrq &amp;amp;&amp;amp; $surp &amp;lt; 1000) {                                              # max. Strom b. Battery_ChargeRequest &lt;br /&gt;
      $load = 21;&lt;br /&gt;
    }&lt;br /&gt;
	else {&lt;br /&gt;
	  $load = $maxcspc;&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Batterie Einstellung MaxChargeCurrent&lt;br /&gt;
  ##########################################&lt;br /&gt;
  if ($load != $actmcc) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$vebus MaxChargeCurrent $load&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
    Log3 ($name, 3, qq{$name - userFn ChargeMgmnt -&amp;gt; MaxChargeCurrent in $vebus set }.&lt;br /&gt;
                    qq{from old $actmcc A to $load A});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent_set&#039;, $load, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist im SolarForecast Device das Reading  &#039;&#039;&#039;Battery_ChargeRequest_01&#039;&#039;&#039; gesetzt, ist der aktuelle SOC kleiner als der optimale SOC und die Batterie wird (eventuell aus dem öffentlichen Netz) geladen. Das kann automatisch durch den Cerbo GX bzw. in anderen Anlagen durch einen entsprechenden Befehl erfolgen.&lt;br /&gt;
Damit die Netzbeladung nicht mit der vollen Ladestromstärke geschieht, wird der Ladestrom auf den gewünschten Wert (hier 21 A -&amp;gt; ca. 1000 W bei einem 48V System) reduziert sofern kein oder zu wenig PV-Überschuß vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== weitere mögliche Aspekte der SOC- und Batterieladesteuerung ====&lt;br /&gt;
&lt;br /&gt;
SolarForecast liefert durch seine internen Logiken bereits sehr hilfreiche Signale zur Steuerung von Batteriesystemen in Form von Readings an. Abhängig von den individuellen Möglichkeiten der vorhandenen Anlage käme zum Beispiel zusätzlich zu einer Steurung des optimalen SOC oder der Zeitfenster für die Batterieaufladung auch eine Steuerung des Ladestroms bzw. der verwendeten Ladeleistung in Betracht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hintergründe:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Das Laden eines Akkus mit möglichst gleichbleibender und geringer Leistung wirkt sich positiv auf dessen Langlebigkeit aus, was u.a. auch daran liegt, dass der Temperaturstreß im Akku bei langsamer Energiezuführung nur gering ist.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom führt zu einem geringen Absacken der Akkuspannung beim (ggf, temporären) Abschalten des Ladestroms, was sich positiv auf die SOC-Schätzung auswirkt.&lt;br /&gt;
    &lt;br /&gt;
* Ein geringer Ladestrom führt, insb. bei Nutzung passiver Balancer (sind in den Akku-Systemen üblicherweise verbaut), zu einer geringen Differenz zwischen den einzelnen Zellspannungen und damit zu einer besseren Kapazitätsausnutzung eins Akkus.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom kann zu einem zeitlich punktgenauen Zielfüllstand (im Winter 100%, ansonsten natürlich weniger) am Ende des Tages führen.&lt;br /&gt;
    &lt;br /&gt;
* Eine geringer Ladestrom führt auch zu geringen Leitungsverlusten, da der Strom quadratisch zu den Leitungsverlusten beiträgt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann auch die Verweildauer oder die Begrenzung des SOC, auf den die Batterie maximal geladen werden soll, Gegenstand von Optimierungen sein.&lt;br /&gt;
&lt;br /&gt;
Die häufig zu findende Empfehlung, Akkus nicht zu lange bei einem SOC von 100% verweilen zu lassen, liegt weniger an dem SOC als solchem, sondern daran, dass &#039;&#039;SOC=100%&#039;&#039; üblicherweise dadurch ermittelt wird, dass eine Zelle im Akku einen Spannungsschwellenwert überschreitet, der – würde dieser Schwellenwert zeitlich länger überschritten sein – zu einer Schädigung des Akkus führen könnte. Schädlich sind insbesondere häufige Nachladevorgänge bei Werten um die 100% SOC, da Zellen dann ja häufiger und damit - integral gesehen - auch länger den o.g. Schwellenwert überschreiten.&lt;br /&gt;
&lt;br /&gt;
Einige Akku-Hersteller, z.B. BYD, haben auf o.g, Grund in der (neueren) Firmware Ihrer Systeme einen SOC-Threshold (bei BYD liegt dieser bei 95%) eingebaut. Dieser Wert muss nach einem erreichten SOC von 100% unterschritten  werden, bevor überhaupt eine weitere Ladung erfolgt. Insbesondere in der dunklen Jahreszeit kann es daher sinnvoll sein, den Akku unter Verwendung von PV-Leistung so zu füllen, dass dieser möglichst nur einmal vor Einbruch der Dunkelheit auf &#039;&#039;SOC=100%&#039;&#039; geladen wird. Hierbei sollte darauf geachtet werden, dass der Ladeschlussstrom des jeweiligen Systems nicht unterschritten wird. &lt;br /&gt;
&lt;br /&gt;
SolarForecast unterstützt die oben betrachtete Batteriesteuerung durch die optionale Angabe von &#039;&#039;&#039;loadAbort&#039;&#039;&#039; im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039;. Das in diesem Kontext erstellte Reading &#039;&#039;&#039;Battery_ChargeAbort_XX&#039;&#039;&#039; stellt die auswertbaren Steuerungsinformationen zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== PV-Prognose und Verbrauch optimierte Beladungssteuerung unter Berücksichtigung einer Wirkleistungsbegrenzung ====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-04-25 143910.png|right|thumb|400px|Batterie Popup &amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Batterie geladen. sobald PV-Überschuß vorhanden ist ohne eine Prognose zu berücksichtigen. Dadurch sind die Batterien im Sommer unter Umständen schon um 10-12 Uhr voll geladen und die Anlage liefert ihre mehr oder weniger volle Energie (je nach Ausrichtung) in das öffentliche Netz. Dann könnte es zu einer Begrenzung der PV-Leistung durch einen Schwellenwert (z.B. 70%-Regelung) oder eventuell Zwangsabregelung durch den Netzbetreiber kommen.&lt;br /&gt;
&lt;br /&gt;
Hintergrund dieser Erweiterung ist das Bestreben, eine optimale Unterstützung bei der Maximierung des Eigenverbrauchs zu geben und einen Beitrag zur Netzstabilität zu leisten.&lt;br /&gt;
Das Ziel der Beladungssteuerung der Batterie ist es, die Ladung der Batterie über den Tag verteilt so zu steuern, dass die Batterie erst dann geladen wird, wenn durch den PV-Überschuß eine Netzeinspeisung erfolgen würde bzw. ein Grenzwert erreicht werden würde, der zu einer Abregelung der PV-Anlage führen könnte.&lt;br /&gt;
Es kann auch zu einer Zwangsabregelung durch den Netzbetreiber führen, was vermieden werden soll.&lt;br /&gt;
 &lt;br /&gt;
Die interne Kalkulationslogik erstellt zu diesem Zweck ein Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039;.&lt;br /&gt;
Dieses Reading gibt dem User ein Signal, ob zu der aktuellen Stunde der Ladevorgang der Batterie freigegeben (1) oder nicht freigegeben werden sollte (0). Die Freigabe zur Ladung bedeutet dass:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; die Batterie mit ihrer vollen Ladeleistung angesteuert werden sollte um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=0&#039;&#039;&#039; die Batterie nur geladen werden sollte wenn der im Attribut plantControl-&amp;gt;feedinPowerLimit definierte Wert überschritten wird&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ist keine Freigabe zur Ladung vorhanden, kann bzw. sollte dennoch eine Ladung der Batterie vorgenommen werden, sofern eine über dem im &amp;lt;br&amp;gt;&lt;br /&gt;
Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limit liegende Einspeiseleistung vorhanden ist. In diesem Status sollte die Batterie nur mit der Differenzleistung von vorhandener Einspeiseleistung und dem gesetzen Einspeiselimit geladen werden und damit das gesetzte Einspeiselimit einhalten ohne die Anlage abzuregeln. Ist die Batterie in einer Balkengrafikebene dargestellt, wird im Mouse-Over Popup die Battrie mit &#039;&#039;&amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;&#039;&#039; gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Möglichkeiten der Batteriesteuerung sind stark von der individuellen Anlage abhängig und können hier nicht beschrieben werden. Ein Umsetzungsbeispiel mit einer Victron-Anlage mit Pylontech Batterie ist weiter unten dargestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Aktivierung und Arbeitsweise =====&lt;br /&gt;
&lt;br /&gt;
Die implementierte Logik zur optimierten Batterie Beladungssteuerung wird aktiviert, wenn folgende Kriterien erfüllt sind: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;capacity&#039;&#039;&#039; in den setupInverterDevXX Atributen ist gesetzt&lt;br /&gt;
* das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; für die jeweilige Batterie ist gesetzt&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;cap&#039;&#039;&#039; im Attribut setupBatteryDevXX der jeweiligen Batterie ist gesetzt&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Die Logik arbeitet wie folgt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Der resultierende Schwellenwert der Wirkleistungsbegrenzung: der Gesamtanlage wird durch die Auswertung der in den Inverter-Attributen setupInverterDevXX  gesetzen Schlüssel limit (optional) und capacity ermittelt. Inverter mit gesetztem Schlüssel feed = grid (deren Energie wird ausschließlich in das öffentlich Netz eingespeist) werden von der Betrachtung in diesem Kontext ausgeschlossen.&lt;br /&gt;
&lt;br /&gt;
;Die benötigte Beladung bis zu maxSoC (im Attribut setupBatteryDevXX) : wird ermittelt und mit der zu erwartenden PV Tagesprognose in Beziehung gesetzt. Sofern die PV-Erzeugung abzgl. Verbrauch noch nicht das Wirkleistungbegrenzungs-Limit erreicht UND noch genügend PV-Überschuß für eine Ladung auf &#039;&#039;maxSoC&#039;&#039; im Laufe der kommenden Stunden des Tages zu erwarten ist, bleibt das Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 0&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
;Wird das Wirkleistungbegrenzungs-Limit erreicht/überschritten und/oder die PV-Überschußprognose: zzgl. eines Sicherheitspuffers unterschritten, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 1&#039;&#039;&#039; gesetzt. Der User kann darauf reagieren und den Batterie Ladevorgang aktivieren. Die Möglichkeiten der Aktivierung sind natürlich von der installierten Anlage abhängig. Das SolarForecast Device greift nicht in die Batteriesteuerung direkt ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders ausgedrückt erfolgt immer dann eine Ladefreigabe, wenn einer der nachfolgenden Sachverhalte &#039;&#039;wahr&#039;&#039; ist:&lt;br /&gt;
&lt;br /&gt;
- die benötigte Ladeenergie (aller installierten Batterien) &amp;gt;= PV-Restüberschuß des Tages (Reading RestOfDayPVforecast) zzgl. Sicherheitsaufschlag&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- der Zeitpunkt des PV-Erzeugungszenit des laufenden Tages überschritten ist (Reading Today_MaxPVforecastTime)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn die aktuelle PV Leistung &amp;gt;= einer eventuellen Wechselrichter-Leistungsbegrenzung ist (Summe aller WR-Begrenzungen)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn das BatSoc-Management _nicht_ aktiviert ist (nicht alle oben genannten Aktivierungskriterien erfüllt sind)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind mehrere Batterien installiert und durch das Management einer Batterie die Einhaltung der genannten Kriterien bzw. Sachverhalte erwirkt wird, bleiben die weiteren Batterien im Modus Ladefreigabe (Battery_ChargeUnrestricted_XX=1).  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Umsetzungsbeispiel Batterie Ladesteuerung mit Victron GX Venus über den Grid Setpoint =====&lt;br /&gt;
&lt;br /&gt;
Ziel der Steuerung ist es abhängig vom Wert des Readings Battery_ChargeUnrestricted_XX (z.B. Battery_ChargeUnrestricted_01) die Ladung des angeschlossenen Batteriesystems zu aktivieren bzw. zu deaktivieren.&lt;br /&gt;
Das vorliegende Beispiel soll umzusetzen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 0 -&amp;gt; Batterie nicht aufladen bzw. nur laden wenn Einspeiselimit überschritten (Attribut plantControl-&amp;gt;feedinPowerLimit)&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 1 -&amp;gt; Batterie aufladen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Grid Setpoint ist ein Parameter in den Victron Systemeinstellungen. Das Victron System wird den eingestellten Grid Setpoint versuchen einzuhalten und bei einem positiven Wert Energie aus dem Netz beziehen bzw. bei einem negativen Grid Setpoint Energie in das Netz einspeisen.&lt;br /&gt;
&lt;br /&gt;
Normalerweise wird das Victron System die erzeugte PV Energie zunächst zur Deckung des Hausverbrauchs verwenden, ist dann noch ein PV Überschuß vorhanden, die Batterien aufladen und bei weiter vohandenen PV Überschuß diese Energie in das öffentliche Netz einspeisen sofern dem System eine Einspeisung erlaubt ist. Anderenfalls werden die Wechselrichter oder MPPT Smartloader heruntergeregelt bzw. limitiert. &lt;br /&gt;
&lt;br /&gt;
In der Standardeinstellung ist beim Victron System ein Grid Setpoint von ca. 20 bis 50 Watt, d.h. das System strebt danach diese Vorgabe zu erfüllen zieht ständig Energie in diesem Bereich aus dem öffentlich Netz von einem gelegentlichen Überschwingen der Regelung abgesehen. Damit ein eventueller PV Überschuß nicht zum Laden der Batterie verwendet, sondern statt dessen in das öffentliche Netz eingespeist wird, muß der Grid Setpoint um diesen Betrag abgesenkt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-24 114403.png|right|thumb|400px|Integration des Grid Setpoint-Managements in den Own_Spec-Bereich]]&lt;br /&gt;
&lt;br /&gt;
Damit man später per Attribut bzw. über den [[#Formatierung_der_Inhalte_im_Bereich_&amp;quot;Graphic_Header_Own_Specification&amp;quot;|Own_Spec-Bereich]] die automatische Ladesteuerung über den Grid Setpoint ein- bzw. ausschalten kann, legen wir ein userattr an:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 userattr &amp;lt;Name&amp;gt; userFn_GridSetpointManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin sind einige Vorbereitungen im Device MQTT2_cerboGX_c0619ab34e08_settings vorzunehmen. Dieses Device ist im vorliegenden Beispiel ein in FHEM vorhandenes MQTT2_DEVICE, über das die Victron CerboGX Einstellungen zugreifbar sowie einstellbar sind. Die Vorgehensweise zur Erstellung des MQTT2_DEVICE ist hier nicht beschrieben und wird vorausgesetzt.&lt;br /&gt;
&lt;br /&gt;
Damit ein entsprechender Set-Befehl zur Einstellung des Grid Setpoints vorhanden ist, werden folgende Attribute gesetzt:&lt;br /&gt;
&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings jsonMap Settings_CGwacs_AcPowerSetPoint_value:GridSetpoint&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings setList GridSetpoint W/c0619ab34e08/settings/0/Settings/CGwacs/AcPowerSetPoint {&amp;quot;value&amp;quot;:$EVTPART1}&lt;br /&gt;
&lt;br /&gt;
Nach dieser Attributierung kann mit einem &amp;quot;&#039;&#039;set MQTT2_cerboGX_c0619ab34e08_settings GridSetpoint &amp;lt;Wert&amp;gt;&#039;&#039;&amp;quot; der Grid Setpoint eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Das Attribut userFn_GridSetpointManagement kann nun im Perl Code ausgewertet werden um das Grid Setpoint-Management ein- bzw. auszuschalten.&lt;br /&gt;
Der nachfolgende Code wird in die Datei &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; eingefügt. Ist diese Datei nicht vorhanden, legen wir sie vorab als Kopie der ausgelieferten 99_myUtils.pm an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Steuerung Start/Stop der Batterieladung über den Victron Grid Setpoint&lt;br /&gt;
############################################################################&lt;br /&gt;
sub gridSetpointMgmt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vicsets   = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                               # Device Victron Einstellungen&lt;br /&gt;
  my $gspdef    = 20;                                                                  # Default Einstellung des Grid Setpoint&lt;br /&gt;
  my $targetgsp = $gspdef;                                                             # Voreinstellung Grid Setpoint&lt;br /&gt;
  my $neggspmax = FHEM::SolarForecast::CurrentVal ($name, &#039;feedinPowerLimit&#039;, 5000);   # max. gewünschte Einspeiseleistung in Watt&lt;br /&gt;
  $neggspmax    = $neggspmax * -1;&lt;br /&gt;
  my $gspm      = AttrVal ($name, &#039;userFn_GridSetpointManagement&#039;, &#039;aus&#039;);             # Freischaltung des Grid Setpoint-Managements&lt;br /&gt;
  my $curgsp    = ReadingsNum ($vicsets, &#039;GridSetpoint&#039;,         $gspdef);             # aktuelle Einstellung Grid Setpoint&lt;br /&gt;
  &lt;br /&gt;
  if ($gspm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name, &#039;Battery_ChargeUnrestricted_01&#039;, 0);         # Ladefreigabe (1 -&amp;gt; Bat Ladefreigabe)&lt;br /&gt;
    my $surp = ReadingsNum ($name, &#039;Current_Surplus&#039;,               0);         # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if (!$bcrq) {                                                               # Grid Setpoint absenken wenn keine .. &lt;br /&gt;
        $targetgsp = $gspdef - $surp;                                           # ..Batterie Ladefreigabe&lt;br /&gt;
        $targetgsp = $neggspmax if($targetgsp &amp;lt; $neggspmax);                    # Begrenzung der Einspeiseleistung&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($curgsp != $targetgsp) {&lt;br /&gt;
	  fhem (&amp;quot;set $vicsets GridSetpoint $targetgsp&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn gridSetpointMgmt -&amp;gt; GridSetpoint in $vicsets set to $targetgsp});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Victron_GridSetpoint_set&#039;, $targetgsp, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Vergleich des Setpoints mit der Vorgabe von &#039;&#039;$neggspmax&#039;&#039; dient dazu die maximale Einspeiseleistung in das öffentliche Netz zu begrenzen. Ist diese Grenze erreicht, wird der noch verbleibende Überschuß in die Batterie geladen. Dadurch wird eine Abregelung der Anlage vermieden wenn der Schwellenwert &#039;&#039;$neggspmax&#039;&#039;erreicht ist sofern die Batterie aufnahmefähig ist und nicht voll geladen ist. &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::gridSetpointMgmt  ($name);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zum Management des automatischen Grid Setpoint und der Anzeige des eingestellten Wertes wird das Attribut und die Readinganzeige in den Own_Spec-Bereich eingebunden, z.B.:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; graphicHeaderOwnspec  #Settings&lt;br /&gt;
                                   SetPoint&amp;amp;nbsp;Management:userFn_GridSetpointManagement&lt;br /&gt;
                                   Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Unterstützung eines netzdienlichen Verhaltens ====&lt;br /&gt;
&lt;br /&gt;
Der Steuerungsprozess der Batterieanlage leistet insgesamt einen kleinen Beitrag zur Netzstabilität, indem die Speicherladung in den Zeitraum der meisten prognostizierten Überschußeinspeisung gelegt wird. Im Sommer kann sich dieser Zeitraum in die Zeit nach dem Maxmimum des prognostizierten PV-Überschusses verlagern, wenn auch danach noch genügend Überschußenergie zu Volladung der Batterie prognostiziert wird. In dem Zusammenhang sollte im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; ein Einspeiselimit gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zur Verdeutlichung soll das Beispiel dienen:&lt;br /&gt;
&lt;br /&gt;
* die Batterie ist zu 60% geladen &lt;br /&gt;
* der User hat upSoC=40 eingestellt&lt;br /&gt;
* der User hat maxSoC=90 eingestellt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Am Vormittag ist genügend Sonne vohanden, das Maximumum der Energie über die Zeit wird aber noch erwartet. &lt;br /&gt;
Zu diesem Zeitpunkt wird das Reading  &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039; auf den Wert &amp;quot;0&amp;quot; gesetzt. Durch den Nutzer erfolgt daraufhin, zum Beipiel über ein Notify, ein anlagenspezifischer Befehl &amp;quot;Ladestop&amp;quot; an die Batterieanlage. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ab diesem Moment wird:&lt;br /&gt;
&lt;br /&gt;
# die Batterie nicht geladen&lt;br /&gt;
# die erzeugte PV-Energie dem Haushalt zur Verfügung gestellt bzw. der verbleibende Überschuß eingespeist, sofern der Überschuß unterhalb des im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limits liegt.&lt;br /&gt;
# ein eventuell über dem Limit &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; vorhandener Überschuß in die Batterie geladen und so die Netzlast verringert sowie die Batterie schonend geladen. (dieser Punkt trifft in den Monaten mit wenig PV-Erzeugung eher nicht zu)  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig liefert die Batterie Energie an das Hausnetz und wird von 60% bis maximal einem SoC-Wert entladen, der durch die [[#Die_dynamische_SOC_Steuerung_mit_Umsetzungsbeispiel|dynamische SOC Steuerung]] bestimmt wird. Dazu muß diese Steuerung natürlich implementiert sein. Sofern der berechnete SoC größer als upSoC ist, wird der maximale Entladungs-SoC auf upSoC gesetzt. &lt;br /&gt;
&lt;br /&gt;
Zusätzlich überprüft das Modul permanent bei jedem Zyklus die Differenz des aktuell vorhandenen SoC zum eingestellten maxSoC.&lt;br /&gt;
Sie soll nicht größer sein um mit dem (noch) zu erwartenden PV-überschuß des Tages der eingestellte maxSoC bzw. dessen Nähe wahrscheinlich erreicht werden kann. &lt;br /&gt;
Sollte der Differenz-Grenzwert erreicht sein, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; gesetzt und der Nutzer sollte dann über einen geeigneten Befehl seine Anlage in den Modus &amp;quot;Laden&amp;quot; umschalten.&lt;br /&gt;
Dieser Vorgang kann beliebig oft während des Tages alternieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Nutzung von batteryTrigger ===&lt;br /&gt;
Ergänzt werden die Möglichkeiten durch das set-Kommando: &lt;br /&gt;
&lt;br /&gt;
 batteryTrigger &amp;lt;1on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;1off&amp;gt;=&amp;lt;Wert&amp;gt; [&amp;lt;2on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;2off&amp;gt;=&amp;lt;Wert&amp;gt; ...] &lt;br /&gt;
&lt;br /&gt;
Das Kommando setzt Triggerpunkte bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %).&lt;br /&gt;
&lt;br /&gt;
Der verwendete SoC wird als resultierender SoC als Summe der aktuellen Ladung aller registrierten Batterie-Geräte im Verhältnis zur installierten Gesamtkapazität gebildet. Das bedeutet, dass alle einzelnen Batterie-Geräte als ein gemeinsamer Cluster betrachtet werden. &lt;br /&gt;
&lt;br /&gt;
Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise definiert werden.&lt;br /&gt;
Überschreiten die letzten drei SoC-Messungen eine definierte Xon-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = on&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
Unterschreiten die letzten drei SoC-Messungen eine definierte Xoff-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = off&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
&lt;br /&gt;
Der Inhalt der Readings kann durch ein User-Programm oder, bei Erzeugung von entsprechenden Events, mittels notify-Device ausgewertet werden um bei Eintreten eines definierten Ereignisses entsprechende Reaktionen auszulösen. Das kann zum Beispiel die Freigabe eines Heizstabes oberhalb eines bestimmten SOC sein oder ein Entladeverbot der Batterie unterhalb eines SOC-Wertes um Reserven für einen eventuellen Stromausfall zu behalten.&lt;br /&gt;
&lt;br /&gt;
Damit die Batterietrigger dynamisch geändert werden können, ist die Einstellung als Set-Kommando und nicht als Attribut ausgeführt.   &lt;br /&gt;
&lt;br /&gt;
Alle Triggerpunkte können mit dem set-Befehl:&lt;br /&gt;
&lt;br /&gt;
 reset batteryTriggerSet&lt;br /&gt;
&lt;br /&gt;
wieder gelöscht werden.&lt;br /&gt;
&lt;br /&gt;
== Verbrauchersteuerung - Registrieren und visualisieren 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;
Die Eigenschaften und das Schaltverhalten wird durch die Angabe der verfügbaren Schlüssel gesteuert. Die Möglichkeiten sind sehr umfangreich. Die nachfolgenden Abschnitte beschreiben die Verwendung am Beispiel oft vorkommender bzw. nachgefragter Sachverhalte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die Phasen der Verbrauchersteuerung ===&lt;br /&gt;
&lt;br /&gt;
Jeder Zyklus eines Verbrauchers durchläuft im Modul die folgenden Phasen:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Planung&#039;&#039;&#039; der Aktivzeiten des Verbrauchers, d.h. wann der Verbraucher geplant eingeschaltet sowie geplant ausgeschaltet wird und damit der Zyklus beendet wird.&lt;br /&gt;
# &#039;&#039;&#039;Start&#039;&#039;&#039; des Zyklus, d.h. Einschalten des Verbrauchers entsprechend der Planungsdaten sofern weitere, in den Consumer-Schlüsseln definierbare Rahmenbedingungen das Einschalten nicht verhindern (z.B. kein oder zu wenig PV-Energieerzeugung / PV-Überschuss)&lt;br /&gt;
# &#039;&#039;&#039;Permanente Überprüfung von&#039;&#039;&#039; eventuell vorhandenen &#039;&#039;&#039;Interruptbedingungen&#039;&#039;&#039; die den Verbraucher temporär ausschalten und, sofern die Interruptbedingung nicht mehr vorliegt, den Verbraucher wieder einschalten und so den gestarteten Zyklus fortsetzen.&lt;br /&gt;
#  &#039;&#039;&#039;Beendigung&#039;&#039;&#039; der Zyklus. Die Beendigung erfolgt entweder (normalerweise) wenn die geplante Endezeit der Zyklus erreicht ist oder eine optionale Endebedingung erfüllt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Steuerung der Phasen ====&lt;br /&gt;
Der Ablauf der Phasen kann durch verschiedene Schlüssel-Wert Paare beeinflusst und gesteuert werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; kann eine &#039;&#039;&#039;zusätzliche externe Bedingung&#039;&#039;&#039; definiert werden um den Einschaltvorgang des Consumers freizugeben. Ist die Bedingung (Regex) nicht erfüllt, erfolgt kein Einschalten des Verbrauchers auch wenn die sonstigen Voraussetzungen wie Zeitplanung, on-Schlüssel, auto-Mode und aktuelle PV-Leistung gegeben sind. Es erfolgt somit eine &#039;&#039;&#039;UND-Verknüpfung&#039;&#039;&#039; des Schlüssels swoncond mit den Planungsdaten und weiteren Einschaltbedingungen.&lt;br /&gt;
&lt;br /&gt;
Der optionale Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; definiert eine &#039;&#039;&#039;vorrangige Ausschaltbedingung&#039;&#039;&#039; (Regex). Sobald diese Bedingung erfüllt ist, wird der Consumer ausgeschaltet auch wenn die geplante Endezeit (consumerXX_planned_stop) noch nicht erreicht ist (&#039;&#039;&#039;ODER-Verknüpfung&#039;&#039;&#039;). Weitere Bedingungen wie off-Schlüssel und auto-Mode müssen zum automatischen Ausschalten erfüllt sein.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; kann während der geplanten Einschaltzeit eine automatische Unterbrechung sowie Wiedereinschaltung des Verbrauchers vorgenommen werden. Der Verbraucher wird temporär ausgeschaltet (interrupted) und wieder eingeschaltet (continued) wenn die Interrupt-Bedingung nicht mehr vorliegt. Die verbleibende Laufzeit wird durch einen Interrupt nicht beeinflusst! &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;power&#039;&#039;&#039; gibt die nominale Leistungsaufnahme des Verbrauchers gemäß seines Datenblattes an. Dieser Wert wird verwendet um die Schaltzeiten des Verbrauchers zu planen und das Schalten in Abhängigkeit des tatsächlichen PV-Überschusses zum Einplanungszeitpunkt zu steuern. Ist &#039;&#039;&#039;power=0&#039;&#039;&#039; gesetzt, wird der Verbraucher unabhängig von einem zum Zeitpunkt des Zyklus-Start eventuell nicht ausreichend vorhandenem PV-Überschuss wie geplant eingeschaltet und somit der Zyklus gestartet.&lt;br /&gt;
&lt;br /&gt;
Durch die Schlüssel &#039;&#039;&#039;notbefore&#039;&#039;&#039; und &#039;&#039;&#039;notafter&#039;&#039;&#039; kann der Startzeitpunkt des Verbrauchers so gesteuert werden, dass der Start des Zyklus nicht vor bzw. nach der angegebenen Zeit eingeplant wird. Diese Steuerung bezieht sich auf die &#039;&#039;Planung&#039;&#039;, d.h. der eigentliche Start des Verbrauchers kann sich unter Umständen durch vorhandene Rahmenbedingungen verzögern. &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; legt die geplanten Einschaltzeit, d.h. die Laufzeit des Zyklus fest. Der Name &#039;&#039;&#039;mintime&#039;&#039;&#039; ist nicht als MInimum-Zeit zu deuten, sondern beschreibt die angegebene Zeit in Minuten die der Zyklus dauern soll.&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist optional, da sich die Standard-Laufzeit des Verbrauchers von dessen Typ abgeleitet wird. Diese Standard Laufzeiten sind:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|dryer&lt;br /&gt;
|90 Minten&lt;br /&gt;
|-&lt;br /&gt;
|dishwasher&lt;br /&gt;
|180 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|washingmachine&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|heater&lt;br /&gt;
|240 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|charger&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|other&lt;br /&gt;
|60 Minuten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Der Verbraucher wurde nicht gestartet obwohl die Startzeit der Einplanung erreicht wurde ===&lt;br /&gt;
&lt;br /&gt;
Wenn die Startzeit des Consumers entsprechend der Einplanung erreicht oder überschritten ist, wird der Consumer eingeschaltet wenn die weiteren Voraussetzungen wahr sind:&lt;br /&gt;
&lt;br /&gt;
* es ist aktuell ein PV-Überschuss vorhanden und der PV-Überschuss deckt die kalkulierten Leistungsaufnahme des Verbrauchers ab. Mit den Schlüsseln &#039;&#039;&#039;power&#039;&#039;&#039; und &#039;&#039;&#039;spignorecond&#039;&#039;&#039; kann die Einschaltung trotz fehlendem PV-Überschuss ermöglicht werden. &lt;br /&gt;
&lt;br /&gt;
* die Angabe im Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; ist wahr (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* das Schalten ist über den Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; freigegeben (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* im Schlüssel &#039;&#039;&#039;on&#039;&#039;&#039; ist ein valides Einschaltkommando hinterlegt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind diese zusätzlichen Bedingungen nicht erfüllt, erfolgt kein Start des eingeplanten Zyklus. Der Verbraucher verbleibt in diesem Fall weiterhin im Status &#039;&#039;planned&#039;&#039; oder &#039;&#039;suspended&#039;&#039;. Die Startbedingungen werden regelmäßig reviewed und der Consumer gestartet sobald alle Startbedingungen wahr sind bzw. Start verhindernde Bedingungen entfallen sind. &lt;br /&gt;
&lt;br /&gt;
Dieser Vorgang erfolgt bis das geplante Ende des Verbaucherzyklus erreicht ist oder die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; zutrifft. Sobald die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; wahr ist, wird der gesamte Planungszyklus des Consumers beendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Kann manuell / automatisiert in den Planungszyklus eines Verbrauchers eingegriffen werden? ===&lt;br /&gt;
&lt;br /&gt;
Die Einplanung und die darauf aufbauenden Schaltprozesse laufen gemäß den hinterlegten Schlüsseloptionen im Modul automatatisch ab ohne dass ein Eingriff durch den Anwender erfolgen muß.&lt;br /&gt;
&lt;br /&gt;
Dennoch kann es gewünscht sein eine Neuplanung oder eine Sofortplanung eines Consumers vorzunehmen weil der Bedarf dazu besteht. Zu diesem Zweck stehen die Set-Kommandos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* consumerNewPlanning &lt;br /&gt;
&lt;br /&gt;
* consumerImmediatePlanning &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
zur Verfügung. &lt;br /&gt;
Beide Befehle initiieren die Consumer-Neuplanung, wobei mit dem Befehl &#039;&#039;consumerImmediatePlanning&#039;&#039; die eventuell im consumerXX Attribut gesetzten Schlüssel notbefore, notafter bzw. mode werden nicht beachtet werden. Dagenen beachtet der Befehl &#039;&#039;consumerNewPlanning&#039;&#039; alle definierten Schlüsseloptionen und dient gewöhnlich dazu einen abgeschlossenen Verbraucherzyklus wiederholt ausführen zu lassen weil die aktuelle Witterungslage dazu geeignet ist. &lt;br /&gt;
&lt;br /&gt;
Ein Anwendungsbeispiel dafür ist zum Beispiel die Ausführung von mehreren Waschmaschinen-Zyklen an einem langen, sonnigen Sommertag.&lt;br /&gt;
Diese beiden Set-Befehle können zum Beispiel über ein auf einen Schalter/Taster reagierendes Notify oder DOIF Device ausgeführt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung eines Verbrauchers mit getrennten Geräten für Messung und Schalten ===&lt;br /&gt;
&lt;br /&gt;
Es existieren in FHEM Geräte, die über verschiedene Kanäle für unterschiedliche Aufgaben verfügen. Diese Kanäle werden jeweils in einem gesonderten Device abgebildet. HomeMatic oder readingsProxy sind Beispiele für solche Varianten.&lt;br /&gt;
&lt;br /&gt;
Um solche Verbraucher einzubinden gibt es im consumerXX Attribut den Schlüssel &#039;&#039;&#039;switchdev&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Bei der Registrierung gibt man als Consumerdevice das Gerät für die Messung an und im Schüssel switchdev das entsprechende FHEM-Device, welches für die Schaltvorgänge benutzt wird. &lt;br /&gt;
Ist switchdev angegeben, beziehen sich die weiteren Schlüssel on, off, swstate, auto und asynchron auf dieses Gerät.&lt;br /&gt;
&lt;br /&gt;
In dem nachfolgenden Beispiel (Homematic) ist &#039;&#039;eg.az.fridge_Pwr&#039;&#039; FHEM Device für die Energiemessung. Die Schlüssel &#039;&#039;pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; geben Readings in diesem Device an damit SolarForecast den Verbrauch und die Energiemengen auslesen kann. Demgegenüber ist im Schlüssel &#039;&#039;switchdev&#039;&#039; das zugehörige Schalter-Device der Kombination angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eg.az.fridge_Pwr&lt;br /&gt;
type=noSchedule switchdev=eg.az.fridge_Sw power=0 icon=fridge pcurr=power:W:5 etotal=energyCalc:Wh &lt;br /&gt;
swstate=state:on:off auto=automatic&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung von Verbrauchern ohne Zeitplanung und aktivem Schalten ===&lt;br /&gt;
Manchmal besteht der Wunsch, Verbraucher in SolarForecast zu integrieren um lediglich folgende Sachverhalte abzubilden:&lt;br /&gt;
&lt;br /&gt;
* Visualisierung des Schaltstatus in der Consumer Legende und/oder der Energieflußgrafik&lt;br /&gt;
* Darstellung des aktuellen Energieverbrauchs in der Energieflußgrafik&lt;br /&gt;
* Erfassung der (externen) Schaltzeiten, d.h. der Zeiten der Gerätenutzung sowie der Verbrauchsdaten um deren Einfluß bei den Planungszeiten anderer Geräte durch SolarForecast berücksichtigen zu lassen&lt;br /&gt;
&lt;br /&gt;
In solchen Fällen werden bei der Registrierung die Schlüssel &#039;&#039;swstate, pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; zur Erfassung der Schaltzustände und der Energieverbrauchs angegeben, jedoch zur Verhinderung der Zeitplanung durch SolarForecast der Schlüssel &#039;&#039;&#039;type=noSchedule&#039;&#039;&#039; gesetzt sowie die Schlüssel &#039;&#039;on&#039;&#039; und &#039;&#039;off&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt eine mögliche Registrierung eines Zwischensteckers (Shelly) zur Erfassung der Daten eines Gefrierschrankes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Shelly.shellyplug4&lt;br /&gt;
type=noSchedule power=65 asynchron=1&lt;br /&gt;
icon=gefrierschrank &lt;br /&gt;
swstate=state:.*on.*:.*off.* &lt;br /&gt;
pcurr=relay_0_power:W:5 etotal=relay_0_energy_Wh:Wh&lt;br /&gt;
&amp;lt;/pre&amp;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;
&lt;br /&gt;
 Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off&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;
&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;
&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. Alternativ kann die Berücksichtigung des zwangsweisen PV Überschuss mit dem Schlüssel &amp;quot;spignorecond&amp;quot; im Consumer-Attribut ausgesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== zusätzliche Readings bzw. Erzeugung von statistischen Readings ==&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den zahlreichen im Modul per Standard erzeugten Readings kann der Anwender weitere Readings generieren lassen.&lt;br /&gt;
Diese zusätzlichen Readings geben entweder einen bestimmten Sachverhalt (Laufzeit, Status der API-Abfragen, etc.) oder einen statistischen Wert, z.B. die Batterieentladung des aktuellen Tages, wieder.&lt;br /&gt;
&lt;br /&gt;
Die zusätzlich erstellten Readings sind durch den Präfix &#039;&#039;&#039;special_&#039;&#039;&#039; im Device gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Diese zusätzlichen Informationen können durch das Setzen einer oder mehrerer Kennzeichen im Attribut &#039;&#039;&#039;ctrlSpecialReadings&#039;&#039;&#039; erzeugt werden. Die mögliche Auswahl wird je nach Bedarf ausgebaut und umfasst zum aktuellen Zeitpunkt (07.02.2025) diese Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;BatPowerIn_Sum: 	die Summe der momentanen Batterieladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;BatPowerOut_Sum: 	die Summe der momentanen Batterieentladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;allStringsFullfilled: 	Erfüllungsstatus der fehlerfreien Generierung aller Strings&lt;br /&gt;
;conForecastTillNextSunrise: 	Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
;currentAPIinterval: 	das aktuelle Abrufintervall der gewählten Strahlungsdaten-API in Sekunden&lt;br /&gt;
;currentRunMtsConsumer_XX: 	die Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; seit dem letzten Einschalten. (letzter Laufzyklus)&lt;br /&gt;
;dayAfterTomorrowPVforecast: 	liefert die Vorhersage der PV Erzeugung für Übermorgen (sofern verfügbar) ohne Autokorrektur (Rohdaten).&lt;br /&gt;
;daysUntilBatteryCare_XX: 	Tage bis zur nächsten Batterie XX Pflege (Erreichen der Ladung &#039;maxSoC&#039; aus Attribut ctrlBatSocManagementXX)&lt;br /&gt;
;lastretrieval_time: 	der letzte Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;lastretrieval_timestamp: 	der Timestamp der letzen Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;response_message: 	die letzte Statusmeldung der gewählten Strahlungsdaten-API&lt;br /&gt;
;runTimeAvgDayConsumer_XX: 	die durchschnittliche Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; an einem Tag&lt;br /&gt;
;runTimeCentralTask: 	die Laufzeit des letzten SolarForecast Intervalls (Gesamtprozess) in Sekunden&lt;br /&gt;
;runTimeTrainAI: 	die Laufzeit des letzten KI Trainingszyklus in Sekunden&lt;br /&gt;
;runTimeLastAPIAnswer: 	die letzte Antwortzeit des Strahlungsdaten-API Abrufs auf einen Request in Sekunden&lt;br /&gt;
;runTimeLastAPIProc: 	die letzte Prozesszeit zur Verarbeitung der empfangenen Strahlungsdaten-API Daten&lt;br /&gt;
;SunMinutes_Remain: 	die verbleibenden Minuten bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;SunHours_Remain: 	die verbleibenden Stunden bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;todayConsumptionForecast: 	Verbrauchsprognose pro Stunde des aktuellen Tages (01-24)&lt;br /&gt;
;todayConForecastTillSunset: 	Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
;todayDoneAPIcalls: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Calls&lt;br /&gt;
;todayDoneAPIrequests: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Requests&lt;br /&gt;
;todayConsumption: 	der gesamte Energieverbrauch (Wh) des Hauses am aktuellen Tag&lt;br /&gt;
;todayGridConsumption: 	die aus dem öffentlichen Netz bezogene Energie am aktuellen Tag&lt;br /&gt;
;todayGridFeedIn: 	die in das öffentliche Netz eingespeiste PV Energie am aktuellen Tag&lt;br /&gt;
;todayMaxAPIcalls: 	die maximal mögliche Anzahl Strahlungsdaten-API Calls. Ein Call kann mehrere API Requests enthalten.&lt;br /&gt;
;todayRemainingAPIcalls: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Calls&lt;br /&gt;
;todayRemainingAPIrequests: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Requests&lt;br /&gt;
;todayBatIn_XX: 	die am aktuellen Tag in die Batterie XX geladene Energie&lt;br /&gt;
;todayBatInSum: 	Summe der am aktuellen Tag in alle Batterien geladene Energie&lt;br /&gt;
;todayBatOut_XX: 	die am aktuellen Tag aus der Batterie XX entnommene Energie&lt;br /&gt;
;todayBatOutSum: 	Summe der am aktuellen Tag aus allen Batterien entnommene Energie&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Manche Angaben sind im Setup des Moduls optional, d.h. sie müssen nicht zwingend beim Setup angegeben werden. Allerdings sind diese Angaben für die Erstellung eines zusätzlichen Readings unter Umständen Voraussetzung. Es empfiehlt sich deshalb bei Setup so viele Informationen wie möglich zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
So ist zum Beispiel für die sinnvolle Erstellung der Informationen &#039;&#039;&#039;todayBatInSum&#039;&#039;&#039; und &#039;&#039;&#039;todayBatOutSum&#039;&#039;&#039; (Readings special_todayBatInSum und special_todayBatOutSum) das Vorhandensein der Schlüssel &#039;&#039;intotal&#039;&#039; und &#039;&#039;outtotal&#039;&#039; im Attribut setupBatteryDevXX notwendig (Beispiel):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupBatteryDev01 MQTT2_cerboGX_c0619ab34e08_battery &lt;br /&gt;
                              pin=BatIn:W pout=BatOut:W charge=SOC_value intotal=BatInTotal:Wh outtotal=BatOutTotal:Wh &lt;br /&gt;
                              cap=InstalledCapacity_Wh:Wh asynchron=1 show=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Fehlersuche ==&lt;br /&gt;
Das Modul SolarForecast ist sehr komplex und es die verschiedensten Datenquellen ausgewertet, zusammengeführt und daraus Ergebnisse berechnet und/oder visualisiert. Wird etwas nicht wie erwartet durch das Modul geliefert, können die Ursachen vielfältig sein. Natürlich kann ein Fehler im Modulcode vorliegen, oftmals gibt es aber andere Ursachen.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgenden Hinweise sollen Hilfe zur Selbsthilfe geben und sind eine Zusammenfassung von realen Fällen die mit dem beschriebenen Wegen und Verfahren gelöst wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die erwartete erzeugte PV-Energie ist im Modul zu gering und wird im Balkendiagramm nicht angezeigt === &lt;br /&gt;
&lt;br /&gt;
Die erzeugte PV-Energie wird nicht richtig angezeigt: Am Vormittag sind keine Werte vorhanden und, wenn dann etwas kommt, ist die Anzeige zu gering. Für 13 und 14 Uhr wurden ca. 5.000Wh erwartet (im Vergleich mit den Daten aus einer anderen Auswertungsquelle). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lösungsweg:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Aus dem List des Devices wurden die für den Fall wesentlichen Readings herausgezogen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVforecast 152 Wh&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVforecast 1400 Wh&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVforecast 2500 Wh&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVforecast 4392 Wh&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVforecast 4000 Wh&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVreal 300 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVforecast 6415 Wh&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVreal 3200 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVforecast 5629 Wh&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVreal 2700 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVforecast 3958 Wh&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVreal 900 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVforecast 945 Wh&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVreal 500 Wh&lt;br /&gt;
   &lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour18_PVforecast 59 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man sieht dass bis 12:00 keine erzeugte Energie vom WR gemeldet wird. Deswegen wird in der Balkengrafik nichts dargestellt. Auch danach bleibt die registrierte PV-Energie hinter den Erwartungen zurück. Zuständig für die Lieferung der PV-Energie an das Modul ist das Reading im Schlüssel:&lt;br /&gt;
&lt;br /&gt;
 setupInverterDev01 SH10rt pv=Total_DC_Power:W &amp;lt;mark&amp;gt;etotal=Total_Export_Energy_from_PV:kWh&amp;lt;/mark&amp;gt; capacity=10000 strings=Hauptdach,Flachdach&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Welche Änderungen es zwischen den Stunden gab, sieht man mit einem &amp;quot;get ... pvHistory XX&amp;quot; (&amp;quot;XX&amp;quot; steht für das Datum, d.h. den Tag, z.B. 02). &amp;lt;br&amp;gt;&lt;br /&gt;
Hier ein Beispiel für die Stunden 10 (9:00 - 9:59) und 11 (10:00 - 10:59). &amp;lt;br&amp;gt;&lt;br /&gt;
Wichtig ist hier der Key etotali01 für den ersten Inverter. Die Differenz zwischen den Werten beider Stunden ist die in der Stunde erzeugte Energie (hier 380 Wh). Diese 380 Wh findest du auch im Key pvrl01 als PVReal für diese Stunde. Das Modul rechnet intern immer mit Wh, kWh werden vorher in Wh umgerechnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
10 =&amp;gt; pvfc: 365, pvrl: 530, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63364714&amp;lt;/mark&amp;gt;, etotali02: 3044110, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;pvrl01: 380&amp;lt;/mark&amp;gt;, pvrl02: 150, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 574, con: 518, gcons: 22, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 1, feedprice: 0.1269&lt;br /&gt;
&lt;br /&gt;
            DoN: 1, sunaz: 137, sunalt: 12&lt;br /&gt;
&lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
      11 =&amp;gt; pvfc: 2966, pvrl: 1862, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63365094&amp;lt;/mark&amp;gt;, etotali02: 3044260, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            pvrl01: 1392, pvrl02: 470, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 774, con: 609, gcons: 25, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 4, feedprice: 0.1269&lt;br /&gt;
           &lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
D.h. wenn zwischen den beiden Stunden keine Differenzen zu finden sind, liegt es sehr wahrscheinlich am Input des Readings:&lt;br /&gt;
&lt;br /&gt;
 etotal=Total_Export_Energy_from_PV:kWh&lt;br /&gt;
&lt;br /&gt;
welches sich in den ersten Stunden nicht ändert und danach auch nur wenig.&lt;br /&gt;
&lt;br /&gt;
Man kann mit dem Attribut:&lt;br /&gt;
&lt;br /&gt;
 ctrlDebug=collectData&lt;br /&gt;
&lt;br /&gt;
die Datensammlung verfolgen (leider entstehen viele Daten im Log). Man sieht welche Werte von dem Inverter/Reading geliefert werden:&lt;br /&gt;
 &lt;br /&gt;
 ....&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; collect Inverter 01 data - device: STP_5000, delivery: default =&amp;gt;&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; pv: 0 W, &amp;lt;mark&amp;gt;etotal: 63378810 Wh&amp;lt;/mark&amp;gt;&lt;br /&gt;
 ....&lt;br /&gt;
&lt;br /&gt;
Dieser Wert muß bei PV Erzeugung kontinuierlich hochzählen. Wenn nicht, muss das angegebene Reading, d.h. die Quelle überprüft werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ergebnis der Prüfung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tatsächlich wurde ein Reading benutzt, das ungeeignet war: Statt &amp;quot;Total_PV_Generation&amp;quot; wurde &amp;quot;Total_export_energy_from_PV&amp;quot; genutzt. In diesem Reading wurde immer die in die Batterie gespeicherte Energie von der gesamten erzeugten Energie abgezogen. Daher war auch vormittags alles 0, da in dieser Periode alle PV-Energie in die Batterie geladen wurde bzw. in weiteren Stunden ein Anteil der dann bei dem PV-Erzeugungswert fehlte.&lt;br /&gt;
&lt;br /&gt;
Nachdem die Ursache beseitigt war, zeigt SolarForecast wieder die erwarteten PV-Erzeugungswerte an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Konfigurationsbeispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Visualisierung solare Vorhersage und reale Erzeugung ===&lt;br /&gt;
&lt;br /&gt;
Zu Beginn jedes neuen Tages gegen 00:00 Uhr werden durch das SolarForecast Device Events für die initiale PV Prognose des kommenden Tages erstellt.&lt;br /&gt;
Der Readingteil dieser Events heißt&lt;br /&gt;
&lt;br /&gt;
 AllPVforecastsToEvent&lt;br /&gt;
&lt;br /&gt;
Die Uhrzeiten der Events sind so aufbereitet und können direkt geloggt werden um sie in einen SVG Plot zu integrieren.&lt;br /&gt;
Im SolarForecast Device ist dieses Reading nicht sichtbar, nur die Events werden erstellt.&lt;br /&gt;
&lt;br /&gt;
Die meteorologischen Bedingungen verändern sich über den Tag permanent. Je nach gewählter Strahlungsdatenquelle (eine API oder DWD Device) erfolgt eine mehr oder weniger dynamische Anpassung der Prognose an die sich verändernde Umwelt.&lt;br /&gt;
&lt;br /&gt;
Aktuelle Prognosedaten sowie die reale PV Erzeugung der vergangenen Stunde können über die Readings&lt;br /&gt;
&lt;br /&gt;
 LastHourPVforecast&lt;br /&gt;
 LastHourPVreal&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-10-20 134050.png|right|thumb|400px|Übersicht solare Vorhersage]]&lt;br /&gt;
geloggt werden. &lt;br /&gt;
&lt;br /&gt;
Werden alle drei Werte in einem SVG kombiniert, kann die Entwicklung der Prognose über den Tag und die Beziehung von Prognose zu realer PV Erzeugnung pro Stunde visualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Für das rechts abgebildete Beispiel des Plots aus einer Datenbank &amp;quot;LogDBShort&amp;quot; sieht das gplot-File wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Created by FHEM/98_SVG.pm, 2024-03-08 15:05:31&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;TL&amp;gt;&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid&lt;br /&gt;
set ylabel &amp;quot;Wh&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Wh&amp;quot;&lt;br /&gt;
set yrange [0:7500]&lt;br /&gt;
set y2range [0:7500]&lt;br /&gt;
&lt;br /&gt;
#LogDBShort SolCast:LastHourPVforecast:::&lt;br /&gt;
#LogDBShort SolCast:LastHourPVreal:::&lt;br /&gt;
#LogDBShort SolCast:AllPVforecastsToEvent:::&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;aktuelle PV Vorhersage&#039; ls l6fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;reale PV Erzeugung&#039; ls l2fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;initiale PV Vorhersage&#039; ls l4 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; In manchen Fällen werden die Vorhersagewerte im SVG-Plot nicht angezeigt wenn FileLog verwendet wird. Ein Setzen des Attribute &amp;quot;fixedrange=3days +1&amp;quot; im SVG löst das Problem. Die Definition des SVG-Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_LogDBShort_SolCast SVG LogDBShort:SVG_LogDBShort_SolCast:HISTORY&lt;br /&gt;
attr SVG_LogDBShort_SolCast fixedrange 3days +1&lt;br /&gt;
attr SVG_LogDBShort_SolCast room Energie-&amp;gt;SolarPrognose&lt;br /&gt;
attr SVG_LogDBShort_SolCast sortby 2&lt;br /&gt;
attr SVG_LogDBShort_SolCast title &amp;quot;Übersicht solare Vorhersage&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Technisch bedingt werden an einem Tag X kurz nach 00:00 Uhr die am Vortag für den Tag X erzeugten Events aktualisiert. Diese Daten erzeugen in der Datenbank einen zweiten Satz an Daten mit dem gleichen Timestamp was für die Anzeige unvorteilhaft ist. &lt;br /&gt;
Um nur die aktualisierten Events von &#039;&#039;&#039;AllPVforecastsToEvent&#039;&#039;&#039; in der Datenbank zu erhalten, bietet sich ein DbRep-Device an. Die nachfolgende Vorschlagsdefinition kann per at-Device jeden Tag kurz vor Mitternacht (z.B. 23:57:10) ausgeführt werden. Es werden immer die in der Vergangenheit geschriebenen (veralteten) Daten aus der Datenbank gelöscht, doppelte Datesätze vermieden und immer die aktuellste initiale Prognose gespeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.Del.AllPVforecastsToEvent DbRep LogDBShort&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent alias Löschen Readings AllPVforecastsToEvent des Folgetages&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent comment ermöglicht dass die Readings AllPVforecastsToEvent am Folgetag wieder neu und aktuell geschrieben werden können&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent devStateIcon initialized:control_3dot_hor_s connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent disable 0&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent event-on-update-reading state&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent icon edit_delete&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent showproctime 1&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent device TYPE=SolarForecast&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_begin next_day_begin&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_end next_day_end&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das angegebene DbLog-Device &#039;&#039;&#039;LogDBShort&#039;&#039;&#039; ist natürlich anzupassen.&lt;br /&gt;
&lt;br /&gt;
Das at-Device zum Starten der Datenbankbereinigung sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define At.Del.AllPVforecastsToEvent at *23:58:10 set Rep.Del.AllPVforecastsToEvent delEntries&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent alias Start Löschen Readings AllPVforecastsToEventn LogDBShort&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent icon clock&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich sind auch hier die eigenen Devicenamen entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
Ab SolarForecast Version 1.51.7 kann die Eventerzeugung für bestimmte SVG Plot-Typen optimiert werden. &amp;lt;br&amp;gt; &lt;br /&gt;
Die Aktivierung dieser Optimierungen ist in der Online Hilfe zum Attribut &#039;&#039;&#039;plantControl-&amp;gt;genPVforecastsToEvent&#039;&#039;&#039; beschrieben. Bei Nutzung des Attributes plantControl-&amp;gt;genPVforecastsToEvent ist ebenfalls das Attribut &#039;&#039;&#039;event-on-update-reading=AllPVforecastsToEvent&#039;&#039;&#039; zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispielkonfiguration 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;
Bitte dabei diese DWD-Version aus dem [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter Contrib] von DS_Starter dazu nutzen&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|55_DWD_OpenData.pm&lt;br /&gt;
|136.2 KB ​&lt;br /&gt;
|29260  &lt;br /&gt;
|DS_Starter&lt;br /&gt;
|55_DWD_OpenData: contrib 1.17.7&lt;br /&gt;
|}&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 downloadTimeout 120&lt;br /&gt;
attr DWD comment Im DWD Wetterdevice verwendet Solarforecast : \&lt;br /&gt;
TTT,Neff,RR1c,ww,SunUp,SunRise,SunSet \&lt;br /&gt;
zusätzlich ist jedoch auch noch Rad1h notwendig \&lt;br /&gt;
wenn dieses DWD-Device als Strahlungsdevice genutzt wird.\&lt;br /&gt;
Die Station 10418 (Lüdenscheid) überträgt aktuell am 09.03.2025 (noch) Rad1h.\&lt;br /&gt;
attr DWD downloadTimeout 120&lt;br /&gt;
attr DWD forecastDays 7&lt;br /&gt;
attr DWD forecastProperties SunUp, SunRise, SunSet, Rad1h, R101, RR1c, TTT, Tx, Tn, Tg, DD, FX1, RR6c, R600, RRhc, Rh00, ww, wwd, Neff&lt;br /&gt;
attr DWD forecastRefresh 1&lt;br /&gt;
attr DWD forecastResolution 1&lt;br /&gt;
attr DWD forecastStation 10418&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 fc_description  -(state fc_time)&lt;br /&gt;
attr DWD verbose 2&lt;br /&gt;
&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;
defmod InverterDummy dummy&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;
defmod 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 feedinPrice 0.08&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 powerCost 0.25&lt;br /&gt;
attr SMA_Energymeter room 015_Zaehler,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;
defmod 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;
attr BatteryDummy userReadings total_pac, power_out, power_in, chargestatus, bat_rated_capacity, bat_loadtotal, bat_unloadtotal&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;
defmod N.PV.TotalConsumption.Dum.Energy notify SMA_Energymeter:Saldo_Wirkleistung:.* {\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung_2 Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&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;MB_USRW610_004&amp;quot;,&amp;quot;Power_Sum__W&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;
fhem &amp;quot;setreading InverterDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(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;
#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;
 # Batterie-total_pac  InverterDummy\&lt;br /&gt;
my $wert7 = sprintf(&amp;quot;%.3f&amp;quot;,((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy bat_rated_capacity &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert7));;\&lt;br /&gt;
 # möglicher Aufruf einer Batterie-Bebladung-Routine....SMABatteryChargewithTibber();;\&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;
defmod Forecast SolarForecast&lt;br /&gt;
attr Forecast DbLogExclude .*&lt;br /&gt;
attr Forecast DbLogInclude Current_BatCharge999&lt;br /&gt;
attr Forecast affectBatteryPreferredCharge 30&lt;br /&gt;
attr Forecast affectConsForecastLastDays 31&lt;br /&gt;
attr Forecast affect70percentRule 0&lt;br /&gt;
attr Forecast comment &amp;quot;wget -qO ./FHEM/76_SolarForecast.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/76_SolarForecast.pm&amp;quot;\&lt;br /&gt;
&amp;quot;wget -qO ./FHEM/55_DWD_OpenData.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/55_DWD_OpenData.pm&amp;quot;\&lt;br /&gt;
&amp;quot;13.01.2025 mit der Version 76_SolarForecast.pm:v1.43.2-s29518/2025-01-12&amp;quot;&lt;br /&gt;
attr Forecast graphicHeaderOwnspec PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal Verbrauch&amp;amp;nbsp;;bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast  Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest FCU-Erzeugung&amp;amp;nbsp;;:Current_PP01\&lt;br /&gt;
attr Forecast consumer01 FBDECT_fbahahttp_11657_0127183 icon=scene_washing_machine@orange type=washingmachine power=10 swstate:state notbefore=09 notafter=20 pcurr=power:W:3 etotal=energy:Wh interruptable=1 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer02 FBDECT_fbahahttp_E8_DF_70_07_3E_57 icon=light_floor_lamp@orange type=other power=15 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer03 FBDECT_fbahahttp_E8_DF_70_07_42_0B icon=raspberrypi@orange type=other power=8 swstate:state pcurr=power:W:1 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer04 FBDECT_fbahahttp_11657_0067275 icon=springbrunnen_icon@orange type=other power=50 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer05 FBDECT_fbahahttp_34_31_C4_D4_31_37 icon=sani_domestic_waterworks@orange type=other power=10 swstate:state pcurr=power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer06 tuya_local_bf5037060f450bdbd4rl0q icon=scene_clothes_dryer@orange type=dryer power=10 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer07 tuya_local_bfac44fb487476efd1vhdu icon=weather_sunset@orange type=noSchedule power=5 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumerControl adviceIcon=light_light_dim_100@gold&lt;br /&gt;
attr Forecast consumerControl showLegend=icon_top&lt;br /&gt;
attr Forecast consumerControl detailLink=1&lt;br /&gt;
attr Forecast ctrlAIdataStorageDuration 1825&lt;br /&gt;
attr Forecast ctrlAIshiftTrainStart 2&lt;br /&gt;
attr Forecast ctrlBatSocManagement01 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlBatSocManagement02 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlDebug none&lt;br /&gt;
attr Forecast plantControl genPVdeviation=continuously&lt;br /&gt;
attr Forecast plantControl cycleInterval=15&lt;br /&gt;
attr Forecast ctrlNextDayForecastReadings 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24&lt;br /&gt;
attr Forecast ctrlNextHoursSoCForecastReadings 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23&lt;br /&gt;
attr Forecast ctrlSpecialReadings BatPowerIn_Sum,BatPowerOut_Sum,SunHours_Remain,SunMinutes_Remain,allStringsFullfilled,conForecastTillNextSunrise,currentAPIinterval,currentRunMtsConsumer_01,currentRunMtsConsumer_02,currentRunMtsConsumer_03,currentRunMtsConsumer_04,currentRunMtsConsumer_05,currentRunMtsConsumer_06,currentRunMtsConsumer_07,dayAfterTomorrowPVforecast,daysUntilBatteryCare_01,daysUntilBatteryCare_02,lastretrieval_time,lastretrieval_timestamp,response_message,runTimeAvgDayConsumer_01,runTimeAvgDayConsumer_02,runTimeAvgDayConsumer_03,runTimeAvgDayConsumer_04,runTimeAvgDayConsumer_05,runTimeAvgDayConsumer_06,runTimeAvgDayConsumer_07,runTimeCentralTask,runTimeLastAPIAnswer,runTimeLastAPIProc,runTimeTrainAI,todayBatIn_01,todayBatIn_02,todayBatOut_01,todayBatOut_02,todayConForecastTillSunset,todayConsumptionForecast,todayDoneAPIcalls,todayDoneAPIrequests,todayGridConsumption,todayGridFeedIn,todayMaxAPIcalls,todayRemainingAPIcalls,todayRemainingAPIrequests&lt;br /&gt;
attr Forecast disable 0&lt;br /&gt;
attr Forecast event-min-interval .*:1800&lt;br /&gt;
attr Forecast event-on-change-reading .*&lt;br /&gt;
attr Forecast flowGraphicControl animate=1 consumerdist=80 h2consumerdist=50 shiftx=0  shifty=0 showconsumer=1 showconsumerdummy=1 showconsumerpower=1 showconsumerremaintime=0 size=400 strokewidth=12&lt;br /&gt;
attr Forecast graphicBeam1Color 3C14FF&lt;br /&gt;
attr Forecast graphicBeam1Content pvReal&lt;br /&gt;
attr Forecast graphicBeam2Color 19FF29&lt;br /&gt;
attr Forecast graphicBeam2Content pvForecast&lt;br /&gt;
attr Forecast graphicBeam3Color D60924&lt;br /&gt;
attr Forecast graphicBeam3Content batsocforecast_02&lt;br /&gt;
attr Forecast graphicBeam3FontColor FFFF0D&lt;br /&gt;
attr Forecast graphicBeam4Color FFFF1F&lt;br /&gt;
attr Forecast graphicBeam4Content batsocforecast_01&lt;br /&gt;
attr Forecast graphicBeam4FontColor 000000&lt;br /&gt;
attr Forecast graphicBeamHeightLevel1 200&lt;br /&gt;
attr Forecast graphicBeamHeightLevel2 200&lt;br /&gt;
attr Forecast graphicHeaderDetail all&lt;br /&gt;
attr Forecast graphicHeaderOwnspec #PV\&lt;br /&gt;
PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal\&lt;br /&gt;
PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast\&lt;br /&gt;
PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast\&lt;br /&gt;
:\&lt;br /&gt;
#\&lt;br /&gt;
AutarkyRate:Current_AutarkyRate\&lt;br /&gt;
Überschuss:Current_Surplus\&lt;br /&gt;
aktueller&amp;amp;nbsp;;Netzbezug:Current_GridConsumption\&lt;br /&gt;
:\&lt;br /&gt;
#Verbrauch\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenuntergang:special_todayConForecastTillSunset\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie01\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_01\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_01\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_01\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_01\&lt;br /&gt;
#Batterie01_tmp\&lt;br /&gt;
Current_PowerBatIn_01:Current_PowerBatIn_01\&lt;br /&gt;
Current_PowerBatOut_01:Current_PowerBatOut_01\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie02\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_02\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_02\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_02\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_02\&lt;br /&gt;
#Batterie02_tmp\&lt;br /&gt;
Current_PowerBatIn_02:Current_PowerBatIn_02\&lt;br /&gt;
Current_PowerBatOut_02:Current_PowerBatOut_02\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Settings\&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto \&lt;br /&gt;
Wetter:graphicShowWeather\&lt;br /&gt;
History:graphicHistoryHour\&lt;br /&gt;
ShowNight:graphicShowNight\&lt;br /&gt;
Debug:ctrlDebug\&lt;br /&gt;
FCU-Modus:FCU-Betriebsmodus@FCU&lt;br /&gt;
attr Forecast graphicHistoryHour 4&lt;br /&gt;
attr Forecast graphicHourCount 24&lt;br /&gt;
attr Forecast graphicLayoutType double&lt;br /&gt;
attr Forecast graphicShowDiff top&lt;br /&gt;
attr Forecast graphicShowNight 1&lt;br /&gt;
attr Forecast graphicShowWeather 1&lt;br /&gt;
attr Forecast group Energy Meter&lt;br /&gt;
attr Forecast room 020_PV,Energie&lt;br /&gt;
attr Forecast setupBatteryDev01 SBS25 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupBatteryDev02 SBS25_2 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupInverterDev01 SB25 pv=total_pac:kW etotal=etotal:kWh capacity=2500 strings=GarageSE limit=70&lt;br /&gt;
attr Forecast setupInverterDev02 SB30 pv=total_pac:kW etotal=etotal:kWh capacity=3000 strings=GarageNW,HausNW limit=70&lt;br /&gt;
attr Forecast setupInverterDev03 SB40 pv=total_pac:kW etotal=etotal:kWh capacity=4000 strings=HausSE1,HausSE2,HausSW limit=70&lt;br /&gt;
attr Forecast setupInverterStrings GarageSE,GarageNW,HausNW,HausSW,HausSE1,HausSE2&lt;br /&gt;
attr Forecast setupMeterDev SMA_Energymeter gcon=Bezug_Wirkleistung:W contotal=Bezug_Wirkleistung_Zaehler:kWh gfeedin=Einspeisung_Wirkleistung:W feedtotal=Einspeisung_Wirkleistung_Zaehler:kWh conprice=0.25:€ feedprice=0.08123:€&lt;br /&gt;
attr Forecast setupOtherProducer01 icon=Heizung_FCU_green@red MB_USRW610_004 pcurr=Power_L1__W:W etotal=Energy_L1_import__kWh:kWh&lt;br /&gt;
attr Forecast setupRadiationAPI DWD&lt;br /&gt;
attr Forecast setupStringPeak GarageSE=2.75 GarageNW=3.200 HausNW=2.230 HausSW=2.230 HausSE1=2.200 HausSE2=2.200&lt;br /&gt;
attr Forecast setupWeatherDev1 DWD&lt;br /&gt;
attr Forecast stateFormat Current_PV&lt;br /&gt;
attr Forecast userReadings Current_BatCharge999 {((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))) / ( (ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0) * 1000)  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0)*1000))*100}&lt;br /&gt;
attr Forecast verbose 2&lt;br /&gt;
&lt;br /&gt;
setstate Forecast 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .FCU_FCU-Betriebsmodus 2&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_ctrlDebug none&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicHistoryHour 4&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowNight 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowWeather 1&lt;br /&gt;
setstate Forecast 2025-01-13 08:24:25 .associatedWith SMA_Energymeter FBDECT_fbahahttp_11657_0127183 FBDECT_fbahahttp_E8_DF_70_07_3E_57 FBDECT_fbahahttp_E8_DF_70_07_42_0B FBDECT_fbahahttp_11657_0067275 FBDECT_fbahahttp_34_31_C4_D4_31_37 tuya_local_bf5037060f450bdbd4rl0q tuya_local_bfac44fb487476efd1vhdu SBS25 SBS25_2 SB25 SB30 SB40 DWD MB_USRW610_004&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .lastupdateForecastValues 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .pvCorrectionFactor_Auto_Soll on_complex_ai&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .signaldone_01 done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .signaldone_02 done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .signaldone_03 done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .signaldone_04 done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .signaldone_05 done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .signaldone_06 done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .signaldone_07 done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .signaldone_08 done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .signaldone_09 done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .signaldone_10 done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .signaldone_11 done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .signaldone_12 done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .signaldone_13 done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .signaldone_14 done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .signaldone_15 done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .signaldone_16 done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .signaldone_17 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .signaldone_18 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_01 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_02 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_01 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_02 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_AutarkyRate 83 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 Current_BatCharge999 10&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_01 12 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_02 8 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Consumption 626 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridConsumption 2 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridFeedIn 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PP_01 746.0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PV 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_01 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_02 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_01 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_02 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumption 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumptionRate 0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Surplus 120 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourGridconsumptionReal 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_ConsumptionForecast 2944 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayConsumptionForecast 3609 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_01 272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PPreal_01 748 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PPreal_01 787 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_01 271 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PPreal_01 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PPreal_01 745 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_01 267 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PPreal_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_01 255 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PPreal_01 752 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_01 226 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_01 50 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PPreal_01 681 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_02 233 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_01 845 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridConsumption 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_01 37 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_02 90 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_01 351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_02 188 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridConsumption 447 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVforecast 127 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridConsumption 1650 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVforecast 478 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVreal 26 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridConsumption 513 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVforecast 868 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVreal 97 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridConsumption 576 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVforecast 1157 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVreal 320 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_01 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_02 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridConsumption 1272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridFeedIn 7 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVforecast 1238 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVreal 945 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_01 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_02 53 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridConsumption 955 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridFeedIn 31 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PPreal_01 562 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVforecast 1168 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVreal 1410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_01 703 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_02 500 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_01 22 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_02 18 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridConsumption 32 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridFeedIn 71 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PPreal_01 777 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVreal 1416 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_01 296 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_02 70 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_01 74 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_02 258 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridConsumption 13 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridFeedIn 17 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PPreal_01 732 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVforecast 880 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVreal 1051 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_01 47 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_02 126 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_01 102 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_02 75 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridConsumption 15 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridFeedIn 23 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PPreal_01 771 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVforecast 117 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVreal 86 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_02 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_02 67 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridConsumption 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridFeedIn 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PPreal_01 723 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_01 349 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_02 124 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_01 73 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_02 450 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridConsumption 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridFeedIn 6 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PPreal_01 671 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecastTime 2025-01-13 14:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVdeviation 30.17 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVforecast 7663 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVreal 5351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunRise 08:28&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunSet 16:46&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_ConsumptionForecast 17043 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour05_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour06_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour07_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour08_PVforecast 10 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour09_PVforecast 161 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour10_PVforecast 275 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour11_PVforecast 532 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour12_PVforecast 730 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour13_PVforecast 1252 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour14_PVforecast 818 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour15_PVforecast 1465 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour16_PVforecast 303 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour17_PVforecast 20 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour18_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour19_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour20_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour21_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour22_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour23_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour24_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_PVforecast 5566 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunRise 08:27&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunSet 16:47&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01 name=&#039;_Waschmaschine&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_start 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_stop 14.01.2025 11:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02 name=&#039;_Esszimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_currentPower 15.3 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03 name=&#039;_FCU&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_currentPower 7.15 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04 name=&#039;_Brunnen&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05 name=&#039;_Zisterne&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06 name=&#039;SW Trockner&#039; state=&#039;unknown&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_stop 14.01.2025 08:30:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07 name=&#039;SW Urlaubslicht-Wohnzimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;noSchedule&#039; info=&#039;von extern umgeschaltet&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 nextCycletime 18:54:09&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 pvCorrectionFactor_10 0.53 (automatic - old factor: 1.00, Sun Alt range: 5, Cloud range: 75, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 pvCorrectionFactor_11 0.56 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 70, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 pvCorrectionFactor_12 0.64 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 pvCorrectionFactor_13 0.88 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 pvCorrectionFactor_14 1.10 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 50, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 pvCorrectionFactor_15 1.01 (automatic - old factor: 1.06, Sun Alt range: 15, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 pvCorrectionFactor_16 1.09 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 45, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 pvCorrectionFactor_17 0.28 (automatic - old factor: 0.52, Sun Alt range: 0, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 pvCorrectionFactor_Auto on_complex_ai&lt;br /&gt;
setstate Forecast 2024-10-30 19:42:19 setupStringAzimuth GarageSE=-55 GarageNW=125 HausNW=125 HausSW=35 HausSE1=-55 HausSE2=-55&lt;br /&gt;
setstate Forecast 2024-10-30 19:37:38 setupStringDeclination GarageSE=40 GarageNW=40 HausNW=50 HausSW=50 HausSE1=50 HausSE2=50&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerIn_Sum 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerOut_Sum 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunHours_Remain 0.00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunMinutes_Remain 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_allStringsFullfilled 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_conForecastTillNextSunrise 9467 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentAPIinterval 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_01 132 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_02 184 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_03 329512 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_04 200 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_05 27 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_06 193 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_07 106 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_dayAfterTomorrowPVforecast 7344 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_01 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_02 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_time 2025-01-13 18:53:54&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_timestamp 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_response_message success&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_01 545.94 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_02 382.10 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_03 1430.13 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_04 262.05 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_05 28.80 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_06 622.63 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_07 276.51 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeCentralTask 0.3744&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIAnswer -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIProc -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeTrainAI 1.2529&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_01 3683.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_02 1617.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_01 2287.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_02 1057.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConForecastTillSunset 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 special_todayConsumptionForecast_01 509 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 special_todayConsumptionForecast_02 499 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 special_todayConsumptionForecast_03 501 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 special_todayConsumptionForecast_04 511 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 special_todayConsumptionForecast_05 503 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 special_todayConsumptionForecast_06 495 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 special_todayConsumptionForecast_07 504 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 special_todayConsumptionForecast_08 561 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 special_todayConsumptionForecast_09 768 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 special_todayConsumptionForecast_10 783 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 special_todayConsumptionForecast_11 692 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 special_todayConsumptionForecast_12 791 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 special_todayConsumptionForecast_13 910 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 special_todayConsumptionForecast_14 1022 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 special_todayConsumptionForecast_15 965 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 special_todayConsumptionForecast_16 812 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 special_todayConsumptionForecast_17 884 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 special_todayConsumptionForecast_18 928 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_19 874 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_20 763 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_21 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_22 765 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_23 643 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_24 601 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIcalls 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIrequests 4532&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridConsumption 5500.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridFeedIn 178.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayMaxAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIrequests n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 state updated&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So sollte es dann als Ergebnis aussehen:&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13.png|zentriert|mini|Ergebnis nach kompletter Einrichtung]]&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13 Teil II.png|alternativtext=Unterer Teil der Anzeige|zentriert|mini]]&lt;br /&gt;
&lt;br /&gt;
== Praxisbeispiele und Lösungsansätze für Steuerungen ==&lt;br /&gt;
=== Fallstudie: Trockner darf pausiert werden, wenn nicht genug PV-Überschuss vorhanden ist, soll aber nach spätestens X Stunden fertig sein ===&lt;br /&gt;
Für diese Aufgabenstellung sind mehrere Schlüssel essentiell wichtig, &#039;&#039;&#039;power&#039;&#039;&#039;, &#039;&#039;&#039;mintime&#039;&#039;&#039;, &#039;&#039;&#039;mode&#039;&#039;&#039; und &#039;&#039;&#039;interruptable&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Die Bedingung, dass der Trockner nach spätestens X Stunden fertig sein soll, steht in einem Widerspruch zu der Möglichkeit den Trockner bei zu wenig PV-Überschuss unterbrechen zu können. Im Extremfall könnte nach dem Start die gesamte Planungszeit ungenügender Überschuss vorliegen und der Trockner nicht arbeiten. Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; (in Minuten) wird nun wie folgt angesetzt:&lt;br /&gt;
&lt;br /&gt;
 mintime = 2,5 x &amp;lt;gewöhnliche Betriebszeit für einen Trockengang (mneed, z.B. 120)&amp;gt; = 300 Minuten&lt;br /&gt;
&lt;br /&gt;
Das bedeutet, der Trockner wird nach 300 Minuten Laufzeit abgeschaltet werden bzw. vom Netz getrennt. Der Trockenvorgang wird natürlich bereits nach 120 Minuten beendet sein, sofern nach Start keine Unterbrechnung des Vorganges erfolgte. Wurde der Vorgang unterbrochen, soll der Trockner innerhalb &lt;br /&gt;
&lt;br /&gt;
 X+120 bis X+300 &lt;br /&gt;
&lt;br /&gt;
fertig sein. &lt;br /&gt;
&lt;br /&gt;
Demnach ist die ausgeführte Laufzeit des Trockners permanent zu überwachen, zu summieren (rtsum) und die notwendige Restzeit (mneed - rtsum) mit der noch verbleibenden Restzeit (mrest) bis zur geplanten Abschaltung des Consumers zu vergleichen. Ist der Consumer gestartet, wird die Laufzeit in der pvHistory für jede Stunde des Tages im Schlüssel &#039;&#039;minutescsmXX&#039;&#039; (XX = Consumernummer) aufgezeichnet und kann darüber ausgewertet werden. Somit ist:&lt;br /&gt;
&lt;br /&gt;
 msum = for (01 .. 24) {Summe von minutescsmXX} des aktuellen Tages&lt;br /&gt;
&lt;br /&gt;
Solange die Bedingung &lt;br /&gt;
&lt;br /&gt;
 mrest &amp;gt;= (mneed - msum)&lt;br /&gt;
&lt;br /&gt;
zutrifft, darf der Trockner unterbrochen werden, anderenfalls darf er nicht mehr unterbrochen werden da die Restzeit evtl. nicht ausreichen könnte um den Vorgang abzuschließen. Für die Planung des Trockners wird der Consumer wie gewöhnlich nach dem Bedarf im Modul registriert. Für die Steuerung der Unterbrechbarkeit wird noch ein Code erstellt, welcher im Trockner-Device &#039;&#039;Dryerdev&#039;&#039; das Reading &#039;&#039;SF_Int&#039;&#039; zur Unterbrechnungssteuerung verwaltet. Dieses Reading wird dem Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; übergeben. Für das Beispiel wird der Consumer &#039;07&#039; verwendet, es kann natürlich jede andere freie Nummer verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Dryerdev:Trockner&lt;br /&gt;
                        icon=scene_cloves_dryer type=dryer power=2000 mode=must mintime=300 &lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic asynchron=1&lt;br /&gt;
                        interruptable=Dryerdev:SF_Int:1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Kombination &#039;&#039;&#039;auto=automatic&#039;&#039;&#039; eröffnet die Möglickeit, in der Consumer-Legende den Trockner-Start zusätzlich manuell freizugeben oder zu verbieten. &lt;br /&gt;
&lt;br /&gt;
Im nachfolgenden Code werden modulinterne Subroutinen verwendet. Diese sind inklusive dem Paket &#039;&#039;FHEM::SolarForecast::&#039;&#039; anzugeben. Die erstellte Subroutine wird in die 99_mySolarForecastUtils.pm eingefügt. Die Datei 99_mySolarForecastUtils.pm wird vorher von 99_myUtils.pm kopiert und enthält für die Übersichtlichkeit nur Routinen für SolarForecast.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Trocknersteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub dryControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # gewöhlich benötigte Zeit für &lt;br /&gt;
                                                                                  # einen Trockengang, z.B. 120 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $dryer     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename des Trockners&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Trockner-Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit des Trockners&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      my $dhash = $defs{$dryer};&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 1, 0);                        # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 0, 0);                        # keine Interrupt-Freigabe&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die gewöhnliche Laufzeit des Trockners für einen Trockenvorgang (120 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::dryControl ($name, &#039;07&#039;, 120);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Fallstudie: Umwälzpumpe Pool soll X Stunden am Tag laufen. Ist kein PV-Überschuß vorhanden, müssen die X Stunden/Tag trotzdem erreicht werden ===&lt;br /&gt;
&lt;br /&gt;
Die Vorgehensweise ähnelt der Fallstudie zuvor. Verändernd kommt hinzu, dass der Planungszeitraum bewusst sehr lang angesetzt wird mit der Option, den Zyklus des Consumers vorfristig zu beenden sobald die Laufzeit von X Stunden am Tag erreicht ist. &lt;br /&gt;
Im folgenden Beispiel soll die Pumpe 5 Stunden am Tag (300 Minuten) laufen und dabei mögliche PV-Überschüsse ausnutzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Pump:Zirkulationspumpe&lt;br /&gt;
                        icon=sani_pump type=other power=50 mode=must mintime=780 notafter=09&lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic &lt;br /&gt;
                        interruptable=1 swoffcond=Pump:SF_Abort:1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit dieser Registrierung wird die Pumpe ca. 09 Uhr täglich starten. Wenn kein bzw. ungenügender PV-Überschuß vorhanden ist, erfolgt eine Unterbrechung nach dem Start. Ist genügender PV-Überschuß (wieder) vorhanden, erfolgt keine Unterbrechnung (mehr). Zusätzlich wird über den Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; eine vorfristige Beendigung veranlasst, sobald die gewünschte Tageslaufzeit erreicht ist.&lt;br /&gt;
&lt;br /&gt;
Zur Verwaltung des Schlüssels &#039;&#039;interruptable&#039;&#039; und des Readings &#039;&#039;SF_Abort&#039;&#039; verwenden wir eine leicht veränderte Subroutine aus dem vorhergehenden Fallbeispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Pumpensteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub pumpControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # Soll-Pumpenzeit, z.B. 300 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $pump      = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename der Pumpe&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;);&lt;br /&gt;
  my $intbl     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;interruptable&#039;, 1); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
  my $dhash     = $defs{$pump};&lt;br /&gt;
&lt;br /&gt;
  readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 0, 0);                                # default keine Zyklusbeendigung&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Pumpen Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit der Pumpe&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
     &lt;br /&gt;
      if ($msum &amp;gt;= $mneed) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 1, 0);                       # vorfristige Zyklusbeendigung&lt;br /&gt;
          return;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=1&amp;quot;) if(!$intbl);  # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=0&amp;quot;) if($intbl);   # keine Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Befehl &#039;&#039;attrKeyVal&#039;&#039; setzt den Schlüssel &#039;&#039;interruptable&#039;&#039; im Attribut &#039;&#039;consumer07&#039;&#039; dynamisch. Diese Strukturänderung wird automatisch im System gespeichert, sofern &#039;&#039;global-&amp;gt;autosave=1&#039;&#039; gesetzt ist. Diese Einstellung ist der FHEM default.  &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die Mindestlaufzeit der Umwälzpumpe (300 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::pumpControl ($name, &#039;07&#039;, 300);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamische Ladestromsteuerung eines Victron MultiPlus II Chargers mit Pylontech Batterie ===&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;
&lt;br /&gt;
 set &amp;lt;Device&amp;gt; MaxChargeCurrent &amp;lt;Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
eingestellt bzw. variiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Modul bietet dem Nutzer die Möglichkeit in dem Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltene Code wird am Ende jedes Zyklus (siehe Attribut &#039;&#039;plantControl-&amp;gt;cycleInterval&#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;
&lt;br /&gt;
&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 $mppt1   = &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common&#039;;              # SmartLoader Device&lt;br /&gt;
  my $maxcspc = 105;                        # max. Ladesollstrom (A) nominal&lt;br /&gt;
  my $spcorr  = 0.9;                        # Korrekturfaktor Überschuss 90%&lt;br /&gt;
  my $sch     = 0.25;                       # Verkürzungsfaktor Zeit bis Vollladung vor Sunset             &lt;br /&gt;
  &lt;br /&gt;
  my $cclvl0  = 15;                         # Ladestrom Level 0 max. 5  A (240 W) pro WR  (720  W)&lt;br /&gt;
  my $cclvl1  = 27;                         # Ladestrom Level 1 max. 9  A (432 W) pro WR  (1296 W)&lt;br /&gt;
  my $cclvl2  = 54;                         # Ladestrom Level 2 max. 18 A (864 W) pro WR  (2592 W)&lt;br /&gt;
  my $cclvl3  = 81;                         # Ladestrom Level 3 max. 27 A (1296 W) pro WR (3888 W)&lt;br /&gt;
  ###############&lt;br /&gt;
  &lt;br /&gt;
  my $cofc   = ReadingsNum ($name,  &#039;special_todayConForecastTillSunset&#039;, 0);&lt;br /&gt;
  my $pvfc   = ReadingsNum ($name,  &#039;RestOfDayPVforecast&#039;, 0);&lt;br /&gt;
  my $cpv    = ReadingsNum ($name,  &#039;Current_PV&#039;,          0);&lt;br /&gt;
  my $mppt1c = ReadingsNum ($mppt1, &#039;DC_0_Current_value&#039;,  0);             # Load I MPPT1 (max. 44 A)&lt;br /&gt;
  my $ssts   = CurrentVal  ($hash,  &#039;sunsetTodayTs&#039;,        0);&lt;br /&gt;
  my $srts   = CurrentVal  ($hash,  &#039;sunriseTodayTs&#039;,       0);&lt;br /&gt;
  my $sdiff  = ($ssts - $srts) / 3600;                                     # Sonnengang heute in h &lt;br /&gt;
  &lt;br /&gt;
  my $solh   = ReadingsNum ($name, &#039;special_SunHours_Remain&#039;, 0);          # h bis SunSet&lt;br /&gt;
  $solh      = $solh - ($sdiff * $sch);                                    # h bis SunSet - X&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;              # Ah Bat bis SOC&lt;br /&gt;
  $ahrem     = sprintf &amp;quot;%.0f&amp;quot;, $ahrem;&lt;br /&gt;
  &lt;br /&gt;
  my $fcdiff = ($pvfc - $cofc) * $spcorr;     # Korrektur d. noch prognostizierten Überschussenergie &lt;br /&gt;
  $fcdiff    = $fcdiff &amp;lt; 0 ? 0 : $fcdiff;     # Wh&lt;br /&gt;
  &lt;br /&gt;
  my $loadcur = $maxcspc;&lt;br /&gt;
  &lt;br /&gt;
  if ($cpv &amp;amp;&amp;amp; $solh &amp;amp;&amp;amp; $ahrem &amp;amp;&amp;amp; $fcdiff &amp;gt; $ahrem) {  # Ladeanforderung und Überschuss übersteigt &lt;br /&gt;
                                                      # Lademenge&lt;br /&gt;
      my $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($ahrem / $solh);    # A = Ah / h -&amp;gt; A Soll Schätzung&lt;br /&gt;
&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Battery charging process should be completed }.&lt;br /&gt;
                      qq{in &amp;gt;$solh&amp;lt; hours});&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; raw Target charging current: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($cspc - $mppt1c);      # SmartLoader IST berücksichtigen&lt;br /&gt;
	  &lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Charge Current minus MPPT load Current &amp;gt;$mppt1c&amp;lt;: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $loadcur = $cspc &amp;lt;= 0       ? 0       :     # nur MPPT Ladung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl0 ? $cclvl0 :     # Übergangsbereich&lt;br /&gt;
                 $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;
	  Log3 ($name, 3, qq{$name - userFn -&amp;gt; MaxChargeCurrent calculated: $loadcur});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent&#039;,       $loadcur.&#039; A&#039;,          1);&lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_HoursUntilChargeFinish&#039;, sprintf (&amp;quot;%.2f&amp;quot;,$solh), 1);&lt;br /&gt;
  CommandSet           (undef, &amp;quot;$vebus MaxChargeCurrent $loadcur&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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. 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;special_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;special_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;Verkürzungsfaktor Zeit bis Vollladung vor Sunset&#039;&#039;) reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche mindest Ladestromstärke ermittelt.&lt;br /&gt;
&lt;br /&gt;
&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 auch während der MQTT Intergration 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;
=== Poolheizung in Abhängigkeit von vorhandenem Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren) ===&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;consumer01&#039;&#039; wird beispielhaft wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr Forecast consumer01 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;&lt;br /&gt;
&lt;br /&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. &lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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, einen 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 Überschuss 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;. &lt;br /&gt;
&lt;br /&gt;
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;
=== PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) ===&lt;br /&gt;
[[Datei:Screenshot 2025-08-04 104835.png|mini|Darstellung der PV-Vorhersage in evcc auf Basis der SolarForecast-Daten]]&lt;br /&gt;
[https://evcc.io evcc] ist ein Energie-Management-System, mit dem u.a. Überschussladen von Elektroautos möglich ist. Hier ist beschreiben, wie die SolarForecast-Vorhersagedaten per API von evcc abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
Lege im SolarForecast-Device ein User-Reading mit dem Namen forecast_json an. Es wandelt die Forecast-Werte in JSON und ins UTC-Zeitformat um, so dass evcc die Daten verwenden kann:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
forecast_json {&lt;br /&gt;
&lt;br /&gt;
    use strict;&lt;br /&gt;
    use warnings;&lt;br /&gt;
    use JSON;&lt;br /&gt;
    use DateTime;&lt;br /&gt;
    use DateTime::Format::Strptime;&lt;br /&gt;
&lt;br /&gt;
    my $hour = 0;&lt;br /&gt;
    my @output;&lt;br /&gt;
&lt;br /&gt;
    # Parser für Datum mit CET/CEST&lt;br /&gt;
    my $parser = DateTime::Format::Strptime-&amp;gt;new(&lt;br /&gt;
        pattern   =&amp;gt; &#039;%Y-%m-%d %H:%M:%S&#039;,&lt;br /&gt;
        time_zone =&amp;gt; &#039;Europe/Berlin&#039;,&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    # Alle NextHour-Daten durchsuchen&lt;br /&gt;
    while ($hour &amp;lt; 100) {&lt;br /&gt;
        my $hour_str = sprintf(&#039;NextHour%02d&#039;, $hour);&lt;br /&gt;
        my $start_str = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;starttime&#039;, &#039;na&#039;); &lt;br /&gt;
        my $pvfc = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;pvfc&#039;, &#039;na&#039;);&lt;br /&gt;
&lt;br /&gt;
        # Schleife beenden, wenn keine Werte mehr vorhanden sind&lt;br /&gt;
        last if $start_str eq &#039;na&#039; or $pvfc eq &#039;na&#039;;&lt;br /&gt;
&lt;br /&gt;
        # parse und konvertiere Zeit&lt;br /&gt;
        my $start_dt = $parser-&amp;gt;parse_datetime($start_str);&lt;br /&gt;
        my $end_dt   = $start_dt-&amp;gt;clone-&amp;gt;add(hours =&amp;gt; 1);&lt;br /&gt;
&lt;br /&gt;
        # nach UTC konvertieren&lt;br /&gt;
        $start_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
        $end_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $start_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            end   =&amp;gt; $end_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            value =&amp;gt; 0 + $pvfc,&lt;br /&gt;
        };&lt;br /&gt;
        &lt;br /&gt;
        $hour++;&lt;br /&gt;
    }  &lt;br /&gt;
&lt;br /&gt;
    # Ausgabe als JSON&lt;br /&gt;
    my $json = JSON-&amp;gt;new-&amp;gt;utf8-&amp;gt;pretty-&amp;gt;encode(\@output);&lt;br /&gt;
    return $json;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Kommunikation läuft über den integrierten FHEM-Webserver, der die JSON-Daten aus dem Reading forecast_json veröffentlicht. Dazu wird in FHEM eine separate Webinstanz auf einem neuen Port erstellt, die ohne [[CsrfToken-HowTo|CSFR-Token]] (Achtung, Auswirkungen auf die Sicherheit beachten!) und nur von localhost aufrufbar ist (Voraussetzung: evcc läuft auf derselben Maschine wie FHEM):&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
defmod WEBapi FHEMWEB 8089&lt;br /&gt;
attr WEBapi csrfToken none&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;In der [https://docs.evcc.io/docs/tariffs#pv-vorhersage evcc-Konfig unter tariffs] steht die Quelle für die Solar-Vorhersage. Der FHEM-Befehl {ReadingsVal(&#039;solarforecast_dev&#039;,&#039;forecast_json&#039;,&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;)} wird encoded und in die uri eingetragen. Trage statt solarforecast_dev den passenden Namen deines SolarForecast-Device ein. evcc holt die Daten aus dem Reading forecast_json dann regelmäßig ab.&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
solar:&lt;br /&gt;
  type: custom&lt;br /&gt;
  interval: 20m    &lt;br /&gt;
  forecast:&lt;br /&gt;
    source: http&lt;br /&gt;
    uri: http://localhost:8089/fhem?cmd=%7BReadingsVal%28%27solarforecast_dev%27%2C%27forecast_json%27%2C%27%27%29%7D&amp;amp;XHR=1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Zur Verbesserung der Sicherheit kann das neue WEBapi Device auch ein [[CsrfToken-HowTo#csrfToken festlegen|festes CSFR-Token]] verwenden. Dieses Token muss dann in der evcc-Konfiguration an die uri mittels &amp;amp;fwcsrf=&amp;lt;festes token&amp;gt; angehängt werden.&lt;br /&gt;
&lt;br /&gt;
== weiterführende Links ==&lt;br /&gt;
* Forenthema &amp;quot;{{Link2Forum|Topic=137058|LinkText=76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support}}&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;
* Photovoltaik Ingenieurbüro Junge: https://www.ing-büro-junge.de/html/photovoltaik.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung&amp;diff=40305</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=40305"/>
		<updated>2025-08-04T15:23:42Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Hinweis|Die vorliegende Wiki-Seite befindet sich im Aufbau.}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Solarprognose und Verbrauchersteuerung&lt;br /&gt;
|ModType=d&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 Prognosewerte können die SolCast API, OpenMeteo API, Forecast.Solar API, Victron VRM Portal API oder alternativ DWD Stahlungswerte-Stationen verwendet werden&lt;br /&gt;
&lt;br /&gt;
::* optionale KI Unterstützung der PV-Prognose bei Verwendung von geeigneten Solar-API&#039;s&lt;br /&gt;
&lt;br /&gt;
::* es wird sowohl die Erzeugungsprognose als auch eine Verbrauchsprognose sowie SoC Prognose (bei Batterie-Integration) erstellt&lt;br /&gt;
&lt;br /&gt;
::* Wetterdaten werden über DWD Wetter-Stationen oder verschiedene API integriert. Es können verschiedene API zur Gewinnung von Solar- und Wetterdaten kombiniert werden. &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 FHEM-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 Integration von bis zu 4 Inverter und Smartloader (DC-DC Batterieladegeräte) ist möglich&lt;br /&gt;
&lt;br /&gt;
::* eine Integration von bis zu 3 nicht PV-Energieerzeugern wie BHKW, Windrädern oder Notstromaggregaten ist möglich&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;
::* Einbindung von bis zu drei Batteriespeichersystemen&lt;br /&gt;
&lt;br /&gt;
::* Bereitstellung von Leitwerten zur optimalen Einstellung/Steuerung von Batteriespeichersystemen&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 Benutzererlebnis 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;
Das Wiki gibt allgemeingültige und teilweise sehr spezifische bzw. tiefgehende Informationen und Handlungsempfehlungen zum SolarForecast Modul. Die dargestellten Informationen beziehen sich auf den zum Zeitpunkt der Wiki-Erstellung vorhandenen Entwicklungsstand des Moduls. Durch die stetige Weiterentwicklung können sich Abweichungen zum beschriebenen Inhalt ergeben oder zur Obsoleszenz dieser Inhalte führen. &lt;br /&gt;
&lt;br /&gt;
Vergleiche deshalb die Informationen immer mit der aktuellen Befehls-Referenz zum Modul!&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Ein SolarForecast Device wird mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 define &amp;lt;Name&amp;gt; SolarForecast &lt;br /&gt;
&lt;br /&gt;
angelegt. Nach der Definition wird der User durch einen Dialog geführt, der einige unerlässliche Einstellungen abfragt und in den entsprechenden Attributen und Readings persistiert. Alle Attribute und Readings die eine Einstellung der Anlage bewirken, sind mit dem Präfix &amp;quot;setup&amp;quot; versehen. &lt;br /&gt;
&lt;br /&gt;
Die Verwendung von setup-Readings gestattet es die Anlagenparameter dynamisch im Betrieb zu verändern. So kann mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringAzimuth   bzw.&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringDeclination &lt;br /&gt;
&lt;br /&gt;
die Ausrichtung und der Neigungswinkel der PV-Module ständig angepasst werden, was zum Beispiel bei einer dem Sonnenstand nachgeführten Anlage von Bedeutung ist.&lt;br /&gt;
&lt;br /&gt;
Die abgefragten Einstellungen während des Dialoges sind ausführlich in den entsprechenden Attributen bzw. Set-Kommandos erläutert. Die benötigten Informationen sind anhängig von der gewählten Prognose-API und können im Umfang variieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 213257.png|right|thumb|400px|Anlagenprüfung über Drucktaste in der Kopfgrafik]]&lt;br /&gt;
&lt;br /&gt;
Sobald alle verlangten Einstellungen vorgenommen sind, sollte eine Anlagenprüfung mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; plantConfiguration check&lt;br /&gt;
&lt;br /&gt;
oder über die angebotene Drucktaste in der Grafik durchgeführt werden. Es wird eine Plausibilitätsprüfung vorgenommen und das Ergebnis sowie eventuelle Hinweise bzw. Fehler ausgegeben.&lt;br /&gt;
Die Prüfung kann beliebig wiederholt werden und sollte sich bei jeder Einstellungsänderung der Anlage durchgeführt werden. Dadurch wird die Wahrscheinlichkeit von fehlerhaften Einstellungen minimiert.&lt;br /&gt;
&lt;br /&gt;
Neben den grundlegenden Einstellungen können im Device weitere sekundäre Anlagenkomponenten wie Batteriesystem(e) (Attribut setupBatteryDev1 - setupBatteryDev3), weitere Wetter-Devices (Attribut setupWeatherDev1 - setupWeatherDev3) oder sonstige Erzeuger (z.B. BHKW, Winderzeugung, Notstromaggregat) integriert werden (Attribut setupOtherProducer01 - setupOtherProducer03).&lt;br /&gt;
&lt;br /&gt;
Die verlangten Parameter der Anlage werden in der Online-Hilfe umfassend beschrieben und deren Funktion erschließt sich zum größten Teil selbst. Dennoch soll nachfolgend auf einige Punkte im Zusammenhang der Einrichtung eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Hinweise zur Struktur der Attribute ===&lt;br /&gt;
&lt;br /&gt;
Durch die umfangreichen Funktionen des Moduls würde bei Nutzung der im FHEM herkömmlich vorhandenen Attributstruktur die Anzahl der benötigten Attribute extrem stark steigen und nicht sinnvoll genutzt werden können. Deshalb gibt es neben den &#039;&#039;gewöhnlichen&#039;&#039; Attributen mit einfachen Werteauswahlmöglichkeiten oder Eingaben (z.B. ctrlDebug, ctrlSpecialReadings) sogenannte &#039;&#039;zusammengesetzte&#039;&#039; Attribute, deren Inhalt durch &#039;&#039;&#039;Schlüssel=Wert Paare&#039;&#039;&#039; gebildet wird und dadurch deutlich mehr Funktionen und Informationen transportieren als ein gewöhnliches Attribut.&lt;br /&gt;
&lt;br /&gt;
Für zusammengesetzte Attribute besteht die zusätzliche Möglichkeit, gewünschte Änderungen der Schlüssel=Wert Paare selektiv vornehmen zu können, ohne das gesamte Attribut aufrufen und ändern zu müssen. Die Vorgang, der vor allem für programmtechnische Manipulationen gedacht ist, kann durch eine Set-Funktion ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; attrKeyVal &amp;lt;Attribut&amp;gt; [&amp;lt;Gerät&amp;gt;] &amp;lt;Schlüssel=Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiele für zusammengesetzte Attribute sind:&lt;br /&gt;
&lt;br /&gt;
* aiControl&lt;br /&gt;
* plantControl&lt;br /&gt;
* setup* Attribute&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktionen der Attribute werden durch einen Präfix geclustert und so inhaltlich, aber vor allem auch in der Attribute Drop-Down Liste, strukturiert dargestellt.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der &#039;&#039;&#039;Präfixe&#039;&#039;&#039; sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ai&#039;&#039;&#039; - Steuerungsfunktionen für KI (z.B. aiControl)&lt;br /&gt;
* &#039;&#039;&#039;consumer&#039;&#039;&#039; - Registrierung und Einstellungen für Verbraucher (z.B. consumer02, consumerControl)&lt;br /&gt;
* &#039;&#039;&#039;ctrl&#039;&#039;&#039; - Steuerungsfunktion allgemeiner Art (z.B. ctrlDebug, ctrlSpecialReadings, ctrlUserExitFn)&lt;br /&gt;
* &#039;&#039;&#039;flowGraphic&#039;&#039;&#039; - Einstellungen für die Energieflußgrafik (z.B. flowGraphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphic&#039;&#039;&#039; - Einstellung für die Grafik allgemein (z.B. graphicSelect, graphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphicBeam&#039;&#039;&#039; -  Einstellungen bestimmte Balkeneigenschaften in der Balkengrafik (z.B. graphicBeamHeightLevel1)&lt;br /&gt;
* &#039;&#039;&#039;plant&#039;&#039;&#039; - übergreifende Einstellungen betreffend der gesamten PV-Anlage bzw. des SolarForecast-Devices (z.B. plantControl)&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039; - Registrierung von Geräten in der Gesamtanlage und Einstellung deren Eigenschaften (Inverter, Zähler, Batterien usw.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Einrichtung der Wechselrichter mit setupInverterDevXX ===&lt;br /&gt;
&lt;br /&gt;
Mit den Attributen setupInverterDev01 bis setupInverterDevXX werden die vorhandenen Wechselrichter der Anlage registriert.&lt;br /&gt;
Das Modul unterscheidet verschiedene Wechselrichter-Typen, die sich durch ihre Arbeitsweise innerhalb der Anlage unterscheiden. Die Schlüssel=Wert Paare in den Attributen können mehrzeilig organisiert werden. Das erleichtert die Übersicht wenn viele dieser Parameter eingegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;PV-Wechselrichter: Es ist der Standard Wechselrichter in einer PV-Anlage. An ihn sind die Solarzellen bzw. Strings angeschlossen. Die zugeordneten Strings können mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ohne diese Angabe werden diesem Gerät alle definierten Strings (siehe Attribut &#039;&#039;setupInverterStrings&#039;&#039;) zugeordnet. Der Wechselrichter liefert seine Energie in das Hausnetz. Alternativ kann mit der Angabe &#039;&#039;&#039;feed=grid&#039;&#039;&#039; die Funktion des Wechselrichters geändert werden. Diese Angabe sagt aus, dass dieser Wechselrichter ausschließlich in das öffentliche Netz einspeist.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel-Setup eines PV-Wechselrichters (SMA STP):&lt;br /&gt;
&lt;br /&gt;
 STP_5000 pvIn=string_1_pdc:kW pvOut=total_pac:kW etotal=etotal:kWh capacity=5000 strings=Süddach asynchron=1 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Solar-Ladegeräte: Solar-Ladegeräte sind DC-DC Wandler und liefern die Energie der angeschlossenen Solarzellen nicht in das Wechselstromnetz, sondern laden direkt eine Batterie bzw. versorgen einen Batteriewechselrichter auf der Gleichstromseite. Die Funktion als Solar-Ladegerät wird mit &#039;&#039;&#039;feed=bat&#039;&#039;&#039; aktiviert, die relevanten Strings können ebenfalls mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ein Beispiel eines Solar-Ladegerätes ist ein Victron SmartSolar MPPT. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel für das Setup eines Solar-Ladegeräts (SmartSolar Charger MPPT):&lt;br /&gt;
&lt;br /&gt;
 MQTT2_cerboGX_c0619ab34e08_solarcharger_Common pv=Yield_Power_value:W etotal=Yield_System_value:kWh capacity=2080 strings=Schleppdach feed=bat synchron=0 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Batterie-Wechselrichter: Dieses Gerät hat keine angeschlossenen Solarzellen und arbeitet als DC-AC bzw. AC-DC Wandler zwischen einer Batterie (=Gleichstromquelle) und dem Wechselstrom-Hausnetz. Die Funktion als Batterie-Wechselrichter wird mit der Angabe &#039;&#039;&#039;strings=none&#039;&#039;&#039; aktiviert. Die Schlüssel &#039;&#039;etotal&#039;&#039; und &#039;&#039;pv&#039;&#039; können bei einem Batterie-Wechselrichter ohne zugeordnete Solarzellen nicht gesetzt werden. Ein Beispiel eines Batterie-Wechselrichter ist der Victron MultiPlus II.&lt;br /&gt;
&lt;br /&gt;
Ein Setup-Beispiel für einen Batterie-Wechselrichter (Victron MultiPlus II):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dc2ac=DC_IN:W&lt;br /&gt;
ac2dc=DC_OUT:W&lt;br /&gt;
capacity=7200&lt;br /&gt;
strings=none&lt;br /&gt;
icon=inverter@darkorange:inverter@grey&lt;br /&gt;
asynchron=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Eigenschaften des Wechselrichters werden durch eine Reihe von &amp;lt;Schlüssel=Wert&amp;gt; Paaren festgelegt. Auf einige dieser Paramter soll hier eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Ausgewählte Schlüssel=Wert Paare ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;pvIn=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvIn&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell zugeführte PV-Leistung bereitstellt. Der Schlüssel ist optional und dient in erster Linie dazu den entsprechenden Input-Wert in der Flußgrafik anzuzeigen sofern man das Attribut flowGraphicControl-&amp;gt;showGenerators=1 setzt. Dadurch ist auch der Eigenverbrauch des Inverters bzw. dessen Wandlungsverlust visuell abschätzbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pvOut=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvOut&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell erzeugte Leistung als positiven Wert liefert. Für einen PV-Wechselrichter (DC-&amp;gt;AC) oder Solar-Ladegerät (DC-&amp;gt;DC) ist es die erzeugte PV-Leistung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ac2dc=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter vom Hausnetz in Richtung Batterie (AC-&amp;gt;DC) wandelt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;dc2ac=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter aus einer Gleichstromquelle, d.h. einer Batterie oder einem Solar-Ladegerät, in Richtung des Hausnetzes (AC) wandelt . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;capacity=&amp;lt;max. WR-Leistung&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In dem Schlüssel &#039;&#039;capacity&#039;&#039; wird die maximal mögliche Leistung in Watt (ohne Einheit) angegeben, die der Wechselrichter lt. seinem Datenblatt in der Lage ist zu leisten. &lt;br /&gt;
&lt;br /&gt;
Die Angabe &#039;&#039;capacity&#039;&#039; hat in erster Linie die Aufgabe, die max. mögliche PV-Leistung für die Prognose zu begrenzen. Oft sind die installierten Peak-Leistungen der PV-Module höher als die angeschlossene Wechselrichter-Leistung bzw. kommt es vor, dass die KI / (korrigierte) API-Prognose über der maximal möglichen Wechselrichter-Leistung liegt. In diesen Fällen wird die Prognose auf die angegebene &#039;&#039;capacity&#039;&#039; begrenzt.&lt;br /&gt;
&lt;br /&gt;
Der Wert in diesem Schlüssel kann, wie andere Schlüssel auch, dynamisch zur Laufzeit mit dem Set-Befehl &amp;quot;[[#Hinweise zur Struktur der Attribute|set &amp;lt;Name&amp;gt; attrKeyVal ...]]&amp;quot; geändert werden. Ein Beispiel zur Anwendung ergibt sich aus folgendem Szenario.&lt;br /&gt;
&lt;br /&gt;
Gegeben sei eine Anlage die aus Solarzellen (1300 W Peak) mit einem Solar-Ladegerät mit max. 1800 W Leistung, einer Batterie und einem Batterie-Wechselrichter besteht. Die Anlage versorgt nur das Hausnetz. Eine Netzeinspeisung ist nicht vorgesehen oder nicht erlaubt.  &lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, es ist ein Tag voller Sonnenschein prognostiziert und die Batterie ist zunächst entladen. Der Haushalt verbraucht 300 W. Dann würden die PV-Module Module ihre volle Leistung von 1300 W Peak leisten können, die sich auch in der Balken-Vorhersage niederschlägt. Die Leistung wird nicht begrenzt, weil:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* sie niedriger ist als die nominale und angegebene Wechselrichter Kapazität von &#039;&#039;capacity=1800&#039;&#039;&lt;br /&gt;
* die erzeugte Energie anteilig für die Verorgung des Hauses und die Aufladung der Batterie verwendet wird&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders verhält es sich wenn nach einer gewissen Zeit die Batterie voll ist und weiterhin volle PV Leistung zur Verfügung steht. In diesem Fall würde der Haushalt seine benötigte Leistung von 300 W abnehmen, aber das Solar-Ladegerät kann keine weitere Leistung mehr abgeben, da die Batterie bereits voll geladen ist, d.h. die Anlagensteuerung würde die PV-Anlage abregeln. In diesem Fall, wenn es einen längeren Zeitraum betrifft, muß auch die Prognose PV-Energie auf 300 Wh (bzw. den durchschnittlichen Energieverbrauch des Hauses pro Stunde) begrenzt werden, damit die PV-Prognose nach unten angepasst wird und so eine realitätsnahere Prognose ermöglicht wird. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;icon=&amp;lt;aktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;][:&amp;lt;inaktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Jeder Wechselrichter wird im Standard durch ein Icon getrennt nach Tag und Nacht, d.h. je nach Aktiv-Status und Inaktiv-Status, symbolisiert.&lt;br /&gt;
&lt;br /&gt;
;Tag bzw. Aktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Sonnensymbol im Standard verwendet. Batterie-Wechselrichter verwenden ein gefärbtes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
;Nacht bzw. Inaktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Symbol der aktuellen Mondphasen im Standard verwendet. Batterie-Wechselrichter verwenden ein ausgegrautes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie angegeben, kann man für Tag und Nacht jeweils ein Wunsch-Icon, wenn gewünscht mit einer alternativen Färbung, auswählen.&lt;br /&gt;
&lt;br /&gt;
 icon=inverter@darkorange:inverter@gray&lt;br /&gt;
&lt;br /&gt;
Soll nur das Icon für die Nacht bzw. Inaktivät geändert werden, kann dies in dieser Form angegeben werden:&lt;br /&gt;
&lt;br /&gt;
 icon=:inverter@gray  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(beachte den führenden &#039;:&#039;)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Der integrierte SolarForecast Grafikbereich ==&lt;br /&gt;
Das SolarForecast Modul beinhaltet eine Grafikdarstellung die sich in mehrere Bereiche gliedert. Diese Bereiche können über Attribute ein- bzw. ausgeblendet sowie die Inhalte festgelegt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 223545.png|right|thumb|400px|Bereiche der integrierten Grafik]]&lt;br /&gt;
&lt;br /&gt;
Der nebenstehende Screenshot gibt die Gliederung der Grafikbereiche wieder:&lt;br /&gt;
&lt;br /&gt;
 1 - der Kopfbereich (Graphic Header)&lt;br /&gt;
 2 - durch den Nutzer selbst definierbarer Inhalt (Graphic Header Own Specification) als Teil des Kopfbereiches&lt;br /&gt;
 3 - Bereich Verbraucherdarstellung (Consumer Legend)&lt;br /&gt;
 4 - Bereich Balkengrafik (Beam Graphic)&lt;br /&gt;
 5 - Energieflußgrafik (Flow Graphic)&lt;br /&gt;
&lt;br /&gt;
Jeder dieser Bereiche hat spezifische Steuerungsattribute zur Anpassung des Verhaltens und ggf. des Inhalts.&lt;br /&gt;
&lt;br /&gt;
=== 1 - Der Grafik Kopfbereich ===&lt;br /&gt;
Im Kopfbereich befinden sich fest verankerte Informationen zur verwendeten Vorhersage-API sowie deren Status, Informationen zum Sonnenaufgang und Sonnenuntergang, dem aktuellen Gesamtstatus des SolarForecast Devices, Abweichungskennzahlen der PV Vorhersage sowie weitere Kennzeichen zur Verfügung.&lt;br /&gt;
Über zwei Drucktasten kann eine Anlagenprüfung durchgeführt und in den Spportthread des Moduls im FHEM Forum abgesprungen werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;graphicHeaderShow&#039;&#039;&#039; kann der gesamte Kopfbereich 1 und 2 (nutzereigener Teilbereich) ausgeblendet werden. Wird der Kopbereich ausgeblendet, ist es hilfreich mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;showLink&#039;&#039;&#039; einen Link zur Detailgrafik einzufügen da der in der Kopfgrafik integrierte Link in diesem Fall nicht mehr zur Verfügung steht. &lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;graphicHeaderDetail&#039;&#039;&#039; definiert welche Bereiche des Grafikkopfes angezeigt werden sollen. Es kann die Anzeige des Energieverbrauches, der PV-Erzeugung und der vom Nutzer selbst definierte Inhalt miteinander frei kombiniert werden.&lt;br /&gt;
&lt;br /&gt;
=== 2 - Der Bereich mit selbst definierbarem Inhalt (Graphic Header Own Specification) ===&lt;br /&gt;
In diesem Bereich kann der User beliebige Readings, Set-Kommandos und Attribute des SolarForecast Devices oder anderer Devices, die sich im gleichen FHEM-System wie das SolarForecast Device befinden, anzeigen lassen.&lt;br /&gt;
&lt;br /&gt;
Dieser Bereich ist als Tabelle mit einer beliebigen Anzahl von Zeilen organisiert. Jede Zeile beinhaltet ein Kommentarfeld und vier Nutzfelder zur Darstellung ausgewähler Werte + Label. Der Bereich bzw. der Inhalt des Bereiches wird mit dem Attribut &#039;&#039;&#039;graphicHeaderOwnspec&#039;&#039;&#039; definiert.  &lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt ein real gesetztes graphicHeaderOwnspec Attribut. Die Leerzeilen sind nicht notwendig, erhöhen aber die Lesbarkeit der Struktur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
Autarkierate:Current_AutarkyRate&lt;br /&gt;
PV&amp;amp;nbsp;übermorgen:special_dayAfterTomorrowPVforecast&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;Sunset:special_todayConForecastTillSunset&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;nächsten&amp;amp;nbsp;Sunrise:special_conForecastTillNextSunrise&lt;br /&gt;
&lt;br /&gt;
#Batterie&lt;br /&gt;
BatteryLive&amp;amp;nbsp;Status:userFn_BatLive_State&lt;br /&gt;
SoC&amp;amp;nbsp;Limit:Settings_CGwacs_BatteryLife_MinimumSocLimit_value@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SoC&amp;amp;nbsp;Ist:SOC_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
SOC&amp;amp;nbsp;Optimum:Battery_OptimumTargetSoC&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
aktuelle&amp;amp;nbsp;Ladung:userFn_Bat_EnergyState&lt;br /&gt;
Verfügbar:userFn_BatLive_UsableEnergy&lt;br /&gt;
benötigte&amp;amp;nbsp;Ladeenergie:userFn_Bat_EnergyRemain&lt;br /&gt;
Ladefreigabe:Battery_ChargeRecommended&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
akt.&amp;amp;nbsp;DC&amp;amp;nbsp;Strom:DC_Current_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
Restladezeit&amp;amp;nbsp;Ziel:userFn_Bat_HoursUntilChargeFinish&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Soll:userFn_Bat_MaxChargeCurrent_set&lt;br /&gt;
:&lt;br /&gt;
&lt;br /&gt;
#Settings&lt;br /&gt;
Batterie&amp;amp;nbsp;Lademanagement:userFn_BatteryChargeManagement&lt;br /&gt;
SoC&amp;amp;nbsp;Management:userFn_BatterySoCManagement&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Ist:MaxChargeCurrent@MQTT2_cerboGX_c0619ab34e08_vebus&lt;br /&gt;
SmartSolar&amp;lt;br&amp;gt;Einspeisung:OvervoltageFeedIn@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
MPII&amp;amp;nbsp;Limit&amp;lt;br&amp;gt;Einspeisung&amp;amp;nbsp;(W):MaxFeedInPower@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SOC&amp;amp;nbsp;Limit&amp;amp;nbsp;Soll:MinimumSocLimit@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Verbr.&amp;amp;nbsp;Neuplanung:consumerNewPlanning&lt;br /&gt;
Wetteranzeige:graphicShowWeather &lt;br /&gt;
&lt;br /&gt;
Anzeige&amp;amp;nbsp;Nachtstunden:graphicShowNight&lt;br /&gt;
hist.&amp;amp;nbsp;Stunden:graphicHistoryHour&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto&lt;br /&gt;
Victron&amp;amp;nbsp;BatteryLife&amp;lt;br&amp;gt;(1=an,10=aus):BatteryLife@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Debug:ctrlDebu&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Kommentarfeld am Beginn einer Zeile wird durch ein &#039;&#039;&#039;#&#039;&#039;&#039; gekennzeichnet. Folgt dem # ein String, wird dieser String als Kommentarangabe gewertet und in der Grafik ausgegeben. Ein leeres Kommentarfeld wird lediglich durch ein # gefolgt von einem Leerzeichen oder NL beschrieben:&lt;br /&gt;
&lt;br /&gt;
 #:&amp;lt;Text&amp;gt;  (bzw nur # für einen &#039;leeren&#039; Titel)&lt;br /&gt;
&lt;br /&gt;
Ein Netzfeld bzw. ein Datensatz wird durch die Angabe von einem Label und dem darzustellenden Wert getrennt durch &#039;:&#039; definiert:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Label&amp;gt;:&amp;lt;Reading, Attribut oder Set-Kommando&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das System erkennt selbständig, ob es sich bei der Angabe um ein Reading, Attribut oder ein Set-Kommando handelt. Sollen Readings, Set-Kommandos und Attribute anderer Devices als dem SolarForecast-Device angezeigt werden, kann dies einfach durch Zusatz von&lt;br /&gt;
&lt;br /&gt;
 ....@&amp;lt;Device-Name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
an den Parameter erreicht werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-12-05 203916.png|right|thumb|400px|Darstellung eigener Grafikbereich]]&lt;br /&gt;
Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten &amp;quot;Wh&amp;quot; bzw. &amp;quot;kWh&amp;quot; werden entsprechend der Einstellung des Attributs &#039;&#039;&#039;graphicEnergyUnit&#039;&#039;&#039; umgerechnet. Im Label sind Leerzeichen durch &amp;quot;&amp;amp;amp;nbsp;&amp;quot; einzufügen, ein Zeilenumbruch durch &amp;quot;&amp;amp;lt;br&amp;amp;gt;&amp;quot;. Ein leeres Feld in einer Zeile wird durch &amp;quot;:&amp;quot; ohne eine weitere Angabe erzeugt.&lt;br /&gt;
&lt;br /&gt;
Die nebenstehende Abbildung zeigt die reale Darstellung der oben angegebenen Struktur im Attribut graphicHeaderOwnspec.&lt;br /&gt;
&lt;br /&gt;
==== Formatierung der Inhalte im Bereich &amp;quot;Graphic Header Own Specification&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
Die angezeigten Inhalte, wie z.B. Readingwerte, des User eigenen Bereiches (Attribut graphicHeaderOwnspec) können durch Spezifikationen im Attribut &#039;&#039;&#039;graphicHeaderOwnspecValForm&#039;&#039;&#039; manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
Die Online-Hilfe zum Attribut graphicHeaderOwnspecValForm erläutert die verfügbaren Möglichkeiten und Optionen.&lt;br /&gt;
Als Beispiel hier einige mögliche Notationen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &#039;userFn_Bat_HoursUntilChargeFinish&#039;                        =&amp;gt; &amp;quot;($VALUE).&#039; Stunden&#039;&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_battery.SOC_value&#039;             =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Settings_CGwacs_BatteryLife_MinimumSocLimit_value&#039;        =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Info_MaxChargeCurrent_value&#039;                              =&amp;gt; &amp;quot;($VALUE).&#039; A&#039;&amp;quot;,&lt;br /&gt;
  &#039;DC_Current_value&#039;                                         =&amp;gt; &amp;quot;%.0f A&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common.Regulated&#039; =&amp;gt; &amp;quot;($VALUE eq &#039;1&#039; ? &#039;Ja&#039; : &#039;Nein&#039;)&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine Besonderheit besteht bei darzustellenden Werten die die Einheiten &#039;Wh&#039; bzw. &#039;kWh&#039; besitzen. Diese Werte und Einheiten werden automatisch entsprechend des gesetzten Attributes graphicEnergyUnit umgerechnet und angezeigt.&lt;br /&gt;
&lt;br /&gt;
Soll in diesen Fällen eine automatische Formatierung umgangen werden, kann eine solche Notation verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &#039;Today_PVforecast&#039; =&amp;gt; &amp;quot;(sprintf &#039;%.1f &amp;amp;amp;nbsp;kWh&#039;, ($VALUE / 1000))&amp;quot;,&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Die Angabe von &amp;amp;amp;nbsp; vor &#039;kWh&#039; verhindert die Erkennung der Einheit und so auch die automatische Umsetzung durch das Modul. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 3 - Bereich Verbraucherdarstellung (Consumer Legend) ===&lt;br /&gt;
Dieser Grafikbereich zeigt die im Modul registrierten Verbraucher sowie deren Status und weitere Informationen an. Sind die Voraussetzungen gegeben, d.h. entsprechende Schlüssel in der ConsumerXX-Attributen gesetzt, können die Verbraucher über das Paneel manuell geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Zur Anpassung der Darstellung sind verschiedene Attribute verfügbar:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;consumerControl-&amp;gt;showLegend: Definiert die Lage bzw. Darstellungsweise der Verbraucherlegende sofern Verbraucher im SolarForecast Device registriert sind.&lt;br /&gt;
;consumerControl-&amp;gt;adviceIcon: Definiert die Art der Information über die geplanten Schaltzeiten eines Verbrauchers in der Verbraucherlegende. &lt;br /&gt;
;consumerControl-&amp;gt;detailLink: Wenn gesetzt, ist der jeweilige Verbraucher klickbar um direkt zur Detailansicht des jeweiligen Geräts auf einer neuen Browserseite zu gelangen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Standard wird das Verbraucherpaneel zwischen dem Kopfbereich und der ersten Balkengrafik Ebene dargestellt. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;showLegend&#039;&#039;&#039; und Argument &#039;&#039;&#039;icon_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_bottom&#039;&#039;&#039; kann das Verbraucherpaneel an das Ende des Grafikbereiches verschoben werden.&lt;br /&gt;
Die Verwendung von &#039;&#039;&#039;text_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_top&#039;&#039;&#039; blendet die Icon-Spalte im Verbraucherpaneel aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Screenshot 2025-02-08 093239.png|Darstellung mit consumerControl showLegend=icon_top (default)&lt;br /&gt;
File:Screenshot 2025-02-08 093646.png|Darstellung mit consumerControl showLegend=icon_bottom&lt;br /&gt;
File:Screenshot 2025-02-08 152018.png|Darstellung mit consumerControl showLegend=text_top bzw. text_bottom&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 213634.png|right|thumb|400px|]]&lt;br /&gt;
Ein Mouse-Over über das Uhrensymbol zeigt nähere Informationen zum Status, den Planungsdaten, Modus und weitere Daten des Verbrauchers. Der Schalter &amp;quot;Aus/Ein&amp;quot; visualisiert den Schaltzustand des Verbrauchers und können auch zum manuellen Schalten des Verbrauchers dienen. Voraussetzung ist, dass im consumer-Attribut die Schlüssel &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; mit den Set-Kommandos zum Schalten des Verbrauchers defininiert sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 222210.png|right|thumb|300px|]]&lt;br /&gt;
Der Auto-Schieberegler zeigt einerseits den Freigabestatus zum Schalten des Verbrauchers durch das SolarForecast Modul und kann andererseits manuell betätigt werden. Der Status des Reglers korrespondiert mit dem im zugehörigen Consumer Attribut vorhandenen Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; angegebenen Reading-Wert.&lt;br /&gt;
&lt;br /&gt;
Die Verbraucherbezeichnungen in dem Paneel können in der Standardkonfiguration angeklickt werden um direkt zur Detailansicht des Devices zu gelangen. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;detailLink&#039;&#039;&#039; kann der Link zur Detailansicht deaktiviert werden.&lt;br /&gt;
&lt;br /&gt;
Das Uhrensymbol kann mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;adviceIcon&#039;&#039;&#039; geändert und/oder dessen Farbe angepasst, sowie einen Informationstext statt eines Icons angezeigt werden. &lt;br /&gt;
&lt;br /&gt;
=== 4 - Bereich Balkengrafik (Beam Graphic) ===&lt;br /&gt;
&lt;br /&gt;
Die Balkengrafik des Moduls ist ein wesentliches Visualisierungshilfsmittel. Im Auslieferungszustand existiert eine Balkengrafikebene, die &#039;&#039;&#039;Ebene 1&#039;&#039;&#039;.&lt;br /&gt;
Jede Ebene kann zwei Balkendiagramme mit auswählbaren Inhalten, Farben und einstellbarem LayoutTyp darstellen. In Ebene 1 kann die Wettervorhersage eingebettet oder, bei Vorhandensein von Batteriegeräten, die zukünftigen Zeiten mit empfohlener Ladefreigabe und SoC-Prognose eingeblendet werden. &lt;br /&gt;
&lt;br /&gt;
Welche Daten in welchen Zeiträumen dargestellt werden sollen, die Bestimmung des Layouts, die Gestaltung der Balken und einiges mehr wird durch Attribute gesteuert. Ein Teil dieser Einstellungen wird über das zusammengesetzete Attribut &#039;&#039;&#039;graphicControl-&amp;gt;&#039;Schlüssel&#039;=&#039;Wert&#039;&#039;&#039;&#039; eingestellt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;grundsätzliche Layout Definitionen&#039;&#039;&#039;&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204342.png|right|thumb|400px|Standardanzeige mit Wetter-Icons, gesetzen Attributen graphicBeam1Color=D4C177, graphicHistoryHour=11]]&lt;br /&gt;
&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingTop:Legt den Platz in px im Balkendiagramm fest, der zwischen dem oberen Rand der jeweiligen Balkengrafik Ebene und der ersten Text- oder Iconreihe dieser Ebene eingefügt wird.&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingBottom:Legt den Platz in px im Balkendiagramm fest, der zwischen der letzten Text- oder Iconreihe der jeweiligen Balkengrafik Ebene und dem unteren Rand dieser Ebene eingefügt wird. &lt;br /&gt;
;graphicControl-&amp;gt;layoutType:Layout-Optionen zur grundlegenden Gestaltung der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourStyle:Format der Zeitangabe in der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourCount:Anzahl der darzustellenden Balken/Stunden in der Balkengrafk&lt;br /&gt;
[[Datei:Screenshot Screenshot 2025-05-21 153613.png|right|thumb|400px|Erweiterung des oberen und unteren Abstandes mit den Attributen graphicControl-&amp;gt;beamPaddingTop und graphicControl-&amp;gt;beamPaddingBottom]]&lt;br /&gt;
;graphicControl-&amp;gt;energyUnit:definiert die Einheit zur Anzeige der elektrischen Leistung in der Grafik&lt;br /&gt;
;graphicHistoryHour:Anzahl der vorangegangenen Stunden die in der Balkengrafik dargestellt werden&lt;br /&gt;
;graphicControl-&amp;gt;beamWidth:Vorgabe Breite der Balken der Balkengrafik in px (sonst automatische Bestimmung) &lt;br /&gt;
;graphicBeamHeightLevel1:Multiplikator zur Festlegung der maximalen Balkenhöhe der jeweiligen Ebene (hier Ebene 1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;Definition der Inhalte und Balkeneigenschaften&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204756.png|right|thumb|400px|Wie oben aber mit gesetzem Attribut graphicShowNight=1]]&lt;br /&gt;
;graphicBeam1Color:Farbauswahl des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2Color:Farbauswahl des sekundären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam1Content:Legt den darzustellenden Inhalt des primären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam2Content:Legt den darzustellenden Inhalt des sekundären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam1FontColor:Auswahl der Schriftfarbe des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2FontColor:Auswahl der Schriftfarbe des sekundären Balkens (Ebene 1)&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 205024.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=0 (ohne Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;zusätzliche Optionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;graphicShowNight:Anzeigen oder Verbergen der Nachtstunden in der Balkengrafik&lt;br /&gt;
;graphicShowWeather:Wettericons in der Balkengrafik anzeigen/verbergen (nur Ebene 1)&lt;br /&gt;
;graphicWeatherColor:Farbe der Wetter-Icons für die Tagesstunden&lt;br /&gt;
;graphicWeatherColorNight:Farbe der Wetter-Icons für die Nachtstunden&lt;br /&gt;
;graphicShowDiff:Zusätzliche Anzeige der Differenz &amp;quot;&amp;lt;primärer Balkeninhalt&amp;gt; - &amp;lt;sekundärer Balkeninhalt&amp;gt;&amp;quot; im Kopf- oder Fußbereich der Balkengrafik&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die genaue Beschreibung und deren Optionen sind der aktuellen Online-Hilfe zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Für alle Ebenen gilt:&#039;&#039;&#039; Ein Attribut mit einer ungeraden Balkennummer (z.B. graphicBeam1Content) bezieht sich immer auf den primären Balken, ein Attribut mit einer geraden Balkennummer (z.B. graphicBeam2Content) bezieht sich immer auf den sekundären Balken.&lt;br /&gt;
&lt;br /&gt;
Die Balken haben, wie die meisten Elemente in der Balkengrafik, eine Mouse-Over Eigenschaft welche relevante Informationen zu den dargestellten Werten anzeigt. &lt;br /&gt;
&lt;br /&gt;
Sind die Nachtunden mit &#039;&#039;&#039;graphicShowNight&#039;&#039;&#039; ausgeblendet, werden keine Balken angezeigt sofern es keine Werte anzuzeigen gibt. Sollten dennoch Werte ungleich 0 anzuzeigen sein, werden diese Werte auch trotz ausgeblendeter Nachstunden angezeigt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 2 ====&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 211741.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=01 (mit Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 2&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam3Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam4Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 4 für Balken 4) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wetter-Icons können nur in Ebene 1 integriert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 2 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 2 gibt, eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgende Ebene.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 3 ====&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 3&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam5Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam6Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 5 für Balken 5) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 3 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 3 gibt, ist eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgenden Ebenen, d.h. auch auf die Ebene 3.&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 5 - Die Energieflußgrafik (Flow Graphic) ===&lt;br /&gt;
[[Datei:Screenshot 2025-02-13 213424.png|right|thumb|400px|Energieflußgrafik mit Verbrauchern in der Nachtdarstellung (Mondphasen) nach Sonnenuntergang]]&lt;br /&gt;
&lt;br /&gt;
Die Energieflußgrafik stellt die registrierten Erzeuger, Batterien, Netzzugänge und Verbraucher strukturiert in mehreren Ebenen dar:&lt;br /&gt;
&lt;br /&gt;
;Ebene 1: In der oberen Ebene befinden sich die PV-Generatoren, Smart-Loader sowie sonstigen Erzeuger &lt;br /&gt;
;Ebene 2: Die mittlere Ebene organisiert den Zugang zum öffentlichen Netz, dem Hausknoten, dem Batterieknoten sowie einem Dummy-Verbraucher (Lampensymbol) für den Energieverbrauch des Hauses der keinem der registrierten Verbraucher zugeordnet werden kann.&lt;br /&gt;
;Ebene 3: In der unteren Ebene werden die registrierten Verbraucher dargestellt. Unterhalb der Verbrauchersymbole werden der aktuelle Verbrauch (bzw. der On/Off-Zustand) sowie darunter die Restlaufzeit (Minuten) des Verbrauchers, sofern er durch das Modul geplant und gestartet wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Position und Gestaltung der Grafikelemente ist umfangreich über das Attribut &#039;&#039;&#039;flowGraphicControl&#039;&#039;&#039; und den darin verfügbaren Schlüsseln einstellbar.&lt;br /&gt;
Die Bedeutung der Schlüssel ist in der Online-Hilfe zum Attribut mit einem Beispiel beschrieben. &lt;br /&gt;
&lt;br /&gt;
Darüber hinaus enthalten die Setup-Attribute &#039;&#039;&#039;setupInverterDevXX&#039;&#039;&#039;, &#039;&#039;&#039;setupOtherProducerXX&#039;&#039;&#039; und &#039;&#039;&#039;consumerXX&#039;&#039;&#039; weitere Einstellungsmöglichkeiten um deren Icons und Färbungen in der Flußgrafik individuell einstellen zu können. So sind zum Beispiel die Icons der PV-Inverter und deren Färbung mit dem Schlüssel &#039;&#039;&#039;icon&#039;&#039;&#039; der setupInverterDevXX-Attribute in Abhängigkeit von Tag und Nacht separat definierbar.&lt;br /&gt;
&lt;br /&gt;
In den Verbraucher-Attributen ist mit dem Schlüssel &#039;&#039;&#039;noshow&#039;&#039;&#039; die Sichtbarkeit in der Flußgrafik definierbar.&lt;br /&gt;
&lt;br /&gt;
Generell steuert das Attribut &#039;&#039;&#039;graphicSelect&#039;&#039;&#039; die Ein- bzw. Ausblendung der gesamten Flußgrafik.&lt;br /&gt;
&lt;br /&gt;
== Die Verbrauchsprognose ==&lt;br /&gt;
Im Gegensatz zu der PV Prognose gibt es keine API oder andere externen Datenquellen die für die Verbrauchsprognose herangezogen werden könnten.&lt;br /&gt;
&lt;br /&gt;
Zum Zweck der Verbrauchsermittlung verwendet das Modul die Meterdaten aus dem Attribut &#039;&#039;setupMeterDev&#039;&#039; sowie den weiteren setup-Attributen &#039;&#039;setupInverterDevXX&#039;&#039;. &lt;br /&gt;
Sind auch andere Erzeuger (BHKW, Windanlagen, etc.) bzw. eine Batterie vorhanden, sind ebenfalls die Attribute &#039;&#039;setupOtherProducerXX&#039;&#039; bzw. &#039;&#039;setupBatteryDev&#039;&#039; für die Berechnung des Hausverbrauchs relevant. In diesen Attributen gibt es die Schlüssel &#039;&#039;*total&#039;&#039; die teilweise optional sind. Für die Verbrauchsprognose bilden sie jedoch die Berechnungsgrundlage und sind deswegen für diese Funktionalität wichtig anzugeben.&lt;br /&gt;
&lt;br /&gt;
Die Verbrauchswerte werden stundengenau erfasst und im Datenspeicher &#039;&#039;pvHistory&#039;&#039; für 31 Tage, sowie im Datenspeicher &#039;&#039;pvCircular&#039;&#039; 210 Tage gespeichert. Die beiden Datenspeicher übernehmen unterschiedliche Aufgaben im Rahmen der Prognoseerstellung. Auf Grundlage der gespeicherten und somit historischen Verbrauchswerte erstellt das Modul eine Prognose für die kommende Zeit.&lt;br /&gt;
&lt;br /&gt;
Mit dem Kommando &lt;br /&gt;
&lt;br /&gt;
   &amp;quot;get ... pvHistory [Tag]&amp;quot; &lt;br /&gt;
&lt;br /&gt;
wird der Inhalt aufgelistet. Die Schlüssel &#039;&#039;confc&#039;&#039;, &#039;&#039;con&#039;&#039; und &#039;&#039;gcon&#039;&#039; zeigen die Verbrauchsprognose, den Verbrauch und den Netzbezug der jeweiligen Stunde des gewählten Tages.&lt;br /&gt;
Die Stunde &amp;quot;99&amp;quot; zeigt die Summen dieser Schlüsssel für den Tag:&lt;br /&gt;
&lt;br /&gt;
      99 =&amp;gt; etotal: , pvfc: 782, pvrl: 0, rad1h: -&lt;br /&gt;
            confc: 14540, con: 13873, gcon: 13873, gfeedin: 0&lt;br /&gt;
            batintotal: , batin: 0, batouttotal: , batout: 0&lt;br /&gt;
            batmaxsoc: -, batsetsoc: -&lt;br /&gt;
            wid: , wcc: , wrp: , pvcorrf: , dayname: So&lt;br /&gt;
            cyclescsm01: 0&lt;br /&gt;
            cyclescsm02: 0&lt;br /&gt;
            cyclescsm03: 0&lt;br /&gt;
            cyclescsm04: 1, hourscsme04: 0.00&lt;br /&gt;
            cyclescsm05: 0&lt;br /&gt;
            cyclescsm06: 0&lt;br /&gt;
            cyclescsm07: 1, hourscsme07: 0.00&lt;br /&gt;
            cyclescsm08: 1, hourscsme08: 0.00&lt;br /&gt;
            cyclescsm09: 1, hourscsme09: 0.03 &lt;br /&gt;
&lt;br /&gt;
In dem Beispiel wurden für den Tag 14540 Wh Verbrauch prognostiziert, 13873 Wh tatsächlich verbraucht und davon 13873 Wh aus dem Netz bezogen. Leider war an diesem Tag keinerlei PV Ertrag vorhanden, was man auch an dem Schlüssel &#039;&#039;pvrl&#039;&#039; erkennen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Inhalt des pvCircular-Speichers kann mit dem Befehl  &lt;br /&gt;
&lt;br /&gt;
     &amp;quot;get ... pvCircular [Tag]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Das nachfolgende Beispiel zeigt die Ausgabe für die Tagesstunde 23:&lt;br /&gt;
&lt;br /&gt;
 23 =&amp;gt; pvapifc: 0, pvaifc: -, pvfc: 0, aihit: 0, pvrl: 0&lt;br /&gt;
       batin01: 0, batin02: -, batin03: -&lt;br /&gt;
       batout01: 619, batout02: -, batout03: -&lt;br /&gt;
       confc: 650, gcon: 23, gfeedin: 0, wcc: 40, rr1c: 0.00&lt;br /&gt;
       temp: -6.00, wid: 100, wtxt: Bewölkungsentwicklung nicht beobachtet&lt;br /&gt;
       pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
       ... &lt;br /&gt;
       con_all =&amp;gt; Sa  @ 617 762&lt;br /&gt;
                  Di  @ 693 645&lt;br /&gt;
                  Mo  @ 620 679&lt;br /&gt;
                  So  @ 669 666 636&lt;br /&gt;
                  Mi  @ 701 626&lt;br /&gt;
                  Do  @ 612 642&lt;br /&gt;
                  Fr  @ 615 606&lt;br /&gt;
&lt;br /&gt;
Der Schüssel &#039;&#039;con_all&#039;&#039; enthält einen Hash aus Arrays die für jeden Wochentag (Mo..So) bis zu 30 Verbrauchswerte (in Wh) für die angezeigte Stunde speichern. Wie hier erkennbar ist, wurden an den drei vergangenen Sonntagen jweils 669 Wh, 666 Wh bzw. 636 Wh in der Stunde 23 (22:00-22:59) verbraucht.&lt;br /&gt;
Der Median aus diesen Werten geht in die Verbrauchsprognose ein. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wochentagsnamen Mo..So sind von den installierten Locales auf Betriebsystemebene abhängig. Ist keine deutsche locale installiert, werden die englischen Wochentagsnamen Mon..Sun verwendet. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Wie wird der Verbrauch des Hauses ermittelt und gespeichert? ===&lt;br /&gt;
Die Verbrauchsdaten des Hauses werden auf Stundenbasis ermittelt und gespeichert. Das &amp;quot;Haus&amp;quot; steht als Synonym aller im Kontext des Solarforecast Devices zusammengeführten Inverter (setupInverterDevXX), sonstigen Erzeuger (setupOtherProducerXX), Netzanschlüsse (setupMeterDev), Verbraucher (consumerXX) und Batterien (setupBatteryDev).&lt;br /&gt;
&lt;br /&gt;
Alle diese Daten werden durch das Modul mit jedem ausgeführten Zyklus (Attribut plantControl-&amp;gt;cycleInterval) und, wenn ein Event eines als &#039;asynchron&#039; definierten Devices auftritt, gesammelt und daraus permanent ein aktualisierter Verbrauch berechnet. Die Berechnung beschreibt folgende Formel:&lt;br /&gt;
&lt;br /&gt;
 PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung - Verbrauch = 0&lt;br /&gt;
&lt;br /&gt;
bzw.&lt;br /&gt;
 &lt;br /&gt;
 Verbrauch (Wh) = PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung&lt;br /&gt;
            con = PV           + PP                 - GridIn          + GridCon   - BatIn          + BatOut&lt;br /&gt;
&lt;br /&gt;
Die PV-Erzeugung beinhaltet die Summe aller durch die angegebnen Inverter (setupInverterDev01 .. setupInverterDevXX) erzeugten Energien. Die &amp;quot;sonstige Erzeugung&amp;quot; summiert sich aus den Werten aller angegebenen Producer (setupOtherProducer01 .. setupOtherProducerXX). Der Verbrauch wird durch die registrierten Geräte consumerXX teilweise direkt erfasst, ist aber grundsätzlich unvollständig da nicht alle Verbrauchswerte im &amp;quot;Haus&amp;quot; gemessen und durch das Modul erfasst werden können.&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel zeigt das Ergebnis bei 300 Wh PV-Erzeugung und gleichzeitige 500 Wh Netzbezug:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 300 + 0 - 0 + 500 - 0 + 0 = 800 Wh&lt;br /&gt;
&lt;br /&gt;
Bei 1300Wh PV-Erzeugung, 100 Wh Netzeinspeisung sowie 200 Wh Batterieladung ergibt sich der Verbrauch zu:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 1300 + 0 - 100 + 0 - 200 + 0 = 1000 Wh&lt;br /&gt;
&lt;br /&gt;
Ohne Erzeugung, aber mit der Energielieferung von 500 Wh aus der Batterie, 800 Wh Netzbezug (mit einem Anteil Batterienachladung aus dem Netz von 200 Wh) sieht die Verbrauchsrechnung wie folgt aus: &lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 0 + 0 - 0 + 800 - 200 + 500 = 1100 Wh&lt;br /&gt;
&lt;br /&gt;
Der so ermittelte Verbrauchsert wird mit jedem Zyklus in der pvHistory im Schlüssel &amp;quot;con&amp;quot; gespeichert. Man kann sich die gespeicherten Werte mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;name&amp;gt; pvHistory [&amp;lt;Tag&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Nachfolgendes Beispiel zeigt einen Datensatz für die Stunde 8 eines Tages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      08 =&amp;gt; pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotali01: 62940734, etotali02: 2928860, etotali03: -&lt;br /&gt;
            pvrl01: 0, pvrl02: 0, pvrl03: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 630, con: 962, gcons: 962, conprice: 0.2958&lt;br /&gt;
            gfeedin: 0, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 120, sunalt: -3&lt;br /&gt;
            batintotal: 3713815.07742543, batouttotal: 3604468.26993988, batin: 0, batout: 0&lt;br /&gt;
            wid: 161, wcc: 89, rr1c: 0.00, pvcorrf: 0.27/0.00 temp: 7.40, &lt;br /&gt;
            csmt01: 110996.12, csme01: 32.1399999999994, minutescsm01: 30&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 2513.67, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1581293.6, csme04: 136.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 1662.17, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 90.53, csme06: 0, minutescsm06: 0&lt;br /&gt;
            csmt07: 39.75, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 38050, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 131627, csme09: 33.2000000000116, minutescsm09: 39&lt;br /&gt;
            minutescsm10: 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Schlüssel &amp;quot;con&amp;quot; ist der gespeicherte Verbrauch von 962 Wh ersichtlich.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit bekommt man mit dem Attribut &#039;&#039;ctrlDebug=collectData&#039;&#039; einen Einblick in die Verbrauchsermittlung bei jedem Zyklus und kann so die Eingangswerte und das daraus resultierende Ergebnis im FHEM Log nachverfolgen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
2024.11.28 11:38:20.080 1: SolCast DEBUG&amp;gt; EnergyConsumption input -&amp;gt; PV: 96, PP: 0, GridIn: 0, GridCon: 582, BatIn: 5, BatOut: 0&lt;br /&gt;
2024.11.28 11:38:20.081 1: SolCast DEBUG&amp;gt; EnergyConsumption result -&amp;gt; 673 Wh&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie wird die Verbrauchsprognose erstellt? ===&lt;br /&gt;
&lt;br /&gt;
Aus den gespeicherten con-Werten (Verbrauchsdaten) der pvCircular (Schlüssel con_all) sowie Einträgen der pvHistory wird der Median der historischen Tage ermittelt und für den kommenden Tag bzw. die kommen Stunden zur Prognose angewendet. Dabei geht per default jeder verfügbare historische Tag gleichberechtigt in die Prognose ein. Mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039; kann festgelegt werden, dass nur gleiche Wochentage (Mo..So) für die Prognose verwendet werden. Hierbei spielt die Vermutung, dass das Verbrauchsverhalten eine gewisse Korrelation zum Wochentag hat, eine Rolle. &lt;br /&gt;
&lt;br /&gt;
Verwendet man die Einstellung consForecastIdentWeekdays=1, hat es sich als vorteilhaft erwiesen, das Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays&#039;&#039;&#039; auf einen niedrigeren Wert als den Default zu setzen. Eine Einstellung auf &#039;8&#039; zum Beispiel verwendet den Median der gleichen Wochentage der vergangenenen 8 Wochen. Dadurch wird nicht zu weit in die Vergangenheit verzweigt und so eine langsame Veränderung des Verbrauchsmedian, zum Beispiel hervorgerufen durch den Übergang vom Winter in das Frühjahr hinein, abgebildet.&lt;br /&gt;
&lt;br /&gt;
Weiteren Einfluß auf die Verbrauchsprognose kann mit dem Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; im Consumerattribut genommen werden. Insbesondere bei der unregelmäßigen Nutzung von Verbrauchern mit hoher Leistung kann die Projektion der aufgezeichneten historischen Werte in die Prognose zu unverhältnismäßig hohen Verbrauchswerwartunden führen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Möglicherweise führt in Fällen die Verwendung eine der nachfolgenden Optionen zu einem besseren Ergebnis:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;1 -&#039;&#039;&#039; die allgemeine Verbrauchsprognose wird um die gespeicherten Energieverbrauchsanteile reduziert.&lt;br /&gt;
* &#039;&#039;&#039;2 -&#039;&#039;&#039; wie bei &#039;1&#039;, jedoch gehen die Planungsdaten des Verbrauchers bei der Prognose der kommenden Stunden wieder mit ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;&#039;exconfc&#039;&#039;&#039; in einem der Consumer verwendet, sollte&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays=4&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
eingestellt werden. Hintergrund ist, dass die Verbrauchsanteile der jeweiligen Verbraucher nur maximal 31 Tage in der pvHistory verfügbar sind. Für längere Zeiträume stehen nur Gesamtsummen des Verbrauchs in der pvCircular zu Verfügung.  &lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=1&#039;&#039;&#039; werden die in der Historie aufgezeichneten Verbrauchsbestandteile aus einer Prognose herausgerechnet. Konkret werden die in der pvHistory aufgezeichneten Verbrauchsbestandteile für die relevante Stunde ermittelt und daraus ein Durchschnitt gebildet der vom Prognosewert subtrahiert wird. Mit dem Attributwert plantControl-&amp;gt;consForecastIdentWeekdays=1 werden wiederum nur identische Wochentage (Mo .. So) zusammengefasst.&lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=2&#039;&#039;&#039; erfolgt ebenso die Eliminierung des Verbrauchsanteils, es wird jedoch auf die Planungsdaten für diesen Verbraucher zugegriffen und die geplanten Energieanteile wiederum der Verbrauchsprognose für die kommenden Stunden hinzugerechnet.&lt;br /&gt;
&lt;br /&gt;
In beiden Anwendungsfällen ist es notwendig, dass dem Modul durch die Angabe entsprechender Readings der Energieverbrauch im Setup des Consumers bekannt gemacht wird damit diese Energieanteile registriert werden können. Allgemein funktioniert die Verbrauchsprognose gut wenn Verbrauchsprozesse regelmäßig in einem wiederkehrenden Zeitraster ablaufen, der Verbrauch durch persönliche Rituale bestimmt ist. So zum Beispiel könnte am Dienstag und Samstag gewöhnlich die Waschmaschine laufen, das E-Auto täglich aufgeladen werden und gebügelt wird oft am Sonntag Nachmittag.&lt;br /&gt;
&lt;br /&gt;
Unregelmäßige Nutzung, vor allem vom Großverbrauchern, lässt sich nur sehr schwer und ungenügend auf zukünftige Verbrauchsprognosen projizieren.&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis der Prognose wird im Kopf der Grafik in der Zeile &#039;&#039;Verbrauch&#039;&#039; sowie in diversen Readings wie &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RestOfDayConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den Rest des Tages)&lt;br /&gt;
* &#039;&#039;&#039;NextHours_Sum04_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für die nächsten 4 Stunden)&lt;br /&gt;
* &#039;&#039;&#039;Tomorrow_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den kommenden Tag)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
angezeigt.&lt;br /&gt;
&lt;br /&gt;
Weitere Aggregationen kann man sich über das Attribut &#039;&#039;&#039;ctrlStatisticReadings&#039;&#039;&#039; bei Bedarf zuschalten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;conForecastTillNextSunrise&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
* &#039;&#039;&#039;todayConForecastTillSunset&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
* &#039;&#039;&#039;todayConsumptionForecast&#039;&#039;&#039; - Verbrauchsprognose aufgesplittet pro Stunde des aktuellen Tages (01-24) &lt;br /&gt;
 &lt;br /&gt;
==== Debugging der Verbrauchsprognose ====&lt;br /&gt;
Um sich einen Einblick über die Erstellung der Verbrauchsprognose zu verschaffen, bietet sich die Einschaltung von:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
an. Mit diesem gesetzten Attribut wird die Erstellung der Prognose im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; ################### Start Consumption forecast ###################&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; Basics - installed locale: de_DE.UTF-8, used scheme: DE&lt;br /&gt;
2025.02.27 19:52:00.064 1: SolCast DEBUG&amp;gt; process Today dayname: Do, Tomorrow dayname: Fr&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 01 - 74.43 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 10 - 290.77 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 24 - 660.70 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 20, hod: 07 - 459.93 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;07&#039; register for exclude day 20, hod: 02 - 0.33 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 30, hod: 08 - 264.78 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next Hours (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; excl. hist 74 Wh for Hour 01, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; estimated cons of Hour 01: 436 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; excl. hist 0 Wh for Hour 02, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 02: 428 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 03: 458 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 04: 503 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 05: 489 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 06: 482 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; excl. hist 460 Wh for Hour 07, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 07: 274 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 265 Wh for Hour 08, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 08: 441 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 09: 558 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 291 Wh for Hour 10, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 10: 443 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 11: 881 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 12: 794 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 13: 840 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 14: 660 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 15: 812 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 16: 752 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 17: 597 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 18: 652 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 19: 634 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 20: 628 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 21: 713 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 22: 596 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 23: 629 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; excl. hist 661 Wh for Hour 24, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons of Hour 24: 660 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons Tomorrow: 16848 Wh, Individual hourly values considered: 72, exclude: 0 Wh (avg of 0 entities)&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Store Consumption forecast values (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour00&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;20&#039; confc: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour01&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;21&#039; confc: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour02&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;22&#039; confc: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour03&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;23&#039; confc: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store &#039;NextHour04&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;24&#039; confc: 660&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour05&#039; hod &#039;01&#039; confc: 436, confcEx: 436&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour06&#039; hod &#039;02&#039; confc: 428, confcEx: 428&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour07&#039; hod &#039;03&#039; confc: 458, confcEx: 458&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour08&#039; hod &#039;04&#039; confc: 503, confcEx: 503&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour09&#039; hod &#039;05&#039; confc: 489, confcEx: 489&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour10&#039; hod &#039;06&#039; confc: 482, confcEx: 482&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour11&#039; hod &#039;07&#039; confc: 274, confcEx: 274&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour12&#039; hod &#039;08&#039; confc: 441, confcEx: 441&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour13&#039; hod &#039;09&#039; confc: 558, confcEx: 558&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour14&#039; hod &#039;10&#039; confc: 443, confcEx: 443&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour15&#039; hod &#039;11&#039; confc: 881, confcEx: 881&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour16&#039; hod &#039;12&#039; confc: 794, confcEx: 794&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour17&#039; hod &#039;13&#039; confc: 840, confcEx: 840&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour18&#039; hod &#039;14&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour19&#039; hod &#039;15&#039; confc: 812, confcEx: 812&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour20&#039; hod &#039;16&#039; confc: 752, confcEx: 752&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour21&#039; hod &#039;17&#039; confc: 597, confcEx: 597&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour22&#039; hod &#039;18&#039; confc: 652, confcEx: 652&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour23&#039; hod &#039;19&#039; confc: 634, confcEx: 634&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour24&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour25&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour26&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour27&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour28&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; consumption calculated - day: 27, hod: 20, con: 574 Wh&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; write pvCircular consumption - hod: 99, todayConsumption: 11210 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe startet mit &#039;&#039;&amp;quot;Start Consumption forecast&#039;&#039;&amp;quot;, es werden die zu exkludierenden historischen Daten für jeden Consumer bzgl. jedem Tag (day) und Stunde des Tages (hod) getrennt registriert. Diese Werte werden durch die gespeicherte Einträge in der pvHistory (max. 31 historische Tage) geliefert. &lt;br /&gt;
&lt;br /&gt;
Im nächsten Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next Hours (new median)&amp;quot;&#039;&#039; werden die Prognosen für die nächsten Stunden kalkuliert und die zuvor registrierten Excludes angewendet. Die Prognose für den kommenden Tag ist im Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next day (new median)&amp;quot;&#039;&#039; protokolliert. Die Prognose für den kommenden Tag ist nicht einfach die Summe der Prognose der nächsten Stunden, denn in den kommenden Stunden werden auch die verfügbaren Planungen der Consumer einbezogen. Für den kommenden Tag können diese Werte unter Umständen nicht einbezogen werden da sie zum Zeitpunkt X noch nicht verfügbar sind.&lt;br /&gt;
&lt;br /&gt;
Im Abschnitt &#039;&#039;&amp;quot;Store Consumption forecast values (new median)&amp;quot;&#039;&#039; erscheinen die effektiv gespeicherten Werte. Diese sind die Grandlage für die grafische Darstellung sowie weiteren Kalkulationen.&lt;br /&gt;
&lt;br /&gt;
=== Wie kann eine fehlerhafte Verbrauchsprognose korrigiert werden? ===&lt;br /&gt;
Wie im vorherigen Abschnitt beschrieben, wird die Prognose aus den gespeicherten &amp;quot;con&amp;quot;-Werten der vergangenen Tage (bzw. Stunden) abgeleitet. &lt;br /&gt;
Grundsätzlich muß zunächst sichergestellt werden, dass die auszulesenden Readings der angegebenen Energiezähler sowie deren Einheiten! korrekt eingestellt sind. Das gilt ebenfalls für die registrierten Verbraucher im Modul.&lt;br /&gt;
&lt;br /&gt;
Für einen ersten Überblick bietet sich das Debug Attribut an zu setzen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
Beispielausgabe des Debug:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2024.09.21 13:28:27.041 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day ###################&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;01&amp;lt; considering possible exclusions: 14082&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;08&amp;lt; considering possible exclusions: 16446&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;15&amp;lt; considering possible exclusions: 14568&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;25&amp;lt; considering possible exclusions: 15522&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; estimated Consumption for tomorrow: 15154, days for avg: 4&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next hours ###################&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 14 -&amp;gt; 850 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 14 -&amp;gt; 643 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 14 -&amp;gt; 590 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 14 -&amp;gt; 522 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 13:00:00, confc: 651, days for avg: 4, hist. consumption registered consumers: 560.97&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 15 -&amp;gt; 720 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 15 -&amp;gt; 743 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 15 -&amp;gt; 897 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 15 -&amp;gt; 557 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 14:00:00, confc: 729, days for avg: 4, hist. consumption registered consumers: 620.97&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 16 -&amp;gt; 676 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 16 -&amp;gt; 790 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 16 -&amp;gt; 785 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 16 -&amp;gt; 581 Wh&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 15:00:00, confc: 708, days for avg: 4, hist. consumption registered consumers: 647.29&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 17 -&amp;gt; 622 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 17 -&amp;gt; 639 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 17 -&amp;gt; 646 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 17 -&amp;gt; 572 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 16:00:00, confc: 619, days for avg: 4, hist. consumption registered consumers: 618.30&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 18 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 18 -&amp;gt; 614 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 18 -&amp;gt; 580 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 18 -&amp;gt; 480 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 17:00:00, confc: 567, days for avg: 4, hist. consumption registered consumers: 583.41&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 19 -&amp;gt; 615 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 19 -&amp;gt; 1659 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 19 -&amp;gt; 597 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 19 -&amp;gt; 618 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 18:00:00, confc: 872, days for avg: 4, hist. consumption registered consumers: 636.97&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 20 -&amp;gt; 611 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 20 -&amp;gt; 1124 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 20 -&amp;gt; 546 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 20 -&amp;gt; 479 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 19:00:00, confc: 690, days for avg: 4, hist. consumption registered consumers: 578.87&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 21 -&amp;gt; 1474 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 21 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 21 -&amp;gt; 619 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 21 -&amp;gt; 433 Wh&lt;br /&gt;
2024.09.21 13:28:27.058 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Im ersten Teil wird die erwartete Consumption für den nächsten Tag unter Berücksichtigung möglicher Ausschlüsse von Verbrauchern ausgegeben. Ausschlüsse von Verbrauchern ergeben sich wenn in dem Verbraucherattribut der Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; gesetzt ist. Er besagt, dass die Verbrauchswerte des Verbrauchers in eine zukünftige Prognose nicht eingehen sollen. Zum Beispiel wenn ein Verbraucher mit sehr hohen Verbrauchswerten nur sporadisch eingesetzt wird und dadurch die Prognose stark verfälschen würde. Es ist auch zu sehen, dass bedingt durch das Attribut &#039;&#039;&#039;affectConsForecastIdentWeekdays = 1&#039;&#039;&#039; nur die historischen Tage 01, 08, 15 und 25 berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Teil wird die berechnete Erwartung für die nächsten Stunden ausgegeben. &lt;br /&gt;
Zur Beschreibung der Fehlersuche gehen wir davon aus, dass die Prognose von 780 Wh am 2024-09-21 20:00:00 zu hoch erscheint weil am Tag &amp;quot;07&amp;quot; ein Wert von 1474 Wh gespeichert ist:&lt;br /&gt;
&lt;br /&gt;
 SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt geben wir die historischen Werte für den Tag 07 aus:&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;Name&amp;gt; pvHistory 07&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz interessiert die Stunde 21. Sie resultiert aus der obigen Angabe &amp;quot;starttime: xxxx-xx-xx 20:00:00&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      21 =&amp;gt; etotal: 64354660, pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 496, con: 1474, gcons: 23, conprice: 0.2958&lt;br /&gt;
            gfeedin: 5, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 289, sunalt: -8&lt;br /&gt;
            batintotal: 3064096.92456668, batouttotal: 2958021.37946804, batin: 0, batout: 1460&lt;br /&gt;
            wid: 101, wcc: 20, rr1c: 0.00, pvcorrf: 1.00/-temp: 26.00, &lt;br /&gt;
            csmt01: 64262.43, csme01: 28.8099999999977, minutescsm01: 25&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 0, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1389417.4, csme04: 94.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 0, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 290.15, csme06: 6.66999999999996, minutescsm06: 54&lt;br /&gt;
            csmt07: 0, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 32800, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 103987.8, csme09: 38, minutescsm09: 43&lt;br /&gt;
            csmt10: 9151.24999999783, csme10: 3.99999999997999, minutescsm10: 60&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz sind die Energieverbrauchsanteile der im Device registrierten Verbraucher mit dem Schlüssel &amp;quot;csmeXX&amp;quot; gespeichert. Dabei ist &amp;quot;XX&amp;quot; die Verbrauchernummer. In dem Beispiel existieren die Anteile csme01 und csme03 - csme10. Keiner dieser Verbraucher hat einen auffälligen Verbrauchswert gespeichert, d.h. die Messung der Verbraucher scheidet als Problemquelle aus. Wäre ein unverhältmismäßig hoher Verbrauch bei einem der Verbraucher feststellbar, müssten die Schlüssel &#039;&#039;&#039;pcurr&#039;&#039;&#039; und &#039;&#039;&#039;etotal&#039;&#039;&#039; im consumerXX-Attribut geprüft, sowie die Datenlieferung des Consumerdevices selbst geprüft werden.  &lt;br /&gt;
&lt;br /&gt;
Es wurde offensichtlich ein hoher Verbrauch von einem nicht registrierten Verbraucher verursacht oder durch die Übertragung eines Meßfehlers des Devices, angegeben im Attribut &#039;&#039;&#039;setupMeterDev&#039;&#039;&#039;, in das SolarForecast Device übertragen. Eine weitere Analyse ist an dieser Stelle nicht möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Behebung des falschen Wertes kann ein Reset der gespeicherten Consumption der relevanten Stunde durchgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; reset consumptionHistory 07 21&lt;br /&gt;
&lt;br /&gt;
== Modulinterne Datenstrukturen ==&lt;br /&gt;
Das Modul speichert die verschiedenen historischen und aktuellen Daten wie PV-Prognose, Witterungsdaten (Regen, Bewölkung), Strahlungsdaten, Einspeisung, Bezug, reale Erzeugungsdaten und vieles mehr zur Laufzeit im Arbeitsspeicher. Dadurch ist die Verarbeitung dieser Daten im Vergleich zu Lesevorgängen aus dem Filesystem bzw. einer Datenbank sehr performant. Allerdings würden diese Daten bei einem FHEM Absturz bzw. bei einem regulären Shutdown verlorengehen.&lt;br /&gt;
&lt;br /&gt;
Deswegen werden die relevanten Daten regelmäßig in Dateien gesichert und bei Bedarf wiederhergestellt. Diese Dateien befinden sich im Verzeichnis &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; und heißen &#039;&#039;&#039;.*_SolarForecast_.*&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Die Daten werden in jedem Zyklus der Zentralschleife (CentralTask) gesammelt bzw. berechnet. Der Zyklus wird mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;cycleInterval&#039;&#039;&#039; eingestellt.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit können diese Daten über get-Kommandos abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvHistory [Tag]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der pvHistory Datenspeicher enthält die vergangenen Kennwerte der letzten 31 Tage mit einer Genauigkeit von einer Stunde. Es werden die Prognosewerte für Erzeugung und Verbrauch, die realen Werte für Erzeugung und Verbrauch sowie ebenso die Laufzeiten jedes einzelnen Verbrauchers (Consumer) festgehalten. Für jeden Tag gibt es die Stunde &amp;quot;99&amp;quot; die eine Summierung der Stundenwerte des Tages bzw. Sonderschlüssel enthält.&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf lässt sich mit dem Befehl &amp;quot;set ... reset pvHistory&amp;quot; der gesamte Inhalt des Speichers löschen (nicht empfohlen). Selektiver funktioniert die Datenlöschung mit &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt;&amp;quot; (Daten eines bestimmten Tages löschen) bzw. &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt; &amp;lt;Stunde&amp;gt;&amp;quot; (Daten der Stunde  eines bestimmten Tages löschen). Die letzten beiden Kommandos müssen über die Kommandozeile im Browser ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvCircular &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Ringspeicher enthält Daten der letzten 24 Stunden sowie fortwährend berechnete Werte wie Korrekturfaktoren der PV-Erzeugung und Prognosequalität.&lt;br /&gt;
Neue Stundenwerte des Tages überschreiben die gespeicherten Schüssel des vorangegangenen Tages sofern es sich nicht um fortwährend berechnete Werte handelt. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... nextHours&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Speicher enthält sämtliche Prognosewerte der kommenden Stunden beginnend mit der aktuellen Stunde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... radiationApiData&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Abhängig von der ausgewählten Strahlungsdaten API enthält dieser Speicher die von der API gelieferten Rohdaten sowie evtl. weitere für die Funktion benötigte Daten wie API-Keys, Response Messages, Anzahl der API Abruf und weitere.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valCurrent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Struktur wird nicht regelmäßig im Filesystem gespeichert und enthält immer aktuell gesammelte oder berechnete/gelieferte Daten wie z.B. die Autarkierate, letze Laufzeit der Zentralschleife (CentralTask), Zeit des Sonnenauf- und untergangs sowie weitere Betriebsdaten. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valConsumerMaster [XX]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zeigt die Daten der aktuell im SolarForecast Device registrierten Verbraucher. Mit der Nummer &#039;&#039;&#039;XX&#039;&#039;&#039; kann ein bestimmter Verbraucher angesprungen werden. Die Nummer korrespondiert mit dem entsprechenden &#039;&#039;&#039;consumerXX&#039;&#039;&#039; Attribut.&lt;br /&gt;
Neben anderen Betriebs- und Energiedaten werden insbesondere folgende Daten ermittelt, die für die zukünftige Planung der Verbraucherschaltzeiten relevant sind:&lt;br /&gt;
&lt;br /&gt;
* epieces - prognostizierte Energiescheiben pro Betriebsstunde &lt;br /&gt;
&lt;br /&gt;
Ausgehend von gespeicherten historischen Verbrauchsdaten des Verbrauchers wird der Energieverbrauch des Verbrauchers in seiner ersten Betriebsstunde prognostiziert, was insbesondere für die Planung der optimalen Startzeit des Verbrauchers in Bezug zu der prognostizierten PV Energie und den Verbrauchswerten weiterer vorhandener bzw. zu planender Verbraucher Berücksichtigung findet. Weitere Informationen zur Verbrauchersteuerung in diesem  [[#Verbrauchersteuerung_-_Registrieren_und_visualisieren_von_Verbrauchern|Abschnitt]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Schnittstelle für Modulautoren bzw. eigenen Code ===&lt;br /&gt;
&lt;br /&gt;
Die im vorherigen Artikel beschriebenen internen Datenstrukturen können durch externen Code abgefragt und ausgewertet werden.&lt;br /&gt;
Dazu stehen die folgenden Funktionen zur Verfügung. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]BatteryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Bn&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valBattery&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CurrentVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valCurrent&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]InverterVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valInverter&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ProducerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valProducer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]HistoryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Day&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvHistory&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CircularVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvCircular&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]NexthoursVal (&#039;&amp;lt;Name&amp;gt;&#039;, &amp;lt;nhr&amp;gt;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... nextHours&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ConsumerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valConsumerMaster&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]RadiationAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;DateTime&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... radiationApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]WeatherAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;TimeCode&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... weatherApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StatusAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;QTag&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... statusApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StringVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valStrings&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Angabe des Packages (FHEM::SolarForecast::) ist nur notwendig wenn die Funktionen von außerhalb des SolarForecast-Devices aufgerufen werden. Innerhalb des Devices (Code-Ausführung im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039;) kann darauf verzichtet werden.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der Platzhalter sind:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     &amp;lt;Name&amp;gt;     - Name des SolarForecast Devices&lt;br /&gt;
     &amp;lt;Day&amp;gt;      - abzufragender Tag (01 - 31)&lt;br /&gt;
     &amp;lt;Bn&amp;gt;       - Batterie Nummer (01, 02, ...)&lt;br /&gt;
     &amp;lt;DateTime&amp;gt; - Startzeit der Form YYYY-MM-DD hh:00:00&lt;br /&gt;
     &amp;lt;TimeCode&amp;gt; - Zeitwert der Form fcX_XX (z.B. fc1_19)&lt;br /&gt;
     &amp;lt;APIname&amp;gt;  - Hauptname der API gemäß setupWeatherDev1 (z.B. OpenMeteo)&lt;br /&gt;
     &amp;lt;String&amp;gt;   - Name des PV-Modulstrings wie im Attribut &#039;setupInverterStrings&#039;&lt;br /&gt;
     &amp;lt;QTag&amp;gt;     - Question Tag, z.B. &#039;?All&#039;&lt;br /&gt;
     &amp;lt;Nr&amp;gt;       - laufende Nummer des Verbrauchers / Gerätes (01, 02, 03, 04,...)&lt;br /&gt;
     &amp;lt;HoD&amp;gt;      - abzufragende Stunde (01 - 24, 99)&lt;br /&gt;
     &amp;lt;nhr&amp;gt;      - nächste Stunde (NextHour00, NextHour01,...)&lt;br /&gt;
     &amp;lt;Key&amp;gt;      - der abzufragende Schlüssel &lt;br /&gt;
     &amp;lt;default&amp;gt;  - def default-Rückgabewert&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Auswerten von internen Arrays ===&lt;br /&gt;
&lt;br /&gt;
Die meisten der internen Datenstrukturen liefern bei der Abfrage einen einfachen String oder numerischen Wert der ausgewertet werden kann. Es gibt allerdings auch intern gespeicherte Wertelisten. Werden die Listenstrukturen mit den oben beschriebenen Befehlen abgefragt, wird eine Referenz auf die Liste geliefert sofern sie vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
Um auf die Werte einer solchen Liste zuzugreifen, ist am Beispiel des Arrays &#039;&#039;surplusslidereg&#039;&#039; aus dem Current-Speicher (get ... valCurrent) dargestellt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
my $splref = CurrentVal ($name, &#039;surplusslidereg&#039;, &#039;.&#039;);&lt;br /&gt;
my $spser  = ref $splref eq &#039;ARRAY&#039; ? join &#039; &#039;, @{$splref} : undef;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Variable $spser enthält bei Vorhandensein der Liste einen String, der die Listenelemente von &#039;surplusslidereg&#039; durch Leerzeichen getrennt enthält.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backup und Wiederherstellung der Moduldaten ==&lt;br /&gt;
Neben der Datenhaltung in den Attributen und Readings des SolarForecast Devices, erzeugt jedes SolarForecast Device Dateien im Verzeichnis  &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; mit folgenden Inhalten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PVH_SolarForecast_&amp;lt;name&amp;gt;        - PV History&lt;br /&gt;
PVC_SolarForecast_&amp;lt;name&amp;gt;        - PV Circular&lt;br /&gt;
PVCfg_SolarForecast_&amp;lt;name&amp;gt;      - PV Anlagenkonfiguration&lt;br /&gt;
PVCsm_SolarForecast_&amp;lt;name&amp;gt;      - Consumer Status&lt;br /&gt;
ScApi_SolarForecast_&amp;lt;name&amp;gt;      - Strahlungswerte aus verwendeter API&lt;br /&gt;
StatApi_SolarForecast_&amp;lt;name&amp;gt;    - Statusdaten der verwendeten API&#039;s&lt;br /&gt;
WeatherApi_SolarForecast_&amp;lt;name&amp;gt; - Wetterdaten der gewählten Wetter-API (außer DWD-Device)&lt;br /&gt;
AItra_SolarForecast_&amp;lt;name&amp;gt;      - KI Entscheidungsquelle (trainierte Daten)&lt;br /&gt;
AIraw_SolarForecast_&amp;lt;name&amp;gt;      - KI Input Daten = Raw Trainigsdaten&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nach Ausprägung und eingesetzten Features des SolarForecast Devices sind alle oder nur ein Teil dieser Dateien vorhanden. Dabei ist &#039;&#039;&#039;&amp;lt;name&amp;gt;&#039;&#039;&#039; der Name des SolarForecast Devices.&lt;br /&gt;
&lt;br /&gt;
Bei einem Filebackup des FHEM-Servers ist darauf zu achten, dass diese Dateien in dem Backup enthalten sind. Der Inhalt der Dateien ist nicht statisch, sondern kann sich dynamisch aktualisieren. Um im Bedarfsfall einen aktuellen Datenstand zu haben, ist mindestens ein tägliches Backup dieser Dateien empfehlenswert. Eventuell auch öfter mit Hilfe einer Versionierung welche z.B. immer die letzten 3 Versionen aufbewahrt.&lt;br /&gt;
&lt;br /&gt;
Beim Start von FHEM werden bestimmte Dateien automatisch gelesen und in das SolarForecast Device importiert. &lt;br /&gt;
Der Vorgang ist mit verbose=3 im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2023.10.02 09:57:07.967 3: SolCast6 - cached data &amp;quot;pvHistory&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.969 3: SolCast6 - cached data &amp;quot;pvCircular&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;consumerMaster&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;radiationApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;statusApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;weatherApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.974 3: SolCast6 - cached data &amp;quot;aiTrainedData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.976 3: SolCast6 - cached data &amp;quot;aiRawData&amp;quot; restored&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bestimmte Betriebsdaten, wie z.B. die witterungsabhängigen Korrekturfaktoren (circular) oder die KI-Daten (aitrained/airaw), bauen sich über die Zeit immer granularer auf und stellen einen wertvollen Datenbestand dar.&lt;br /&gt;
&lt;br /&gt;
Wird das SolarForecast Device gelöscht und anschließend wieder neu mit dem gleichen Namen definiert, können die bisher verfügbaren Daten sehr einfach wiederhergestellt werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. starten von FHEM (bestimmte Daten werden automatisch importiert)&lt;br /&gt;
* 5. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Soll das neue SolarForecast Device mit einem anderen Namen oder weitere SolarForecast Devices erstellt werden, welche die Betriebsdaten des primären Devices verwenden sollen, ist wie folgt vorzugehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. umbenenen der Dateien, wobei &amp;lt;name&amp;gt; durch den Namen des neuen SolarForecast Devices ersetzt wird&lt;br /&gt;
* 5. starten von FHEM (die Daten werden automatisch importiert)&lt;br /&gt;
* 6. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn sich die SolarForecast Devices hinsichtlich ihres Models oder der integrierten Consumer unterscheiden, sind die Dateien &amp;quot;PVCsm_SolarForecast_&amp;lt;name&amp;gt; &amp;quot; , &amp;quot;ScApi_SolarForecast_&amp;lt;name&amp;gt;&amp;quot; von dem Verfahren auszuschließen.&lt;br /&gt;
&lt;br /&gt;
== Batterieintegration und -steuerung ==&lt;br /&gt;
&lt;br /&gt;
=== Wie eine Batterie eingebunden wird ===&lt;br /&gt;
Wie immer muß die Batterieanlage zunächst mit einem für die Batterie spezifischen FHEM-Device in FHEM definiert sein.&lt;br /&gt;
In diesem Device werden Readings erwartet die folgende Werte bereitstellen:&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieentladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die installierte Batteriekapazität liefert (&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; dieser Schlüssel ist für die Aktivierung des Batterie SOC-Managements und die grafische Anzeige des SOC wesentlich!)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Lade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Entlade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* Reading welches den aktuellen Ladezustand (SOC in Prozent) liefert (optional)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Batterie, bzw. das Batteriedevice wird mit dem Attribut &#039;&#039;&#039;setupBatteryDev&#039;&#039;&#039; im SolarForecast Device registriert. Die Syntax des Attributes ist in  der Online-Hilfe zum Attribut umfassend erläutert. &lt;br /&gt;
Auch wenn manche Readings optional sind, wird empfohlen alle Werte bereitzustellen um alle Batterie-Funktionen im Modul nutzen zu können. Durch die Weiterentwicklung des Moduls können optionale Readings später auch obligatorisch werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Visualisierung der Batterie in der Balkengrafik ====&lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;setupBatteryDevXX&#039;&#039;&#039; verfügt über den Schlüssel &#039;&#039;&#039;show&#039;&#039;&#039;, mit dem die Einblendung des bzw. der Batteriesymbole in den Ebenen der Balkengrafik gesteuert werden kann:&lt;br /&gt;
[[Datei:Screenshot 2025-02-23 192002.png|right|thumb|400px|Einblendung der Batterieleiste und Darstellung des Batterie-SoC als Balkencontent in der zweiten Ebene]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 0 - keine Anzeige des Gerätes (default)&lt;br /&gt;
* 1 - Anzeige des Gerätes in der Balkengrafik Ebene 1&lt;br /&gt;
* 2 - Anzeige des Gerätes in der Balkengrafik Ebene 2 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Symbole und die Farbgebung der Batterie(n) können mittels des Schlüssels &#039;&#039;&#039;icon&#039;&#039;&#039; verändert werden. Die Online-Hilfe gibt weitere Informationen zur Ausgestaltung. &lt;br /&gt;
&lt;br /&gt;
In der Batteriedarstellung wird das Symbol der aktuellen Stunde hervorgehoben. Ein Mouse-Over zeigt wesentliche Betriebszustände der Batterie. Die Batteriesymbole vergangener Stunden zeigen mit einem Mouse-Over die erreichten SoC (State of Charge) Stände. Die kommenden Stunden visualisieren die folgenden Prognosen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der prognostizierte SoC unter Berücksichtigung der PV-Prognose und der [[#Aktivierung_des_Batterie_SOC-Managements|Batteriesteuerung]] sofern sie im Modul aktiviert ist.&lt;br /&gt;
* eine Freigabe bzw. Empfehlung der Batterieladung zur [[#Unterstützung_eines_netzdienlichen_Verhaltens|Unterstützung eines netzdienlichen Verhaltens]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Neben der Einblendung der Batterieleiste über der Balkengrafik selbst können bestimmte Batteriekennwerte als Balkeninhalt dargestellt werden. Die Auswahl erfolgt über das Attribut &#039;&#039;&#039;graphicBeamXContent&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Aktivierung des Batterie SOC- und Lade-Managements ===&lt;br /&gt;
Das integrierte SOC- und Lade-Management verfolgt insbesondere zwei Ziele: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* den Ladezustand der Batterie(n) zu optmimieren, was besonders in den Monaten mit geringerer PV-Erzeugung einen wertvollen Beitrag zur Erhöhung der Autarkierate und Batteriepflege leisten kann&lt;br /&gt;
 &lt;br /&gt;
* eine PV-Prognose und Verbrauch optimierte Beladungssteuerung, die in den Monaten mit hoher PV-Erzeugung hilft eine evtl. Abregelung der Anlage zu verhindern, die Batterie ausgewogen über den Tag zu laden und ein netzdienliches Verhalten zu unterstützen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese beiden Aspekte der Batteriesteuerung werden in den folgenden Abschnitten beschrieben. Sind mehrere Batterien installiert, kann die Steuerung getrennt für jede einzelne Batterie aktiviert und eingestellt werden. Dabei ist zu beachten, dass vom Modul nur Signale und Readings bereitgestellt werden, die durch eine entsprechende Routine ausgewertet werden können um spezifische Befehle zur Umsetzung der Steuerung an das Batteriesystem zu senden. &lt;br /&gt;
 &lt;br /&gt;
Für eine Aktivierung des Managements muß zunächst das Batterie-Device wie im vorigen Abschnitt im SolarForecast Device registriert werden.&lt;br /&gt;
Das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; aktiviert die im Modul integrierte SOC- und Lade-Management Routine: &lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; ctrlBatSocManagement01 lowSoc=&amp;lt;Wert&amp;gt; upSoC=&amp;lt;Wert&amp;gt; [maxSoC=&amp;lt;Wert&amp;gt;] [careCycle=&amp;lt;Wert&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
Die einzelnen Schlüssel werden der Kalkulationsroutine als Steuerungsparameter übergeben und bedeuten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;lowSoc:unterer Mindest-SoC, die Batterie wird nicht tiefer als dieser Wert entladen (muß &amp;gt; 0 sein). Dieser Wert kann zum Beispiel dazu dienen, stets eine Mindestenergiemenge für den Fall eines Stromausfalls im öffentlichen Netz in den Batterien vorzuhalten.&lt;br /&gt;
&lt;br /&gt;
;upSoC:oberer Mindest-SoC, Der übliche Wert des optimalen SoC bewegt sich in Perioden mit hohen PV-Überschuß tendenziell zwischen &#039;lowSoC&#039; und &#039;upSoC&#039;, in Perioden mit geringer PV-Ausbeute bzw. geringem PV Energieüberschuß bewegt sich der optimale SoC tendenziell zwischen &#039;upSoC&#039; und &#039;maxSoC&#039;. Die Einstellung von upSoC=50 für ein ausgewogenes Verhalten kann als guter Startwert dienen.&lt;br /&gt;
&lt;br /&gt;
;maxSoC:maximaler Mindest-SoC, d.h. der SoC Wert der mindestens im Abstand von &#039;careCycle&#039; Tagen erreicht werden muß um den Ladungsausgleich im Speicherverbund auszuführen. Die Angabe ist optional (muß &amp;lt;= 100 sein, default: 95)&lt;br /&gt;
&lt;br /&gt;
;careCycle:maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens &#039;maxSoC&#039; auftreten darf. Die Angabe ist optional. (default: 20)&lt;br /&gt;
&lt;br /&gt;
;loadAbort: definiert eine vom Anwender gewünnschte Bedingung für einen generellen Ladeabbruch und Wiederfreigabe der Lademöglichkeit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle Werte sind ganze Zahlen in %. Dabei gilt: &lt;br /&gt;
&lt;br /&gt;
 lowSoc &amp;lt; upSoC &amp;lt; maxSoC&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====  Erläuterung der Batterie-Steuerungsreadings ==== &lt;br /&gt;
&lt;br /&gt;
Für die Steuerung des Batteriesystems gibt es im SolarForecast einen Satz an Readings, die unterschiedliche Zustände signalisieren und für entsprechende Steuerungsaufgaben bezüglich der Batteriesysteme eingesetzt werden können. In den nachfolgenden Abschnitten werden diese Zusammenhänge noch dataillierter beschrieben.&lt;br /&gt;
&lt;br /&gt;
;Hinweis: SolarForecast stellt lediglich Steuerungsinformationen zur Verfügung. Die Umsetzung des Eingriffs in das Batteriesystem erfolgt durch den Anwender selbst über entsprechende Skripte. In den thematischen Abschnitten werden Beispiele für solche Steuerungsskripte vorgestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle erstellten Readings gelten für ein Batteriesystem, es können mehrere Batteriesysteme in SolarForecast integriert sein. Die Endung &#039;&#039;XX&#039;&#039; der Readings beschreibt die Nummer des Batteriesystems und korrespondiert mit der Endung des entsprechenden Attributes &#039;&#039;ctrlBatSocManagementXX&#039;&#039; bzw. &#039;&#039;setupBatteryDevXX&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Battery_OptimumTargetSoC_XX: Mit den im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; hinterlegten Parametern unter Berücksichtigung von PV- und Verbrauchsprognosen wird ein optimaler SOC-Wert errechnet. Dieser Wert dient zur Einstellung des unteren SOC des Batteriesystems.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeRequest_XX: Dieses Reading signalisiert mit 1 eine Anforderung zur Zwangsladung der Batterie um die Batterie vor Schäden zu schützen (wenn der SOC unter ctrlBatSocManagementXX-&amp;gt;lowSoc gefallen ist) oder wenn der aktuelle SOC unter den berechneten Mindest-SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeUnrestricted_XX: Dieses Reading kann den Wert &#039;&#039;&#039;0&#039;&#039;&#039; oder &#039;&#039;&#039;1&#039;&#039;&#039; einnehmen. Ist der Inhalt 0, sollte die Batterie nur geladen werden, wenn der im Attribut &#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039; definierte Wert überschritten wird. Ist der Inhalt 1, sollte die Batterie mit der vollen zur Verfügung stehenden Ladeleistung angesteuert werden, um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeAbort_XX: Im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; kann mit dem Schlüssel &#039;&#039;loadAbort&#039;&#039; eine Bedingung definiert werden, bei deren Eintritt die Ladung der Batterie abgebrochen werden soll. In diesem Fall wird &#039;&#039;Battery_ChargeAbort_XX=1&#039;&#039; gesetzt. Mit einem entsprechenden Befehl kann der Anwender das Batteriesystem anweisen den Ladevorgang abzubrechen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Nutzung des Batterie SOC-Management ====&lt;br /&gt;
&lt;br /&gt;
Oftmals wird durch die Anlagenhersteller ein hoher statischer SOC eingestellt bzw. empfohlen, der eine längere Verharrungszeit auf einem tiefen SOC-Wert verhindern soll. Allerdings wechseln sich in auch in den Herbst-, Frühlings- und Wintermonaten Zeiten mit wenig PV-Erzeugung mit Phasen stärkerer Solarstrahlung bei klarem Himmel und Sonnenschein ab.&lt;br /&gt;
&lt;br /&gt;
Ein statischer SOC würde dazu führen, dass in den erwähnten Phasen zuviel Energie in das öffentliche Netz eingespeist wird. Dies soll verhindert werden da die wertvolle Energie besser im eigenen Netz gespeichert und in Dunkelphasen verwendet werden kann. Andererseits soll die Batterie nicht zu lange auf einem tiefen SOC verbleiben und außerdem in gewissen Abständen auf einen so hohen SOC geladen werden der den internen Zellausgleich ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Die SOC Kalkulationsroutine des Moduls errechnet unter Berücksichtigung des prognostizierten PV-Ertrages der kommenden Tage, des aktuellen SOC und der im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; (nachfolgend beschrieben) angegebenen Steuerparameter den Vorschlag für eine optimale SOC-Einstellung. Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert.&lt;br /&gt;
&lt;br /&gt;
Durch das Modul selbst findet keine Steuerung der Batterie statt. Es stellt entsprechende Readings zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen SoC.&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SoC unter den optimalen SoC gefallen ist. In diesem Fall sollte die Batterie, unter Umständen mit Netzstrom, zwangsgeladen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Readings können zur Steuerung des SoC (State of Charge) sowie zur Steuerung des verwendeten Ladestroms der Batterie verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ermittlung des optimalen SOC erfolgt nach folgender Logik:&lt;br /&gt;
&lt;br /&gt;
# 	Ausgehend von &#039;lowSoc&#039; wird der Mindest-SoC kurz vor Sonnenuntergang um 5% inkrementiert sofern am laufenden Tag &#039;maxSoC&#039; nicht erreicht wurde und die PV-Prognose keinen hinreichenden Ertrag des kommenden Tages vorhersagt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Wird &#039;maxSoC&#039; (wieder) erreicht, wird Mindest-SoC um 5%, aber nicht tiefer als &#039;lowSoc&#039;, verringert. Ist der berechnete Mindest-SoC größer als &#039;upSoc&#039;, wird der Mindest-SoC auf &#039;upSoc&#039; gesetzt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#   Mindest-SoC wird soweit verringert, dass die prognostizierte PV Energie des aktuellen bzw. des folgenden Tages von der Batterie aufgenommen werden kann. Mindest-SoC wird typisch auf &#039;upSoc&#039; und nicht tiefer als &#039;lowSoc&#039; verringert.  &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Das Modul erfasst den letzten Zeitpunkt am &#039;maxSoC&#039;-Level, um eine Ladung auf &#039;maxSoC&#039; mindestens alle &#039;careCycle&#039; Tage zu realisieren. Zu diesem Zweck wird der optimierte SoC in Abhängigkeit der Resttage bis zum nächsten &#039;careCycle&#039; Zeitpunkt derart verändert, dass durch eine tägliche 5% SoC-Steigerung &#039;maxSoC&#039; am &#039;careCycle&#039; Zeitpunkt rechnerisch erreicht wird. Wird zwischenzeitlich &#039;maxSoC&#039; erreicht, beginnt der &#039;careCycle&#039; Zeitraum erneut. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im fünften Schritt werden die Grenzen &#039;lowSoc&#039; und &#039;upSoc&#039; berücksichtigt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im letzten Schritt erfolgt Generierung des Readings &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; zur Signalisierung einer eventuell empfohlenen Zwangsladung auf den berechneten Min-SoC. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei sehr wenig Erzeugungungsprognose, d.h. wenn sich der berechnete Min-SoC oberhalb von &#039;upSoC&#039; bewegt, wird &#039;upSoC&#039; eingestellt. Liegt der berechnete Min-SoC unterhalb von &#039;upSoC&#039;, ist jedoch größer als &#039;lowSoC&#039;, wird der berechnete SOC im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; eingestellt. Somit eignet sich die Angabe im Schlüssel &#039;upSoC&#039; um in Zeiten geringer Solarenergieerzeugung die Batterie für eine Notstromerzeugung auf mindestens diesem Wert zu halten. Sollte die PV-Prognose kurzfristig einen größeren Ertrag vorhersagen als die Batterie durch die Einhaltung von &#039;upSoC&#039; aufnehmen kann, wird der Min-SoC unter &#039;upSoC&#039; abgesenkt um möglichst allen PV-Überschuß in der Batterie zu speichern und somit dem Eigenverbrauch zuzuführen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der berechnete Mindest-SoC ist immer nur ein unterer Grenzwert. Die Batterie kann durch Ladevorgänge natürlich jederzeit einen höheren als den im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; dargestellten optimalen SoC haben. Der optimale SoC sollte nicht unterschritten werden um die oben genannten Zusammenhänge abbilden zu können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Die dynamische SOC Steuerung mit Umsetzungsbeispiel =====&lt;br /&gt;
Das Modul bietet eine Unterstützung zur automatisierten Einstellung eines optimalen SoC Wertes.&lt;br /&gt;
&lt;br /&gt;
Ziel ist es, den Minimum SoC in Abhängigkeit der zu erwartenden Solarerträge des aktuellen und des folgenden Tages so einzustellen, dass der prognostizierte Solarertrag von der Batterie aufgenommen werden kann. Die Einspeisung in das öffentliche Netz soll minimiert werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin soll ein unterer SoC nicht unterschritten, sowie ein oberer Minimum SoC im Normalfall nicht überschritten werden. Der obere Grenzwert stellt sicher, dass die Batterie mindestens bis zu diesem Wert wieder entladen werden kann. Dadurch bleibt innerhalb der Batterie immer genügend Kapazität verfügbar um unvorhergesehene PV Energie aufnehmen zu können.&lt;br /&gt;
&lt;br /&gt;
Aktiviert wird die Unterstützung der Batteriesteuerung durch das Setzen des Attributes &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; z.B. mit diesen Angaben:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagementXX lowSoc=x upSoC=x maxSoC=x careCycle=x &lt;br /&gt;
&lt;br /&gt;
so zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=98 careCycle=20&lt;br /&gt;
&lt;br /&gt;
Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert. &lt;br /&gt;
Ist dieses Attribut gesetzt, werden Steuerungs-Readings erstellt, die der Nutzer auswerten und seine Batterieanlage z.B. via notify oder DOIF steuern kann. &amp;lt;bR&amp;gt;&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen Mindest-SoC.&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SOC unter den optimalen SOC bzw. minimalen SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
Die Schlüssel &#039;&#039;&#039;lowSoc&#039;&#039;&#039; und &#039;&#039;&#039;upSoC&#039;&#039;&#039; sind die unteren und oberen Grenzen, zwischen denen sich der Minimum SoC im normalen Betrieb bewegen soll.&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;maxSoC&#039;&#039;&#039; stellt eine Ladungsgrenze dar, die mindestens alle X (careCycle) Tage erreicht werden soll. Zu diesem Zweck errechnet das Modul die Anzahl der nötigen Erhöhungen der Minimum Batterieladung von 5% pro Tag um ausgehend vom aktuellen SoC-Level. Der resultierende Minimum SoC Wert wird entsprechend angepasst. Wurde der einstellte maxSoC Level erreicht, startet der Wartungszyklus (careCycle) erneut. &amp;lt;br&amp;gt;&lt;br /&gt;
Der maxSoC in Verbindung mit dem durch &#039;&#039;&#039;careCycle&#039;&#039;&#039; definierten Zyklus soll sicherstellen, dass der Batterieverbund in regelmäßigen Abständen einen Ladungsausgleich vollziehen kann. &lt;br /&gt;
&lt;br /&gt;
Durch die Modullogik erfolgt eine 5 protentige Anhebung des Minimum SoC wenn am Vortag maxSoC nicht erreicht wurde. Die Anhebung erfolgt aber nicht über upSoC. upSoC ist die obere Grenze des Minimum SoC. Wird am Vortag mindestens die maxSoC Ladung erreicht, verringert sich der Minimum SoC wieder schrittweise um 5%, aber nicht tiefer als lowSoc.&lt;br /&gt;
&lt;br /&gt;
Ergänzt wird die Logik noch um die PV Vorhersage. Dabei wird die obige Minimum SoC Berechnung um die Erwartung der PV Erwartung am aktuellen und folgenden Tag korrigiert. Das bedeutet, dass der Minimum SoC z.B. von heute 50% auf 10% abgesenkt und dadurch die gespeicherte Energie dem Haushalt zugeführt wird, wenn am heutigen oder kommenden Tag eine entsprechende PV Energie zu erwarten ist um die Batterie wieder vollständig zu zuladen.&lt;br /&gt;
Dadurch ist immer genügend &amp;quot;Freiplatz&amp;quot; in der Batterie und andererseits hat die Batterie in langen Dunkelphasen eine Reserve für einen eventuellen Stromausfall (falls der abgesichert werden soll) und wird vor einem dauerhaften tiefen SoC geschützt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Umsetzungsbeispiel =====&lt;br /&gt;
&lt;br /&gt;
Wie das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; genutzt werden kann, wird am Beispiel einer Victron Batterieanlage gezeigt. Die Anlage wird durch Cerbo GX Gerät gesteuert. Der Cerbo GX ist per MQTT2 in FHEM eingebunden. Umgesetzt ist die Steuerung der Batterie &#039;01&#039;, d.h. die Angabe &#039;XX&#039; ist durch &#039;01&#039; ersetzt.&lt;br /&gt;
&lt;br /&gt;
Die folgende kleine Logik ist in einem &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; File eingebaut und wird regelmäßig mit&lt;br /&gt;
&lt;br /&gt;
 batSocChargeMgmnt (&#039;&amp;lt;Name SolarForecast Device&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
aufgerufen. Der Aufruf erfolgt durch Angabe der Routine im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; des SolarForecast Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
  # Hinweis: die Zeichen &#039;::&#039; vor der Routine sind durch das SolarForecast Package bedingt&lt;br /&gt;
  ::batSocChargeMgmnt ($name);&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Routine wird dadurch automatisch am Ende jedes Zyklus (siehe Attribut plantControl-&amp;gt;cycleInterval) ausgeführt.&lt;br /&gt;
Um die SOC Managementfunktion nach Bedarf ein- bzw. ausschalten zu können wird zunächst im SolarForecast Device ein userattr zur Steuerung der SOC-Logik angelegt:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; userattr userFn_BatterySoCManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
Die Perl Routine &#039;&#039;&#039;batSocChargeMgmnt&#039;&#039;&#039; ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#  Batterie SOC und Max. Ladestrom Management&lt;br /&gt;
############################################################################&lt;br /&gt;
sub batSocChargeMgmnt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vebus   = &#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;;                            # Victron Vebus Device&lt;br /&gt;
  my $vicsets = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                         # Victron Einstellungen&lt;br /&gt;
&lt;br /&gt;
  my $maxcspc = 105;                                                           # max. Ladestrom (A) Victron MPII Verbund&lt;br /&gt;
  my $actmcc  = ReadingsNum ($vebus, &#039;MaxChargeCurrent&#039;, undef);               # akt. Ladestromeinstellung&lt;br /&gt;
  my $load    = $actmcc // $maxcspc;                                           # Soll-Ladestrom (A)&lt;br /&gt;
&lt;br /&gt;
  ## Battery SoC Management&lt;br /&gt;
  ###########################&lt;br /&gt;
  my $ubsm = AttrVal ($name, &#039;userFn_BatterySoCManagement&#039;, &#039;aus&#039;); &lt;br /&gt;
  &lt;br /&gt;
  if ($ubsm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name,    &#039;Battery_ChargeRequest_01&#039;,     0);&lt;br /&gt;
    my $csoc = ReadingsNum ($vicsets, &#039;MinimumSocLimit&#039;,             10);      # akt. SoC&lt;br /&gt;
    my $osoc = ReadingsNum ($name,    &#039;Battery_OptimumTargetSoC_01&#039;, 10);      # Soll-SoC&lt;br /&gt;
    my $surp = ReadingsNum ($name,    &#039;Current_Surplus&#039;,              0);      # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if ($csoc != $osoc) {&lt;br /&gt;
      CommandSet (undef, &amp;quot;$vicsets MinimumSocLimit $osoc&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn SoCMgmnt -&amp;gt; MinimumSocLimit in $vicsets set to $osoc %});&lt;br /&gt;
    }&lt;br /&gt;
	                                           &lt;br /&gt;
    if ($bcrq &amp;amp;&amp;amp; $surp &amp;lt; 1000) {                                              # max. Strom b. Battery_ChargeRequest &lt;br /&gt;
      $load = 21;&lt;br /&gt;
    }&lt;br /&gt;
	else {&lt;br /&gt;
	  $load = $maxcspc;&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Batterie Einstellung MaxChargeCurrent&lt;br /&gt;
  ##########################################&lt;br /&gt;
  if ($load != $actmcc) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$vebus MaxChargeCurrent $load&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
    Log3 ($name, 3, qq{$name - userFn ChargeMgmnt -&amp;gt; MaxChargeCurrent in $vebus set }.&lt;br /&gt;
                    qq{from old $actmcc A to $load A});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent_set&#039;, $load, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist im SolarForecast Device das Reading  &#039;&#039;&#039;Battery_ChargeRequest_01&#039;&#039;&#039; gesetzt, ist der aktuelle SOC kleiner als der optimale SOC und die Batterie wird (eventuell aus dem öffentlichen Netz) geladen. Das kann automatisch durch den Cerbo GX bzw. in anderen Anlagen durch einen entsprechenden Befehl erfolgen.&lt;br /&gt;
Damit die Netzbeladung nicht mit der vollen Ladestromstärke geschieht, wird der Ladestrom auf den gewünschten Wert (hier 21 A -&amp;gt; ca. 1000 W bei einem 48V System) reduziert sofern kein oder zu wenig PV-Überschuß vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== weitere mögliche Aspekte der SOC- und Batterieladesteuerung ====&lt;br /&gt;
&lt;br /&gt;
SolarForecast liefert durch seine internen Logiken bereits sehr hilfreiche Signale zur Steuerung von Batteriesystemen in Form von Readings an. Abhängig von den individuellen Möglichkeiten der vorhandenen Anlage käme zum Beispiel zusätzlich zu einer Steurung des optimalen SOC oder der Zeitfenster für die Batterieaufladung auch eine Steuerung des Ladestroms bzw. der verwendeten Ladeleistung in Betracht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hintergründe:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Das Laden eines Akkus mit möglichst gleichbleibender und geringer Leistung wirkt sich positiv auf dessen Langlebigkeit aus, was u.a. auch daran liegt, dass der Temperaturstreß im Akku bei langsamer Energiezuführung nur gering ist.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom führt zu einem geringen Absacken der Akkuspannung beim (ggf, temporären) Abschalten des Ladestroms, was sich positiv auf die SOC-Schätzung auswirkt.&lt;br /&gt;
    &lt;br /&gt;
* Ein geringer Ladestrom führt, insb. bei Nutzung passiver Balancer (sind in den Akku-Systemen üblicherweise verbaut), zu einer geringen Differenz zwischen den einzelnen Zellspannungen und damit zu einer besseren Kapazitätsausnutzung eins Akkus.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom kann zu einem zeitlich punktgenauen Zielfüllstand (im Winter 100%, ansonsten natürlich weniger) am Ende des Tages führen.&lt;br /&gt;
    &lt;br /&gt;
* Eine geringer Ladestrom führt auch zu geringen Leitungsverlusten, da der Strom quadratisch zu den Leitungsverlusten beiträgt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann auch die Verweildauer oder die Begrenzung des SOC, auf den die Batterie maximal geladen werden soll, Gegenstand von Optimierungen sein.&lt;br /&gt;
&lt;br /&gt;
Die häufig zu findende Empfehlung, Akkus nicht zu lange bei einem SOC von 100% verweilen zu lassen, liegt weniger an dem SOC als solchem, sondern daran, dass &#039;&#039;SOC=100%&#039;&#039; üblicherweise dadurch ermittelt wird, dass eine Zelle im Akku einen Spannungsschwellenwert überschreitet, der – würde dieser Schwellenwert zeitlich länger überschritten sein – zu einer Schädigung des Akkus führen könnte. Schädlich sind insbesondere häufige Nachladevorgänge bei Werten um die 100% SOC, da Zellen dann ja häufiger und damit - integral gesehen - auch länger den o.g. Schwellenwert überschreiten.&lt;br /&gt;
&lt;br /&gt;
Einige Akku-Hersteller, z.B. BYD, haben auf o.g, Grund in der (neueren) Firmware Ihrer Systeme einen SOC-Threshold (bei BYD liegt dieser bei 95%) eingebaut. Dieser Wert muss nach einem erreichten SOC von 100% unterschritten  werden, bevor überhaupt eine weitere Ladung erfolgt. Insbesondere in der dunklen Jahreszeit kann es daher sinnvoll sein, den Akku unter Verwendung von PV-Leistung so zu füllen, dass dieser möglichst nur einmal vor Einbruch der Dunkelheit auf &#039;&#039;SOC=100%&#039;&#039; geladen wird. Hierbei sollte darauf geachtet werden, dass der Ladeschlussstrom des jeweiligen Systems nicht unterschritten wird. &lt;br /&gt;
&lt;br /&gt;
SolarForecast unterstützt die oben betrachtete Batteriesteuerung durch die optionale Angabe von &#039;&#039;&#039;loadAbort&#039;&#039;&#039; im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039;. Das in diesem Kontext erstellte Reading &#039;&#039;&#039;Battery_ChargeAbort_XX&#039;&#039;&#039; stellt die auswertbaren Steuerungsinformationen zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== PV-Prognose und Verbrauch optimierte Beladungssteuerung unter Berücksichtigung einer Wirkleistungsbegrenzung ====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-04-25 143910.png|right|thumb|400px|Batterie Popup &amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Batterie geladen. sobald PV-Überschuß vorhanden ist ohne eine Prognose zu berücksichtigen. Dadurch sind die Batterien im Sommer unter Umständen schon um 10-12 Uhr voll geladen und die Anlage liefert ihre mehr oder weniger volle Energie (je nach Ausrichtung) in das öffentliche Netz. Dann könnte es zu einer Begrenzung der PV-Leistung durch einen Schwellenwert (z.B. 70%-Regelung) oder eventuell Zwangsabregelung durch den Netzbetreiber kommen.&lt;br /&gt;
&lt;br /&gt;
Hintergrund dieser Erweiterung ist das Bestreben, eine optimale Unterstützung bei der Maximierung des Eigenverbrauchs zu geben und einen Beitrag zur Netzstabilität zu leisten.&lt;br /&gt;
Das Ziel der Beladungssteuerung der Batterie ist es, die Ladung der Batterie über den Tag verteilt so zu steuern, dass die Batterie erst dann geladen wird, wenn durch den PV-Überschuß eine Netzeinspeisung erfolgen würde bzw. ein Grenzwert erreicht werden würde, der zu einer Abregelung der PV-Anlage führen könnte.&lt;br /&gt;
Es kann auch zu einer Zwangsabregelung durch den Netzbetreiber führen, was vermieden werden soll.&lt;br /&gt;
 &lt;br /&gt;
Die interne Kalkulationslogik erstellt zu diesem Zweck ein Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039;.&lt;br /&gt;
Dieses Reading gibt dem User ein Signal, ob zu der aktuellen Stunde der Ladevorgang der Batterie freigegeben (1) oder nicht freigegeben werden sollte (0). Die Freigabe zur Ladung bedeutet dass:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; die Batterie mit ihrer vollen Ladeleistung angesteuert werden sollte um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=0&#039;&#039;&#039; die Batterie nur geladen werden sollte wenn der im Attribut plantControl-&amp;gt;feedinPowerLimit definierte Wert überschritten wird&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ist keine Freigabe zur Ladung vorhanden, kann bzw. sollte dennoch eine Ladung der Batterie vorgenommen werden, sofern eine über dem im &amp;lt;br&amp;gt;&lt;br /&gt;
Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limit liegende Einspeiseleistung vorhanden ist. In diesem Status sollte die Batterie nur mit der Differenzleistung von vorhandener Einspeiseleistung und dem gesetzen Einspeiselimit geladen werden und damit das gesetzte Einspeiselimit einhalten ohne die Anlage abzuregeln. Ist die Batterie in einer Balkengrafikebene dargestellt, wird im Mouse-Over Popup die Battrie mit &#039;&#039;&amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;&#039;&#039; gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Möglichkeiten der Batteriesteuerung sind stark von der individuellen Anlage abhängig und können hier nicht beschrieben werden. Ein Umsetzungsbeispiel mit einer Victron-Anlage mit Pylontech Batterie ist weiter unten dargestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Aktivierung und Arbeitsweise =====&lt;br /&gt;
&lt;br /&gt;
Die implementierte Logik zur optimierten Batterie Beladungssteuerung wird aktiviert, wenn folgende Kriterien erfüllt sind: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;capacity&#039;&#039;&#039; in den setupInverterDevXX Atributen ist gesetzt&lt;br /&gt;
* das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; für die jeweilige Batterie ist gesetzt&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;cap&#039;&#039;&#039; im Attribut setupBatteryDevXX der jeweiligen Batterie ist gesetzt&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Die Logik arbeitet wie folgt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Der resultierende Schwellenwert der Wirkleistungsbegrenzung: der Gesamtanlage wird durch die Auswertung der in den Inverter-Attributen setupInverterDevXX  gesetzen Schlüssel limit (optional) und capacity ermittelt. Inverter mit gesetztem Schlüssel feed = grid (deren Energie wird ausschließlich in das öffentlich Netz eingespeist) werden von der Betrachtung in diesem Kontext ausgeschlossen.&lt;br /&gt;
&lt;br /&gt;
;Die benötigte Beladung bis zu maxSoC (im Attribut setupBatteryDevXX) : wird ermittelt und mit der zu erwartenden PV Tagesprognose in Beziehung gesetzt. Sofern die PV-Erzeugung abzgl. Verbrauch noch nicht das Wirkleistungbegrenzungs-Limit erreicht UND noch genügend PV-Überschuß für eine Ladung auf &#039;&#039;maxSoC&#039;&#039; im Laufe der kommenden Stunden des Tages zu erwarten ist, bleibt das Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 0&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
;Wird das Wirkleistungbegrenzungs-Limit erreicht/überschritten und/oder die PV-Überschußprognose: zzgl. eines Sicherheitspuffers unterschritten, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 1&#039;&#039;&#039; gesetzt. Der User kann darauf reagieren und den Batterie Ladevorgang aktivieren. Die Möglichkeiten der Aktivierung sind natürlich von der installierten Anlage abhängig. Das SolarForecast Device greift nicht in die Batteriesteuerung direkt ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders ausgedrückt erfolgt immer dann eine Ladefreigabe, wenn einer der nachfolgenden Sachverhalte &#039;&#039;wahr&#039;&#039; ist:&lt;br /&gt;
&lt;br /&gt;
- die benötigte Ladeenergie (aller installierten Batterien) &amp;gt;= PV-Restüberschuß des Tages (Reading RestOfDayPVforecast) zzgl. Sicherheitsaufschlag&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- der Zeitpunkt des PV-Erzeugungszenit des laufenden Tages überschritten ist (Reading Today_MaxPVforecastTime)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn die aktuelle PV Leistung &amp;gt;= einer eventuellen Wechselrichter-Leistungsbegrenzung ist (Summe aller WR-Begrenzungen)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn das BatSoc-Management _nicht_ aktiviert ist (nicht alle oben genannten Aktivierungskriterien erfüllt sind)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind mehrere Batterien installiert und durch das Management einer Batterie die Einhaltung der genannten Kriterien bzw. Sachverhalte erwirkt wird, bleiben die weiteren Batterien im Modus Ladefreigabe (Battery_ChargeUnrestricted_XX=1).  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Umsetzungsbeispiel Batterie Ladesteuerung mit Victron GX Venus über den Grid Setpoint =====&lt;br /&gt;
&lt;br /&gt;
Ziel der Steuerung ist es abhängig vom Wert des Readings Battery_ChargeUnrestricted_XX (z.B. Battery_ChargeUnrestricted_01) die Ladung des angeschlossenen Batteriesystems zu aktivieren bzw. zu deaktivieren.&lt;br /&gt;
Das vorliegende Beispiel soll umzusetzen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 0 -&amp;gt; Batterie nicht aufladen bzw. nur laden wenn Einspeiselimit überschritten (Attribut plantControl-&amp;gt;feedinPowerLimit)&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 1 -&amp;gt; Batterie aufladen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Grid Setpoint ist ein Parameter in den Victron Systemeinstellungen. Das Victron System wird den eingestellten Grid Setpoint versuchen einzuhalten und bei einem positiven Wert Energie aus dem Netz beziehen bzw. bei einem negativen Grid Setpoint Energie in das Netz einspeisen.&lt;br /&gt;
&lt;br /&gt;
Normalerweise wird das Victron System die erzeugte PV Energie zunächst zur Deckung des Hausverbrauchs verwenden, ist dann noch ein PV Überschuß vorhanden, die Batterien aufladen und bei weiter vohandenen PV Überschuß diese Energie in das öffentliche Netz einspeisen sofern dem System eine Einspeisung erlaubt ist. Anderenfalls werden die Wechselrichter oder MPPT Smartloader heruntergeregelt bzw. limitiert. &lt;br /&gt;
&lt;br /&gt;
In der Standardeinstellung ist beim Victron System ein Grid Setpoint von ca. 20 bis 50 Watt, d.h. das System strebt danach diese Vorgabe zu erfüllen zieht ständig Energie in diesem Bereich aus dem öffentlich Netz von einem gelegentlichen Überschwingen der Regelung abgesehen. Damit ein eventueller PV Überschuß nicht zum Laden der Batterie verwendet, sondern statt dessen in das öffentliche Netz eingespeist wird, muß der Grid Setpoint um diesen Betrag abgesenkt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-24 114403.png|right|thumb|400px|Integration des Grid Setpoint-Managements in den Own_Spec-Bereich]]&lt;br /&gt;
&lt;br /&gt;
Damit man später per Attribut bzw. über den [[#Formatierung_der_Inhalte_im_Bereich_&amp;quot;Graphic_Header_Own_Specification&amp;quot;|Own_Spec-Bereich]] die automatische Ladesteuerung über den Grid Setpoint ein- bzw. ausschalten kann, legen wir ein userattr an:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 userattr &amp;lt;Name&amp;gt; userFn_GridSetpointManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin sind einige Vorbereitungen im Device MQTT2_cerboGX_c0619ab34e08_settings vorzunehmen. Dieses Device ist im vorliegenden Beispiel ein in FHEM vorhandenes MQTT2_DEVICE, über das die Victron CerboGX Einstellungen zugreifbar sowie einstellbar sind. Die Vorgehensweise zur Erstellung des MQTT2_DEVICE ist hier nicht beschrieben und wird vorausgesetzt.&lt;br /&gt;
&lt;br /&gt;
Damit ein entsprechender Set-Befehl zur Einstellung des Grid Setpoints vorhanden ist, werden folgende Attribute gesetzt:&lt;br /&gt;
&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings jsonMap Settings_CGwacs_AcPowerSetPoint_value:GridSetpoint&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings setList GridSetpoint W/c0619ab34e08/settings/0/Settings/CGwacs/AcPowerSetPoint {&amp;quot;value&amp;quot;:$EVTPART1}&lt;br /&gt;
&lt;br /&gt;
Nach dieser Attributierung kann mit einem &amp;quot;&#039;&#039;set MQTT2_cerboGX_c0619ab34e08_settings GridSetpoint &amp;lt;Wert&amp;gt;&#039;&#039;&amp;quot; der Grid Setpoint eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Das Attribut userFn_GridSetpointManagement kann nun im Perl Code ausgewertet werden um das Grid Setpoint-Management ein- bzw. auszuschalten.&lt;br /&gt;
Der nachfolgende Code wird in die Datei &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; eingefügt. Ist diese Datei nicht vorhanden, legen wir sie vorab als Kopie der ausgelieferten 99_myUtils.pm an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Steuerung Start/Stop der Batterieladung über den Victron Grid Setpoint&lt;br /&gt;
############################################################################&lt;br /&gt;
sub gridSetpointMgmt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vicsets   = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                               # Device Victron Einstellungen&lt;br /&gt;
  my $gspdef    = 20;                                                                  # Default Einstellung des Grid Setpoint&lt;br /&gt;
  my $targetgsp = $gspdef;                                                             # Voreinstellung Grid Setpoint&lt;br /&gt;
  my $neggspmax = FHEM::SolarForecast::CurrentVal ($name, &#039;feedinPowerLimit&#039;, 5000);   # max. gewünschte Einspeiseleistung in Watt&lt;br /&gt;
  $neggspmax    = $neggspmax * -1;&lt;br /&gt;
  my $gspm      = AttrVal ($name, &#039;userFn_GridSetpointManagement&#039;, &#039;aus&#039;);             # Freischaltung des Grid Setpoint-Managements&lt;br /&gt;
  my $curgsp    = ReadingsNum ($vicsets, &#039;GridSetpoint&#039;,         $gspdef);             # aktuelle Einstellung Grid Setpoint&lt;br /&gt;
  &lt;br /&gt;
  if ($gspm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name, &#039;Battery_ChargeUnrestricted_01&#039;, 0);         # Ladefreigabe (1 -&amp;gt; Bat Ladefreigabe)&lt;br /&gt;
    my $surp = ReadingsNum ($name, &#039;Current_Surplus&#039;,               0);         # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if (!$bcrq) {                                                               # Grid Setpoint absenken wenn keine .. &lt;br /&gt;
        $targetgsp = $gspdef - $surp;                                           # ..Batterie Ladefreigabe&lt;br /&gt;
        $targetgsp = $neggspmax if($targetgsp &amp;lt; $neggspmax);                    # Begrenzung der Einspeiseleistung&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($curgsp != $targetgsp) {&lt;br /&gt;
	  fhem (&amp;quot;set $vicsets GridSetpoint $targetgsp&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn gridSetpointMgmt -&amp;gt; GridSetpoint in $vicsets set to $targetgsp});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Victron_GridSetpoint_set&#039;, $targetgsp, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Vergleich des Setpoints mit der Vorgabe von &#039;&#039;$neggspmax&#039;&#039; dient dazu die maximale Einspeiseleistung in das öffentliche Netz zu begrenzen. Ist diese Grenze erreicht, wird der noch verbleibende Überschuß in die Batterie geladen. Dadurch wird eine Abregelung der Anlage vermieden wenn der Schwellenwert &#039;&#039;$neggspmax&#039;&#039;erreicht ist sofern die Batterie aufnahmefähig ist und nicht voll geladen ist. &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::gridSetpointMgmt  ($name);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zum Management des automatischen Grid Setpoint und der Anzeige des eingestellten Wertes wird das Attribut und die Readinganzeige in den Own_Spec-Bereich eingebunden, z.B.:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; graphicHeaderOwnspec  #Settings&lt;br /&gt;
                                   SetPoint&amp;amp;nbsp;Management:userFn_GridSetpointManagement&lt;br /&gt;
                                   Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Unterstützung eines netzdienlichen Verhaltens ====&lt;br /&gt;
&lt;br /&gt;
Der Steuerungsprozess der Batterieanlage leistet insgesamt einen kleinen Beitrag zur Netzstabilität, indem die Speicherladung in den Zeitraum der meisten prognostizierten Überschußeinspeisung gelegt wird. Im Sommer kann sich dieser Zeitraum in die Zeit nach dem Maxmimum des prognostizierten PV-Überschusses verlagern, wenn auch danach noch genügend Überschußenergie zu Volladung der Batterie prognostiziert wird. In dem Zusammenhang sollte im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; ein Einspeiselimit gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zur Verdeutlichung soll das Beispiel dienen:&lt;br /&gt;
&lt;br /&gt;
* die Batterie ist zu 60% geladen &lt;br /&gt;
* der User hat upSoC=40 eingestellt&lt;br /&gt;
* der User hat maxSoC=90 eingestellt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Am Vormittag ist genügend Sonne vohanden, das Maximumum der Energie über die Zeit wird aber noch erwartet. &lt;br /&gt;
Zu diesem Zeitpunkt wird das Reading  &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039; auf den Wert &amp;quot;0&amp;quot; gesetzt. Durch den Nutzer erfolgt daraufhin, zum Beipiel über ein Notify, ein anlagenspezifischer Befehl &amp;quot;Ladestop&amp;quot; an die Batterieanlage. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ab diesem Moment wird:&lt;br /&gt;
&lt;br /&gt;
# die Batterie nicht geladen&lt;br /&gt;
# die erzeugte PV-Energie dem Haushalt zur Verfügung gestellt bzw. der verbleibende Überschuß eingespeist, sofern der Überschuß unterhalb des im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limits liegt.&lt;br /&gt;
# ein eventuell über dem Limit &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; vorhandener Überschuß in die Batterie geladen und so die Netzlast verringert sowie die Batterie schonend geladen. (dieser Punkt trifft in den Monaten mit wenig PV-Erzeugung eher nicht zu)  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig liefert die Batterie Energie an das Hausnetz und wird von 60% bis maximal einem SoC-Wert entladen, der durch die [[#Die_dynamische_SOC_Steuerung_mit_Umsetzungsbeispiel|dynamische SOC Steuerung]] bestimmt wird. Dazu muß diese Steuerung natürlich implementiert sein. Sofern der berechnete SoC größer als upSoC ist, wird der maximale Entladungs-SoC auf upSoC gesetzt. &lt;br /&gt;
&lt;br /&gt;
Zusätzlich überprüft das Modul permanent bei jedem Zyklus die Differenz des aktuell vorhandenen SoC zum eingestellten maxSoC.&lt;br /&gt;
Sie soll nicht größer sein um mit dem (noch) zu erwartenden PV-überschuß des Tages der eingestellte maxSoC bzw. dessen Nähe wahrscheinlich erreicht werden kann. &lt;br /&gt;
Sollte der Differenz-Grenzwert erreicht sein, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; gesetzt und der Nutzer sollte dann über einen geeigneten Befehl seine Anlage in den Modus &amp;quot;Laden&amp;quot; umschalten.&lt;br /&gt;
Dieser Vorgang kann beliebig oft während des Tages alternieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Nutzung von batteryTrigger ===&lt;br /&gt;
Ergänzt werden die Möglichkeiten durch das set-Kommando: &lt;br /&gt;
&lt;br /&gt;
 batteryTrigger &amp;lt;1on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;1off&amp;gt;=&amp;lt;Wert&amp;gt; [&amp;lt;2on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;2off&amp;gt;=&amp;lt;Wert&amp;gt; ...] &lt;br /&gt;
&lt;br /&gt;
Das Kommando setzt Triggerpunkte bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %).&lt;br /&gt;
&lt;br /&gt;
Der verwendete SoC wird als resultierender SoC als Summe der aktuellen Ladung aller registrierten Batterie-Geräte im Verhältnis zur installierten Gesamtkapazität gebildet. Das bedeutet, dass alle einzelnen Batterie-Geräte als ein gemeinsamer Cluster betrachtet werden. &lt;br /&gt;
&lt;br /&gt;
Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise definiert werden.&lt;br /&gt;
Überschreiten die letzten drei SoC-Messungen eine definierte Xon-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = on&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
Unterschreiten die letzten drei SoC-Messungen eine definierte Xoff-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = off&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
&lt;br /&gt;
Der Inhalt der Readings kann durch ein User-Programm oder, bei Erzeugung von entsprechenden Events, mittels notify-Device ausgewertet werden um bei Eintreten eines definierten Ereignisses entsprechende Reaktionen auszulösen. Das kann zum Beispiel die Freigabe eines Heizstabes oberhalb eines bestimmten SOC sein oder ein Entladeverbot der Batterie unterhalb eines SOC-Wertes um Reserven für einen eventuellen Stromausfall zu behalten.&lt;br /&gt;
&lt;br /&gt;
Damit die Batterietrigger dynamisch geändert werden können, ist die Einstellung als Set-Kommando und nicht als Attribut ausgeführt.   &lt;br /&gt;
&lt;br /&gt;
Alle Triggerpunkte können mit dem set-Befehl:&lt;br /&gt;
&lt;br /&gt;
 reset batteryTriggerSet&lt;br /&gt;
&lt;br /&gt;
wieder gelöscht werden.&lt;br /&gt;
&lt;br /&gt;
== Verbrauchersteuerung - Registrieren und visualisieren 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;
Die Eigenschaften und das Schaltverhalten wird durch die Angabe der verfügbaren Schlüssel gesteuert. Die Möglichkeiten sind sehr umfangreich. Die nachfolgenden Abschnitte beschreiben die Verwendung am Beispiel oft vorkommender bzw. nachgefragter Sachverhalte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die Phasen der Verbrauchersteuerung ===&lt;br /&gt;
&lt;br /&gt;
Jeder Zyklus eines Verbrauchers durchläuft im Modul die folgenden Phasen:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Planung&#039;&#039;&#039; der Aktivzeiten des Verbrauchers, d.h. wann der Verbraucher geplant eingeschaltet sowie geplant ausgeschaltet wird und damit der Zyklus beendet wird.&lt;br /&gt;
# &#039;&#039;&#039;Start&#039;&#039;&#039; des Zyklus, d.h. Einschalten des Verbrauchers entsprechend der Planungsdaten sofern weitere, in den Consumer-Schlüsseln definierbare Rahmenbedingungen das Einschalten nicht verhindern (z.B. kein oder zu wenig PV-Energieerzeugung / PV-Überschuss)&lt;br /&gt;
# &#039;&#039;&#039;Permanente Überprüfung von&#039;&#039;&#039; eventuell vorhandenen &#039;&#039;&#039;Interruptbedingungen&#039;&#039;&#039; die den Verbraucher temporär ausschalten und, sofern die Interruptbedingung nicht mehr vorliegt, den Verbraucher wieder einschalten und so den gestarteten Zyklus fortsetzen.&lt;br /&gt;
#  &#039;&#039;&#039;Beendigung&#039;&#039;&#039; der Zyklus. Die Beendigung erfolgt entweder (normalerweise) wenn die geplante Endezeit der Zyklus erreicht ist oder eine optionale Endebedingung erfüllt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Steuerung der Phasen ====&lt;br /&gt;
Der Ablauf der Phasen kann durch verschiedene Schlüssel-Wert Paare beeinflusst und gesteuert werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; kann eine &#039;&#039;&#039;zusätzliche externe Bedingung&#039;&#039;&#039; definiert werden um den Einschaltvorgang des Consumers freizugeben. Ist die Bedingung (Regex) nicht erfüllt, erfolgt kein Einschalten des Verbrauchers auch wenn die sonstigen Voraussetzungen wie Zeitplanung, on-Schlüssel, auto-Mode und aktuelle PV-Leistung gegeben sind. Es erfolgt somit eine &#039;&#039;&#039;UND-Verknüpfung&#039;&#039;&#039; des Schlüssels swoncond mit den Planungsdaten und weiteren Einschaltbedingungen.&lt;br /&gt;
&lt;br /&gt;
Der optionale Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; definiert eine &#039;&#039;&#039;vorrangige Ausschaltbedingung&#039;&#039;&#039; (Regex). Sobald diese Bedingung erfüllt ist, wird der Consumer ausgeschaltet auch wenn die geplante Endezeit (consumerXX_planned_stop) noch nicht erreicht ist (&#039;&#039;&#039;ODER-Verknüpfung&#039;&#039;&#039;). Weitere Bedingungen wie off-Schlüssel und auto-Mode müssen zum automatischen Ausschalten erfüllt sein.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; kann während der geplanten Einschaltzeit eine automatische Unterbrechung sowie Wiedereinschaltung des Verbrauchers vorgenommen werden. Der Verbraucher wird temporär ausgeschaltet (interrupted) und wieder eingeschaltet (continued) wenn die Interrupt-Bedingung nicht mehr vorliegt. Die verbleibende Laufzeit wird durch einen Interrupt nicht beeinflusst! &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;power&#039;&#039;&#039; gibt die nominale Leistungsaufnahme des Verbrauchers gemäß seines Datenblattes an. Dieser Wert wird verwendet um die Schaltzeiten des Verbrauchers zu planen und das Schalten in Abhängigkeit des tatsächlichen PV-Überschusses zum Einplanungszeitpunkt zu steuern. Ist &#039;&#039;&#039;power=0&#039;&#039;&#039; gesetzt, wird der Verbraucher unabhängig von einem zum Zeitpunkt des Zyklus-Start eventuell nicht ausreichend vorhandenem PV-Überschuss wie geplant eingeschaltet und somit der Zyklus gestartet.&lt;br /&gt;
&lt;br /&gt;
Durch die Schlüssel &#039;&#039;&#039;notbefore&#039;&#039;&#039; und &#039;&#039;&#039;notafter&#039;&#039;&#039; kann der Startzeitpunkt des Verbrauchers so gesteuert werden, dass der Start des Zyklus nicht vor bzw. nach der angegebenen Zeit eingeplant wird. Diese Steuerung bezieht sich auf die &#039;&#039;Planung&#039;&#039;, d.h. der eigentliche Start des Verbrauchers kann sich unter Umständen durch vorhandene Rahmenbedingungen verzögern. &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; legt die geplanten Einschaltzeit, d.h. die Laufzeit des Zyklus fest. Der Name &#039;&#039;&#039;mintime&#039;&#039;&#039; ist nicht als MInimum-Zeit zu deuten, sondern beschreibt die angegebene Zeit in Minuten die der Zyklus dauern soll.&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist optional, da sich die Standard-Laufzeit des Verbrauchers von dessen Typ abgeleitet wird. Diese Standard Laufzeiten sind:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|dryer&lt;br /&gt;
|90 Minten&lt;br /&gt;
|-&lt;br /&gt;
|dishwasher&lt;br /&gt;
|180 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|washingmachine&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|heater&lt;br /&gt;
|240 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|charger&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|other&lt;br /&gt;
|60 Minuten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Der Verbraucher wurde nicht gestartet obwohl die Startzeit der Einplanung erreicht wurde ===&lt;br /&gt;
&lt;br /&gt;
Wenn die Startzeit des Consumers entsprechend der Einplanung erreicht oder überschritten ist, wird der Consumer eingeschaltet wenn die weiteren Voraussetzungen wahr sind:&lt;br /&gt;
&lt;br /&gt;
* es ist aktuell ein PV-Überschuss vorhanden und der PV-Überschuss deckt die kalkulierten Leistungsaufnahme des Verbrauchers ab. Mit den Schlüsseln &#039;&#039;&#039;power&#039;&#039;&#039; und &#039;&#039;&#039;spignorecond&#039;&#039;&#039; kann die Einschaltung trotz fehlendem PV-Überschuss ermöglicht werden. &lt;br /&gt;
&lt;br /&gt;
* die Angabe im Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; ist wahr (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* das Schalten ist über den Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; freigegeben (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* im Schlüssel &#039;&#039;&#039;on&#039;&#039;&#039; ist ein valides Einschaltkommando hinterlegt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind diese zusätzlichen Bedingungen nicht erfüllt, erfolgt kein Start des eingeplanten Zyklus. Der Verbraucher verbleibt in diesem Fall weiterhin im Status &#039;&#039;planned&#039;&#039; oder &#039;&#039;suspended&#039;&#039;. Die Startbedingungen werden regelmäßig reviewed und der Consumer gestartet sobald alle Startbedingungen wahr sind bzw. Start verhindernde Bedingungen entfallen sind. &lt;br /&gt;
&lt;br /&gt;
Dieser Vorgang erfolgt bis das geplante Ende des Verbaucherzyklus erreicht ist oder die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; zutrifft. Sobald die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; wahr ist, wird der gesamte Planungszyklus des Consumers beendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Kann manuell / automatisiert in den Planungszyklus eines Verbrauchers eingegriffen werden? ===&lt;br /&gt;
&lt;br /&gt;
Die Einplanung und die darauf aufbauenden Schaltprozesse laufen gemäß den hinterlegten Schlüsseloptionen im Modul automatatisch ab ohne dass ein Eingriff durch den Anwender erfolgen muß.&lt;br /&gt;
&lt;br /&gt;
Dennoch kann es gewünscht sein eine Neuplanung oder eine Sofortplanung eines Consumers vorzunehmen weil der Bedarf dazu besteht. Zu diesem Zweck stehen die Set-Kommandos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* consumerNewPlanning &lt;br /&gt;
&lt;br /&gt;
* consumerImmediatePlanning &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
zur Verfügung. &lt;br /&gt;
Beide Befehle initiieren die Consumer-Neuplanung, wobei mit dem Befehl &#039;&#039;consumerImmediatePlanning&#039;&#039; die eventuell im consumerXX Attribut gesetzten Schlüssel notbefore, notafter bzw. mode werden nicht beachtet werden. Dagenen beachtet der Befehl &#039;&#039;consumerNewPlanning&#039;&#039; alle definierten Schlüsseloptionen und dient gewöhnlich dazu einen abgeschlossenen Verbraucherzyklus wiederholt ausführen zu lassen weil die aktuelle Witterungslage dazu geeignet ist. &lt;br /&gt;
&lt;br /&gt;
Ein Anwendungsbeispiel dafür ist zum Beispiel die Ausführung von mehreren Waschmaschinen-Zyklen an einem langen, sonnigen Sommertag.&lt;br /&gt;
Diese beiden Set-Befehle können zum Beispiel über ein auf einen Schalter/Taster reagierendes Notify oder DOIF Device ausgeführt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung eines Verbrauchers mit getrennten Geräten für Messung und Schalten ===&lt;br /&gt;
&lt;br /&gt;
Es existieren in FHEM Geräte, die über verschiedene Kanäle für unterschiedliche Aufgaben verfügen. Diese Kanäle werden jeweils in einem gesonderten Device abgebildet. HomeMatic oder readingsProxy sind Beispiele für solche Varianten.&lt;br /&gt;
&lt;br /&gt;
Um solche Verbraucher einzubinden gibt es im consumerXX Attribut den Schlüssel &#039;&#039;&#039;switchdev&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Bei der Registrierung gibt man als Consumerdevice das Gerät für die Messung an und im Schüssel switchdev das entsprechende FHEM-Device, welches für die Schaltvorgänge benutzt wird. &lt;br /&gt;
Ist switchdev angegeben, beziehen sich die weiteren Schlüssel on, off, swstate, auto und asynchron auf dieses Gerät.&lt;br /&gt;
&lt;br /&gt;
In dem nachfolgenden Beispiel (Homematic) ist &#039;&#039;eg.az.fridge_Pwr&#039;&#039; FHEM Device für die Energiemessung. Die Schlüssel &#039;&#039;pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; geben Readings in diesem Device an damit SolarForecast den Verbrauch und die Energiemengen auslesen kann. Demgegenüber ist im Schlüssel &#039;&#039;switchdev&#039;&#039; das zugehörige Schalter-Device der Kombination angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eg.az.fridge_Pwr&lt;br /&gt;
type=noSchedule switchdev=eg.az.fridge_Sw power=0 icon=fridge pcurr=power:W:5 etotal=energyCalc:Wh &lt;br /&gt;
swstate=state:on:off auto=automatic&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung von Verbrauchern ohne Zeitplanung und aktivem Schalten ===&lt;br /&gt;
Manchmal besteht der Wunsch, Verbraucher in SolarForecast zu integrieren um lediglich folgende Sachverhalte abzubilden:&lt;br /&gt;
&lt;br /&gt;
* Visualisierung des Schaltstatus in der Consumer Legende und/oder der Energieflußgrafik&lt;br /&gt;
* Darstellung des aktuellen Energieverbrauchs in der Energieflußgrafik&lt;br /&gt;
* Erfassung der (externen) Schaltzeiten, d.h. der Zeiten der Gerätenutzung sowie der Verbrauchsdaten um deren Einfluß bei den Planungszeiten anderer Geräte durch SolarForecast berücksichtigen zu lassen&lt;br /&gt;
&lt;br /&gt;
In solchen Fällen werden bei der Registrierung die Schlüssel &#039;&#039;swstate, pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; zur Erfassung der Schaltzustände und der Energieverbrauchs angegeben, jedoch zur Verhinderung der Zeitplanung durch SolarForecast der Schlüssel &#039;&#039;&#039;type=noSchedule&#039;&#039;&#039; gesetzt sowie die Schlüssel &#039;&#039;on&#039;&#039; und &#039;&#039;off&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt eine mögliche Registrierung eines Zwischensteckers (Shelly) zur Erfassung der Daten eines Gefrierschrankes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Shelly.shellyplug4&lt;br /&gt;
type=noSchedule power=65 asynchron=1&lt;br /&gt;
icon=gefrierschrank &lt;br /&gt;
swstate=state:.*on.*:.*off.* &lt;br /&gt;
pcurr=relay_0_power:W:5 etotal=relay_0_energy_Wh:Wh&lt;br /&gt;
&amp;lt;/pre&amp;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;
&lt;br /&gt;
 Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off&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;
&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;
&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. Alternativ kann die Berücksichtigung des zwangsweisen PV Überschuss mit dem Schlüssel &amp;quot;spignorecond&amp;quot; im Consumer-Attribut ausgesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== zusätzliche Readings bzw. Erzeugung von statistischen Readings ==&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den zahlreichen im Modul per Standard erzeugten Readings kann der Anwender weitere Readings generieren lassen.&lt;br /&gt;
Diese zusätzlichen Readings geben entweder einen bestimmten Sachverhalt (Laufzeit, Status der API-Abfragen, etc.) oder einen statistischen Wert, z.B. die Batterieentladung des aktuellen Tages, wieder.&lt;br /&gt;
&lt;br /&gt;
Die zusätzlich erstellten Readings sind durch den Präfix &#039;&#039;&#039;special_&#039;&#039;&#039; im Device gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Diese zusätzlichen Informationen können durch das Setzen einer oder mehrerer Kennzeichen im Attribut &#039;&#039;&#039;ctrlSpecialReadings&#039;&#039;&#039; erzeugt werden. Die mögliche Auswahl wird je nach Bedarf ausgebaut und umfasst zum aktuellen Zeitpunkt (07.02.2025) diese Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;BatPowerIn_Sum: 	die Summe der momentanen Batterieladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;BatPowerOut_Sum: 	die Summe der momentanen Batterieentladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;allStringsFullfilled: 	Erfüllungsstatus der fehlerfreien Generierung aller Strings&lt;br /&gt;
;conForecastTillNextSunrise: 	Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
;currentAPIinterval: 	das aktuelle Abrufintervall der gewählten Strahlungsdaten-API in Sekunden&lt;br /&gt;
;currentRunMtsConsumer_XX: 	die Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; seit dem letzten Einschalten. (letzter Laufzyklus)&lt;br /&gt;
;dayAfterTomorrowPVforecast: 	liefert die Vorhersage der PV Erzeugung für Übermorgen (sofern verfügbar) ohne Autokorrektur (Rohdaten).&lt;br /&gt;
;daysUntilBatteryCare_XX: 	Tage bis zur nächsten Batterie XX Pflege (Erreichen der Ladung &#039;maxSoC&#039; aus Attribut ctrlBatSocManagementXX)&lt;br /&gt;
;lastretrieval_time: 	der letzte Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;lastretrieval_timestamp: 	der Timestamp der letzen Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;response_message: 	die letzte Statusmeldung der gewählten Strahlungsdaten-API&lt;br /&gt;
;runTimeAvgDayConsumer_XX: 	die durchschnittliche Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; an einem Tag&lt;br /&gt;
;runTimeCentralTask: 	die Laufzeit des letzten SolarForecast Intervalls (Gesamtprozess) in Sekunden&lt;br /&gt;
;runTimeTrainAI: 	die Laufzeit des letzten KI Trainingszyklus in Sekunden&lt;br /&gt;
;runTimeLastAPIAnswer: 	die letzte Antwortzeit des Strahlungsdaten-API Abrufs auf einen Request in Sekunden&lt;br /&gt;
;runTimeLastAPIProc: 	die letzte Prozesszeit zur Verarbeitung der empfangenen Strahlungsdaten-API Daten&lt;br /&gt;
;SunMinutes_Remain: 	die verbleibenden Minuten bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;SunHours_Remain: 	die verbleibenden Stunden bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;todayConsumptionForecast: 	Verbrauchsprognose pro Stunde des aktuellen Tages (01-24)&lt;br /&gt;
;todayConForecastTillSunset: 	Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
;todayDoneAPIcalls: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Calls&lt;br /&gt;
;todayDoneAPIrequests: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Requests&lt;br /&gt;
;todayConsumption: 	der gesamte Energieverbrauch (Wh) des Hauses am aktuellen Tag&lt;br /&gt;
;todayGridConsumption: 	die aus dem öffentlichen Netz bezogene Energie am aktuellen Tag&lt;br /&gt;
;todayGridFeedIn: 	die in das öffentliche Netz eingespeiste PV Energie am aktuellen Tag&lt;br /&gt;
;todayMaxAPIcalls: 	die maximal mögliche Anzahl Strahlungsdaten-API Calls. Ein Call kann mehrere API Requests enthalten.&lt;br /&gt;
;todayRemainingAPIcalls: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Calls&lt;br /&gt;
;todayRemainingAPIrequests: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Requests&lt;br /&gt;
;todayBatIn_XX: 	die am aktuellen Tag in die Batterie XX geladene Energie&lt;br /&gt;
;todayBatInSum: 	Summe der am aktuellen Tag in alle Batterien geladene Energie&lt;br /&gt;
;todayBatOut_XX: 	die am aktuellen Tag aus der Batterie XX entnommene Energie&lt;br /&gt;
;todayBatOutSum: 	Summe der am aktuellen Tag aus allen Batterien entnommene Energie&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Manche Angaben sind im Setup des Moduls optional, d.h. sie müssen nicht zwingend beim Setup angegeben werden. Allerdings sind diese Angaben für die Erstellung eines zusätzlichen Readings unter Umständen Voraussetzung. Es empfiehlt sich deshalb bei Setup so viele Informationen wie möglich zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
So ist zum Beispiel für die sinnvolle Erstellung der Informationen &#039;&#039;&#039;todayBatInSum&#039;&#039;&#039; und &#039;&#039;&#039;todayBatOutSum&#039;&#039;&#039; (Readings special_todayBatInSum und special_todayBatOutSum) das Vorhandensein der Schlüssel &#039;&#039;intotal&#039;&#039; und &#039;&#039;outtotal&#039;&#039; im Attribut setupBatteryDevXX notwendig (Beispiel):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupBatteryDev01 MQTT2_cerboGX_c0619ab34e08_battery &lt;br /&gt;
                              pin=BatIn:W pout=BatOut:W charge=SOC_value intotal=BatInTotal:Wh outtotal=BatOutTotal:Wh &lt;br /&gt;
                              cap=InstalledCapacity_Wh:Wh asynchron=1 show=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Fehlersuche ==&lt;br /&gt;
Das Modul SolarForecast ist sehr komplex und es die verschiedensten Datenquellen ausgewertet, zusammengeführt und daraus Ergebnisse berechnet und/oder visualisiert. Wird etwas nicht wie erwartet durch das Modul geliefert, können die Ursachen vielfältig sein. Natürlich kann ein Fehler im Modulcode vorliegen, oftmals gibt es aber andere Ursachen.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgenden Hinweise sollen Hilfe zur Selbsthilfe geben und sind eine Zusammenfassung von realen Fällen die mit dem beschriebenen Wegen und Verfahren gelöst wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die erwartete erzeugte PV-Energie ist im Modul zu gering und wird im Balkendiagramm nicht angezeigt === &lt;br /&gt;
&lt;br /&gt;
Die erzeugte PV-Energie wird nicht richtig angezeigt: Am Vormittag sind keine Werte vorhanden und, wenn dann etwas kommt, ist die Anzeige zu gering. Für 13 und 14 Uhr wurden ca. 5.000Wh erwartet (im Vergleich mit den Daten aus einer anderen Auswertungsquelle). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lösungsweg:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Aus dem List des Devices wurden die für den Fall wesentlichen Readings herausgezogen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVforecast 152 Wh&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVforecast 1400 Wh&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVforecast 2500 Wh&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVforecast 4392 Wh&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVforecast 4000 Wh&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVreal 300 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVforecast 6415 Wh&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVreal 3200 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVforecast 5629 Wh&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVreal 2700 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVforecast 3958 Wh&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVreal 900 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVforecast 945 Wh&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVreal 500 Wh&lt;br /&gt;
   &lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour18_PVforecast 59 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man sieht dass bis 12:00 keine erzeugte Energie vom WR gemeldet wird. Deswegen wird in der Balkengrafik nichts dargestellt. Auch danach bleibt die registrierte PV-Energie hinter den Erwartungen zurück. Zuständig für die Lieferung der PV-Energie an das Modul ist das Reading im Schlüssel:&lt;br /&gt;
&lt;br /&gt;
 setupInverterDev01 SH10rt pv=Total_DC_Power:W &amp;lt;mark&amp;gt;etotal=Total_Export_Energy_from_PV:kWh&amp;lt;/mark&amp;gt; capacity=10000 strings=Hauptdach,Flachdach&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Welche Änderungen es zwischen den Stunden gab, sieht man mit einem &amp;quot;get ... pvHistory XX&amp;quot; (&amp;quot;XX&amp;quot; steht für das Datum, d.h. den Tag, z.B. 02). &amp;lt;br&amp;gt;&lt;br /&gt;
Hier ein Beispiel für die Stunden 10 (9:00 - 9:59) und 11 (10:00 - 10:59). &amp;lt;br&amp;gt;&lt;br /&gt;
Wichtig ist hier der Key etotali01 für den ersten Inverter. Die Differenz zwischen den Werten beider Stunden ist die in der Stunde erzeugte Energie (hier 380 Wh). Diese 380 Wh findest du auch im Key pvrl01 als PVReal für diese Stunde. Das Modul rechnet intern immer mit Wh, kWh werden vorher in Wh umgerechnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
10 =&amp;gt; pvfc: 365, pvrl: 530, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63364714&amp;lt;/mark&amp;gt;, etotali02: 3044110, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;pvrl01: 380&amp;lt;/mark&amp;gt;, pvrl02: 150, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 574, con: 518, gcons: 22, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 1, feedprice: 0.1269&lt;br /&gt;
&lt;br /&gt;
            DoN: 1, sunaz: 137, sunalt: 12&lt;br /&gt;
&lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
      11 =&amp;gt; pvfc: 2966, pvrl: 1862, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63365094&amp;lt;/mark&amp;gt;, etotali02: 3044260, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            pvrl01: 1392, pvrl02: 470, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 774, con: 609, gcons: 25, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 4, feedprice: 0.1269&lt;br /&gt;
           &lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
D.h. wenn zwischen den beiden Stunden keine Differenzen zu finden sind, liegt es sehr wahrscheinlich am Input des Readings:&lt;br /&gt;
&lt;br /&gt;
 etotal=Total_Export_Energy_from_PV:kWh&lt;br /&gt;
&lt;br /&gt;
welches sich in den ersten Stunden nicht ändert und danach auch nur wenig.&lt;br /&gt;
&lt;br /&gt;
Man kann mit dem Attribut:&lt;br /&gt;
&lt;br /&gt;
 ctrlDebug=collectData&lt;br /&gt;
&lt;br /&gt;
die Datensammlung verfolgen (leider entstehen viele Daten im Log). Man sieht welche Werte von dem Inverter/Reading geliefert werden:&lt;br /&gt;
 &lt;br /&gt;
 ....&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; collect Inverter 01 data - device: STP_5000, delivery: default =&amp;gt;&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; pv: 0 W, &amp;lt;mark&amp;gt;etotal: 63378810 Wh&amp;lt;/mark&amp;gt;&lt;br /&gt;
 ....&lt;br /&gt;
&lt;br /&gt;
Dieser Wert muß bei PV Erzeugung kontinuierlich hochzählen. Wenn nicht, muss das angegebene Reading, d.h. die Quelle überprüft werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ergebnis der Prüfung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tatsächlich wurde ein Reading benutzt, das ungeeignet war: Statt &amp;quot;Total_PV_Generation&amp;quot; wurde &amp;quot;Total_export_energy_from_PV&amp;quot; genutzt. In diesem Reading wurde immer die in die Batterie gespeicherte Energie von der gesamten erzeugten Energie abgezogen. Daher war auch vormittags alles 0, da in dieser Periode alle PV-Energie in die Batterie geladen wurde bzw. in weiteren Stunden ein Anteil der dann bei dem PV-Erzeugungswert fehlte.&lt;br /&gt;
&lt;br /&gt;
Nachdem die Ursache beseitigt war, zeigt SolarForecast wieder die erwarteten PV-Erzeugungswerte an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Konfigurationsbeispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Visualisierung solare Vorhersage und reale Erzeugung ===&lt;br /&gt;
&lt;br /&gt;
Zu Beginn jedes neuen Tages gegen 00:00 Uhr werden durch das SolarForecast Device Events für die initiale PV Prognose des kommenden Tages erstellt.&lt;br /&gt;
Der Readingteil dieser Events heißt&lt;br /&gt;
&lt;br /&gt;
 AllPVforecastsToEvent&lt;br /&gt;
&lt;br /&gt;
Die Uhrzeiten der Events sind so aufbereitet und können direkt geloggt werden um sie in einen SVG Plot zu integrieren.&lt;br /&gt;
Im SolarForecast Device ist dieses Reading nicht sichtbar, nur die Events werden erstellt.&lt;br /&gt;
&lt;br /&gt;
Die meteorologischen Bedingungen verändern sich über den Tag permanent. Je nach gewählter Strahlungsdatenquelle (eine API oder DWD Device) erfolgt eine mehr oder weniger dynamische Anpassung der Prognose an die sich verändernde Umwelt.&lt;br /&gt;
&lt;br /&gt;
Aktuelle Prognosedaten sowie die reale PV Erzeugung der vergangenen Stunde können über die Readings&lt;br /&gt;
&lt;br /&gt;
 LastHourPVforecast&lt;br /&gt;
 LastHourPVreal&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-10-20 134050.png|right|thumb|400px|Übersicht solare Vorhersage]]&lt;br /&gt;
geloggt werden. &lt;br /&gt;
&lt;br /&gt;
Werden alle drei Werte in einem SVG kombiniert, kann die Entwicklung der Prognose über den Tag und die Beziehung von Prognose zu realer PV Erzeugnung pro Stunde visualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Für das rechts abgebildete Beispiel des Plots aus einer Datenbank &amp;quot;LogDBShort&amp;quot; sieht das gplot-File wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Created by FHEM/98_SVG.pm, 2024-03-08 15:05:31&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;TL&amp;gt;&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid&lt;br /&gt;
set ylabel &amp;quot;Wh&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Wh&amp;quot;&lt;br /&gt;
set yrange [0:7500]&lt;br /&gt;
set y2range [0:7500]&lt;br /&gt;
&lt;br /&gt;
#LogDBShort SolCast:LastHourPVforecast:::&lt;br /&gt;
#LogDBShort SolCast:LastHourPVreal:::&lt;br /&gt;
#LogDBShort SolCast:AllPVforecastsToEvent:::&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;aktuelle PV Vorhersage&#039; ls l6fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;reale PV Erzeugung&#039; ls l2fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;initiale PV Vorhersage&#039; ls l4 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; In manchen Fällen werden die Vorhersagewerte im SVG-Plot nicht angezeigt wenn FileLog verwendet wird. Ein Setzen des Attribute &amp;quot;fixedrange=3days +1&amp;quot; im SVG löst das Problem. Die Definition des SVG-Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_LogDBShort_SolCast SVG LogDBShort:SVG_LogDBShort_SolCast:HISTORY&lt;br /&gt;
attr SVG_LogDBShort_SolCast fixedrange 3days +1&lt;br /&gt;
attr SVG_LogDBShort_SolCast room Energie-&amp;gt;SolarPrognose&lt;br /&gt;
attr SVG_LogDBShort_SolCast sortby 2&lt;br /&gt;
attr SVG_LogDBShort_SolCast title &amp;quot;Übersicht solare Vorhersage&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Technisch bedingt werden an einem Tag X kurz nach 00:00 Uhr die am Vortag für den Tag X erzeugten Events aktualisiert. Diese Daten erzeugen in der Datenbank einen zweiten Satz an Daten mit dem gleichen Timestamp was für die Anzeige unvorteilhaft ist. &lt;br /&gt;
Um nur die aktualisierten Events von &#039;&#039;&#039;AllPVforecastsToEvent&#039;&#039;&#039; in der Datenbank zu erhalten, bietet sich ein DbRep-Device an. Die nachfolgende Vorschlagsdefinition kann per at-Device jeden Tag kurz vor Mitternacht (z.B. 23:57:10) ausgeführt werden. Es werden immer die in der Vergangenheit geschriebenen (veralteten) Daten aus der Datenbank gelöscht, doppelte Datesätze vermieden und immer die aktuellste initiale Prognose gespeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.Del.AllPVforecastsToEvent DbRep LogDBShort&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent alias Löschen Readings AllPVforecastsToEvent des Folgetages&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent comment ermöglicht dass die Readings AllPVforecastsToEvent am Folgetag wieder neu und aktuell geschrieben werden können&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent devStateIcon initialized:control_3dot_hor_s connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent disable 0&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent event-on-update-reading state&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent icon edit_delete&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent showproctime 1&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent device TYPE=SolarForecast&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_begin next_day_begin&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_end next_day_end&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das angegebene DbLog-Device &#039;&#039;&#039;LogDBShort&#039;&#039;&#039; ist natürlich anzupassen.&lt;br /&gt;
&lt;br /&gt;
Das at-Device zum Starten der Datenbankbereinigung sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define At.Del.AllPVforecastsToEvent at *23:58:10 set Rep.Del.AllPVforecastsToEvent delEntries&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent alias Start Löschen Readings AllPVforecastsToEventn LogDBShort&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent icon clock&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich sind auch hier die eigenen Devicenamen entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
Ab SolarForecast Version 1.51.7 kann die Eventerzeugung für bestimmte SVG Plot-Typen optimiert werden. &amp;lt;br&amp;gt; &lt;br /&gt;
Die Aktivierung dieser Optimierungen ist in der Online Hilfe zum Attribut &#039;&#039;&#039;plantControl-&amp;gt;genPVforecastsToEvent&#039;&#039;&#039; beschrieben. Bei Nutzung des Attributes plantControl-&amp;gt;genPVforecastsToEvent ist ebenfalls das Attribut &#039;&#039;&#039;event-on-update-reading=AllPVforecastsToEvent&#039;&#039;&#039; zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispielkonfiguration 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;
Bitte dabei diese DWD-Version aus dem [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter Contrib] von DS_Starter dazu nutzen&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|55_DWD_OpenData.pm&lt;br /&gt;
|136.2 KB ​&lt;br /&gt;
|29260  &lt;br /&gt;
|DS_Starter&lt;br /&gt;
|55_DWD_OpenData: contrib 1.17.7&lt;br /&gt;
|}&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 downloadTimeout 120&lt;br /&gt;
attr DWD comment Im DWD Wetterdevice verwendet Solarforecast : \&lt;br /&gt;
TTT,Neff,RR1c,ww,SunUp,SunRise,SunSet \&lt;br /&gt;
zusätzlich ist jedoch auch noch Rad1h notwendig \&lt;br /&gt;
wenn dieses DWD-Device als Strahlungsdevice genutzt wird.\&lt;br /&gt;
Die Station 10418 (Lüdenscheid) überträgt aktuell am 09.03.2025 (noch) Rad1h.\&lt;br /&gt;
attr DWD downloadTimeout 120&lt;br /&gt;
attr DWD forecastDays 7&lt;br /&gt;
attr DWD forecastProperties SunUp, SunRise, SunSet, Rad1h, R101, RR1c, TTT, Tx, Tn, Tg, DD, FX1, RR6c, R600, RRhc, Rh00, ww, wwd, Neff&lt;br /&gt;
attr DWD forecastRefresh 1&lt;br /&gt;
attr DWD forecastResolution 1&lt;br /&gt;
attr DWD forecastStation 10418&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 fc_description  -(state fc_time)&lt;br /&gt;
attr DWD verbose 2&lt;br /&gt;
&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;
defmod InverterDummy dummy&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;
defmod 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 feedinPrice 0.08&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 powerCost 0.25&lt;br /&gt;
attr SMA_Energymeter room 015_Zaehler,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;
defmod 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;
attr BatteryDummy userReadings total_pac, power_out, power_in, chargestatus, bat_rated_capacity, bat_loadtotal, bat_unloadtotal&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;
defmod N.PV.TotalConsumption.Dum.Energy notify SMA_Energymeter:Saldo_Wirkleistung:.* {\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung_2 Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&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;MB_USRW610_004&amp;quot;,&amp;quot;Power_Sum__W&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;
fhem &amp;quot;setreading InverterDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(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;
#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;
 # Batterie-total_pac  InverterDummy\&lt;br /&gt;
my $wert7 = sprintf(&amp;quot;%.3f&amp;quot;,((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy bat_rated_capacity &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert7));;\&lt;br /&gt;
 # möglicher Aufruf einer Batterie-Bebladung-Routine....SMABatteryChargewithTibber();;\&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;
defmod Forecast SolarForecast&lt;br /&gt;
attr Forecast DbLogExclude .*&lt;br /&gt;
attr Forecast DbLogInclude Current_BatCharge999&lt;br /&gt;
attr Forecast affectBatteryPreferredCharge 30&lt;br /&gt;
attr Forecast affectConsForecastLastDays 31&lt;br /&gt;
attr Forecast affect70percentRule 0&lt;br /&gt;
attr Forecast comment &amp;quot;wget -qO ./FHEM/76_SolarForecast.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/76_SolarForecast.pm&amp;quot;\&lt;br /&gt;
&amp;quot;wget -qO ./FHEM/55_DWD_OpenData.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/55_DWD_OpenData.pm&amp;quot;\&lt;br /&gt;
&amp;quot;13.01.2025 mit der Version 76_SolarForecast.pm:v1.43.2-s29518/2025-01-12&amp;quot;&lt;br /&gt;
attr Forecast graphicHeaderOwnspec PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal Verbrauch&amp;amp;nbsp;;bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast  Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest FCU-Erzeugung&amp;amp;nbsp;;:Current_PP01\&lt;br /&gt;
attr Forecast consumer01 FBDECT_fbahahttp_11657_0127183 icon=scene_washing_machine@orange type=washingmachine power=10 swstate:state notbefore=09 notafter=20 pcurr=power:W:3 etotal=energy:Wh interruptable=1 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer02 FBDECT_fbahahttp_E8_DF_70_07_3E_57 icon=light_floor_lamp@orange type=other power=15 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer03 FBDECT_fbahahttp_E8_DF_70_07_42_0B icon=raspberrypi@orange type=other power=8 swstate:state pcurr=power:W:1 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer04 FBDECT_fbahahttp_11657_0067275 icon=springbrunnen_icon@orange type=other power=50 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer05 FBDECT_fbahahttp_34_31_C4_D4_31_37 icon=sani_domestic_waterworks@orange type=other power=10 swstate:state pcurr=power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer06 tuya_local_bf5037060f450bdbd4rl0q icon=scene_clothes_dryer@orange type=dryer power=10 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer07 tuya_local_bfac44fb487476efd1vhdu icon=weather_sunset@orange type=noSchedule power=5 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumerControl adviceIcon=light_light_dim_100@gold&lt;br /&gt;
attr Forecast consumerControl showLegend=icon_top&lt;br /&gt;
attr Forecast consumerControl detailLink=1&lt;br /&gt;
attr Forecast ctrlAIdataStorageDuration 1825&lt;br /&gt;
attr Forecast ctrlAIshiftTrainStart 2&lt;br /&gt;
attr Forecast ctrlBatSocManagement01 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlBatSocManagement02 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlDebug none&lt;br /&gt;
attr Forecast plantControl genPVdeviation=continuously&lt;br /&gt;
attr Forecast plantControl cycleInterval=15&lt;br /&gt;
attr Forecast ctrlNextDayForecastReadings 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24&lt;br /&gt;
attr Forecast ctrlNextHoursSoCForecastReadings 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23&lt;br /&gt;
attr Forecast ctrlSpecialReadings BatPowerIn_Sum,BatPowerOut_Sum,SunHours_Remain,SunMinutes_Remain,allStringsFullfilled,conForecastTillNextSunrise,currentAPIinterval,currentRunMtsConsumer_01,currentRunMtsConsumer_02,currentRunMtsConsumer_03,currentRunMtsConsumer_04,currentRunMtsConsumer_05,currentRunMtsConsumer_06,currentRunMtsConsumer_07,dayAfterTomorrowPVforecast,daysUntilBatteryCare_01,daysUntilBatteryCare_02,lastretrieval_time,lastretrieval_timestamp,response_message,runTimeAvgDayConsumer_01,runTimeAvgDayConsumer_02,runTimeAvgDayConsumer_03,runTimeAvgDayConsumer_04,runTimeAvgDayConsumer_05,runTimeAvgDayConsumer_06,runTimeAvgDayConsumer_07,runTimeCentralTask,runTimeLastAPIAnswer,runTimeLastAPIProc,runTimeTrainAI,todayBatIn_01,todayBatIn_02,todayBatOut_01,todayBatOut_02,todayConForecastTillSunset,todayConsumptionForecast,todayDoneAPIcalls,todayDoneAPIrequests,todayGridConsumption,todayGridFeedIn,todayMaxAPIcalls,todayRemainingAPIcalls,todayRemainingAPIrequests&lt;br /&gt;
attr Forecast disable 0&lt;br /&gt;
attr Forecast event-min-interval .*:1800&lt;br /&gt;
attr Forecast event-on-change-reading .*&lt;br /&gt;
attr Forecast flowGraphicControl animate=1 consumerdist=80 h2consumerdist=50 shiftx=0  shifty=0 showconsumer=1 showconsumerdummy=1 showconsumerpower=1 showconsumerremaintime=0 size=400 strokewidth=12&lt;br /&gt;
attr Forecast graphicBeam1Color 3C14FF&lt;br /&gt;
attr Forecast graphicBeam1Content pvReal&lt;br /&gt;
attr Forecast graphicBeam2Color 19FF29&lt;br /&gt;
attr Forecast graphicBeam2Content pvForecast&lt;br /&gt;
attr Forecast graphicBeam3Color D60924&lt;br /&gt;
attr Forecast graphicBeam3Content batsocforecast_02&lt;br /&gt;
attr Forecast graphicBeam3FontColor FFFF0D&lt;br /&gt;
attr Forecast graphicBeam4Color FFFF1F&lt;br /&gt;
attr Forecast graphicBeam4Content batsocforecast_01&lt;br /&gt;
attr Forecast graphicBeam4FontColor 000000&lt;br /&gt;
attr Forecast graphicBeamHeightLevel1 200&lt;br /&gt;
attr Forecast graphicBeamHeightLevel2 200&lt;br /&gt;
attr Forecast graphicHeaderDetail all&lt;br /&gt;
attr Forecast graphicHeaderOwnspec #PV\&lt;br /&gt;
PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal\&lt;br /&gt;
PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast\&lt;br /&gt;
PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast\&lt;br /&gt;
:\&lt;br /&gt;
#\&lt;br /&gt;
AutarkyRate:Current_AutarkyRate\&lt;br /&gt;
Überschuss:Current_Surplus\&lt;br /&gt;
aktueller&amp;amp;nbsp;;Netzbezug:Current_GridConsumption\&lt;br /&gt;
:\&lt;br /&gt;
#Verbrauch\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenuntergang:special_todayConForecastTillSunset\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie01\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_01\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_01\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_01\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_01\&lt;br /&gt;
#Batterie01_tmp\&lt;br /&gt;
Current_PowerBatIn_01:Current_PowerBatIn_01\&lt;br /&gt;
Current_PowerBatOut_01:Current_PowerBatOut_01\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie02\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_02\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_02\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_02\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_02\&lt;br /&gt;
#Batterie02_tmp\&lt;br /&gt;
Current_PowerBatIn_02:Current_PowerBatIn_02\&lt;br /&gt;
Current_PowerBatOut_02:Current_PowerBatOut_02\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Settings\&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto \&lt;br /&gt;
Wetter:graphicShowWeather\&lt;br /&gt;
History:graphicHistoryHour\&lt;br /&gt;
ShowNight:graphicShowNight\&lt;br /&gt;
Debug:ctrlDebug\&lt;br /&gt;
FCU-Modus:FCU-Betriebsmodus@FCU&lt;br /&gt;
attr Forecast graphicHistoryHour 4&lt;br /&gt;
attr Forecast graphicHourCount 24&lt;br /&gt;
attr Forecast graphicLayoutType double&lt;br /&gt;
attr Forecast graphicShowDiff top&lt;br /&gt;
attr Forecast graphicShowNight 1&lt;br /&gt;
attr Forecast graphicShowWeather 1&lt;br /&gt;
attr Forecast group Energy Meter&lt;br /&gt;
attr Forecast room 020_PV,Energie&lt;br /&gt;
attr Forecast setupBatteryDev01 SBS25 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupBatteryDev02 SBS25_2 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupInverterDev01 SB25 pv=total_pac:kW etotal=etotal:kWh capacity=2500 strings=GarageSE limit=70&lt;br /&gt;
attr Forecast setupInverterDev02 SB30 pv=total_pac:kW etotal=etotal:kWh capacity=3000 strings=GarageNW,HausNW limit=70&lt;br /&gt;
attr Forecast setupInverterDev03 SB40 pv=total_pac:kW etotal=etotal:kWh capacity=4000 strings=HausSE1,HausSE2,HausSW limit=70&lt;br /&gt;
attr Forecast setupInverterStrings GarageSE,GarageNW,HausNW,HausSW,HausSE1,HausSE2&lt;br /&gt;
attr Forecast setupMeterDev SMA_Energymeter gcon=Bezug_Wirkleistung:W contotal=Bezug_Wirkleistung_Zaehler:kWh gfeedin=Einspeisung_Wirkleistung:W feedtotal=Einspeisung_Wirkleistung_Zaehler:kWh conprice=0.25:€ feedprice=0.08123:€&lt;br /&gt;
attr Forecast setupOtherProducer01 icon=Heizung_FCU_green@red MB_USRW610_004 pcurr=Power_L1__W:W etotal=Energy_L1_import__kWh:kWh&lt;br /&gt;
attr Forecast setupRadiationAPI DWD&lt;br /&gt;
attr Forecast setupStringPeak GarageSE=2.75 GarageNW=3.200 HausNW=2.230 HausSW=2.230 HausSE1=2.200 HausSE2=2.200&lt;br /&gt;
attr Forecast setupWeatherDev1 DWD&lt;br /&gt;
attr Forecast stateFormat Current_PV&lt;br /&gt;
attr Forecast userReadings Current_BatCharge999 {((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))) / ( (ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0) * 1000)  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0)*1000))*100}&lt;br /&gt;
attr Forecast verbose 2&lt;br /&gt;
&lt;br /&gt;
setstate Forecast 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .FCU_FCU-Betriebsmodus 2&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_ctrlDebug none&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicHistoryHour 4&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowNight 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowWeather 1&lt;br /&gt;
setstate Forecast 2025-01-13 08:24:25 .associatedWith SMA_Energymeter FBDECT_fbahahttp_11657_0127183 FBDECT_fbahahttp_E8_DF_70_07_3E_57 FBDECT_fbahahttp_E8_DF_70_07_42_0B FBDECT_fbahahttp_11657_0067275 FBDECT_fbahahttp_34_31_C4_D4_31_37 tuya_local_bf5037060f450bdbd4rl0q tuya_local_bfac44fb487476efd1vhdu SBS25 SBS25_2 SB25 SB30 SB40 DWD MB_USRW610_004&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .lastupdateForecastValues 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .pvCorrectionFactor_Auto_Soll on_complex_ai&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .signaldone_01 done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .signaldone_02 done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .signaldone_03 done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .signaldone_04 done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .signaldone_05 done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .signaldone_06 done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .signaldone_07 done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .signaldone_08 done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .signaldone_09 done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .signaldone_10 done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .signaldone_11 done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .signaldone_12 done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .signaldone_13 done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .signaldone_14 done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .signaldone_15 done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .signaldone_16 done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .signaldone_17 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .signaldone_18 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_01 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_02 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_01 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_02 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_AutarkyRate 83 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 Current_BatCharge999 10&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_01 12 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_02 8 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Consumption 626 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridConsumption 2 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridFeedIn 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PP_01 746.0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PV 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_01 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_02 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_01 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_02 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumption 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumptionRate 0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Surplus 120 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourGridconsumptionReal 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_ConsumptionForecast 2944 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayConsumptionForecast 3609 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_01 272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PPreal_01 748 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PPreal_01 787 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_01 271 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PPreal_01 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PPreal_01 745 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_01 267 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PPreal_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_01 255 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PPreal_01 752 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_01 226 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_01 50 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PPreal_01 681 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_02 233 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_01 845 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridConsumption 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_01 37 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_02 90 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_01 351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_02 188 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridConsumption 447 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVforecast 127 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridConsumption 1650 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVforecast 478 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVreal 26 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridConsumption 513 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVforecast 868 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVreal 97 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridConsumption 576 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVforecast 1157 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVreal 320 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_01 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_02 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridConsumption 1272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridFeedIn 7 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVforecast 1238 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVreal 945 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_01 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_02 53 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridConsumption 955 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridFeedIn 31 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PPreal_01 562 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVforecast 1168 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVreal 1410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_01 703 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_02 500 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_01 22 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_02 18 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridConsumption 32 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridFeedIn 71 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PPreal_01 777 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVreal 1416 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_01 296 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_02 70 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_01 74 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_02 258 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridConsumption 13 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridFeedIn 17 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PPreal_01 732 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVforecast 880 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVreal 1051 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_01 47 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_02 126 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_01 102 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_02 75 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridConsumption 15 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridFeedIn 23 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PPreal_01 771 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVforecast 117 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVreal 86 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_02 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_02 67 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridConsumption 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridFeedIn 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PPreal_01 723 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_01 349 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_02 124 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_01 73 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_02 450 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridConsumption 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridFeedIn 6 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PPreal_01 671 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecastTime 2025-01-13 14:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVdeviation 30.17 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVforecast 7663 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVreal 5351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunRise 08:28&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunSet 16:46&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_ConsumptionForecast 17043 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour05_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour06_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour07_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour08_PVforecast 10 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour09_PVforecast 161 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour10_PVforecast 275 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour11_PVforecast 532 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour12_PVforecast 730 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour13_PVforecast 1252 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour14_PVforecast 818 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour15_PVforecast 1465 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour16_PVforecast 303 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour17_PVforecast 20 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour18_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour19_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour20_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour21_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour22_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour23_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour24_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_PVforecast 5566 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunRise 08:27&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunSet 16:47&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01 name=&#039;_Waschmaschine&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_start 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_stop 14.01.2025 11:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02 name=&#039;_Esszimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_currentPower 15.3 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03 name=&#039;_FCU&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_currentPower 7.15 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04 name=&#039;_Brunnen&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05 name=&#039;_Zisterne&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06 name=&#039;SW Trockner&#039; state=&#039;unknown&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_stop 14.01.2025 08:30:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07 name=&#039;SW Urlaubslicht-Wohnzimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;noSchedule&#039; info=&#039;von extern umgeschaltet&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 nextCycletime 18:54:09&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 pvCorrectionFactor_10 0.53 (automatic - old factor: 1.00, Sun Alt range: 5, Cloud range: 75, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 pvCorrectionFactor_11 0.56 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 70, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 pvCorrectionFactor_12 0.64 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 pvCorrectionFactor_13 0.88 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 pvCorrectionFactor_14 1.10 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 50, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 pvCorrectionFactor_15 1.01 (automatic - old factor: 1.06, Sun Alt range: 15, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 pvCorrectionFactor_16 1.09 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 45, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 pvCorrectionFactor_17 0.28 (automatic - old factor: 0.52, Sun Alt range: 0, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 pvCorrectionFactor_Auto on_complex_ai&lt;br /&gt;
setstate Forecast 2024-10-30 19:42:19 setupStringAzimuth GarageSE=-55 GarageNW=125 HausNW=125 HausSW=35 HausSE1=-55 HausSE2=-55&lt;br /&gt;
setstate Forecast 2024-10-30 19:37:38 setupStringDeclination GarageSE=40 GarageNW=40 HausNW=50 HausSW=50 HausSE1=50 HausSE2=50&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerIn_Sum 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerOut_Sum 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunHours_Remain 0.00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunMinutes_Remain 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_allStringsFullfilled 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_conForecastTillNextSunrise 9467 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentAPIinterval 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_01 132 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_02 184 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_03 329512 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_04 200 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_05 27 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_06 193 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_07 106 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_dayAfterTomorrowPVforecast 7344 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_01 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_02 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_time 2025-01-13 18:53:54&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_timestamp 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_response_message success&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_01 545.94 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_02 382.10 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_03 1430.13 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_04 262.05 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_05 28.80 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_06 622.63 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_07 276.51 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeCentralTask 0.3744&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIAnswer -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIProc -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeTrainAI 1.2529&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_01 3683.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_02 1617.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_01 2287.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_02 1057.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConForecastTillSunset 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 special_todayConsumptionForecast_01 509 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 special_todayConsumptionForecast_02 499 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 special_todayConsumptionForecast_03 501 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 special_todayConsumptionForecast_04 511 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 special_todayConsumptionForecast_05 503 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 special_todayConsumptionForecast_06 495 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 special_todayConsumptionForecast_07 504 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 special_todayConsumptionForecast_08 561 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 special_todayConsumptionForecast_09 768 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 special_todayConsumptionForecast_10 783 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 special_todayConsumptionForecast_11 692 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 special_todayConsumptionForecast_12 791 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 special_todayConsumptionForecast_13 910 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 special_todayConsumptionForecast_14 1022 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 special_todayConsumptionForecast_15 965 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 special_todayConsumptionForecast_16 812 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 special_todayConsumptionForecast_17 884 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 special_todayConsumptionForecast_18 928 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_19 874 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_20 763 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_21 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_22 765 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_23 643 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_24 601 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIcalls 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIrequests 4532&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridConsumption 5500.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridFeedIn 178.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayMaxAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIrequests n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 state updated&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So sollte es dann als Ergebnis aussehen:&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13.png|zentriert|mini|Ergebnis nach kompletter Einrichtung]]&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13 Teil II.png|alternativtext=Unterer Teil der Anzeige|zentriert|mini]]&lt;br /&gt;
&lt;br /&gt;
== Praxisbeispiele und Lösungsansätze für Steuerungen ==&lt;br /&gt;
=== Fallstudie: Trockner darf pausiert werden, wenn nicht genug PV-Überschuss vorhanden ist, soll aber nach spätestens X Stunden fertig sein ===&lt;br /&gt;
Für diese Aufgabenstellung sind mehrere Schlüssel essentiell wichtig, &#039;&#039;&#039;power&#039;&#039;&#039;, &#039;&#039;&#039;mintime&#039;&#039;&#039;, &#039;&#039;&#039;mode&#039;&#039;&#039; und &#039;&#039;&#039;interruptable&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Die Bedingung, dass der Trockner nach spätestens X Stunden fertig sein soll, steht in einem Widerspruch zu der Möglichkeit den Trockner bei zu wenig PV-Überschuss unterbrechen zu können. Im Extremfall könnte nach dem Start die gesamte Planungszeit ungenügender Überschuss vorliegen und der Trockner nicht arbeiten. Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; (in Minuten) wird nun wie folgt angesetzt:&lt;br /&gt;
&lt;br /&gt;
 mintime = 2,5 x &amp;lt;gewöhnliche Betriebszeit für einen Trockengang (mneed, z.B. 120)&amp;gt; = 300 Minuten&lt;br /&gt;
&lt;br /&gt;
Das bedeutet, der Trockner wird nach 300 Minuten Laufzeit abgeschaltet werden bzw. vom Netz getrennt. Der Trockenvorgang wird natürlich bereits nach 120 Minuten beendet sein, sofern nach Start keine Unterbrechnung des Vorganges erfolgte. Wurde der Vorgang unterbrochen, soll der Trockner innerhalb &lt;br /&gt;
&lt;br /&gt;
 X+120 bis X+300 &lt;br /&gt;
&lt;br /&gt;
fertig sein. &lt;br /&gt;
&lt;br /&gt;
Demnach ist die ausgeführte Laufzeit des Trockners permanent zu überwachen, zu summieren (rtsum) und die notwendige Restzeit (mneed - rtsum) mit der noch verbleibenden Restzeit (mrest) bis zur geplanten Abschaltung des Consumers zu vergleichen. Ist der Consumer gestartet, wird die Laufzeit in der pvHistory für jede Stunde des Tages im Schlüssel &#039;&#039;minutescsmXX&#039;&#039; (XX = Consumernummer) aufgezeichnet und kann darüber ausgewertet werden. Somit ist:&lt;br /&gt;
&lt;br /&gt;
 msum = for (01 .. 24) {Summe von minutescsmXX} des aktuellen Tages&lt;br /&gt;
&lt;br /&gt;
Solange die Bedingung &lt;br /&gt;
&lt;br /&gt;
 mrest &amp;gt;= (mneed - msum)&lt;br /&gt;
&lt;br /&gt;
zutrifft, darf der Trockner unterbrochen werden, anderenfalls darf er nicht mehr unterbrochen werden da die Restzeit evtl. nicht ausreichen könnte um den Vorgang abzuschließen. Für die Planung des Trockners wird der Consumer wie gewöhnlich nach dem Bedarf im Modul registriert. Für die Steuerung der Unterbrechbarkeit wird noch ein Code erstellt, welcher im Trockner-Device &#039;&#039;Dryerdev&#039;&#039; das Reading &#039;&#039;SF_Int&#039;&#039; zur Unterbrechnungssteuerung verwaltet. Dieses Reading wird dem Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; übergeben. Für das Beispiel wird der Consumer &#039;07&#039; verwendet, es kann natürlich jede andere freie Nummer verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Dryerdev:Trockner&lt;br /&gt;
                        icon=scene_cloves_dryer type=dryer power=2000 mode=must mintime=300 &lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic asynchron=1&lt;br /&gt;
                        interruptable=Dryerdev:SF_Int:1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Kombination &#039;&#039;&#039;auto=automatic&#039;&#039;&#039; eröffnet die Möglickeit, in der Consumer-Legende den Trockner-Start zusätzlich manuell freizugeben oder zu verbieten. &lt;br /&gt;
&lt;br /&gt;
Im nachfolgenden Code werden modulinterne Subroutinen verwendet. Diese sind inklusive dem Paket &#039;&#039;FHEM::SolarForecast::&#039;&#039; anzugeben. Die erstellte Subroutine wird in die 99_mySolarForecastUtils.pm eingefügt. Die Datei 99_mySolarForecastUtils.pm wird vorher von 99_myUtils.pm kopiert und enthält für die Übersichtlichkeit nur Routinen für SolarForecast.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Trocknersteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub dryControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # gewöhlich benötigte Zeit für &lt;br /&gt;
                                                                                  # einen Trockengang, z.B. 120 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $dryer     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename des Trockners&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Trockner-Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit des Trockners&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      my $dhash = $defs{$dryer};&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 1, 0);                        # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 0, 0);                        # keine Interrupt-Freigabe&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die gewöhnliche Laufzeit des Trockners für einen Trockenvorgang (120 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::dryControl ($name, &#039;07&#039;, 120);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Fallstudie: Umwälzpumpe Pool soll X Stunden am Tag laufen. Ist kein PV-Überschuß vorhanden, müssen die X Stunden/Tag trotzdem erreicht werden ===&lt;br /&gt;
&lt;br /&gt;
Die Vorgehensweise ähnelt der Fallstudie zuvor. Verändernd kommt hinzu, dass der Planungszeitraum bewusst sehr lang angesetzt wird mit der Option, den Zyklus des Consumers vorfristig zu beenden sobald die Laufzeit von X Stunden am Tag erreicht ist. &lt;br /&gt;
Im folgenden Beispiel soll die Pumpe 5 Stunden am Tag (300 Minuten) laufen und dabei mögliche PV-Überschüsse ausnutzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Pump:Zirkulationspumpe&lt;br /&gt;
                        icon=sani_pump type=other power=50 mode=must mintime=780 notafter=09&lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic &lt;br /&gt;
                        interruptable=1 swoffcond=Pump:SF_Abort:1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit dieser Registrierung wird die Pumpe ca. 09 Uhr täglich starten. Wenn kein bzw. ungenügender PV-Überschuß vorhanden ist, erfolgt eine Unterbrechung nach dem Start. Ist genügender PV-Überschuß (wieder) vorhanden, erfolgt keine Unterbrechnung (mehr). Zusätzlich wird über den Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; eine vorfristige Beendigung veranlasst, sobald die gewünschte Tageslaufzeit erreicht ist.&lt;br /&gt;
&lt;br /&gt;
Zur Verwaltung des Schlüssels &#039;&#039;interruptable&#039;&#039; und des Readings &#039;&#039;SF_Abort&#039;&#039; verwenden wir eine leicht veränderte Subroutine aus dem vorhergehenden Fallbeispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Pumpensteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub pumpControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # Soll-Pumpenzeit, z.B. 300 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $pump      = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename der Pumpe&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;);&lt;br /&gt;
  my $intbl     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;interruptable&#039;, 1); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
  my $dhash     = $defs{$pump};&lt;br /&gt;
&lt;br /&gt;
  readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 0, 0);                                # default keine Zyklusbeendigung&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Pumpen Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit der Pumpe&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
     &lt;br /&gt;
      if ($msum &amp;gt;= $mneed) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 1, 0);                       # vorfristige Zyklusbeendigung&lt;br /&gt;
          return;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=1&amp;quot;) if(!$intbl);  # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=0&amp;quot;) if($intbl);   # keine Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Befehl &#039;&#039;attrKeyVal&#039;&#039; setzt den Schlüssel &#039;&#039;interruptable&#039;&#039; im Attribut &#039;&#039;consumer07&#039;&#039; dynamisch. Diese Strukturänderung wird automatisch im System gespeichert, sofern &#039;&#039;global-&amp;gt;autosave=1&#039;&#039; gesetzt ist. Diese Einstellung ist der FHEM default.  &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die Mindestlaufzeit der Umwälzpumpe (300 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::pumpControl ($name, &#039;07&#039;, 300);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamische Ladestromsteuerung eines Victron MultiPlus II Chargers mit Pylontech Batterie ===&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;
&lt;br /&gt;
 set &amp;lt;Device&amp;gt; MaxChargeCurrent &amp;lt;Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
eingestellt bzw. variiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Modul bietet dem Nutzer die Möglichkeit in dem Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltene Code wird am Ende jedes Zyklus (siehe Attribut &#039;&#039;plantControl-&amp;gt;cycleInterval&#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;
&lt;br /&gt;
&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 $mppt1   = &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common&#039;;              # SmartLoader Device&lt;br /&gt;
  my $maxcspc = 105;                        # max. Ladesollstrom (A) nominal&lt;br /&gt;
  my $spcorr  = 0.9;                        # Korrekturfaktor Überschuss 90%&lt;br /&gt;
  my $sch     = 0.25;                       # Verkürzungsfaktor Zeit bis Vollladung vor Sunset             &lt;br /&gt;
  &lt;br /&gt;
  my $cclvl0  = 15;                         # Ladestrom Level 0 max. 5  A (240 W) pro WR  (720  W)&lt;br /&gt;
  my $cclvl1  = 27;                         # Ladestrom Level 1 max. 9  A (432 W) pro WR  (1296 W)&lt;br /&gt;
  my $cclvl2  = 54;                         # Ladestrom Level 2 max. 18 A (864 W) pro WR  (2592 W)&lt;br /&gt;
  my $cclvl3  = 81;                         # Ladestrom Level 3 max. 27 A (1296 W) pro WR (3888 W)&lt;br /&gt;
  ###############&lt;br /&gt;
  &lt;br /&gt;
  my $cofc   = ReadingsNum ($name,  &#039;special_todayConForecastTillSunset&#039;, 0);&lt;br /&gt;
  my $pvfc   = ReadingsNum ($name,  &#039;RestOfDayPVforecast&#039;, 0);&lt;br /&gt;
  my $cpv    = ReadingsNum ($name,  &#039;Current_PV&#039;,          0);&lt;br /&gt;
  my $mppt1c = ReadingsNum ($mppt1, &#039;DC_0_Current_value&#039;,  0);             # Load I MPPT1 (max. 44 A)&lt;br /&gt;
  my $ssts   = CurrentVal  ($hash,  &#039;sunsetTodayTs&#039;,        0);&lt;br /&gt;
  my $srts   = CurrentVal  ($hash,  &#039;sunriseTodayTs&#039;,       0);&lt;br /&gt;
  my $sdiff  = ($ssts - $srts) / 3600;                                     # Sonnengang heute in h &lt;br /&gt;
  &lt;br /&gt;
  my $solh   = ReadingsNum ($name, &#039;special_SunHours_Remain&#039;, 0);          # h bis SunSet&lt;br /&gt;
  $solh      = $solh - ($sdiff * $sch);                                    # h bis SunSet - X&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;              # Ah Bat bis SOC&lt;br /&gt;
  $ahrem     = sprintf &amp;quot;%.0f&amp;quot;, $ahrem;&lt;br /&gt;
  &lt;br /&gt;
  my $fcdiff = ($pvfc - $cofc) * $spcorr;     # Korrektur d. noch prognostizierten Überschussenergie &lt;br /&gt;
  $fcdiff    = $fcdiff &amp;lt; 0 ? 0 : $fcdiff;     # Wh&lt;br /&gt;
  &lt;br /&gt;
  my $loadcur = $maxcspc;&lt;br /&gt;
  &lt;br /&gt;
  if ($cpv &amp;amp;&amp;amp; $solh &amp;amp;&amp;amp; $ahrem &amp;amp;&amp;amp; $fcdiff &amp;gt; $ahrem) {  # Ladeanforderung und Überschuss übersteigt &lt;br /&gt;
                                                      # Lademenge&lt;br /&gt;
      my $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($ahrem / $solh);    # A = Ah / h -&amp;gt; A Soll Schätzung&lt;br /&gt;
&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Battery charging process should be completed }.&lt;br /&gt;
                      qq{in &amp;gt;$solh&amp;lt; hours});&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; raw Target charging current: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($cspc - $mppt1c);      # SmartLoader IST berücksichtigen&lt;br /&gt;
	  &lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Charge Current minus MPPT load Current &amp;gt;$mppt1c&amp;lt;: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $loadcur = $cspc &amp;lt;= 0       ? 0       :     # nur MPPT Ladung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl0 ? $cclvl0 :     # Übergangsbereich&lt;br /&gt;
                 $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;
	  Log3 ($name, 3, qq{$name - userFn -&amp;gt; MaxChargeCurrent calculated: $loadcur});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent&#039;,       $loadcur.&#039; A&#039;,          1);&lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_HoursUntilChargeFinish&#039;, sprintf (&amp;quot;%.2f&amp;quot;,$solh), 1);&lt;br /&gt;
  CommandSet           (undef, &amp;quot;$vebus MaxChargeCurrent $loadcur&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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. 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;special_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;special_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;Verkürzungsfaktor Zeit bis Vollladung vor Sunset&#039;&#039;) reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche mindest Ladestromstärke ermittelt.&lt;br /&gt;
&lt;br /&gt;
&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 auch während der MQTT Intergration 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;
=== Poolheizung in Abhängigkeit von vorhandenem Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren) ===&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;consumer01&#039;&#039; wird beispielhaft wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr Forecast consumer01 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;&lt;br /&gt;
&lt;br /&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. &lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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, einen 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 Überschuss 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;. &lt;br /&gt;
&lt;br /&gt;
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;
=== PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) ===&lt;br /&gt;
[[Datei:Screenshot 2025-08-04 104835.png|mini|Darstellung der PV-Vorhersage in evcc auf Basis der SolarForecast-Daten]]&lt;br /&gt;
[https://evcc.io evcc] ist ein Energie-Management-System, mit dem u.a. Überschussladen von Elektroautos möglich ist. Hier ist beschreiben, wie die SolarForecast-Vorhersagedaten per API von evcc abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
Lege im SolarForecast-Device ein User-Reading mit dem Namen forecast_json an. Es wandelt die Forecast-Werte in JSON und ins UTC-Zeitformat um, so dass evcc die Daten verwenden kann:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
forecast_json {&lt;br /&gt;
&lt;br /&gt;
    use strict;&lt;br /&gt;
    use warnings;&lt;br /&gt;
    use JSON;&lt;br /&gt;
    use DateTime;&lt;br /&gt;
    use DateTime::Format::Strptime;&lt;br /&gt;
&lt;br /&gt;
    my $hour = 0;&lt;br /&gt;
    my @output;&lt;br /&gt;
&lt;br /&gt;
    # Parser für Datum mit CET/CEST&lt;br /&gt;
    my $parser = DateTime::Format::Strptime-&amp;gt;new(&lt;br /&gt;
        pattern   =&amp;gt; &#039;%Y-%m-%d %H:%M:%S&#039;,&lt;br /&gt;
        time_zone =&amp;gt; &#039;Europe/Berlin&#039;,&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    # Alle NextHour-Daten durchsuchen&lt;br /&gt;
    while ($hour &amp;lt; 100) {&lt;br /&gt;
        my $hour_str = sprintf(&#039;NextHour%02d&#039;, $hour);&lt;br /&gt;
        my $start_str = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;starttime&#039;, &#039;na&#039;); &lt;br /&gt;
        my $pvfc = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;pvfc&#039;, &#039;na&#039;);&lt;br /&gt;
&lt;br /&gt;
        # Schleife beenden, wenn keine Werte mehr vorhanden sind&lt;br /&gt;
        last if $start_str eq &#039;na&#039; or $pvfc eq &#039;na&#039;;&lt;br /&gt;
&lt;br /&gt;
        # parse und konvertiere Zeit&lt;br /&gt;
        my $start_dt = $parser-&amp;gt;parse_datetime($start_str);&lt;br /&gt;
        my $end_dt   = $start_dt-&amp;gt;clone-&amp;gt;add(hours =&amp;gt; 1);&lt;br /&gt;
&lt;br /&gt;
        # nach UTC konvertieren&lt;br /&gt;
        $start_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
        $end_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $start_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            end   =&amp;gt; $end_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            value =&amp;gt; 0 + $pvfc,&lt;br /&gt;
        };&lt;br /&gt;
        &lt;br /&gt;
        $hour++;&lt;br /&gt;
    }  &lt;br /&gt;
&lt;br /&gt;
    # Ausgabe als JSON&lt;br /&gt;
    my $json = JSON-&amp;gt;new-&amp;gt;utf8-&amp;gt;pretty-&amp;gt;encode(\@output);&lt;br /&gt;
    return $json;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Kommunikation von FHEM zu evcc läuft über den integrierten FHEM-Webserver, der die JSON-Daten aus dem Reading forecast_json veröffentlicht. Dazu wird in FHEM eine separate Webinstanz auf einem neuen Port erstellt, die ohne [[CsrfToken-HowTo|CSFR-Token]] (Achtung, Auswirkungen auf die Sicherheit beachten!) und nur von localhost aufrufbar ist (Voraussetzung: evcc läuft auf derselben Maschine wie FHEM):&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
defmod WEBapi FHEMWEB 8089&lt;br /&gt;
attr WEBapi csrfToken none&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;In der [https://docs.evcc.io/docs/tariffs#pv-vorhersage evcc-Konfig unter tariffs] steht die Quelle für die Solar-Vorhersage. Der FHEM-Befehl {ReadingsVal(&#039;solarforecast_dev&#039;,&#039;forecast_json&#039;,&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;)} wird encoded und in die uri eingetragen. Trage statt solarforecast_dev den passenden Namen deines SolarForecast-Device ein. evcc holt die Daten aus dem Reading forecast_json dann regelmäßig ab.&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
solar:&lt;br /&gt;
  type: custom&lt;br /&gt;
  interval: 20m    &lt;br /&gt;
  forecast:&lt;br /&gt;
    source: http&lt;br /&gt;
    uri: http://localhost:8089/fhem?cmd=%7BReadingsVal%28%27solarforecast_dev%27%2C%27forecast_json%27%2C%27%27%29%7D&amp;amp;XHR=1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Zur Verbesserung der Sicherheit kann das neue WEBapi Device auch ein [[CsrfToken-HowTo#csrfToken festlegen|festes CSFR-Token]] verwenden. Dieses Token muss dann in der evcc-Konfiguration an die uri mittels &amp;amp;fwcsrf=&amp;lt;festes token&amp;gt; angehängt werden.&lt;br /&gt;
&lt;br /&gt;
== weiterführende Links ==&lt;br /&gt;
* Forenthema &amp;quot;{{Link2Forum|Topic=137058|LinkText=76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support}}&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;
* Photovoltaik Ingenieurbüro Junge: https://www.ing-büro-junge.de/html/photovoltaik.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung&amp;diff=40304</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=40304"/>
		<updated>2025-08-04T12:08:00Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Hinweis|Die vorliegende Wiki-Seite befindet sich im Aufbau.}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Solarprognose und Verbrauchersteuerung&lt;br /&gt;
|ModType=d&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 Prognosewerte können die SolCast API, OpenMeteo API, Forecast.Solar API, Victron VRM Portal API oder alternativ DWD Stahlungswerte-Stationen verwendet werden&lt;br /&gt;
&lt;br /&gt;
::* optionale KI Unterstützung der PV-Prognose bei Verwendung von geeigneten Solar-API&#039;s&lt;br /&gt;
&lt;br /&gt;
::* es wird sowohl die Erzeugungsprognose als auch eine Verbrauchsprognose sowie SoC Prognose (bei Batterie-Integration) erstellt&lt;br /&gt;
&lt;br /&gt;
::* Wetterdaten werden über DWD Wetter-Stationen oder verschiedene API integriert. Es können verschiedene API zur Gewinnung von Solar- und Wetterdaten kombiniert werden. &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 FHEM-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 Integration von bis zu 4 Inverter und Smartloader (DC-DC Batterieladegeräte) ist möglich&lt;br /&gt;
&lt;br /&gt;
::* eine Integration von bis zu 3 nicht PV-Energieerzeugern wie BHKW, Windrädern oder Notstromaggregaten ist möglich&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;
::* Einbindung von bis zu drei Batteriespeichersystemen&lt;br /&gt;
&lt;br /&gt;
::* Bereitstellung von Leitwerten zur optimalen Einstellung/Steuerung von Batteriespeichersystemen&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 Benutzererlebnis 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;
Das Wiki gibt allgemeingültige und teilweise sehr spezifische bzw. tiefgehende Informationen und Handlungsempfehlungen zum SolarForecast Modul. Die dargestellten Informationen beziehen sich auf den zum Zeitpunkt der Wiki-Erstellung vorhandenen Entwicklungsstand des Moduls. Durch die stetige Weiterentwicklung können sich Abweichungen zum beschriebenen Inhalt ergeben oder zur Obsoleszenz dieser Inhalte führen. &lt;br /&gt;
&lt;br /&gt;
Vergleiche deshalb die Informationen immer mit der aktuellen Befehls-Referenz zum Modul!&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Ein SolarForecast Device wird mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 define &amp;lt;Name&amp;gt; SolarForecast &lt;br /&gt;
&lt;br /&gt;
angelegt. Nach der Definition wird der User durch einen Dialog geführt, der einige unerlässliche Einstellungen abfragt und in den entsprechenden Attributen und Readings persistiert. Alle Attribute und Readings die eine Einstellung der Anlage bewirken, sind mit dem Präfix &amp;quot;setup&amp;quot; versehen. &lt;br /&gt;
&lt;br /&gt;
Die Verwendung von setup-Readings gestattet es die Anlagenparameter dynamisch im Betrieb zu verändern. So kann mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringAzimuth   bzw.&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringDeclination &lt;br /&gt;
&lt;br /&gt;
die Ausrichtung und der Neigungswinkel der PV-Module ständig angepasst werden, was zum Beispiel bei einer dem Sonnenstand nachgeführten Anlage von Bedeutung ist.&lt;br /&gt;
&lt;br /&gt;
Die abgefragten Einstellungen während des Dialoges sind ausführlich in den entsprechenden Attributen bzw. Set-Kommandos erläutert. Die benötigten Informationen sind anhängig von der gewählten Prognose-API und können im Umfang variieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 213257.png|right|thumb|400px|Anlagenprüfung über Drucktaste in der Kopfgrafik]]&lt;br /&gt;
&lt;br /&gt;
Sobald alle verlangten Einstellungen vorgenommen sind, sollte eine Anlagenprüfung mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; plantConfiguration check&lt;br /&gt;
&lt;br /&gt;
oder über die angebotene Drucktaste in der Grafik durchgeführt werden. Es wird eine Plausibilitätsprüfung vorgenommen und das Ergebnis sowie eventuelle Hinweise bzw. Fehler ausgegeben.&lt;br /&gt;
Die Prüfung kann beliebig wiederholt werden und sollte sich bei jeder Einstellungsänderung der Anlage durchgeführt werden. Dadurch wird die Wahrscheinlichkeit von fehlerhaften Einstellungen minimiert.&lt;br /&gt;
&lt;br /&gt;
Neben den grundlegenden Einstellungen können im Device weitere sekundäre Anlagenkomponenten wie Batteriesystem(e) (Attribut setupBatteryDev1 - setupBatteryDev3), weitere Wetter-Devices (Attribut setupWeatherDev1 - setupWeatherDev3) oder sonstige Erzeuger (z.B. BHKW, Winderzeugung, Notstromaggregat) integriert werden (Attribut setupOtherProducer01 - setupOtherProducer03).&lt;br /&gt;
&lt;br /&gt;
Die verlangten Parameter der Anlage werden in der Online-Hilfe umfassend beschrieben und deren Funktion erschließt sich zum größten Teil selbst. Dennoch soll nachfolgend auf einige Punkte im Zusammenhang der Einrichtung eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Hinweise zur Struktur der Attribute ===&lt;br /&gt;
&lt;br /&gt;
Durch die umfangreichen Funktionen des Moduls würde bei Nutzung der im FHEM herkömmlich vorhandenen Attributstruktur die Anzahl der benötigten Attribute extrem stark steigen und nicht sinnvoll genutzt werden können. Deshalb gibt es neben den &#039;&#039;gewöhnlichen&#039;&#039; Attributen mit einfachen Werteauswahlmöglichkeiten oder Eingaben (z.B. ctrlDebug, ctrlSpecialReadings) sogenannte &#039;&#039;zusammengesetzte&#039;&#039; Attribute, deren Inhalt durch &#039;&#039;&#039;Schlüssel=Wert Paare&#039;&#039;&#039; gebildet wird und dadurch deutlich mehr Funktionen und Informationen transportieren als ein gewöhnliches Attribut.&lt;br /&gt;
&lt;br /&gt;
Für zusammengesetzte Attribute besteht die zusätzliche Möglichkeit, gewünschte Änderungen der Schlüssel=Wert Paare selektiv vornehmen zu können, ohne das gesamte Attribut aufrufen und ändern zu müssen. Die Vorgang, der vor allem für programmtechnische Manipulationen gedacht ist, kann durch eine Set-Funktion ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; attrKeyVal &amp;lt;Attribut&amp;gt; [&amp;lt;Gerät&amp;gt;] &amp;lt;Schlüssel=Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiele für zusammengesetzte Attribute sind:&lt;br /&gt;
&lt;br /&gt;
* aiControl&lt;br /&gt;
* plantControl&lt;br /&gt;
* setup* Attribute&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktionen der Attribute werden durch einen Präfix geclustert und so inhaltlich, aber vor allem auch in der Attribute Drop-Down Liste, strukturiert dargestellt.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der &#039;&#039;&#039;Präfixe&#039;&#039;&#039; sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ai&#039;&#039;&#039; - Steuerungsfunktionen für KI (z.B. aiControl)&lt;br /&gt;
* &#039;&#039;&#039;consumer&#039;&#039;&#039; - Registrierung und Einstellungen für Verbraucher (z.B. consumer02, consumerControl)&lt;br /&gt;
* &#039;&#039;&#039;ctrl&#039;&#039;&#039; - Steuerungsfunktion allgemeiner Art (z.B. ctrlDebug, ctrlSpecialReadings, ctrlUserExitFn)&lt;br /&gt;
* &#039;&#039;&#039;flowGraphic&#039;&#039;&#039; - Einstellungen für die Energieflußgrafik (z.B. flowGraphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphic&#039;&#039;&#039; - Einstellung für die Grafik allgemein (z.B. graphicSelect, graphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphicBeam&#039;&#039;&#039; -  Einstellungen bestimmte Balkeneigenschaften in der Balkengrafik (z.B. graphicBeamHeightLevel1)&lt;br /&gt;
* &#039;&#039;&#039;plant&#039;&#039;&#039; - übergreifende Einstellungen betreffend der gesamten PV-Anlage bzw. des SolarForecast-Devices (z.B. plantControl)&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039; - Registrierung von Geräten in der Gesamtanlage und Einstellung deren Eigenschaften (Inverter, Zähler, Batterien usw.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Einrichtung der Wechselrichter mit setupInverterDevXX ===&lt;br /&gt;
&lt;br /&gt;
Mit den Attributen setupInverterDev01 bis setupInverterDevXX werden die vorhandenen Wechselrichter der Anlage registriert.&lt;br /&gt;
Das Modul unterscheidet verschiedene Wechselrichter-Typen, die sich durch ihre Arbeitsweise innerhalb der Anlage unterscheiden. Die Schlüssel=Wert Paare in den Attributen können mehrzeilig organisiert werden. Das erleichtert die Übersicht wenn viele dieser Parameter eingegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;PV-Wechselrichter: Es ist der Standard Wechselrichter in einer PV-Anlage. An ihn sind die Solarzellen bzw. Strings angeschlossen. Die zugeordneten Strings können mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ohne diese Angabe werden diesem Gerät alle definierten Strings (siehe Attribut &#039;&#039;setupInverterStrings&#039;&#039;) zugeordnet. Der Wechselrichter liefert seine Energie in das Hausnetz. Alternativ kann mit der Angabe &#039;&#039;&#039;feed=grid&#039;&#039;&#039; die Funktion des Wechselrichters geändert werden. Diese Angabe sagt aus, dass dieser Wechselrichter ausschließlich in das öffentliche Netz einspeist.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel-Setup eines PV-Wechselrichters (SMA STP):&lt;br /&gt;
&lt;br /&gt;
 STP_5000 pvIn=string_1_pdc:kW pvOut=total_pac:kW etotal=etotal:kWh capacity=5000 strings=Süddach asynchron=1 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Solar-Ladegeräte: Solar-Ladegeräte sind DC-DC Wandler und liefern die Energie der angeschlossenen Solarzellen nicht in das Wechselstromnetz, sondern laden direkt eine Batterie bzw. versorgen einen Batteriewechselrichter auf der Gleichstromseite. Die Funktion als Solar-Ladegerät wird mit &#039;&#039;&#039;feed=bat&#039;&#039;&#039; aktiviert, die relevanten Strings können ebenfalls mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ein Beispiel eines Solar-Ladegerätes ist ein Victron SmartSolar MPPT. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel für das Setup eines Solar-Ladegeräts (SmartSolar Charger MPPT):&lt;br /&gt;
&lt;br /&gt;
 MQTT2_cerboGX_c0619ab34e08_solarcharger_Common pv=Yield_Power_value:W etotal=Yield_System_value:kWh capacity=2080 strings=Schleppdach feed=bat synchron=0 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Batterie-Wechselrichter: Dieses Gerät hat keine angeschlossenen Solarzellen und arbeitet als DC-AC bzw. AC-DC Wandler zwischen einer Batterie (=Gleichstromquelle) und dem Wechselstrom-Hausnetz. Die Funktion als Batterie-Wechselrichter wird mit der Angabe &#039;&#039;&#039;strings=none&#039;&#039;&#039; aktiviert. Die Schlüssel &#039;&#039;etotal&#039;&#039; und &#039;&#039;pv&#039;&#039; können bei einem Batterie-Wechselrichter ohne zugeordnete Solarzellen nicht gesetzt werden. Ein Beispiel eines Batterie-Wechselrichter ist der Victron MultiPlus II.&lt;br /&gt;
&lt;br /&gt;
Ein Setup-Beispiel für einen Batterie-Wechselrichter (Victron MultiPlus II):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dc2ac=DC_IN:W&lt;br /&gt;
ac2dc=DC_OUT:W&lt;br /&gt;
capacity=7200&lt;br /&gt;
strings=none&lt;br /&gt;
icon=inverter@darkorange:inverter@grey&lt;br /&gt;
asynchron=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Eigenschaften des Wechselrichters werden durch eine Reihe von &amp;lt;Schlüssel=Wert&amp;gt; Paaren festgelegt. Auf einige dieser Paramter soll hier eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Ausgewählte Schlüssel=Wert Paare ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;pvIn=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvIn&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell zugeführte PV-Leistung bereitstellt. Der Schlüssel ist optional und dient in erster Linie dazu den entsprechenden Input-Wert in der Flußgrafik anzuzeigen sofern man das Attribut flowGraphicControl-&amp;gt;showGenerators=1 setzt. Dadurch ist auch der Eigenverbrauch des Inverters bzw. dessen Wandlungsverlust visuell abschätzbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pvOut=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvOut&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell erzeugte Leistung als positiven Wert liefert. Für einen PV-Wechselrichter (DC-&amp;gt;AC) oder Solar-Ladegerät (DC-&amp;gt;DC) ist es die erzeugte PV-Leistung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ac2dc=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter vom Hausnetz in Richtung Batterie (AC-&amp;gt;DC) wandelt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;dc2ac=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter aus einer Gleichstromquelle, d.h. einer Batterie oder einem Solar-Ladegerät, in Richtung des Hausnetzes (AC) wandelt . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;capacity=&amp;lt;max. WR-Leistung&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In dem Schlüssel &#039;&#039;capacity&#039;&#039; wird die maximal mögliche Leistung in Watt (ohne Einheit) angegeben, die der Wechselrichter lt. seinem Datenblatt in der Lage ist zu leisten. &lt;br /&gt;
&lt;br /&gt;
Die Angabe &#039;&#039;capacity&#039;&#039; hat in erster Linie die Aufgabe, die max. mögliche PV-Leistung für die Prognose zu begrenzen. Oft sind die installierten Peak-Leistungen der PV-Module höher als die angeschlossene Wechselrichter-Leistung bzw. kommt es vor, dass die KI / (korrigierte) API-Prognose über der maximal möglichen Wechselrichter-Leistung liegt. In diesen Fällen wird die Prognose auf die angegebene &#039;&#039;capacity&#039;&#039; begrenzt.&lt;br /&gt;
&lt;br /&gt;
Der Wert in diesem Schlüssel kann, wie andere Schlüssel auch, dynamisch zur Laufzeit mit dem Set-Befehl &amp;quot;[[#Hinweise zur Struktur der Attribute|set &amp;lt;Name&amp;gt; attrKeyVal ...]]&amp;quot; geändert werden. Ein Beispiel zur Anwendung ergibt sich aus folgendem Szenario.&lt;br /&gt;
&lt;br /&gt;
Gegeben sei eine Anlage die aus Solarzellen (1300 W Peak) mit einem Solar-Ladegerät mit max. 1800 W Leistung, einer Batterie und einem Batterie-Wechselrichter besteht. Die Anlage versorgt nur das Hausnetz. Eine Netzeinspeisung ist nicht vorgesehen oder nicht erlaubt.  &lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, es ist ein Tag voller Sonnenschein prognostiziert und die Batterie ist zunächst entladen. Der Haushalt verbraucht 300 W. Dann würden die PV-Module Module ihre volle Leistung von 1300 W Peak leisten können, die sich auch in der Balken-Vorhersage niederschlägt. Die Leistung wird nicht begrenzt, weil:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* sie niedriger ist als die nominale und angegebene Wechselrichter Kapazität von &#039;&#039;capacity=1800&#039;&#039;&lt;br /&gt;
* die erzeugte Energie anteilig für die Verorgung des Hauses und die Aufladung der Batterie verwendet wird&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders verhält es sich wenn nach einer gewissen Zeit die Batterie voll ist und weiterhin volle PV Leistung zur Verfügung steht. In diesem Fall würde der Haushalt seine benötigte Leistung von 300 W abnehmen, aber das Solar-Ladegerät kann keine weitere Leistung mehr abgeben, da die Batterie bereits voll geladen ist, d.h. die Anlagensteuerung würde die PV-Anlage abregeln. In diesem Fall, wenn es einen längeren Zeitraum betrifft, muß auch die Prognose PV-Energie auf 300 Wh (bzw. den durchschnittlichen Energieverbrauch des Hauses pro Stunde) begrenzt werden, damit die PV-Prognose nach unten angepasst wird und so eine realitätsnahere Prognose ermöglicht wird. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;icon=&amp;lt;aktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;][:&amp;lt;inaktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Jeder Wechselrichter wird im Standard durch ein Icon getrennt nach Tag und Nacht, d.h. je nach Aktiv-Status und Inaktiv-Status, symbolisiert.&lt;br /&gt;
&lt;br /&gt;
;Tag bzw. Aktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Sonnensymbol im Standard verwendet. Batterie-Wechselrichter verwenden ein gefärbtes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
;Nacht bzw. Inaktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Symbol der aktuellen Mondphasen im Standard verwendet. Batterie-Wechselrichter verwenden ein ausgegrautes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie angegeben, kann man für Tag und Nacht jeweils ein Wunsch-Icon, wenn gewünscht mit einer alternativen Färbung, auswählen.&lt;br /&gt;
&lt;br /&gt;
 icon=inverter@darkorange:inverter@gray&lt;br /&gt;
&lt;br /&gt;
Soll nur das Icon für die Nacht bzw. Inaktivät geändert werden, kann dies in dieser Form angegeben werden:&lt;br /&gt;
&lt;br /&gt;
 icon=:inverter@gray  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(beachte den führenden &#039;:&#039;)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Der integrierte SolarForecast Grafikbereich ==&lt;br /&gt;
Das SolarForecast Modul beinhaltet eine Grafikdarstellung die sich in mehrere Bereiche gliedert. Diese Bereiche können über Attribute ein- bzw. ausgeblendet sowie die Inhalte festgelegt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 223545.png|right|thumb|400px|Bereiche der integrierten Grafik]]&lt;br /&gt;
&lt;br /&gt;
Der nebenstehende Screenshot gibt die Gliederung der Grafikbereiche wieder:&lt;br /&gt;
&lt;br /&gt;
 1 - der Kopfbereich (Graphic Header)&lt;br /&gt;
 2 - durch den Nutzer selbst definierbarer Inhalt (Graphic Header Own Specification) als Teil des Kopfbereiches&lt;br /&gt;
 3 - Bereich Verbraucherdarstellung (Consumer Legend)&lt;br /&gt;
 4 - Bereich Balkengrafik (Beam Graphic)&lt;br /&gt;
 5 - Energieflußgrafik (Flow Graphic)&lt;br /&gt;
&lt;br /&gt;
Jeder dieser Bereiche hat spezifische Steuerungsattribute zur Anpassung des Verhaltens und ggf. des Inhalts.&lt;br /&gt;
&lt;br /&gt;
=== 1 - Der Grafik Kopfbereich ===&lt;br /&gt;
Im Kopfbereich befinden sich fest verankerte Informationen zur verwendeten Vorhersage-API sowie deren Status, Informationen zum Sonnenaufgang und Sonnenuntergang, dem aktuellen Gesamtstatus des SolarForecast Devices, Abweichungskennzahlen der PV Vorhersage sowie weitere Kennzeichen zur Verfügung.&lt;br /&gt;
Über zwei Drucktasten kann eine Anlagenprüfung durchgeführt und in den Spportthread des Moduls im FHEM Forum abgesprungen werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;graphicHeaderShow&#039;&#039;&#039; kann der gesamte Kopfbereich 1 und 2 (nutzereigener Teilbereich) ausgeblendet werden. Wird der Kopbereich ausgeblendet, ist es hilfreich mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;showLink&#039;&#039;&#039; einen Link zur Detailgrafik einzufügen da der in der Kopfgrafik integrierte Link in diesem Fall nicht mehr zur Verfügung steht. &lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;graphicHeaderDetail&#039;&#039;&#039; definiert welche Bereiche des Grafikkopfes angezeigt werden sollen. Es kann die Anzeige des Energieverbrauches, der PV-Erzeugung und der vom Nutzer selbst definierte Inhalt miteinander frei kombiniert werden.&lt;br /&gt;
&lt;br /&gt;
=== 2 - Der Bereich mit selbst definierbarem Inhalt (Graphic Header Own Specification) ===&lt;br /&gt;
In diesem Bereich kann der User beliebige Readings, Set-Kommandos und Attribute des SolarForecast Devices oder anderer Devices, die sich im gleichen FHEM-System wie das SolarForecast Device befinden, anzeigen lassen.&lt;br /&gt;
&lt;br /&gt;
Dieser Bereich ist als Tabelle mit einer beliebigen Anzahl von Zeilen organisiert. Jede Zeile beinhaltet ein Kommentarfeld und vier Nutzfelder zur Darstellung ausgewähler Werte + Label. Der Bereich bzw. der Inhalt des Bereiches wird mit dem Attribut &#039;&#039;&#039;graphicHeaderOwnspec&#039;&#039;&#039; definiert.  &lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt ein real gesetztes graphicHeaderOwnspec Attribut. Die Leerzeilen sind nicht notwendig, erhöhen aber die Lesbarkeit der Struktur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
Autarkierate:Current_AutarkyRate&lt;br /&gt;
PV&amp;amp;nbsp;übermorgen:special_dayAfterTomorrowPVforecast&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;Sunset:special_todayConForecastTillSunset&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;nächsten&amp;amp;nbsp;Sunrise:special_conForecastTillNextSunrise&lt;br /&gt;
&lt;br /&gt;
#Batterie&lt;br /&gt;
BatteryLive&amp;amp;nbsp;Status:userFn_BatLive_State&lt;br /&gt;
SoC&amp;amp;nbsp;Limit:Settings_CGwacs_BatteryLife_MinimumSocLimit_value@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SoC&amp;amp;nbsp;Ist:SOC_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
SOC&amp;amp;nbsp;Optimum:Battery_OptimumTargetSoC&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
aktuelle&amp;amp;nbsp;Ladung:userFn_Bat_EnergyState&lt;br /&gt;
Verfügbar:userFn_BatLive_UsableEnergy&lt;br /&gt;
benötigte&amp;amp;nbsp;Ladeenergie:userFn_Bat_EnergyRemain&lt;br /&gt;
Ladefreigabe:Battery_ChargeRecommended&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
akt.&amp;amp;nbsp;DC&amp;amp;nbsp;Strom:DC_Current_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
Restladezeit&amp;amp;nbsp;Ziel:userFn_Bat_HoursUntilChargeFinish&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Soll:userFn_Bat_MaxChargeCurrent_set&lt;br /&gt;
:&lt;br /&gt;
&lt;br /&gt;
#Settings&lt;br /&gt;
Batterie&amp;amp;nbsp;Lademanagement:userFn_BatteryChargeManagement&lt;br /&gt;
SoC&amp;amp;nbsp;Management:userFn_BatterySoCManagement&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Ist:MaxChargeCurrent@MQTT2_cerboGX_c0619ab34e08_vebus&lt;br /&gt;
SmartSolar&amp;lt;br&amp;gt;Einspeisung:OvervoltageFeedIn@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
MPII&amp;amp;nbsp;Limit&amp;lt;br&amp;gt;Einspeisung&amp;amp;nbsp;(W):MaxFeedInPower@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SOC&amp;amp;nbsp;Limit&amp;amp;nbsp;Soll:MinimumSocLimit@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Verbr.&amp;amp;nbsp;Neuplanung:consumerNewPlanning&lt;br /&gt;
Wetteranzeige:graphicShowWeather &lt;br /&gt;
&lt;br /&gt;
Anzeige&amp;amp;nbsp;Nachtstunden:graphicShowNight&lt;br /&gt;
hist.&amp;amp;nbsp;Stunden:graphicHistoryHour&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto&lt;br /&gt;
Victron&amp;amp;nbsp;BatteryLife&amp;lt;br&amp;gt;(1=an,10=aus):BatteryLife@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Debug:ctrlDebu&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Kommentarfeld am Beginn einer Zeile wird durch ein &#039;&#039;&#039;#&#039;&#039;&#039; gekennzeichnet. Folgt dem # ein String, wird dieser String als Kommentarangabe gewertet und in der Grafik ausgegeben. Ein leeres Kommentarfeld wird lediglich durch ein # gefolgt von einem Leerzeichen oder NL beschrieben:&lt;br /&gt;
&lt;br /&gt;
 #:&amp;lt;Text&amp;gt;  (bzw nur # für einen &#039;leeren&#039; Titel)&lt;br /&gt;
&lt;br /&gt;
Ein Netzfeld bzw. ein Datensatz wird durch die Angabe von einem Label und dem darzustellenden Wert getrennt durch &#039;:&#039; definiert:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Label&amp;gt;:&amp;lt;Reading, Attribut oder Set-Kommando&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das System erkennt selbständig, ob es sich bei der Angabe um ein Reading, Attribut oder ein Set-Kommando handelt. Sollen Readings, Set-Kommandos und Attribute anderer Devices als dem SolarForecast-Device angezeigt werden, kann dies einfach durch Zusatz von&lt;br /&gt;
&lt;br /&gt;
 ....@&amp;lt;Device-Name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
an den Parameter erreicht werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-12-05 203916.png|right|thumb|400px|Darstellung eigener Grafikbereich]]&lt;br /&gt;
Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten &amp;quot;Wh&amp;quot; bzw. &amp;quot;kWh&amp;quot; werden entsprechend der Einstellung des Attributs &#039;&#039;&#039;graphicEnergyUnit&#039;&#039;&#039; umgerechnet. Im Label sind Leerzeichen durch &amp;quot;&amp;amp;amp;nbsp;&amp;quot; einzufügen, ein Zeilenumbruch durch &amp;quot;&amp;amp;lt;br&amp;amp;gt;&amp;quot;. Ein leeres Feld in einer Zeile wird durch &amp;quot;:&amp;quot; ohne eine weitere Angabe erzeugt.&lt;br /&gt;
&lt;br /&gt;
Die nebenstehende Abbildung zeigt die reale Darstellung der oben angegebenen Struktur im Attribut graphicHeaderOwnspec.&lt;br /&gt;
&lt;br /&gt;
==== Formatierung der Inhalte im Bereich &amp;quot;Graphic Header Own Specification&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
Die angezeigten Inhalte, wie z.B. Readingwerte, des User eigenen Bereiches (Attribut graphicHeaderOwnspec) können durch Spezifikationen im Attribut &#039;&#039;&#039;graphicHeaderOwnspecValForm&#039;&#039;&#039; manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
Die Online-Hilfe zum Attribut graphicHeaderOwnspecValForm erläutert die verfügbaren Möglichkeiten und Optionen.&lt;br /&gt;
Als Beispiel hier einige mögliche Notationen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &#039;userFn_Bat_HoursUntilChargeFinish&#039;                        =&amp;gt; &amp;quot;($VALUE).&#039; Stunden&#039;&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_battery.SOC_value&#039;             =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Settings_CGwacs_BatteryLife_MinimumSocLimit_value&#039;        =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Info_MaxChargeCurrent_value&#039;                              =&amp;gt; &amp;quot;($VALUE).&#039; A&#039;&amp;quot;,&lt;br /&gt;
  &#039;DC_Current_value&#039;                                         =&amp;gt; &amp;quot;%.0f A&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common.Regulated&#039; =&amp;gt; &amp;quot;($VALUE eq &#039;1&#039; ? &#039;Ja&#039; : &#039;Nein&#039;)&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine Besonderheit besteht bei darzustellenden Werten die die Einheiten &#039;Wh&#039; bzw. &#039;kWh&#039; besitzen. Diese Werte und Einheiten werden automatisch entsprechend des gesetzten Attributes graphicEnergyUnit umgerechnet und angezeigt.&lt;br /&gt;
&lt;br /&gt;
Soll in diesen Fällen eine automatische Formatierung umgangen werden, kann eine solche Notation verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &#039;Today_PVforecast&#039; =&amp;gt; &amp;quot;(sprintf &#039;%.1f &amp;amp;amp;nbsp;kWh&#039;, ($VALUE / 1000))&amp;quot;,&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Die Angabe von &amp;amp;amp;nbsp; vor &#039;kWh&#039; verhindert die Erkennung der Einheit und so auch die automatische Umsetzung durch das Modul. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 3 - Bereich Verbraucherdarstellung (Consumer Legend) ===&lt;br /&gt;
Dieser Grafikbereich zeigt die im Modul registrierten Verbraucher sowie deren Status und weitere Informationen an. Sind die Voraussetzungen gegeben, d.h. entsprechende Schlüssel in der ConsumerXX-Attributen gesetzt, können die Verbraucher über das Paneel manuell geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Zur Anpassung der Darstellung sind verschiedene Attribute verfügbar:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;consumerControl-&amp;gt;showLegend: Definiert die Lage bzw. Darstellungsweise der Verbraucherlegende sofern Verbraucher im SolarForecast Device registriert sind.&lt;br /&gt;
;consumerControl-&amp;gt;adviceIcon: Definiert die Art der Information über die geplanten Schaltzeiten eines Verbrauchers in der Verbraucherlegende. &lt;br /&gt;
;consumerControl-&amp;gt;detailLink: Wenn gesetzt, ist der jeweilige Verbraucher klickbar um direkt zur Detailansicht des jeweiligen Geräts auf einer neuen Browserseite zu gelangen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Standard wird das Verbraucherpaneel zwischen dem Kopfbereich und der ersten Balkengrafik Ebene dargestellt. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;showLegend&#039;&#039;&#039; und Argument &#039;&#039;&#039;icon_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_bottom&#039;&#039;&#039; kann das Verbraucherpaneel an das Ende des Grafikbereiches verschoben werden.&lt;br /&gt;
Die Verwendung von &#039;&#039;&#039;text_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_top&#039;&#039;&#039; blendet die Icon-Spalte im Verbraucherpaneel aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Screenshot 2025-02-08 093239.png|Darstellung mit consumerControl showLegend=icon_top (default)&lt;br /&gt;
File:Screenshot 2025-02-08 093646.png|Darstellung mit consumerControl showLegend=icon_bottom&lt;br /&gt;
File:Screenshot 2025-02-08 152018.png|Darstellung mit consumerControl showLegend=text_top bzw. text_bottom&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 213634.png|right|thumb|400px|]]&lt;br /&gt;
Ein Mouse-Over über das Uhrensymbol zeigt nähere Informationen zum Status, den Planungsdaten, Modus und weitere Daten des Verbrauchers. Der Schalter &amp;quot;Aus/Ein&amp;quot; visualisiert den Schaltzustand des Verbrauchers und können auch zum manuellen Schalten des Verbrauchers dienen. Voraussetzung ist, dass im consumer-Attribut die Schlüssel &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; mit den Set-Kommandos zum Schalten des Verbrauchers defininiert sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 222210.png|right|thumb|300px|]]&lt;br /&gt;
Der Auto-Schieberegler zeigt einerseits den Freigabestatus zum Schalten des Verbrauchers durch das SolarForecast Modul und kann andererseits manuell betätigt werden. Der Status des Reglers korrespondiert mit dem im zugehörigen Consumer Attribut vorhandenen Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; angegebenen Reading-Wert.&lt;br /&gt;
&lt;br /&gt;
Die Verbraucherbezeichnungen in dem Paneel können in der Standardkonfiguration angeklickt werden um direkt zur Detailansicht des Devices zu gelangen. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;detailLink&#039;&#039;&#039; kann der Link zur Detailansicht deaktiviert werden.&lt;br /&gt;
&lt;br /&gt;
Das Uhrensymbol kann mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;adviceIcon&#039;&#039;&#039; geändert und/oder dessen Farbe angepasst, sowie einen Informationstext statt eines Icons angezeigt werden. &lt;br /&gt;
&lt;br /&gt;
=== 4 - Bereich Balkengrafik (Beam Graphic) ===&lt;br /&gt;
&lt;br /&gt;
Die Balkengrafik des Moduls ist ein wesentliches Visualisierungshilfsmittel. Im Auslieferungszustand existiert eine Balkengrafikebene, die &#039;&#039;&#039;Ebene 1&#039;&#039;&#039;.&lt;br /&gt;
Jede Ebene kann zwei Balkendiagramme mit auswählbaren Inhalten, Farben und einstellbarem LayoutTyp darstellen. In Ebene 1 kann die Wettervorhersage eingebettet oder, bei Vorhandensein von Batteriegeräten, die zukünftigen Zeiten mit empfohlener Ladefreigabe und SoC-Prognose eingeblendet werden. &lt;br /&gt;
&lt;br /&gt;
Welche Daten in welchen Zeiträumen dargestellt werden sollen, die Bestimmung des Layouts, die Gestaltung der Balken und einiges mehr wird durch Attribute gesteuert. Ein Teil dieser Einstellungen wird über das zusammengesetzete Attribut &#039;&#039;&#039;graphicControl-&amp;gt;&#039;Schlüssel&#039;=&#039;Wert&#039;&#039;&#039;&#039; eingestellt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;grundsätzliche Layout Definitionen&#039;&#039;&#039;&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204342.png|right|thumb|400px|Standardanzeige mit Wetter-Icons, gesetzen Attributen graphicBeam1Color=D4C177, graphicHistoryHour=11]]&lt;br /&gt;
&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingTop:Legt den Platz in px im Balkendiagramm fest, der zwischen dem oberen Rand der jeweiligen Balkengrafik Ebene und der ersten Text- oder Iconreihe dieser Ebene eingefügt wird.&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingBottom:Legt den Platz in px im Balkendiagramm fest, der zwischen der letzten Text- oder Iconreihe der jeweiligen Balkengrafik Ebene und dem unteren Rand dieser Ebene eingefügt wird. &lt;br /&gt;
;graphicControl-&amp;gt;layoutType:Layout-Optionen zur grundlegenden Gestaltung der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourStyle:Format der Zeitangabe in der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourCount:Anzahl der darzustellenden Balken/Stunden in der Balkengrafk&lt;br /&gt;
[[Datei:Screenshot Screenshot 2025-05-21 153613.png|right|thumb|400px|Erweiterung des oberen und unteren Abstandes mit den Attributen graphicControl-&amp;gt;beamPaddingTop und graphicControl-&amp;gt;beamPaddingBottom]]&lt;br /&gt;
;graphicControl-&amp;gt;energyUnit:definiert die Einheit zur Anzeige der elektrischen Leistung in der Grafik&lt;br /&gt;
;graphicHistoryHour:Anzahl der vorangegangenen Stunden die in der Balkengrafik dargestellt werden&lt;br /&gt;
;graphicControl-&amp;gt;beamWidth:Vorgabe Breite der Balken der Balkengrafik in px (sonst automatische Bestimmung) &lt;br /&gt;
;graphicBeamHeightLevel1:Multiplikator zur Festlegung der maximalen Balkenhöhe der jeweiligen Ebene (hier Ebene 1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;Definition der Inhalte und Balkeneigenschaften&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204756.png|right|thumb|400px|Wie oben aber mit gesetzem Attribut graphicShowNight=1]]&lt;br /&gt;
;graphicBeam1Color:Farbauswahl des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2Color:Farbauswahl des sekundären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam1Content:Legt den darzustellenden Inhalt des primären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam2Content:Legt den darzustellenden Inhalt des sekundären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam1FontColor:Auswahl der Schriftfarbe des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2FontColor:Auswahl der Schriftfarbe des sekundären Balkens (Ebene 1)&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 205024.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=0 (ohne Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;zusätzliche Optionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;graphicShowNight:Anzeigen oder Verbergen der Nachtstunden in der Balkengrafik&lt;br /&gt;
;graphicShowWeather:Wettericons in der Balkengrafik anzeigen/verbergen (nur Ebene 1)&lt;br /&gt;
;graphicWeatherColor:Farbe der Wetter-Icons für die Tagesstunden&lt;br /&gt;
;graphicWeatherColorNight:Farbe der Wetter-Icons für die Nachtstunden&lt;br /&gt;
;graphicShowDiff:Zusätzliche Anzeige der Differenz &amp;quot;&amp;lt;primärer Balkeninhalt&amp;gt; - &amp;lt;sekundärer Balkeninhalt&amp;gt;&amp;quot; im Kopf- oder Fußbereich der Balkengrafik&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die genaue Beschreibung und deren Optionen sind der aktuellen Online-Hilfe zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Für alle Ebenen gilt:&#039;&#039;&#039; Ein Attribut mit einer ungeraden Balkennummer (z.B. graphicBeam1Content) bezieht sich immer auf den primären Balken, ein Attribut mit einer geraden Balkennummer (z.B. graphicBeam2Content) bezieht sich immer auf den sekundären Balken.&lt;br /&gt;
&lt;br /&gt;
Die Balken haben, wie die meisten Elemente in der Balkengrafik, eine Mouse-Over Eigenschaft welche relevante Informationen zu den dargestellten Werten anzeigt. &lt;br /&gt;
&lt;br /&gt;
Sind die Nachtunden mit &#039;&#039;&#039;graphicShowNight&#039;&#039;&#039; ausgeblendet, werden keine Balken angezeigt sofern es keine Werte anzuzeigen gibt. Sollten dennoch Werte ungleich 0 anzuzeigen sein, werden diese Werte auch trotz ausgeblendeter Nachstunden angezeigt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 2 ====&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 211741.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=01 (mit Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 2&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam3Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam4Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 4 für Balken 4) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wetter-Icons können nur in Ebene 1 integriert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 2 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 2 gibt, eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgende Ebene.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 3 ====&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 3&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam5Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam6Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 5 für Balken 5) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 3 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 3 gibt, ist eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgenden Ebenen, d.h. auch auf die Ebene 3.&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 5 - Die Energieflußgrafik (Flow Graphic) ===&lt;br /&gt;
[[Datei:Screenshot 2025-02-13 213424.png|right|thumb|400px|Energieflußgrafik mit Verbrauchern in der Nachtdarstellung (Mondphasen) nach Sonnenuntergang]]&lt;br /&gt;
&lt;br /&gt;
Die Energieflußgrafik stellt die registrierten Erzeuger, Batterien, Netzzugänge und Verbraucher strukturiert in mehreren Ebenen dar:&lt;br /&gt;
&lt;br /&gt;
;Ebene 1: In der oberen Ebene befinden sich die PV-Generatoren, Smart-Loader sowie sonstigen Erzeuger &lt;br /&gt;
;Ebene 2: Die mittlere Ebene organisiert den Zugang zum öffentlichen Netz, dem Hausknoten, dem Batterieknoten sowie einem Dummy-Verbraucher (Lampensymbol) für den Energieverbrauch des Hauses der keinem der registrierten Verbraucher zugeordnet werden kann.&lt;br /&gt;
;Ebene 3: In der unteren Ebene werden die registrierten Verbraucher dargestellt. Unterhalb der Verbrauchersymbole werden der aktuelle Verbrauch (bzw. der On/Off-Zustand) sowie darunter die Restlaufzeit (Minuten) des Verbrauchers, sofern er durch das Modul geplant und gestartet wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Position und Gestaltung der Grafikelemente ist umfangreich über das Attribut &#039;&#039;&#039;flowGraphicControl&#039;&#039;&#039; und den darin verfügbaren Schlüsseln einstellbar.&lt;br /&gt;
Die Bedeutung der Schlüssel ist in der Online-Hilfe zum Attribut mit einem Beispiel beschrieben. &lt;br /&gt;
&lt;br /&gt;
Darüber hinaus enthalten die Setup-Attribute &#039;&#039;&#039;setupInverterDevXX&#039;&#039;&#039;, &#039;&#039;&#039;setupOtherProducerXX&#039;&#039;&#039; und &#039;&#039;&#039;consumerXX&#039;&#039;&#039; weitere Einstellungsmöglichkeiten um deren Icons und Färbungen in der Flußgrafik individuell einstellen zu können. So sind zum Beispiel die Icons der PV-Inverter und deren Färbung mit dem Schlüssel &#039;&#039;&#039;icon&#039;&#039;&#039; der setupInverterDevXX-Attribute in Abhängigkeit von Tag und Nacht separat definierbar.&lt;br /&gt;
&lt;br /&gt;
In den Verbraucher-Attributen ist mit dem Schlüssel &#039;&#039;&#039;noshow&#039;&#039;&#039; die Sichtbarkeit in der Flußgrafik definierbar.&lt;br /&gt;
&lt;br /&gt;
Generell steuert das Attribut &#039;&#039;&#039;graphicSelect&#039;&#039;&#039; die Ein- bzw. Ausblendung der gesamten Flußgrafik.&lt;br /&gt;
&lt;br /&gt;
== Die Verbrauchsprognose ==&lt;br /&gt;
Im Gegensatz zu der PV Prognose gibt es keine API oder andere externen Datenquellen die für die Verbrauchsprognose herangezogen werden könnten.&lt;br /&gt;
&lt;br /&gt;
Zum Zweck der Verbrauchsermittlung verwendet das Modul die Meterdaten aus dem Attribut &#039;&#039;setupMeterDev&#039;&#039; sowie den weiteren setup-Attributen &#039;&#039;setupInverterDevXX&#039;&#039;. &lt;br /&gt;
Sind auch andere Erzeuger (BHKW, Windanlagen, etc.) bzw. eine Batterie vorhanden, sind ebenfalls die Attribute &#039;&#039;setupOtherProducerXX&#039;&#039; bzw. &#039;&#039;setupBatteryDev&#039;&#039; für die Berechnung des Hausverbrauchs relevant. In diesen Attributen gibt es die Schlüssel &#039;&#039;*total&#039;&#039; die teilweise optional sind. Für die Verbrauchsprognose bilden sie jedoch die Berechnungsgrundlage und sind deswegen für diese Funktionalität wichtig anzugeben.&lt;br /&gt;
&lt;br /&gt;
Die Verbrauchswerte werden stundengenau erfasst und im Datenspeicher &#039;&#039;pvHistory&#039;&#039; für 31 Tage, sowie im Datenspeicher &#039;&#039;pvCircular&#039;&#039; 210 Tage gespeichert. Die beiden Datenspeicher übernehmen unterschiedliche Aufgaben im Rahmen der Prognoseerstellung. Auf Grundlage der gespeicherten und somit historischen Verbrauchswerte erstellt das Modul eine Prognose für die kommende Zeit.&lt;br /&gt;
&lt;br /&gt;
Mit dem Kommando &lt;br /&gt;
&lt;br /&gt;
   &amp;quot;get ... pvHistory [Tag]&amp;quot; &lt;br /&gt;
&lt;br /&gt;
wird der Inhalt aufgelistet. Die Schlüssel &#039;&#039;confc&#039;&#039;, &#039;&#039;con&#039;&#039; und &#039;&#039;gcon&#039;&#039; zeigen die Verbrauchsprognose, den Verbrauch und den Netzbezug der jeweiligen Stunde des gewählten Tages.&lt;br /&gt;
Die Stunde &amp;quot;99&amp;quot; zeigt die Summen dieser Schlüsssel für den Tag:&lt;br /&gt;
&lt;br /&gt;
      99 =&amp;gt; etotal: , pvfc: 782, pvrl: 0, rad1h: -&lt;br /&gt;
            confc: 14540, con: 13873, gcon: 13873, gfeedin: 0&lt;br /&gt;
            batintotal: , batin: 0, batouttotal: , batout: 0&lt;br /&gt;
            batmaxsoc: -, batsetsoc: -&lt;br /&gt;
            wid: , wcc: , wrp: , pvcorrf: , dayname: So&lt;br /&gt;
            cyclescsm01: 0&lt;br /&gt;
            cyclescsm02: 0&lt;br /&gt;
            cyclescsm03: 0&lt;br /&gt;
            cyclescsm04: 1, hourscsme04: 0.00&lt;br /&gt;
            cyclescsm05: 0&lt;br /&gt;
            cyclescsm06: 0&lt;br /&gt;
            cyclescsm07: 1, hourscsme07: 0.00&lt;br /&gt;
            cyclescsm08: 1, hourscsme08: 0.00&lt;br /&gt;
            cyclescsm09: 1, hourscsme09: 0.03 &lt;br /&gt;
&lt;br /&gt;
In dem Beispiel wurden für den Tag 14540 Wh Verbrauch prognostiziert, 13873 Wh tatsächlich verbraucht und davon 13873 Wh aus dem Netz bezogen. Leider war an diesem Tag keinerlei PV Ertrag vorhanden, was man auch an dem Schlüssel &#039;&#039;pvrl&#039;&#039; erkennen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Inhalt des pvCircular-Speichers kann mit dem Befehl  &lt;br /&gt;
&lt;br /&gt;
     &amp;quot;get ... pvCircular [Tag]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Das nachfolgende Beispiel zeigt die Ausgabe für die Tagesstunde 23:&lt;br /&gt;
&lt;br /&gt;
 23 =&amp;gt; pvapifc: 0, pvaifc: -, pvfc: 0, aihit: 0, pvrl: 0&lt;br /&gt;
       batin01: 0, batin02: -, batin03: -&lt;br /&gt;
       batout01: 619, batout02: -, batout03: -&lt;br /&gt;
       confc: 650, gcon: 23, gfeedin: 0, wcc: 40, rr1c: 0.00&lt;br /&gt;
       temp: -6.00, wid: 100, wtxt: Bewölkungsentwicklung nicht beobachtet&lt;br /&gt;
       pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
       ... &lt;br /&gt;
       con_all =&amp;gt; Sa  @ 617 762&lt;br /&gt;
                  Di  @ 693 645&lt;br /&gt;
                  Mo  @ 620 679&lt;br /&gt;
                  So  @ 669 666 636&lt;br /&gt;
                  Mi  @ 701 626&lt;br /&gt;
                  Do  @ 612 642&lt;br /&gt;
                  Fr  @ 615 606&lt;br /&gt;
&lt;br /&gt;
Der Schüssel &#039;&#039;con_all&#039;&#039; enthält einen Hash aus Arrays die für jeden Wochentag (Mo..So) bis zu 30 Verbrauchswerte (in Wh) für die angezeigte Stunde speichern. Wie hier erkennbar ist, wurden an den drei vergangenen Sonntagen jweils 669 Wh, 666 Wh bzw. 636 Wh in der Stunde 23 (22:00-22:59) verbraucht.&lt;br /&gt;
Der Median aus diesen Werten geht in die Verbrauchsprognose ein. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wochentagsnamen Mo..So sind von den installierten Locales auf Betriebsystemebene abhängig. Ist keine deutsche locale installiert, werden die englischen Wochentagsnamen Mon..Sun verwendet. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Wie wird der Verbrauch des Hauses ermittelt und gespeichert? ===&lt;br /&gt;
Die Verbrauchsdaten des Hauses werden auf Stundenbasis ermittelt und gespeichert. Das &amp;quot;Haus&amp;quot; steht als Synonym aller im Kontext des Solarforecast Devices zusammengeführten Inverter (setupInverterDevXX), sonstigen Erzeuger (setupOtherProducerXX), Netzanschlüsse (setupMeterDev), Verbraucher (consumerXX) und Batterien (setupBatteryDev).&lt;br /&gt;
&lt;br /&gt;
Alle diese Daten werden durch das Modul mit jedem ausgeführten Zyklus (Attribut plantControl-&amp;gt;cycleInterval) und, wenn ein Event eines als &#039;asynchron&#039; definierten Devices auftritt, gesammelt und daraus permanent ein aktualisierter Verbrauch berechnet. Die Berechnung beschreibt folgende Formel:&lt;br /&gt;
&lt;br /&gt;
 PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung - Verbrauch = 0&lt;br /&gt;
&lt;br /&gt;
bzw.&lt;br /&gt;
 &lt;br /&gt;
 Verbrauch (Wh) = PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung&lt;br /&gt;
            con = PV           + PP                 - GridIn          + GridCon   - BatIn          + BatOut&lt;br /&gt;
&lt;br /&gt;
Die PV-Erzeugung beinhaltet die Summe aller durch die angegebnen Inverter (setupInverterDev01 .. setupInverterDevXX) erzeugten Energien. Die &amp;quot;sonstige Erzeugung&amp;quot; summiert sich aus den Werten aller angegebenen Producer (setupOtherProducer01 .. setupOtherProducerXX). Der Verbrauch wird durch die registrierten Geräte consumerXX teilweise direkt erfasst, ist aber grundsätzlich unvollständig da nicht alle Verbrauchswerte im &amp;quot;Haus&amp;quot; gemessen und durch das Modul erfasst werden können.&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel zeigt das Ergebnis bei 300 Wh PV-Erzeugung und gleichzeitige 500 Wh Netzbezug:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 300 + 0 - 0 + 500 - 0 + 0 = 800 Wh&lt;br /&gt;
&lt;br /&gt;
Bei 1300Wh PV-Erzeugung, 100 Wh Netzeinspeisung sowie 200 Wh Batterieladung ergibt sich der Verbrauch zu:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 1300 + 0 - 100 + 0 - 200 + 0 = 1000 Wh&lt;br /&gt;
&lt;br /&gt;
Ohne Erzeugung, aber mit der Energielieferung von 500 Wh aus der Batterie, 800 Wh Netzbezug (mit einem Anteil Batterienachladung aus dem Netz von 200 Wh) sieht die Verbrauchsrechnung wie folgt aus: &lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 0 + 0 - 0 + 800 - 200 + 500 = 1100 Wh&lt;br /&gt;
&lt;br /&gt;
Der so ermittelte Verbrauchsert wird mit jedem Zyklus in der pvHistory im Schlüssel &amp;quot;con&amp;quot; gespeichert. Man kann sich die gespeicherten Werte mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;name&amp;gt; pvHistory [&amp;lt;Tag&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Nachfolgendes Beispiel zeigt einen Datensatz für die Stunde 8 eines Tages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      08 =&amp;gt; pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotali01: 62940734, etotali02: 2928860, etotali03: -&lt;br /&gt;
            pvrl01: 0, pvrl02: 0, pvrl03: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 630, con: 962, gcons: 962, conprice: 0.2958&lt;br /&gt;
            gfeedin: 0, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 120, sunalt: -3&lt;br /&gt;
            batintotal: 3713815.07742543, batouttotal: 3604468.26993988, batin: 0, batout: 0&lt;br /&gt;
            wid: 161, wcc: 89, rr1c: 0.00, pvcorrf: 0.27/0.00 temp: 7.40, &lt;br /&gt;
            csmt01: 110996.12, csme01: 32.1399999999994, minutescsm01: 30&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 2513.67, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1581293.6, csme04: 136.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 1662.17, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 90.53, csme06: 0, minutescsm06: 0&lt;br /&gt;
            csmt07: 39.75, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 38050, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 131627, csme09: 33.2000000000116, minutescsm09: 39&lt;br /&gt;
            minutescsm10: 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Schlüssel &amp;quot;con&amp;quot; ist der gespeicherte Verbrauch von 962 Wh ersichtlich.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit bekommt man mit dem Attribut &#039;&#039;ctrlDebug=collectData&#039;&#039; einen Einblick in die Verbrauchsermittlung bei jedem Zyklus und kann so die Eingangswerte und das daraus resultierende Ergebnis im FHEM Log nachverfolgen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
2024.11.28 11:38:20.080 1: SolCast DEBUG&amp;gt; EnergyConsumption input -&amp;gt; PV: 96, PP: 0, GridIn: 0, GridCon: 582, BatIn: 5, BatOut: 0&lt;br /&gt;
2024.11.28 11:38:20.081 1: SolCast DEBUG&amp;gt; EnergyConsumption result -&amp;gt; 673 Wh&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie wird die Verbrauchsprognose erstellt? ===&lt;br /&gt;
&lt;br /&gt;
Aus den gespeicherten con-Werten (Verbrauchsdaten) der pvCircular (Schlüssel con_all) sowie Einträgen der pvHistory wird der Median der historischen Tage ermittelt und für den kommenden Tag bzw. die kommen Stunden zur Prognose angewendet. Dabei geht per default jeder verfügbare historische Tag gleichberechtigt in die Prognose ein. Mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039; kann festgelegt werden, dass nur gleiche Wochentage (Mo..So) für die Prognose verwendet werden. Hierbei spielt die Vermutung, dass das Verbrauchsverhalten eine gewisse Korrelation zum Wochentag hat, eine Rolle. &lt;br /&gt;
&lt;br /&gt;
Verwendet man die Einstellung consForecastIdentWeekdays=1, hat es sich als vorteilhaft erwiesen, das Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays&#039;&#039;&#039; auf einen niedrigeren Wert als den Default zu setzen. Eine Einstellung auf &#039;8&#039; zum Beispiel verwendet den Median der gleichen Wochentage der vergangenenen 8 Wochen. Dadurch wird nicht zu weit in die Vergangenheit verzweigt und so eine langsame Veränderung des Verbrauchsmedian, zum Beispiel hervorgerufen durch den Übergang vom Winter in das Frühjahr hinein, abgebildet.&lt;br /&gt;
&lt;br /&gt;
Weiteren Einfluß auf die Verbrauchsprognose kann mit dem Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; im Consumerattribut genommen werden. Insbesondere bei der unregelmäßigen Nutzung von Verbrauchern mit hoher Leistung kann die Projektion der aufgezeichneten historischen Werte in die Prognose zu unverhältnismäßig hohen Verbrauchswerwartunden führen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Möglicherweise führt in Fällen die Verwendung eine der nachfolgenden Optionen zu einem besseren Ergebnis:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;1 -&#039;&#039;&#039; die allgemeine Verbrauchsprognose wird um die gespeicherten Energieverbrauchsanteile reduziert.&lt;br /&gt;
* &#039;&#039;&#039;2 -&#039;&#039;&#039; wie bei &#039;1&#039;, jedoch gehen die Planungsdaten des Verbrauchers bei der Prognose der kommenden Stunden wieder mit ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;&#039;exconfc&#039;&#039;&#039; in einem der Consumer verwendet, sollte&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays=4&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
eingestellt werden. Hintergrund ist, dass die Verbrauchsanteile der jeweiligen Verbraucher nur maximal 31 Tage in der pvHistory verfügbar sind. Für längere Zeiträume stehen nur Gesamtsummen des Verbrauchs in der pvCircular zu Verfügung.  &lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=1&#039;&#039;&#039; werden die in der Historie aufgezeichneten Verbrauchsbestandteile aus einer Prognose herausgerechnet. Konkret werden die in der pvHistory aufgezeichneten Verbrauchsbestandteile für die relevante Stunde ermittelt und daraus ein Durchschnitt gebildet der vom Prognosewert subtrahiert wird. Mit dem Attributwert plantControl-&amp;gt;consForecastIdentWeekdays=1 werden wiederum nur identische Wochentage (Mo .. So) zusammengefasst.&lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=2&#039;&#039;&#039; erfolgt ebenso die Eliminierung des Verbrauchsanteils, es wird jedoch auf die Planungsdaten für diesen Verbraucher zugegriffen und die geplanten Energieanteile wiederum der Verbrauchsprognose für die kommenden Stunden hinzugerechnet.&lt;br /&gt;
&lt;br /&gt;
In beiden Anwendungsfällen ist es notwendig, dass dem Modul durch die Angabe entsprechender Readings der Energieverbrauch im Setup des Consumers bekannt gemacht wird damit diese Energieanteile registriert werden können. Allgemein funktioniert die Verbrauchsprognose gut wenn Verbrauchsprozesse regelmäßig in einem wiederkehrenden Zeitraster ablaufen, der Verbrauch durch persönliche Rituale bestimmt ist. So zum Beispiel könnte am Dienstag und Samstag gewöhnlich die Waschmaschine laufen, das E-Auto täglich aufgeladen werden und gebügelt wird oft am Sonntag Nachmittag.&lt;br /&gt;
&lt;br /&gt;
Unregelmäßige Nutzung, vor allem vom Großverbrauchern, lässt sich nur sehr schwer und ungenügend auf zukünftige Verbrauchsprognosen projizieren.&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis der Prognose wird im Kopf der Grafik in der Zeile &#039;&#039;Verbrauch&#039;&#039; sowie in diversen Readings wie &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RestOfDayConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den Rest des Tages)&lt;br /&gt;
* &#039;&#039;&#039;NextHours_Sum04_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für die nächsten 4 Stunden)&lt;br /&gt;
* &#039;&#039;&#039;Tomorrow_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den kommenden Tag)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
angezeigt.&lt;br /&gt;
&lt;br /&gt;
Weitere Aggregationen kann man sich über das Attribut &#039;&#039;&#039;ctrlStatisticReadings&#039;&#039;&#039; bei Bedarf zuschalten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;conForecastTillNextSunrise&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
* &#039;&#039;&#039;todayConForecastTillSunset&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
* &#039;&#039;&#039;todayConsumptionForecast&#039;&#039;&#039; - Verbrauchsprognose aufgesplittet pro Stunde des aktuellen Tages (01-24) &lt;br /&gt;
 &lt;br /&gt;
==== Debugging der Verbrauchsprognose ====&lt;br /&gt;
Um sich einen Einblick über die Erstellung der Verbrauchsprognose zu verschaffen, bietet sich die Einschaltung von:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
an. Mit diesem gesetzten Attribut wird die Erstellung der Prognose im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; ################### Start Consumption forecast ###################&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; Basics - installed locale: de_DE.UTF-8, used scheme: DE&lt;br /&gt;
2025.02.27 19:52:00.064 1: SolCast DEBUG&amp;gt; process Today dayname: Do, Tomorrow dayname: Fr&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 01 - 74.43 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 10 - 290.77 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 24 - 660.70 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 20, hod: 07 - 459.93 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;07&#039; register for exclude day 20, hod: 02 - 0.33 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 30, hod: 08 - 264.78 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next Hours (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; excl. hist 74 Wh for Hour 01, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; estimated cons of Hour 01: 436 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; excl. hist 0 Wh for Hour 02, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 02: 428 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 03: 458 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 04: 503 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 05: 489 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 06: 482 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; excl. hist 460 Wh for Hour 07, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 07: 274 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 265 Wh for Hour 08, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 08: 441 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 09: 558 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 291 Wh for Hour 10, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 10: 443 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 11: 881 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 12: 794 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 13: 840 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 14: 660 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 15: 812 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 16: 752 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 17: 597 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 18: 652 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 19: 634 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 20: 628 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 21: 713 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 22: 596 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 23: 629 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; excl. hist 661 Wh for Hour 24, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons of Hour 24: 660 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons Tomorrow: 16848 Wh, Individual hourly values considered: 72, exclude: 0 Wh (avg of 0 entities)&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Store Consumption forecast values (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour00&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;20&#039; confc: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour01&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;21&#039; confc: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour02&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;22&#039; confc: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour03&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;23&#039; confc: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store &#039;NextHour04&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;24&#039; confc: 660&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour05&#039; hod &#039;01&#039; confc: 436, confcEx: 436&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour06&#039; hod &#039;02&#039; confc: 428, confcEx: 428&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour07&#039; hod &#039;03&#039; confc: 458, confcEx: 458&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour08&#039; hod &#039;04&#039; confc: 503, confcEx: 503&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour09&#039; hod &#039;05&#039; confc: 489, confcEx: 489&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour10&#039; hod &#039;06&#039; confc: 482, confcEx: 482&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour11&#039; hod &#039;07&#039; confc: 274, confcEx: 274&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour12&#039; hod &#039;08&#039; confc: 441, confcEx: 441&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour13&#039; hod &#039;09&#039; confc: 558, confcEx: 558&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour14&#039; hod &#039;10&#039; confc: 443, confcEx: 443&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour15&#039; hod &#039;11&#039; confc: 881, confcEx: 881&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour16&#039; hod &#039;12&#039; confc: 794, confcEx: 794&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour17&#039; hod &#039;13&#039; confc: 840, confcEx: 840&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour18&#039; hod &#039;14&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour19&#039; hod &#039;15&#039; confc: 812, confcEx: 812&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour20&#039; hod &#039;16&#039; confc: 752, confcEx: 752&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour21&#039; hod &#039;17&#039; confc: 597, confcEx: 597&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour22&#039; hod &#039;18&#039; confc: 652, confcEx: 652&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour23&#039; hod &#039;19&#039; confc: 634, confcEx: 634&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour24&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour25&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour26&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour27&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour28&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; consumption calculated - day: 27, hod: 20, con: 574 Wh&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; write pvCircular consumption - hod: 99, todayConsumption: 11210 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe startet mit &#039;&#039;&amp;quot;Start Consumption forecast&#039;&#039;&amp;quot;, es werden die zu exkludierenden historischen Daten für jeden Consumer bzgl. jedem Tag (day) und Stunde des Tages (hod) getrennt registriert. Diese Werte werden durch die gespeicherte Einträge in der pvHistory (max. 31 historische Tage) geliefert. &lt;br /&gt;
&lt;br /&gt;
Im nächsten Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next Hours (new median)&amp;quot;&#039;&#039; werden die Prognosen für die nächsten Stunden kalkuliert und die zuvor registrierten Excludes angewendet. Die Prognose für den kommenden Tag ist im Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next day (new median)&amp;quot;&#039;&#039; protokolliert. Die Prognose für den kommenden Tag ist nicht einfach die Summe der Prognose der nächsten Stunden, denn in den kommenden Stunden werden auch die verfügbaren Planungen der Consumer einbezogen. Für den kommenden Tag können diese Werte unter Umständen nicht einbezogen werden da sie zum Zeitpunkt X noch nicht verfügbar sind.&lt;br /&gt;
&lt;br /&gt;
Im Abschnitt &#039;&#039;&amp;quot;Store Consumption forecast values (new median)&amp;quot;&#039;&#039; erscheinen die effektiv gespeicherten Werte. Diese sind die Grandlage für die grafische Darstellung sowie weiteren Kalkulationen.&lt;br /&gt;
&lt;br /&gt;
=== Wie kann eine fehlerhafte Verbrauchsprognose korrigiert werden? ===&lt;br /&gt;
Wie im vorherigen Abschnitt beschrieben, wird die Prognose aus den gespeicherten &amp;quot;con&amp;quot;-Werten der vergangenen Tage (bzw. Stunden) abgeleitet. &lt;br /&gt;
Grundsätzlich muß zunächst sichergestellt werden, dass die auszulesenden Readings der angegebenen Energiezähler sowie deren Einheiten! korrekt eingestellt sind. Das gilt ebenfalls für die registrierten Verbraucher im Modul.&lt;br /&gt;
&lt;br /&gt;
Für einen ersten Überblick bietet sich das Debug Attribut an zu setzen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
Beispielausgabe des Debug:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2024.09.21 13:28:27.041 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day ###################&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;01&amp;lt; considering possible exclusions: 14082&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;08&amp;lt; considering possible exclusions: 16446&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;15&amp;lt; considering possible exclusions: 14568&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;25&amp;lt; considering possible exclusions: 15522&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; estimated Consumption for tomorrow: 15154, days for avg: 4&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next hours ###################&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 14 -&amp;gt; 850 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 14 -&amp;gt; 643 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 14 -&amp;gt; 590 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 14 -&amp;gt; 522 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 13:00:00, confc: 651, days for avg: 4, hist. consumption registered consumers: 560.97&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 15 -&amp;gt; 720 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 15 -&amp;gt; 743 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 15 -&amp;gt; 897 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 15 -&amp;gt; 557 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 14:00:00, confc: 729, days for avg: 4, hist. consumption registered consumers: 620.97&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 16 -&amp;gt; 676 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 16 -&amp;gt; 790 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 16 -&amp;gt; 785 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 16 -&amp;gt; 581 Wh&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 15:00:00, confc: 708, days for avg: 4, hist. consumption registered consumers: 647.29&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 17 -&amp;gt; 622 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 17 -&amp;gt; 639 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 17 -&amp;gt; 646 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 17 -&amp;gt; 572 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 16:00:00, confc: 619, days for avg: 4, hist. consumption registered consumers: 618.30&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 18 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 18 -&amp;gt; 614 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 18 -&amp;gt; 580 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 18 -&amp;gt; 480 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 17:00:00, confc: 567, days for avg: 4, hist. consumption registered consumers: 583.41&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 19 -&amp;gt; 615 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 19 -&amp;gt; 1659 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 19 -&amp;gt; 597 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 19 -&amp;gt; 618 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 18:00:00, confc: 872, days for avg: 4, hist. consumption registered consumers: 636.97&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 20 -&amp;gt; 611 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 20 -&amp;gt; 1124 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 20 -&amp;gt; 546 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 20 -&amp;gt; 479 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 19:00:00, confc: 690, days for avg: 4, hist. consumption registered consumers: 578.87&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 21 -&amp;gt; 1474 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 21 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 21 -&amp;gt; 619 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 21 -&amp;gt; 433 Wh&lt;br /&gt;
2024.09.21 13:28:27.058 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Im ersten Teil wird die erwartete Consumption für den nächsten Tag unter Berücksichtigung möglicher Ausschlüsse von Verbrauchern ausgegeben. Ausschlüsse von Verbrauchern ergeben sich wenn in dem Verbraucherattribut der Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; gesetzt ist. Er besagt, dass die Verbrauchswerte des Verbrauchers in eine zukünftige Prognose nicht eingehen sollen. Zum Beispiel wenn ein Verbraucher mit sehr hohen Verbrauchswerten nur sporadisch eingesetzt wird und dadurch die Prognose stark verfälschen würde. Es ist auch zu sehen, dass bedingt durch das Attribut &#039;&#039;&#039;affectConsForecastIdentWeekdays = 1&#039;&#039;&#039; nur die historischen Tage 01, 08, 15 und 25 berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Teil wird die berechnete Erwartung für die nächsten Stunden ausgegeben. &lt;br /&gt;
Zur Beschreibung der Fehlersuche gehen wir davon aus, dass die Prognose von 780 Wh am 2024-09-21 20:00:00 zu hoch erscheint weil am Tag &amp;quot;07&amp;quot; ein Wert von 1474 Wh gespeichert ist:&lt;br /&gt;
&lt;br /&gt;
 SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt geben wir die historischen Werte für den Tag 07 aus:&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;Name&amp;gt; pvHistory 07&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz interessiert die Stunde 21. Sie resultiert aus der obigen Angabe &amp;quot;starttime: xxxx-xx-xx 20:00:00&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      21 =&amp;gt; etotal: 64354660, pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 496, con: 1474, gcons: 23, conprice: 0.2958&lt;br /&gt;
            gfeedin: 5, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 289, sunalt: -8&lt;br /&gt;
            batintotal: 3064096.92456668, batouttotal: 2958021.37946804, batin: 0, batout: 1460&lt;br /&gt;
            wid: 101, wcc: 20, rr1c: 0.00, pvcorrf: 1.00/-temp: 26.00, &lt;br /&gt;
            csmt01: 64262.43, csme01: 28.8099999999977, minutescsm01: 25&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 0, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1389417.4, csme04: 94.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 0, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 290.15, csme06: 6.66999999999996, minutescsm06: 54&lt;br /&gt;
            csmt07: 0, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 32800, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 103987.8, csme09: 38, minutescsm09: 43&lt;br /&gt;
            csmt10: 9151.24999999783, csme10: 3.99999999997999, minutescsm10: 60&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz sind die Energieverbrauchsanteile der im Device registrierten Verbraucher mit dem Schlüssel &amp;quot;csmeXX&amp;quot; gespeichert. Dabei ist &amp;quot;XX&amp;quot; die Verbrauchernummer. In dem Beispiel existieren die Anteile csme01 und csme03 - csme10. Keiner dieser Verbraucher hat einen auffälligen Verbrauchswert gespeichert, d.h. die Messung der Verbraucher scheidet als Problemquelle aus. Wäre ein unverhältmismäßig hoher Verbrauch bei einem der Verbraucher feststellbar, müssten die Schlüssel &#039;&#039;&#039;pcurr&#039;&#039;&#039; und &#039;&#039;&#039;etotal&#039;&#039;&#039; im consumerXX-Attribut geprüft, sowie die Datenlieferung des Consumerdevices selbst geprüft werden.  &lt;br /&gt;
&lt;br /&gt;
Es wurde offensichtlich ein hoher Verbrauch von einem nicht registrierten Verbraucher verursacht oder durch die Übertragung eines Meßfehlers des Devices, angegeben im Attribut &#039;&#039;&#039;setupMeterDev&#039;&#039;&#039;, in das SolarForecast Device übertragen. Eine weitere Analyse ist an dieser Stelle nicht möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Behebung des falschen Wertes kann ein Reset der gespeicherten Consumption der relevanten Stunde durchgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; reset consumptionHistory 07 21&lt;br /&gt;
&lt;br /&gt;
== Modulinterne Datenstrukturen ==&lt;br /&gt;
Das Modul speichert die verschiedenen historischen und aktuellen Daten wie PV-Prognose, Witterungsdaten (Regen, Bewölkung), Strahlungsdaten, Einspeisung, Bezug, reale Erzeugungsdaten und vieles mehr zur Laufzeit im Arbeitsspeicher. Dadurch ist die Verarbeitung dieser Daten im Vergleich zu Lesevorgängen aus dem Filesystem bzw. einer Datenbank sehr performant. Allerdings würden diese Daten bei einem FHEM Absturz bzw. bei einem regulären Shutdown verlorengehen.&lt;br /&gt;
&lt;br /&gt;
Deswegen werden die relevanten Daten regelmäßig in Dateien gesichert und bei Bedarf wiederhergestellt. Diese Dateien befinden sich im Verzeichnis &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; und heißen &#039;&#039;&#039;.*_SolarForecast_.*&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Die Daten werden in jedem Zyklus der Zentralschleife (CentralTask) gesammelt bzw. berechnet. Der Zyklus wird mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;cycleInterval&#039;&#039;&#039; eingestellt.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit können diese Daten über get-Kommandos abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvHistory [Tag]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der pvHistory Datenspeicher enthält die vergangenen Kennwerte der letzten 31 Tage mit einer Genauigkeit von einer Stunde. Es werden die Prognosewerte für Erzeugung und Verbrauch, die realen Werte für Erzeugung und Verbrauch sowie ebenso die Laufzeiten jedes einzelnen Verbrauchers (Consumer) festgehalten. Für jeden Tag gibt es die Stunde &amp;quot;99&amp;quot; die eine Summierung der Stundenwerte des Tages bzw. Sonderschlüssel enthält.&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf lässt sich mit dem Befehl &amp;quot;set ... reset pvHistory&amp;quot; der gesamte Inhalt des Speichers löschen (nicht empfohlen). Selektiver funktioniert die Datenlöschung mit &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt;&amp;quot; (Daten eines bestimmten Tages löschen) bzw. &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt; &amp;lt;Stunde&amp;gt;&amp;quot; (Daten der Stunde  eines bestimmten Tages löschen). Die letzten beiden Kommandos müssen über die Kommandozeile im Browser ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvCircular &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Ringspeicher enthält Daten der letzten 24 Stunden sowie fortwährend berechnete Werte wie Korrekturfaktoren der PV-Erzeugung und Prognosequalität.&lt;br /&gt;
Neue Stundenwerte des Tages überschreiben die gespeicherten Schüssel des vorangegangenen Tages sofern es sich nicht um fortwährend berechnete Werte handelt. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... nextHours&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Speicher enthält sämtliche Prognosewerte der kommenden Stunden beginnend mit der aktuellen Stunde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... radiationApiData&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Abhängig von der ausgewählten Strahlungsdaten API enthält dieser Speicher die von der API gelieferten Rohdaten sowie evtl. weitere für die Funktion benötigte Daten wie API-Keys, Response Messages, Anzahl der API Abruf und weitere.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valCurrent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Struktur wird nicht regelmäßig im Filesystem gespeichert und enthält immer aktuell gesammelte oder berechnete/gelieferte Daten wie z.B. die Autarkierate, letze Laufzeit der Zentralschleife (CentralTask), Zeit des Sonnenauf- und untergangs sowie weitere Betriebsdaten. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valConsumerMaster [XX]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zeigt die Daten der aktuell im SolarForecast Device registrierten Verbraucher. Mit der Nummer &#039;&#039;&#039;XX&#039;&#039;&#039; kann ein bestimmter Verbraucher angesprungen werden. Die Nummer korrespondiert mit dem entsprechenden &#039;&#039;&#039;consumerXX&#039;&#039;&#039; Attribut.&lt;br /&gt;
Neben anderen Betriebs- und Energiedaten werden insbesondere folgende Daten ermittelt, die für die zukünftige Planung der Verbraucherschaltzeiten relevant sind:&lt;br /&gt;
&lt;br /&gt;
* epieces - prognostizierte Energiescheiben pro Betriebsstunde &lt;br /&gt;
&lt;br /&gt;
Ausgehend von gespeicherten historischen Verbrauchsdaten des Verbrauchers wird der Energieverbrauch des Verbrauchers in seiner ersten Betriebsstunde prognostiziert, was insbesondere für die Planung der optimalen Startzeit des Verbrauchers in Bezug zu der prognostizierten PV Energie und den Verbrauchswerten weiterer vorhandener bzw. zu planender Verbraucher Berücksichtigung findet. Weitere Informationen zur Verbrauchersteuerung in diesem  [[#Verbrauchersteuerung_-_Registrieren_und_visualisieren_von_Verbrauchern|Abschnitt]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Schnittstelle für Modulautoren bzw. eigenen Code ===&lt;br /&gt;
&lt;br /&gt;
Die im vorherigen Artikel beschriebenen internen Datenstrukturen können durch externen Code abgefragt und ausgewertet werden.&lt;br /&gt;
Dazu stehen die folgenden Funktionen zur Verfügung. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]BatteryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Bn&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valBattery&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CurrentVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valCurrent&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]InverterVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valInverter&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ProducerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valProducer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]HistoryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Day&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvHistory&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CircularVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvCircular&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]NexthoursVal (&#039;&amp;lt;Name&amp;gt;&#039;, &amp;lt;nhr&amp;gt;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... nextHours&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ConsumerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valConsumerMaster&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]RadiationAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;DateTime&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... radiationApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]WeatherAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;TimeCode&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... weatherApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StatusAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;QTag&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... statusApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StringVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valStrings&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Angabe des Packages (FHEM::SolarForecast::) ist nur notwendig wenn die Funktionen von außerhalb des SolarForecast-Devices aufgerufen werden. Innerhalb des Devices (Code-Ausführung im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039;) kann darauf verzichtet werden.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der Platzhalter sind:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     &amp;lt;Name&amp;gt;     - Name des SolarForecast Devices&lt;br /&gt;
     &amp;lt;Day&amp;gt;      - abzufragender Tag (01 - 31)&lt;br /&gt;
     &amp;lt;Bn&amp;gt;       - Batterie Nummer (01, 02, ...)&lt;br /&gt;
     &amp;lt;DateTime&amp;gt; - Startzeit der Form YYYY-MM-DD hh:00:00&lt;br /&gt;
     &amp;lt;TimeCode&amp;gt; - Zeitwert der Form fcX_XX (z.B. fc1_19)&lt;br /&gt;
     &amp;lt;APIname&amp;gt;  - Hauptname der API gemäß setupWeatherDev1 (z.B. OpenMeteo)&lt;br /&gt;
     &amp;lt;String&amp;gt;   - Name des PV-Modulstrings wie im Attribut &#039;setupInverterStrings&#039;&lt;br /&gt;
     &amp;lt;QTag&amp;gt;     - Question Tag, z.B. &#039;?All&#039;&lt;br /&gt;
     &amp;lt;Nr&amp;gt;       - laufende Nummer des Verbrauchers / Gerätes (01, 02, 03, 04,...)&lt;br /&gt;
     &amp;lt;HoD&amp;gt;      - abzufragende Stunde (01 - 24, 99)&lt;br /&gt;
     &amp;lt;nhr&amp;gt;      - nächste Stunde (NextHour00, NextHour01,...)&lt;br /&gt;
     &amp;lt;Key&amp;gt;      - der abzufragende Schlüssel &lt;br /&gt;
     &amp;lt;default&amp;gt;  - def default-Rückgabewert&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Auswerten von internen Arrays ===&lt;br /&gt;
&lt;br /&gt;
Die meisten der internen Datenstrukturen liefern bei der Abfrage einen einfachen String oder numerischen Wert der ausgewertet werden kann. Es gibt allerdings auch intern gespeicherte Wertelisten. Werden die Listenstrukturen mit den oben beschriebenen Befehlen abgefragt, wird eine Referenz auf die Liste geliefert sofern sie vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
Um auf die Werte einer solchen Liste zuzugreifen, ist am Beispiel des Arrays &#039;&#039;surplusslidereg&#039;&#039; aus dem Current-Speicher (get ... valCurrent) dargestellt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
my $splref = CurrentVal ($name, &#039;surplusslidereg&#039;, &#039;.&#039;);&lt;br /&gt;
my $spser  = ref $splref eq &#039;ARRAY&#039; ? join &#039; &#039;, @{$splref} : undef;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Variable $spser enthält bei Vorhandensein der Liste einen String, der die Listenelemente von &#039;surplusslidereg&#039; durch Leerzeichen getrennt enthält.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backup und Wiederherstellung der Moduldaten ==&lt;br /&gt;
Neben der Datenhaltung in den Attributen und Readings des SolarForecast Devices, erzeugt jedes SolarForecast Device Dateien im Verzeichnis  &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; mit folgenden Inhalten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PVH_SolarForecast_&amp;lt;name&amp;gt;        - PV History&lt;br /&gt;
PVC_SolarForecast_&amp;lt;name&amp;gt;        - PV Circular&lt;br /&gt;
PVCfg_SolarForecast_&amp;lt;name&amp;gt;      - PV Anlagenkonfiguration&lt;br /&gt;
PVCsm_SolarForecast_&amp;lt;name&amp;gt;      - Consumer Status&lt;br /&gt;
ScApi_SolarForecast_&amp;lt;name&amp;gt;      - Strahlungswerte aus verwendeter API&lt;br /&gt;
StatApi_SolarForecast_&amp;lt;name&amp;gt;    - Statusdaten der verwendeten API&#039;s&lt;br /&gt;
WeatherApi_SolarForecast_&amp;lt;name&amp;gt; - Wetterdaten der gewählten Wetter-API (außer DWD-Device)&lt;br /&gt;
AItra_SolarForecast_&amp;lt;name&amp;gt;      - KI Entscheidungsquelle (trainierte Daten)&lt;br /&gt;
AIraw_SolarForecast_&amp;lt;name&amp;gt;      - KI Input Daten = Raw Trainigsdaten&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nach Ausprägung und eingesetzten Features des SolarForecast Devices sind alle oder nur ein Teil dieser Dateien vorhanden. Dabei ist &#039;&#039;&#039;&amp;lt;name&amp;gt;&#039;&#039;&#039; der Name des SolarForecast Devices.&lt;br /&gt;
&lt;br /&gt;
Bei einem Filebackup des FHEM-Servers ist darauf zu achten, dass diese Dateien in dem Backup enthalten sind. Der Inhalt der Dateien ist nicht statisch, sondern kann sich dynamisch aktualisieren. Um im Bedarfsfall einen aktuellen Datenstand zu haben, ist mindestens ein tägliches Backup dieser Dateien empfehlenswert. Eventuell auch öfter mit Hilfe einer Versionierung welche z.B. immer die letzten 3 Versionen aufbewahrt.&lt;br /&gt;
&lt;br /&gt;
Beim Start von FHEM werden bestimmte Dateien automatisch gelesen und in das SolarForecast Device importiert. &lt;br /&gt;
Der Vorgang ist mit verbose=3 im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2023.10.02 09:57:07.967 3: SolCast6 - cached data &amp;quot;pvHistory&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.969 3: SolCast6 - cached data &amp;quot;pvCircular&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;consumerMaster&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;radiationApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;statusApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;weatherApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.974 3: SolCast6 - cached data &amp;quot;aiTrainedData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.976 3: SolCast6 - cached data &amp;quot;aiRawData&amp;quot; restored&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bestimmte Betriebsdaten, wie z.B. die witterungsabhängigen Korrekturfaktoren (circular) oder die KI-Daten (aitrained/airaw), bauen sich über die Zeit immer granularer auf und stellen einen wertvollen Datenbestand dar.&lt;br /&gt;
&lt;br /&gt;
Wird das SolarForecast Device gelöscht und anschließend wieder neu mit dem gleichen Namen definiert, können die bisher verfügbaren Daten sehr einfach wiederhergestellt werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. starten von FHEM (bestimmte Daten werden automatisch importiert)&lt;br /&gt;
* 5. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Soll das neue SolarForecast Device mit einem anderen Namen oder weitere SolarForecast Devices erstellt werden, welche die Betriebsdaten des primären Devices verwenden sollen, ist wie folgt vorzugehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. umbenenen der Dateien, wobei &amp;lt;name&amp;gt; durch den Namen des neuen SolarForecast Devices ersetzt wird&lt;br /&gt;
* 5. starten von FHEM (die Daten werden automatisch importiert)&lt;br /&gt;
* 6. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn sich die SolarForecast Devices hinsichtlich ihres Models oder der integrierten Consumer unterscheiden, sind die Dateien &amp;quot;PVCsm_SolarForecast_&amp;lt;name&amp;gt; &amp;quot; , &amp;quot;ScApi_SolarForecast_&amp;lt;name&amp;gt;&amp;quot; von dem Verfahren auszuschließen.&lt;br /&gt;
&lt;br /&gt;
== Batterieintegration und -steuerung ==&lt;br /&gt;
&lt;br /&gt;
=== Wie eine Batterie eingebunden wird ===&lt;br /&gt;
Wie immer muß die Batterieanlage zunächst mit einem für die Batterie spezifischen FHEM-Device in FHEM definiert sein.&lt;br /&gt;
In diesem Device werden Readings erwartet die folgende Werte bereitstellen:&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieentladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die installierte Batteriekapazität liefert (&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; dieser Schlüssel ist für die Aktivierung des Batterie SOC-Managements und die grafische Anzeige des SOC wesentlich!)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Lade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Entlade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* Reading welches den aktuellen Ladezustand (SOC in Prozent) liefert (optional)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Batterie, bzw. das Batteriedevice wird mit dem Attribut &#039;&#039;&#039;setupBatteryDev&#039;&#039;&#039; im SolarForecast Device registriert. Die Syntax des Attributes ist in  der Online-Hilfe zum Attribut umfassend erläutert. &lt;br /&gt;
Auch wenn manche Readings optional sind, wird empfohlen alle Werte bereitzustellen um alle Batterie-Funktionen im Modul nutzen zu können. Durch die Weiterentwicklung des Moduls können optionale Readings später auch obligatorisch werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Visualisierung der Batterie in der Balkengrafik ====&lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;setupBatteryDevXX&#039;&#039;&#039; verfügt über den Schlüssel &#039;&#039;&#039;show&#039;&#039;&#039;, mit dem die Einblendung des bzw. der Batteriesymbole in den Ebenen der Balkengrafik gesteuert werden kann:&lt;br /&gt;
[[Datei:Screenshot 2025-02-23 192002.png|right|thumb|400px|Einblendung der Batterieleiste und Darstellung des Batterie-SoC als Balkencontent in der zweiten Ebene]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 0 - keine Anzeige des Gerätes (default)&lt;br /&gt;
* 1 - Anzeige des Gerätes in der Balkengrafik Ebene 1&lt;br /&gt;
* 2 - Anzeige des Gerätes in der Balkengrafik Ebene 2 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Symbole und die Farbgebung der Batterie(n) können mittels des Schlüssels &#039;&#039;&#039;icon&#039;&#039;&#039; verändert werden. Die Online-Hilfe gibt weitere Informationen zur Ausgestaltung. &lt;br /&gt;
&lt;br /&gt;
In der Batteriedarstellung wird das Symbol der aktuellen Stunde hervorgehoben. Ein Mouse-Over zeigt wesentliche Betriebszustände der Batterie. Die Batteriesymbole vergangener Stunden zeigen mit einem Mouse-Over die erreichten SoC (State of Charge) Stände. Die kommenden Stunden visualisieren die folgenden Prognosen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der prognostizierte SoC unter Berücksichtigung der PV-Prognose und der [[#Aktivierung_des_Batterie_SOC-Managements|Batteriesteuerung]] sofern sie im Modul aktiviert ist.&lt;br /&gt;
* eine Freigabe bzw. Empfehlung der Batterieladung zur [[#Unterstützung_eines_netzdienlichen_Verhaltens|Unterstützung eines netzdienlichen Verhaltens]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Neben der Einblendung der Batterieleiste über der Balkengrafik selbst können bestimmte Batteriekennwerte als Balkeninhalt dargestellt werden. Die Auswahl erfolgt über das Attribut &#039;&#039;&#039;graphicBeamXContent&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Aktivierung des Batterie SOC- und Lade-Managements ===&lt;br /&gt;
Das integrierte SOC- und Lade-Management verfolgt insbesondere zwei Ziele: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* den Ladezustand der Batterie(n) zu optmimieren, was besonders in den Monaten mit geringerer PV-Erzeugung einen wertvollen Beitrag zur Erhöhung der Autarkierate und Batteriepflege leisten kann&lt;br /&gt;
 &lt;br /&gt;
* eine PV-Prognose und Verbrauch optimierte Beladungssteuerung, die in den Monaten mit hoher PV-Erzeugung hilft eine evtl. Abregelung der Anlage zu verhindern, die Batterie ausgewogen über den Tag zu laden und ein netzdienliches Verhalten zu unterstützen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese beiden Aspekte der Batteriesteuerung werden in den folgenden Abschnitten beschrieben. Sind mehrere Batterien installiert, kann die Steuerung getrennt für jede einzelne Batterie aktiviert und eingestellt werden. Dabei ist zu beachten, dass vom Modul nur Signale und Readings bereitgestellt werden, die durch eine entsprechende Routine ausgewertet werden können um spezifische Befehle zur Umsetzung der Steuerung an das Batteriesystem zu senden. &lt;br /&gt;
 &lt;br /&gt;
Für eine Aktivierung des Managements muß zunächst das Batterie-Device wie im vorigen Abschnitt im SolarForecast Device registriert werden.&lt;br /&gt;
Das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; aktiviert die im Modul integrierte SOC- und Lade-Management Routine: &lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; ctrlBatSocManagement01 lowSoc=&amp;lt;Wert&amp;gt; upSoC=&amp;lt;Wert&amp;gt; [maxSoC=&amp;lt;Wert&amp;gt;] [careCycle=&amp;lt;Wert&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
Die einzelnen Schlüssel werden der Kalkulationsroutine als Steuerungsparameter übergeben und bedeuten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;lowSoc:unterer Mindest-SoC, die Batterie wird nicht tiefer als dieser Wert entladen (muß &amp;gt; 0 sein). Dieser Wert kann zum Beispiel dazu dienen, stets eine Mindestenergiemenge für den Fall eines Stromausfalls im öffentlichen Netz in den Batterien vorzuhalten.&lt;br /&gt;
&lt;br /&gt;
;upSoC:oberer Mindest-SoC, Der übliche Wert des optimalen SoC bewegt sich in Perioden mit hohen PV-Überschuß tendenziell zwischen &#039;lowSoC&#039; und &#039;upSoC&#039;, in Perioden mit geringer PV-Ausbeute bzw. geringem PV Energieüberschuß bewegt sich der optimale SoC tendenziell zwischen &#039;upSoC&#039; und &#039;maxSoC&#039;. Die Einstellung von upSoC=50 für ein ausgewogenes Verhalten kann als guter Startwert dienen.&lt;br /&gt;
&lt;br /&gt;
;maxSoC:maximaler Mindest-SoC, d.h. der SoC Wert der mindestens im Abstand von &#039;careCycle&#039; Tagen erreicht werden muß um den Ladungsausgleich im Speicherverbund auszuführen. Die Angabe ist optional (muß &amp;lt;= 100 sein, default: 95)&lt;br /&gt;
&lt;br /&gt;
;careCycle:maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens &#039;maxSoC&#039; auftreten darf. Die Angabe ist optional. (default: 20)&lt;br /&gt;
&lt;br /&gt;
;loadAbort: definiert eine vom Anwender gewünnschte Bedingung für einen generellen Ladeabbruch und Wiederfreigabe der Lademöglichkeit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle Werte sind ganze Zahlen in %. Dabei gilt: &lt;br /&gt;
&lt;br /&gt;
 lowSoc &amp;lt; upSoC &amp;lt; maxSoC&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====  Erläuterung der Batterie-Steuerungsreadings ==== &lt;br /&gt;
&lt;br /&gt;
Für die Steuerung des Batteriesystems gibt es im SolarForecast einen Satz an Readings, die unterschiedliche Zustände signalisieren und für entsprechende Steuerungsaufgaben bezüglich der Batteriesysteme eingesetzt werden können. In den nachfolgenden Abschnitten werden diese Zusammenhänge noch dataillierter beschrieben.&lt;br /&gt;
&lt;br /&gt;
;Hinweis: SolarForecast stellt lediglich Steuerungsinformationen zur Verfügung. Die Umsetzung des Eingriffs in das Batteriesystem erfolgt durch den Anwender selbst über entsprechende Skripte. In den thematischen Abschnitten werden Beispiele für solche Steuerungsskripte vorgestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle erstellten Readings gelten für ein Batteriesystem, es können mehrere Batteriesysteme in SolarForecast integriert sein. Die Endung &#039;&#039;XX&#039;&#039; der Readings beschreibt die Nummer des Batteriesystems und korrespondiert mit der Endung des entsprechenden Attributes &#039;&#039;ctrlBatSocManagementXX&#039;&#039; bzw. &#039;&#039;setupBatteryDevXX&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Battery_OptimumTargetSoC_XX: Mit den im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; hinterlegten Parametern unter Berücksichtigung von PV- und Verbrauchsprognosen wird ein optimaler SOC-Wert errechnet. Dieser Wert dient zur Einstellung des unteren SOC des Batteriesystems.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeRequest_XX: Dieses Reading signalisiert mit 1 eine Anforderung zur Zwangsladung der Batterie um die Batterie vor Schäden zu schützen (wenn der SOC unter ctrlBatSocManagementXX-&amp;gt;lowSoc gefallen ist) oder wenn der aktuelle SOC unter den berechneten Mindest-SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeUnrestricted_XX: Dieses Reading kann den Wert &#039;&#039;&#039;0&#039;&#039;&#039; oder &#039;&#039;&#039;1&#039;&#039;&#039; einnehmen. Ist der Inhalt 0, sollte die Batterie nur geladen werden, wenn der im Attribut &#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039; definierte Wert überschritten wird. Ist der Inhalt 1, sollte die Batterie mit der vollen zur Verfügung stehenden Ladeleistung angesteuert werden, um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeAbort_XX: Im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; kann mit dem Schlüssel &#039;&#039;loadAbort&#039;&#039; eine Bedingung definiert werden, bei deren Eintritt die Ladung der Batterie abgebrochen werden soll. In diesem Fall wird &#039;&#039;Battery_ChargeAbort_XX=1&#039;&#039; gesetzt. Mit einem entsprechenden Befehl kann der Anwender das Batteriesystem anweisen den Ladevorgang abzubrechen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Nutzung des Batterie SOC-Management ====&lt;br /&gt;
&lt;br /&gt;
Oftmals wird durch die Anlagenhersteller ein hoher statischer SOC eingestellt bzw. empfohlen, der eine längere Verharrungszeit auf einem tiefen SOC-Wert verhindern soll. Allerdings wechseln sich in auch in den Herbst-, Frühlings- und Wintermonaten Zeiten mit wenig PV-Erzeugung mit Phasen stärkerer Solarstrahlung bei klarem Himmel und Sonnenschein ab.&lt;br /&gt;
&lt;br /&gt;
Ein statischer SOC würde dazu führen, dass in den erwähnten Phasen zuviel Energie in das öffentliche Netz eingespeist wird. Dies soll verhindert werden da die wertvolle Energie besser im eigenen Netz gespeichert und in Dunkelphasen verwendet werden kann. Andererseits soll die Batterie nicht zu lange auf einem tiefen SOC verbleiben und außerdem in gewissen Abständen auf einen so hohen SOC geladen werden der den internen Zellausgleich ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Die SOC Kalkulationsroutine des Moduls errechnet unter Berücksichtigung des prognostizierten PV-Ertrages der kommenden Tage, des aktuellen SOC und der im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; (nachfolgend beschrieben) angegebenen Steuerparameter den Vorschlag für eine optimale SOC-Einstellung. Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert.&lt;br /&gt;
&lt;br /&gt;
Durch das Modul selbst findet keine Steuerung der Batterie statt. Es stellt entsprechende Readings zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen SoC.&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SoC unter den optimalen SoC gefallen ist. In diesem Fall sollte die Batterie, unter Umständen mit Netzstrom, zwangsgeladen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Readings können zur Steuerung des SoC (State of Charge) sowie zur Steuerung des verwendeten Ladestroms der Batterie verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ermittlung des optimalen SOC erfolgt nach folgender Logik:&lt;br /&gt;
&lt;br /&gt;
# 	Ausgehend von &#039;lowSoc&#039; wird der Mindest-SoC kurz vor Sonnenuntergang um 5% inkrementiert sofern am laufenden Tag &#039;maxSoC&#039; nicht erreicht wurde und die PV-Prognose keinen hinreichenden Ertrag des kommenden Tages vorhersagt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Wird &#039;maxSoC&#039; (wieder) erreicht, wird Mindest-SoC um 5%, aber nicht tiefer als &#039;lowSoc&#039;, verringert. Ist der berechnete Mindest-SoC größer als &#039;upSoc&#039;, wird der Mindest-SoC auf &#039;upSoc&#039; gesetzt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#   Mindest-SoC wird soweit verringert, dass die prognostizierte PV Energie des aktuellen bzw. des folgenden Tages von der Batterie aufgenommen werden kann. Mindest-SoC wird typisch auf &#039;upSoc&#039; und nicht tiefer als &#039;lowSoc&#039; verringert.  &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Das Modul erfasst den letzten Zeitpunkt am &#039;maxSoC&#039;-Level, um eine Ladung auf &#039;maxSoC&#039; mindestens alle &#039;careCycle&#039; Tage zu realisieren. Zu diesem Zweck wird der optimierte SoC in Abhängigkeit der Resttage bis zum nächsten &#039;careCycle&#039; Zeitpunkt derart verändert, dass durch eine tägliche 5% SoC-Steigerung &#039;maxSoC&#039; am &#039;careCycle&#039; Zeitpunkt rechnerisch erreicht wird. Wird zwischenzeitlich &#039;maxSoC&#039; erreicht, beginnt der &#039;careCycle&#039; Zeitraum erneut. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im fünften Schritt werden die Grenzen &#039;lowSoc&#039; und &#039;upSoc&#039; berücksichtigt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im letzten Schritt erfolgt Generierung des Readings &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; zur Signalisierung einer eventuell empfohlenen Zwangsladung auf den berechneten Min-SoC. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei sehr wenig Erzeugungungsprognose, d.h. wenn sich der berechnete Min-SoC oberhalb von &#039;upSoC&#039; bewegt, wird &#039;upSoC&#039; eingestellt. Liegt der berechnete Min-SoC unterhalb von &#039;upSoC&#039;, ist jedoch größer als &#039;lowSoC&#039;, wird der berechnete SOC im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; eingestellt. Somit eignet sich die Angabe im Schlüssel &#039;upSoC&#039; um in Zeiten geringer Solarenergieerzeugung die Batterie für eine Notstromerzeugung auf mindestens diesem Wert zu halten. Sollte die PV-Prognose kurzfristig einen größeren Ertrag vorhersagen als die Batterie durch die Einhaltung von &#039;upSoC&#039; aufnehmen kann, wird der Min-SoC unter &#039;upSoC&#039; abgesenkt um möglichst allen PV-Überschuß in der Batterie zu speichern und somit dem Eigenverbrauch zuzuführen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der berechnete Mindest-SoC ist immer nur ein unterer Grenzwert. Die Batterie kann durch Ladevorgänge natürlich jederzeit einen höheren als den im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; dargestellten optimalen SoC haben. Der optimale SoC sollte nicht unterschritten werden um die oben genannten Zusammenhänge abbilden zu können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Die dynamische SOC Steuerung mit Umsetzungsbeispiel =====&lt;br /&gt;
Das Modul bietet eine Unterstützung zur automatisierten Einstellung eines optimalen SoC Wertes.&lt;br /&gt;
&lt;br /&gt;
Ziel ist es, den Minimum SoC in Abhängigkeit der zu erwartenden Solarerträge des aktuellen und des folgenden Tages so einzustellen, dass der prognostizierte Solarertrag von der Batterie aufgenommen werden kann. Die Einspeisung in das öffentliche Netz soll minimiert werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin soll ein unterer SoC nicht unterschritten, sowie ein oberer Minimum SoC im Normalfall nicht überschritten werden. Der obere Grenzwert stellt sicher, dass die Batterie mindestens bis zu diesem Wert wieder entladen werden kann. Dadurch bleibt innerhalb der Batterie immer genügend Kapazität verfügbar um unvorhergesehene PV Energie aufnehmen zu können.&lt;br /&gt;
&lt;br /&gt;
Aktiviert wird die Unterstützung der Batteriesteuerung durch das Setzen des Attributes &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; z.B. mit diesen Angaben:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagementXX lowSoc=x upSoC=x maxSoC=x careCycle=x &lt;br /&gt;
&lt;br /&gt;
so zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=98 careCycle=20&lt;br /&gt;
&lt;br /&gt;
Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert. &lt;br /&gt;
Ist dieses Attribut gesetzt, werden Steuerungs-Readings erstellt, die der Nutzer auswerten und seine Batterieanlage z.B. via notify oder DOIF steuern kann. &amp;lt;bR&amp;gt;&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen Mindest-SoC.&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SOC unter den optimalen SOC bzw. minimalen SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
Die Schlüssel &#039;&#039;&#039;lowSoc&#039;&#039;&#039; und &#039;&#039;&#039;upSoC&#039;&#039;&#039; sind die unteren und oberen Grenzen, zwischen denen sich der Minimum SoC im normalen Betrieb bewegen soll.&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;maxSoC&#039;&#039;&#039; stellt eine Ladungsgrenze dar, die mindestens alle X (careCycle) Tage erreicht werden soll. Zu diesem Zweck errechnet das Modul die Anzahl der nötigen Erhöhungen der Minimum Batterieladung von 5% pro Tag um ausgehend vom aktuellen SoC-Level. Der resultierende Minimum SoC Wert wird entsprechend angepasst. Wurde der einstellte maxSoC Level erreicht, startet der Wartungszyklus (careCycle) erneut. &amp;lt;br&amp;gt;&lt;br /&gt;
Der maxSoC in Verbindung mit dem durch &#039;&#039;&#039;careCycle&#039;&#039;&#039; definierten Zyklus soll sicherstellen, dass der Batterieverbund in regelmäßigen Abständen einen Ladungsausgleich vollziehen kann. &lt;br /&gt;
&lt;br /&gt;
Durch die Modullogik erfolgt eine 5 protentige Anhebung des Minimum SoC wenn am Vortag maxSoC nicht erreicht wurde. Die Anhebung erfolgt aber nicht über upSoC. upSoC ist die obere Grenze des Minimum SoC. Wird am Vortag mindestens die maxSoC Ladung erreicht, verringert sich der Minimum SoC wieder schrittweise um 5%, aber nicht tiefer als lowSoc.&lt;br /&gt;
&lt;br /&gt;
Ergänzt wird die Logik noch um die PV Vorhersage. Dabei wird die obige Minimum SoC Berechnung um die Erwartung der PV Erwartung am aktuellen und folgenden Tag korrigiert. Das bedeutet, dass der Minimum SoC z.B. von heute 50% auf 10% abgesenkt und dadurch die gespeicherte Energie dem Haushalt zugeführt wird, wenn am heutigen oder kommenden Tag eine entsprechende PV Energie zu erwarten ist um die Batterie wieder vollständig zu zuladen.&lt;br /&gt;
Dadurch ist immer genügend &amp;quot;Freiplatz&amp;quot; in der Batterie und andererseits hat die Batterie in langen Dunkelphasen eine Reserve für einen eventuellen Stromausfall (falls der abgesichert werden soll) und wird vor einem dauerhaften tiefen SoC geschützt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Umsetzungsbeispiel =====&lt;br /&gt;
&lt;br /&gt;
Wie das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; genutzt werden kann, wird am Beispiel einer Victron Batterieanlage gezeigt. Die Anlage wird durch Cerbo GX Gerät gesteuert. Der Cerbo GX ist per MQTT2 in FHEM eingebunden. Umgesetzt ist die Steuerung der Batterie &#039;01&#039;, d.h. die Angabe &#039;XX&#039; ist durch &#039;01&#039; ersetzt.&lt;br /&gt;
&lt;br /&gt;
Die folgende kleine Logik ist in einem &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; File eingebaut und wird regelmäßig mit&lt;br /&gt;
&lt;br /&gt;
 batSocChargeMgmnt (&#039;&amp;lt;Name SolarForecast Device&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
aufgerufen. Der Aufruf erfolgt durch Angabe der Routine im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; des SolarForecast Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
  # Hinweis: die Zeichen &#039;::&#039; vor der Routine sind durch das SolarForecast Package bedingt&lt;br /&gt;
  ::batSocChargeMgmnt ($name);&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Routine wird dadurch automatisch am Ende jedes Zyklus (siehe Attribut plantControl-&amp;gt;cycleInterval) ausgeführt.&lt;br /&gt;
Um die SOC Managementfunktion nach Bedarf ein- bzw. ausschalten zu können wird zunächst im SolarForecast Device ein userattr zur Steuerung der SOC-Logik angelegt:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; userattr userFn_BatterySoCManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
Die Perl Routine &#039;&#039;&#039;batSocChargeMgmnt&#039;&#039;&#039; ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#  Batterie SOC und Max. Ladestrom Management&lt;br /&gt;
############################################################################&lt;br /&gt;
sub batSocChargeMgmnt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vebus   = &#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;;                            # Victron Vebus Device&lt;br /&gt;
  my $vicsets = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                         # Victron Einstellungen&lt;br /&gt;
&lt;br /&gt;
  my $maxcspc = 105;                                                           # max. Ladestrom (A) Victron MPII Verbund&lt;br /&gt;
  my $actmcc  = ReadingsNum ($vebus, &#039;MaxChargeCurrent&#039;, undef);               # akt. Ladestromeinstellung&lt;br /&gt;
  my $load    = $actmcc // $maxcspc;                                           # Soll-Ladestrom (A)&lt;br /&gt;
&lt;br /&gt;
  ## Battery SoC Management&lt;br /&gt;
  ###########################&lt;br /&gt;
  my $ubsm = AttrVal ($name, &#039;userFn_BatterySoCManagement&#039;, &#039;aus&#039;); &lt;br /&gt;
  &lt;br /&gt;
  if ($ubsm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name,    &#039;Battery_ChargeRequest_01&#039;,     0);&lt;br /&gt;
    my $csoc = ReadingsNum ($vicsets, &#039;MinimumSocLimit&#039;,             10);      # akt. SoC&lt;br /&gt;
    my $osoc = ReadingsNum ($name,    &#039;Battery_OptimumTargetSoC_01&#039;, 10);      # Soll-SoC&lt;br /&gt;
    my $surp = ReadingsNum ($name,    &#039;Current_Surplus&#039;,              0);      # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if ($csoc != $osoc) {&lt;br /&gt;
      CommandSet (undef, &amp;quot;$vicsets MinimumSocLimit $osoc&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn SoCMgmnt -&amp;gt; MinimumSocLimit in $vicsets set to $osoc %});&lt;br /&gt;
    }&lt;br /&gt;
	                                           &lt;br /&gt;
    if ($bcrq &amp;amp;&amp;amp; $surp &amp;lt; 1000) {                                              # max. Strom b. Battery_ChargeRequest &lt;br /&gt;
      $load = 21;&lt;br /&gt;
    }&lt;br /&gt;
	else {&lt;br /&gt;
	  $load = $maxcspc;&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Batterie Einstellung MaxChargeCurrent&lt;br /&gt;
  ##########################################&lt;br /&gt;
  if ($load != $actmcc) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$vebus MaxChargeCurrent $load&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
    Log3 ($name, 3, qq{$name - userFn ChargeMgmnt -&amp;gt; MaxChargeCurrent in $vebus set }.&lt;br /&gt;
                    qq{from old $actmcc A to $load A});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent_set&#039;, $load, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist im SolarForecast Device das Reading  &#039;&#039;&#039;Battery_ChargeRequest_01&#039;&#039;&#039; gesetzt, ist der aktuelle SOC kleiner als der optimale SOC und die Batterie wird (eventuell aus dem öffentlichen Netz) geladen. Das kann automatisch durch den Cerbo GX bzw. in anderen Anlagen durch einen entsprechenden Befehl erfolgen.&lt;br /&gt;
Damit die Netzbeladung nicht mit der vollen Ladestromstärke geschieht, wird der Ladestrom auf den gewünschten Wert (hier 21 A -&amp;gt; ca. 1000 W bei einem 48V System) reduziert sofern kein oder zu wenig PV-Überschuß vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== weitere mögliche Aspekte der SOC- und Batterieladesteuerung ====&lt;br /&gt;
&lt;br /&gt;
SolarForecast liefert durch seine internen Logiken bereits sehr hilfreiche Signale zur Steuerung von Batteriesystemen in Form von Readings an. Abhängig von den individuellen Möglichkeiten der vorhandenen Anlage käme zum Beispiel zusätzlich zu einer Steurung des optimalen SOC oder der Zeitfenster für die Batterieaufladung auch eine Steuerung des Ladestroms bzw. der verwendeten Ladeleistung in Betracht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hintergründe:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Das Laden eines Akkus mit möglichst gleichbleibender und geringer Leistung wirkt sich positiv auf dessen Langlebigkeit aus, was u.a. auch daran liegt, dass der Temperaturstreß im Akku bei langsamer Energiezuführung nur gering ist.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom führt zu einem geringen Absacken der Akkuspannung beim (ggf, temporären) Abschalten des Ladestroms, was sich positiv auf die SOC-Schätzung auswirkt.&lt;br /&gt;
    &lt;br /&gt;
* Ein geringer Ladestrom führt, insb. bei Nutzung passiver Balancer (sind in den Akku-Systemen üblicherweise verbaut), zu einer geringen Differenz zwischen den einzelnen Zellspannungen und damit zu einer besseren Kapazitätsausnutzung eins Akkus.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom kann zu einem zeitlich punktgenauen Zielfüllstand (im Winter 100%, ansonsten natürlich weniger) am Ende des Tages führen.&lt;br /&gt;
    &lt;br /&gt;
* Eine geringer Ladestrom führt auch zu geringen Leitungsverlusten, da der Strom quadratisch zu den Leitungsverlusten beiträgt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann auch die Verweildauer oder die Begrenzung des SOC, auf den die Batterie maximal geladen werden soll, Gegenstand von Optimierungen sein.&lt;br /&gt;
&lt;br /&gt;
Die häufig zu findende Empfehlung, Akkus nicht zu lange bei einem SOC von 100% verweilen zu lassen, liegt weniger an dem SOC als solchem, sondern daran, dass &#039;&#039;SOC=100%&#039;&#039; üblicherweise dadurch ermittelt wird, dass eine Zelle im Akku einen Spannungsschwellenwert überschreitet, der – würde dieser Schwellenwert zeitlich länger überschritten sein – zu einer Schädigung des Akkus führen könnte. Schädlich sind insbesondere häufige Nachladevorgänge bei Werten um die 100% SOC, da Zellen dann ja häufiger und damit - integral gesehen - auch länger den o.g. Schwellenwert überschreiten.&lt;br /&gt;
&lt;br /&gt;
Einige Akku-Hersteller, z.B. BYD, haben auf o.g, Grund in der (neueren) Firmware Ihrer Systeme einen SOC-Threshold (bei BYD liegt dieser bei 95%) eingebaut. Dieser Wert muss nach einem erreichten SOC von 100% unterschritten  werden, bevor überhaupt eine weitere Ladung erfolgt. Insbesondere in der dunklen Jahreszeit kann es daher sinnvoll sein, den Akku unter Verwendung von PV-Leistung so zu füllen, dass dieser möglichst nur einmal vor Einbruch der Dunkelheit auf &#039;&#039;SOC=100%&#039;&#039; geladen wird. Hierbei sollte darauf geachtet werden, dass der Ladeschlussstrom des jeweiligen Systems nicht unterschritten wird. &lt;br /&gt;
&lt;br /&gt;
SolarForecast unterstützt die oben betrachtete Batteriesteuerung durch die optionale Angabe von &#039;&#039;&#039;loadAbort&#039;&#039;&#039; im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039;. Das in diesem Kontext erstellte Reading &#039;&#039;&#039;Battery_ChargeAbort_XX&#039;&#039;&#039; stellt die auswertbaren Steuerungsinformationen zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== PV-Prognose und Verbrauch optimierte Beladungssteuerung unter Berücksichtigung einer Wirkleistungsbegrenzung ====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-04-25 143910.png|right|thumb|400px|Batterie Popup &amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Batterie geladen. sobald PV-Überschuß vorhanden ist ohne eine Prognose zu berücksichtigen. Dadurch sind die Batterien im Sommer unter Umständen schon um 10-12 Uhr voll geladen und die Anlage liefert ihre mehr oder weniger volle Energie (je nach Ausrichtung) in das öffentliche Netz. Dann könnte es zu einer Begrenzung der PV-Leistung durch einen Schwellenwert (z.B. 70%-Regelung) oder eventuell Zwangsabregelung durch den Netzbetreiber kommen.&lt;br /&gt;
&lt;br /&gt;
Hintergrund dieser Erweiterung ist das Bestreben, eine optimale Unterstützung bei der Maximierung des Eigenverbrauchs zu geben und einen Beitrag zur Netzstabilität zu leisten.&lt;br /&gt;
Das Ziel der Beladungssteuerung der Batterie ist es, die Ladung der Batterie über den Tag verteilt so zu steuern, dass die Batterie erst dann geladen wird, wenn durch den PV-Überschuß eine Netzeinspeisung erfolgen würde bzw. ein Grenzwert erreicht werden würde, der zu einer Abregelung der PV-Anlage führen könnte.&lt;br /&gt;
Es kann auch zu einer Zwangsabregelung durch den Netzbetreiber führen, was vermieden werden soll.&lt;br /&gt;
 &lt;br /&gt;
Die interne Kalkulationslogik erstellt zu diesem Zweck ein Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039;.&lt;br /&gt;
Dieses Reading gibt dem User ein Signal, ob zu der aktuellen Stunde der Ladevorgang der Batterie freigegeben (1) oder nicht freigegeben werden sollte (0). Die Freigabe zur Ladung bedeutet dass:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; die Batterie mit ihrer vollen Ladeleistung angesteuert werden sollte um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=0&#039;&#039;&#039; die Batterie nur geladen werden sollte wenn der im Attribut plantControl-&amp;gt;feedinPowerLimit definierte Wert überschritten wird&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ist keine Freigabe zur Ladung vorhanden, kann bzw. sollte dennoch eine Ladung der Batterie vorgenommen werden, sofern eine über dem im &amp;lt;br&amp;gt;&lt;br /&gt;
Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limit liegende Einspeiseleistung vorhanden ist. In diesem Status sollte die Batterie nur mit der Differenzleistung von vorhandener Einspeiseleistung und dem gesetzen Einspeiselimit geladen werden und damit das gesetzte Einspeiselimit einhalten ohne die Anlage abzuregeln. Ist die Batterie in einer Balkengrafikebene dargestellt, wird im Mouse-Over Popup die Battrie mit &#039;&#039;&amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;&#039;&#039; gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Möglichkeiten der Batteriesteuerung sind stark von der individuellen Anlage abhängig und können hier nicht beschrieben werden. Ein Umsetzungsbeispiel mit einer Victron-Anlage mit Pylontech Batterie ist weiter unten dargestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Aktivierung und Arbeitsweise =====&lt;br /&gt;
&lt;br /&gt;
Die implementierte Logik zur optimierten Batterie Beladungssteuerung wird aktiviert, wenn folgende Kriterien erfüllt sind: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;capacity&#039;&#039;&#039; in den setupInverterDevXX Atributen ist gesetzt&lt;br /&gt;
* das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; für die jeweilige Batterie ist gesetzt&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;cap&#039;&#039;&#039; im Attribut setupBatteryDevXX der jeweiligen Batterie ist gesetzt&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Die Logik arbeitet wie folgt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Der resultierende Schwellenwert der Wirkleistungsbegrenzung: der Gesamtanlage wird durch die Auswertung der in den Inverter-Attributen setupInverterDevXX  gesetzen Schlüssel limit (optional) und capacity ermittelt. Inverter mit gesetztem Schlüssel feed = grid (deren Energie wird ausschließlich in das öffentlich Netz eingespeist) werden von der Betrachtung in diesem Kontext ausgeschlossen.&lt;br /&gt;
&lt;br /&gt;
;Die benötigte Beladung bis zu maxSoC (im Attribut setupBatteryDevXX) : wird ermittelt und mit der zu erwartenden PV Tagesprognose in Beziehung gesetzt. Sofern die PV-Erzeugung abzgl. Verbrauch noch nicht das Wirkleistungbegrenzungs-Limit erreicht UND noch genügend PV-Überschuß für eine Ladung auf &#039;&#039;maxSoC&#039;&#039; im Laufe der kommenden Stunden des Tages zu erwarten ist, bleibt das Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 0&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
;Wird das Wirkleistungbegrenzungs-Limit erreicht/überschritten und/oder die PV-Überschußprognose: zzgl. eines Sicherheitspuffers unterschritten, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 1&#039;&#039;&#039; gesetzt. Der User kann darauf reagieren und den Batterie Ladevorgang aktivieren. Die Möglichkeiten der Aktivierung sind natürlich von der installierten Anlage abhängig. Das SolarForecast Device greift nicht in die Batteriesteuerung direkt ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders ausgedrückt erfolgt immer dann eine Ladefreigabe, wenn einer der nachfolgenden Sachverhalte &#039;&#039;wahr&#039;&#039; ist:&lt;br /&gt;
&lt;br /&gt;
- die benötigte Ladeenergie (aller installierten Batterien) &amp;gt;= PV-Restüberschuß des Tages (Reading RestOfDayPVforecast) zzgl. Sicherheitsaufschlag&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- der Zeitpunkt des PV-Erzeugungszenit des laufenden Tages überschritten ist (Reading Today_MaxPVforecastTime)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn die aktuelle PV Leistung &amp;gt;= einer eventuellen Wechselrichter-Leistungsbegrenzung ist (Summe aller WR-Begrenzungen)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn das BatSoc-Management _nicht_ aktiviert ist (nicht alle oben genannten Aktivierungskriterien erfüllt sind)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind mehrere Batterien installiert und durch das Management einer Batterie die Einhaltung der genannten Kriterien bzw. Sachverhalte erwirkt wird, bleiben die weiteren Batterien im Modus Ladefreigabe (Battery_ChargeUnrestricted_XX=1).  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Umsetzungsbeispiel Batterie Ladesteuerung mit Victron GX Venus über den Grid Setpoint =====&lt;br /&gt;
&lt;br /&gt;
Ziel der Steuerung ist es abhängig vom Wert des Readings Battery_ChargeUnrestricted_XX (z.B. Battery_ChargeUnrestricted_01) die Ladung des angeschlossenen Batteriesystems zu aktivieren bzw. zu deaktivieren.&lt;br /&gt;
Das vorliegende Beispiel soll umzusetzen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 0 -&amp;gt; Batterie nicht aufladen bzw. nur laden wenn Einspeiselimit überschritten (Attribut plantControl-&amp;gt;feedinPowerLimit)&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 1 -&amp;gt; Batterie aufladen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Grid Setpoint ist ein Parameter in den Victron Systemeinstellungen. Das Victron System wird den eingestellten Grid Setpoint versuchen einzuhalten und bei einem positiven Wert Energie aus dem Netz beziehen bzw. bei einem negativen Grid Setpoint Energie in das Netz einspeisen.&lt;br /&gt;
&lt;br /&gt;
Normalerweise wird das Victron System die erzeugte PV Energie zunächst zur Deckung des Hausverbrauchs verwenden, ist dann noch ein PV Überschuß vorhanden, die Batterien aufladen und bei weiter vohandenen PV Überschuß diese Energie in das öffentliche Netz einspeisen sofern dem System eine Einspeisung erlaubt ist. Anderenfalls werden die Wechselrichter oder MPPT Smartloader heruntergeregelt bzw. limitiert. &lt;br /&gt;
&lt;br /&gt;
In der Standardeinstellung ist beim Victron System ein Grid Setpoint von ca. 20 bis 50 Watt, d.h. das System strebt danach diese Vorgabe zu erfüllen zieht ständig Energie in diesem Bereich aus dem öffentlich Netz von einem gelegentlichen Überschwingen der Regelung abgesehen. Damit ein eventueller PV Überschuß nicht zum Laden der Batterie verwendet, sondern statt dessen in das öffentliche Netz eingespeist wird, muß der Grid Setpoint um diesen Betrag abgesenkt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-24 114403.png|right|thumb|400px|Integration des Grid Setpoint-Managements in den Own_Spec-Bereich]]&lt;br /&gt;
&lt;br /&gt;
Damit man später per Attribut bzw. über den [[#Formatierung_der_Inhalte_im_Bereich_&amp;quot;Graphic_Header_Own_Specification&amp;quot;|Own_Spec-Bereich]] die automatische Ladesteuerung über den Grid Setpoint ein- bzw. ausschalten kann, legen wir ein userattr an:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 userattr &amp;lt;Name&amp;gt; userFn_GridSetpointManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin sind einige Vorbereitungen im Device MQTT2_cerboGX_c0619ab34e08_settings vorzunehmen. Dieses Device ist im vorliegenden Beispiel ein in FHEM vorhandenes MQTT2_DEVICE, über das die Victron CerboGX Einstellungen zugreifbar sowie einstellbar sind. Die Vorgehensweise zur Erstellung des MQTT2_DEVICE ist hier nicht beschrieben und wird vorausgesetzt.&lt;br /&gt;
&lt;br /&gt;
Damit ein entsprechender Set-Befehl zur Einstellung des Grid Setpoints vorhanden ist, werden folgende Attribute gesetzt:&lt;br /&gt;
&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings jsonMap Settings_CGwacs_AcPowerSetPoint_value:GridSetpoint&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings setList GridSetpoint W/c0619ab34e08/settings/0/Settings/CGwacs/AcPowerSetPoint {&amp;quot;value&amp;quot;:$EVTPART1}&lt;br /&gt;
&lt;br /&gt;
Nach dieser Attributierung kann mit einem &amp;quot;&#039;&#039;set MQTT2_cerboGX_c0619ab34e08_settings GridSetpoint &amp;lt;Wert&amp;gt;&#039;&#039;&amp;quot; der Grid Setpoint eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Das Attribut userFn_GridSetpointManagement kann nun im Perl Code ausgewertet werden um das Grid Setpoint-Management ein- bzw. auszuschalten.&lt;br /&gt;
Der nachfolgende Code wird in die Datei &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; eingefügt. Ist diese Datei nicht vorhanden, legen wir sie vorab als Kopie der ausgelieferten 99_myUtils.pm an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Steuerung Start/Stop der Batterieladung über den Victron Grid Setpoint&lt;br /&gt;
############################################################################&lt;br /&gt;
sub gridSetpointMgmt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vicsets   = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                               # Device Victron Einstellungen&lt;br /&gt;
  my $gspdef    = 20;                                                                  # Default Einstellung des Grid Setpoint&lt;br /&gt;
  my $targetgsp = $gspdef;                                                             # Voreinstellung Grid Setpoint&lt;br /&gt;
  my $neggspmax = FHEM::SolarForecast::CurrentVal ($name, &#039;feedinPowerLimit&#039;, 5000);   # max. gewünschte Einspeiseleistung in Watt&lt;br /&gt;
  $neggspmax    = $neggspmax * -1;&lt;br /&gt;
  my $gspm      = AttrVal ($name, &#039;userFn_GridSetpointManagement&#039;, &#039;aus&#039;);             # Freischaltung des Grid Setpoint-Managements&lt;br /&gt;
  my $curgsp    = ReadingsNum ($vicsets, &#039;GridSetpoint&#039;,         $gspdef);             # aktuelle Einstellung Grid Setpoint&lt;br /&gt;
  &lt;br /&gt;
  if ($gspm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name, &#039;Battery_ChargeUnrestricted_01&#039;, 0);         # Ladefreigabe (1 -&amp;gt; Bat Ladefreigabe)&lt;br /&gt;
    my $surp = ReadingsNum ($name, &#039;Current_Surplus&#039;,               0);         # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if (!$bcrq) {                                                               # Grid Setpoint absenken wenn keine .. &lt;br /&gt;
        $targetgsp = $gspdef - $surp;                                           # ..Batterie Ladefreigabe&lt;br /&gt;
        $targetgsp = $neggspmax if($targetgsp &amp;lt; $neggspmax);                    # Begrenzung der Einspeiseleistung&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($curgsp != $targetgsp) {&lt;br /&gt;
	  fhem (&amp;quot;set $vicsets GridSetpoint $targetgsp&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn gridSetpointMgmt -&amp;gt; GridSetpoint in $vicsets set to $targetgsp});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Victron_GridSetpoint_set&#039;, $targetgsp, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Vergleich des Setpoints mit der Vorgabe von &#039;&#039;$neggspmax&#039;&#039; dient dazu die maximale Einspeiseleistung in das öffentliche Netz zu begrenzen. Ist diese Grenze erreicht, wird der noch verbleibende Überschuß in die Batterie geladen. Dadurch wird eine Abregelung der Anlage vermieden wenn der Schwellenwert &#039;&#039;$neggspmax&#039;&#039;erreicht ist sofern die Batterie aufnahmefähig ist und nicht voll geladen ist. &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::gridSetpointMgmt  ($name);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zum Management des automatischen Grid Setpoint und der Anzeige des eingestellten Wertes wird das Attribut und die Readinganzeige in den Own_Spec-Bereich eingebunden, z.B.:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; graphicHeaderOwnspec  #Settings&lt;br /&gt;
                                   SetPoint&amp;amp;nbsp;Management:userFn_GridSetpointManagement&lt;br /&gt;
                                   Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Unterstützung eines netzdienlichen Verhaltens ====&lt;br /&gt;
&lt;br /&gt;
Der Steuerungsprozess der Batterieanlage leistet insgesamt einen kleinen Beitrag zur Netzstabilität, indem die Speicherladung in den Zeitraum der meisten prognostizierten Überschußeinspeisung gelegt wird. Im Sommer kann sich dieser Zeitraum in die Zeit nach dem Maxmimum des prognostizierten PV-Überschusses verlagern, wenn auch danach noch genügend Überschußenergie zu Volladung der Batterie prognostiziert wird. In dem Zusammenhang sollte im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; ein Einspeiselimit gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zur Verdeutlichung soll das Beispiel dienen:&lt;br /&gt;
&lt;br /&gt;
* die Batterie ist zu 60% geladen &lt;br /&gt;
* der User hat upSoC=40 eingestellt&lt;br /&gt;
* der User hat maxSoC=90 eingestellt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Am Vormittag ist genügend Sonne vohanden, das Maximumum der Energie über die Zeit wird aber noch erwartet. &lt;br /&gt;
Zu diesem Zeitpunkt wird das Reading  &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039; auf den Wert &amp;quot;0&amp;quot; gesetzt. Durch den Nutzer erfolgt daraufhin, zum Beipiel über ein Notify, ein anlagenspezifischer Befehl &amp;quot;Ladestop&amp;quot; an die Batterieanlage. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ab diesem Moment wird:&lt;br /&gt;
&lt;br /&gt;
# die Batterie nicht geladen&lt;br /&gt;
# die erzeugte PV-Energie dem Haushalt zur Verfügung gestellt bzw. der verbleibende Überschuß eingespeist, sofern der Überschuß unterhalb des im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limits liegt.&lt;br /&gt;
# ein eventuell über dem Limit &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; vorhandener Überschuß in die Batterie geladen und so die Netzlast verringert sowie die Batterie schonend geladen. (dieser Punkt trifft in den Monaten mit wenig PV-Erzeugung eher nicht zu)  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig liefert die Batterie Energie an das Hausnetz und wird von 60% bis maximal einem SoC-Wert entladen, der durch die [[#Die_dynamische_SOC_Steuerung_mit_Umsetzungsbeispiel|dynamische SOC Steuerung]] bestimmt wird. Dazu muß diese Steuerung natürlich implementiert sein. Sofern der berechnete SoC größer als upSoC ist, wird der maximale Entladungs-SoC auf upSoC gesetzt. &lt;br /&gt;
&lt;br /&gt;
Zusätzlich überprüft das Modul permanent bei jedem Zyklus die Differenz des aktuell vorhandenen SoC zum eingestellten maxSoC.&lt;br /&gt;
Sie soll nicht größer sein um mit dem (noch) zu erwartenden PV-überschuß des Tages der eingestellte maxSoC bzw. dessen Nähe wahrscheinlich erreicht werden kann. &lt;br /&gt;
Sollte der Differenz-Grenzwert erreicht sein, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; gesetzt und der Nutzer sollte dann über einen geeigneten Befehl seine Anlage in den Modus &amp;quot;Laden&amp;quot; umschalten.&lt;br /&gt;
Dieser Vorgang kann beliebig oft während des Tages alternieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Nutzung von batteryTrigger ===&lt;br /&gt;
Ergänzt werden die Möglichkeiten durch das set-Kommando: &lt;br /&gt;
&lt;br /&gt;
 batteryTrigger &amp;lt;1on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;1off&amp;gt;=&amp;lt;Wert&amp;gt; [&amp;lt;2on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;2off&amp;gt;=&amp;lt;Wert&amp;gt; ...] &lt;br /&gt;
&lt;br /&gt;
Das Kommando setzt Triggerpunkte bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %).&lt;br /&gt;
&lt;br /&gt;
Der verwendete SoC wird als resultierender SoC als Summe der aktuellen Ladung aller registrierten Batterie-Geräte im Verhältnis zur installierten Gesamtkapazität gebildet. Das bedeutet, dass alle einzelnen Batterie-Geräte als ein gemeinsamer Cluster betrachtet werden. &lt;br /&gt;
&lt;br /&gt;
Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise definiert werden.&lt;br /&gt;
Überschreiten die letzten drei SoC-Messungen eine definierte Xon-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = on&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
Unterschreiten die letzten drei SoC-Messungen eine definierte Xoff-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = off&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
&lt;br /&gt;
Der Inhalt der Readings kann durch ein User-Programm oder, bei Erzeugung von entsprechenden Events, mittels notify-Device ausgewertet werden um bei Eintreten eines definierten Ereignisses entsprechende Reaktionen auszulösen. Das kann zum Beispiel die Freigabe eines Heizstabes oberhalb eines bestimmten SOC sein oder ein Entladeverbot der Batterie unterhalb eines SOC-Wertes um Reserven für einen eventuellen Stromausfall zu behalten.&lt;br /&gt;
&lt;br /&gt;
Damit die Batterietrigger dynamisch geändert werden können, ist die Einstellung als Set-Kommando und nicht als Attribut ausgeführt.   &lt;br /&gt;
&lt;br /&gt;
Alle Triggerpunkte können mit dem set-Befehl:&lt;br /&gt;
&lt;br /&gt;
 reset batteryTriggerSet&lt;br /&gt;
&lt;br /&gt;
wieder gelöscht werden.&lt;br /&gt;
&lt;br /&gt;
== Verbrauchersteuerung - Registrieren und visualisieren 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;
Die Eigenschaften und das Schaltverhalten wird durch die Angabe der verfügbaren Schlüssel gesteuert. Die Möglichkeiten sind sehr umfangreich. Die nachfolgenden Abschnitte beschreiben die Verwendung am Beispiel oft vorkommender bzw. nachgefragter Sachverhalte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die Phasen der Verbrauchersteuerung ===&lt;br /&gt;
&lt;br /&gt;
Jeder Zyklus eines Verbrauchers durchläuft im Modul die folgenden Phasen:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Planung&#039;&#039;&#039; der Aktivzeiten des Verbrauchers, d.h. wann der Verbraucher geplant eingeschaltet sowie geplant ausgeschaltet wird und damit der Zyklus beendet wird.&lt;br /&gt;
# &#039;&#039;&#039;Start&#039;&#039;&#039; des Zyklus, d.h. Einschalten des Verbrauchers entsprechend der Planungsdaten sofern weitere, in den Consumer-Schlüsseln definierbare Rahmenbedingungen das Einschalten nicht verhindern (z.B. kein oder zu wenig PV-Energieerzeugung / PV-Überschuss)&lt;br /&gt;
# &#039;&#039;&#039;Permanente Überprüfung von&#039;&#039;&#039; eventuell vorhandenen &#039;&#039;&#039;Interruptbedingungen&#039;&#039;&#039; die den Verbraucher temporär ausschalten und, sofern die Interruptbedingung nicht mehr vorliegt, den Verbraucher wieder einschalten und so den gestarteten Zyklus fortsetzen.&lt;br /&gt;
#  &#039;&#039;&#039;Beendigung&#039;&#039;&#039; der Zyklus. Die Beendigung erfolgt entweder (normalerweise) wenn die geplante Endezeit der Zyklus erreicht ist oder eine optionale Endebedingung erfüllt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Steuerung der Phasen ====&lt;br /&gt;
Der Ablauf der Phasen kann durch verschiedene Schlüssel-Wert Paare beeinflusst und gesteuert werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; kann eine &#039;&#039;&#039;zusätzliche externe Bedingung&#039;&#039;&#039; definiert werden um den Einschaltvorgang des Consumers freizugeben. Ist die Bedingung (Regex) nicht erfüllt, erfolgt kein Einschalten des Verbrauchers auch wenn die sonstigen Voraussetzungen wie Zeitplanung, on-Schlüssel, auto-Mode und aktuelle PV-Leistung gegeben sind. Es erfolgt somit eine &#039;&#039;&#039;UND-Verknüpfung&#039;&#039;&#039; des Schlüssels swoncond mit den Planungsdaten und weiteren Einschaltbedingungen.&lt;br /&gt;
&lt;br /&gt;
Der optionale Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; definiert eine &#039;&#039;&#039;vorrangige Ausschaltbedingung&#039;&#039;&#039; (Regex). Sobald diese Bedingung erfüllt ist, wird der Consumer ausgeschaltet auch wenn die geplante Endezeit (consumerXX_planned_stop) noch nicht erreicht ist (&#039;&#039;&#039;ODER-Verknüpfung&#039;&#039;&#039;). Weitere Bedingungen wie off-Schlüssel und auto-Mode müssen zum automatischen Ausschalten erfüllt sein.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; kann während der geplanten Einschaltzeit eine automatische Unterbrechung sowie Wiedereinschaltung des Verbrauchers vorgenommen werden. Der Verbraucher wird temporär ausgeschaltet (interrupted) und wieder eingeschaltet (continued) wenn die Interrupt-Bedingung nicht mehr vorliegt. Die verbleibende Laufzeit wird durch einen Interrupt nicht beeinflusst! &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;power&#039;&#039;&#039; gibt die nominale Leistungsaufnahme des Verbrauchers gemäß seines Datenblattes an. Dieser Wert wird verwendet um die Schaltzeiten des Verbrauchers zu planen und das Schalten in Abhängigkeit des tatsächlichen PV-Überschusses zum Einplanungszeitpunkt zu steuern. Ist &#039;&#039;&#039;power=0&#039;&#039;&#039; gesetzt, wird der Verbraucher unabhängig von einem zum Zeitpunkt des Zyklus-Start eventuell nicht ausreichend vorhandenem PV-Überschuss wie geplant eingeschaltet und somit der Zyklus gestartet.&lt;br /&gt;
&lt;br /&gt;
Durch die Schlüssel &#039;&#039;&#039;notbefore&#039;&#039;&#039; und &#039;&#039;&#039;notafter&#039;&#039;&#039; kann der Startzeitpunkt des Verbrauchers so gesteuert werden, dass der Start des Zyklus nicht vor bzw. nach der angegebenen Zeit eingeplant wird. Diese Steuerung bezieht sich auf die &#039;&#039;Planung&#039;&#039;, d.h. der eigentliche Start des Verbrauchers kann sich unter Umständen durch vorhandene Rahmenbedingungen verzögern. &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; legt die geplanten Einschaltzeit, d.h. die Laufzeit des Zyklus fest. Der Name &#039;&#039;&#039;mintime&#039;&#039;&#039; ist nicht als MInimum-Zeit zu deuten, sondern beschreibt die angegebene Zeit in Minuten die der Zyklus dauern soll.&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist optional, da sich die Standard-Laufzeit des Verbrauchers von dessen Typ abgeleitet wird. Diese Standard Laufzeiten sind:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|dryer&lt;br /&gt;
|90 Minten&lt;br /&gt;
|-&lt;br /&gt;
|dishwasher&lt;br /&gt;
|180 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|washingmachine&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|heater&lt;br /&gt;
|240 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|charger&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|other&lt;br /&gt;
|60 Minuten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Der Verbraucher wurde nicht gestartet obwohl die Startzeit der Einplanung erreicht wurde ===&lt;br /&gt;
&lt;br /&gt;
Wenn die Startzeit des Consumers entsprechend der Einplanung erreicht oder überschritten ist, wird der Consumer eingeschaltet wenn die weiteren Voraussetzungen wahr sind:&lt;br /&gt;
&lt;br /&gt;
* es ist aktuell ein PV-Überschuss vorhanden und der PV-Überschuss deckt die kalkulierten Leistungsaufnahme des Verbrauchers ab. Mit den Schlüsseln &#039;&#039;&#039;power&#039;&#039;&#039; und &#039;&#039;&#039;spignorecond&#039;&#039;&#039; kann die Einschaltung trotz fehlendem PV-Überschuss ermöglicht werden. &lt;br /&gt;
&lt;br /&gt;
* die Angabe im Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; ist wahr (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* das Schalten ist über den Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; freigegeben (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* im Schlüssel &#039;&#039;&#039;on&#039;&#039;&#039; ist ein valides Einschaltkommando hinterlegt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind diese zusätzlichen Bedingungen nicht erfüllt, erfolgt kein Start des eingeplanten Zyklus. Der Verbraucher verbleibt in diesem Fall weiterhin im Status &#039;&#039;planned&#039;&#039; oder &#039;&#039;suspended&#039;&#039;. Die Startbedingungen werden regelmäßig reviewed und der Consumer gestartet sobald alle Startbedingungen wahr sind bzw. Start verhindernde Bedingungen entfallen sind. &lt;br /&gt;
&lt;br /&gt;
Dieser Vorgang erfolgt bis das geplante Ende des Verbaucherzyklus erreicht ist oder die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; zutrifft. Sobald die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; wahr ist, wird der gesamte Planungszyklus des Consumers beendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Kann manuell / automatisiert in den Planungszyklus eines Verbrauchers eingegriffen werden? ===&lt;br /&gt;
&lt;br /&gt;
Die Einplanung und die darauf aufbauenden Schaltprozesse laufen gemäß den hinterlegten Schlüsseloptionen im Modul automatatisch ab ohne dass ein Eingriff durch den Anwender erfolgen muß.&lt;br /&gt;
&lt;br /&gt;
Dennoch kann es gewünscht sein eine Neuplanung oder eine Sofortplanung eines Consumers vorzunehmen weil der Bedarf dazu besteht. Zu diesem Zweck stehen die Set-Kommandos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* consumerNewPlanning &lt;br /&gt;
&lt;br /&gt;
* consumerImmediatePlanning &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
zur Verfügung. &lt;br /&gt;
Beide Befehle initiieren die Consumer-Neuplanung, wobei mit dem Befehl &#039;&#039;consumerImmediatePlanning&#039;&#039; die eventuell im consumerXX Attribut gesetzten Schlüssel notbefore, notafter bzw. mode werden nicht beachtet werden. Dagenen beachtet der Befehl &#039;&#039;consumerNewPlanning&#039;&#039; alle definierten Schlüsseloptionen und dient gewöhnlich dazu einen abgeschlossenen Verbraucherzyklus wiederholt ausführen zu lassen weil die aktuelle Witterungslage dazu geeignet ist. &lt;br /&gt;
&lt;br /&gt;
Ein Anwendungsbeispiel dafür ist zum Beispiel die Ausführung von mehreren Waschmaschinen-Zyklen an einem langen, sonnigen Sommertag.&lt;br /&gt;
Diese beiden Set-Befehle können zum Beispiel über ein auf einen Schalter/Taster reagierendes Notify oder DOIF Device ausgeführt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung eines Verbrauchers mit getrennten Geräten für Messung und Schalten ===&lt;br /&gt;
&lt;br /&gt;
Es existieren in FHEM Geräte, die über verschiedene Kanäle für unterschiedliche Aufgaben verfügen. Diese Kanäle werden jeweils in einem gesonderten Device abgebildet. HomeMatic oder readingsProxy sind Beispiele für solche Varianten.&lt;br /&gt;
&lt;br /&gt;
Um solche Verbraucher einzubinden gibt es im consumerXX Attribut den Schlüssel &#039;&#039;&#039;switchdev&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Bei der Registrierung gibt man als Consumerdevice das Gerät für die Messung an und im Schüssel switchdev das entsprechende FHEM-Device, welches für die Schaltvorgänge benutzt wird. &lt;br /&gt;
Ist switchdev angegeben, beziehen sich die weiteren Schlüssel on, off, swstate, auto und asynchron auf dieses Gerät.&lt;br /&gt;
&lt;br /&gt;
In dem nachfolgenden Beispiel (Homematic) ist &#039;&#039;eg.az.fridge_Pwr&#039;&#039; FHEM Device für die Energiemessung. Die Schlüssel &#039;&#039;pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; geben Readings in diesem Device an damit SolarForecast den Verbrauch und die Energiemengen auslesen kann. Demgegenüber ist im Schlüssel &#039;&#039;switchdev&#039;&#039; das zugehörige Schalter-Device der Kombination angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eg.az.fridge_Pwr&lt;br /&gt;
type=noSchedule switchdev=eg.az.fridge_Sw power=0 icon=fridge pcurr=power:W:5 etotal=energyCalc:Wh &lt;br /&gt;
swstate=state:on:off auto=automatic&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung von Verbrauchern ohne Zeitplanung und aktivem Schalten ===&lt;br /&gt;
Manchmal besteht der Wunsch, Verbraucher in SolarForecast zu integrieren um lediglich folgende Sachverhalte abzubilden:&lt;br /&gt;
&lt;br /&gt;
* Visualisierung des Schaltstatus in der Consumer Legende und/oder der Energieflußgrafik&lt;br /&gt;
* Darstellung des aktuellen Energieverbrauchs in der Energieflußgrafik&lt;br /&gt;
* Erfassung der (externen) Schaltzeiten, d.h. der Zeiten der Gerätenutzung sowie der Verbrauchsdaten um deren Einfluß bei den Planungszeiten anderer Geräte durch SolarForecast berücksichtigen zu lassen&lt;br /&gt;
&lt;br /&gt;
In solchen Fällen werden bei der Registrierung die Schlüssel &#039;&#039;swstate, pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; zur Erfassung der Schaltzustände und der Energieverbrauchs angegeben, jedoch zur Verhinderung der Zeitplanung durch SolarForecast der Schlüssel &#039;&#039;&#039;type=noSchedule&#039;&#039;&#039; gesetzt sowie die Schlüssel &#039;&#039;on&#039;&#039; und &#039;&#039;off&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt eine mögliche Registrierung eines Zwischensteckers (Shelly) zur Erfassung der Daten eines Gefrierschrankes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Shelly.shellyplug4&lt;br /&gt;
type=noSchedule power=65 asynchron=1&lt;br /&gt;
icon=gefrierschrank &lt;br /&gt;
swstate=state:.*on.*:.*off.* &lt;br /&gt;
pcurr=relay_0_power:W:5 etotal=relay_0_energy_Wh:Wh&lt;br /&gt;
&amp;lt;/pre&amp;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;
&lt;br /&gt;
 Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off&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;
&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;
&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. Alternativ kann die Berücksichtigung des zwangsweisen PV Überschuss mit dem Schlüssel &amp;quot;spignorecond&amp;quot; im Consumer-Attribut ausgesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== zusätzliche Readings bzw. Erzeugung von statistischen Readings ==&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den zahlreichen im Modul per Standard erzeugten Readings kann der Anwender weitere Readings generieren lassen.&lt;br /&gt;
Diese zusätzlichen Readings geben entweder einen bestimmten Sachverhalt (Laufzeit, Status der API-Abfragen, etc.) oder einen statistischen Wert, z.B. die Batterieentladung des aktuellen Tages, wieder.&lt;br /&gt;
&lt;br /&gt;
Die zusätzlich erstellten Readings sind durch den Präfix &#039;&#039;&#039;special_&#039;&#039;&#039; im Device gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Diese zusätzlichen Informationen können durch das Setzen einer oder mehrerer Kennzeichen im Attribut &#039;&#039;&#039;ctrlSpecialReadings&#039;&#039;&#039; erzeugt werden. Die mögliche Auswahl wird je nach Bedarf ausgebaut und umfasst zum aktuellen Zeitpunkt (07.02.2025) diese Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;BatPowerIn_Sum: 	die Summe der momentanen Batterieladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;BatPowerOut_Sum: 	die Summe der momentanen Batterieentladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;allStringsFullfilled: 	Erfüllungsstatus der fehlerfreien Generierung aller Strings&lt;br /&gt;
;conForecastTillNextSunrise: 	Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
;currentAPIinterval: 	das aktuelle Abrufintervall der gewählten Strahlungsdaten-API in Sekunden&lt;br /&gt;
;currentRunMtsConsumer_XX: 	die Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; seit dem letzten Einschalten. (letzter Laufzyklus)&lt;br /&gt;
;dayAfterTomorrowPVforecast: 	liefert die Vorhersage der PV Erzeugung für Übermorgen (sofern verfügbar) ohne Autokorrektur (Rohdaten).&lt;br /&gt;
;daysUntilBatteryCare_XX: 	Tage bis zur nächsten Batterie XX Pflege (Erreichen der Ladung &#039;maxSoC&#039; aus Attribut ctrlBatSocManagementXX)&lt;br /&gt;
;lastretrieval_time: 	der letzte Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;lastretrieval_timestamp: 	der Timestamp der letzen Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;response_message: 	die letzte Statusmeldung der gewählten Strahlungsdaten-API&lt;br /&gt;
;runTimeAvgDayConsumer_XX: 	die durchschnittliche Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; an einem Tag&lt;br /&gt;
;runTimeCentralTask: 	die Laufzeit des letzten SolarForecast Intervalls (Gesamtprozess) in Sekunden&lt;br /&gt;
;runTimeTrainAI: 	die Laufzeit des letzten KI Trainingszyklus in Sekunden&lt;br /&gt;
;runTimeLastAPIAnswer: 	die letzte Antwortzeit des Strahlungsdaten-API Abrufs auf einen Request in Sekunden&lt;br /&gt;
;runTimeLastAPIProc: 	die letzte Prozesszeit zur Verarbeitung der empfangenen Strahlungsdaten-API Daten&lt;br /&gt;
;SunMinutes_Remain: 	die verbleibenden Minuten bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;SunHours_Remain: 	die verbleibenden Stunden bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;todayConsumptionForecast: 	Verbrauchsprognose pro Stunde des aktuellen Tages (01-24)&lt;br /&gt;
;todayConForecastTillSunset: 	Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
;todayDoneAPIcalls: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Calls&lt;br /&gt;
;todayDoneAPIrequests: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Requests&lt;br /&gt;
;todayConsumption: 	der gesamte Energieverbrauch (Wh) des Hauses am aktuellen Tag&lt;br /&gt;
;todayGridConsumption: 	die aus dem öffentlichen Netz bezogene Energie am aktuellen Tag&lt;br /&gt;
;todayGridFeedIn: 	die in das öffentliche Netz eingespeiste PV Energie am aktuellen Tag&lt;br /&gt;
;todayMaxAPIcalls: 	die maximal mögliche Anzahl Strahlungsdaten-API Calls. Ein Call kann mehrere API Requests enthalten.&lt;br /&gt;
;todayRemainingAPIcalls: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Calls&lt;br /&gt;
;todayRemainingAPIrequests: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Requests&lt;br /&gt;
;todayBatIn_XX: 	die am aktuellen Tag in die Batterie XX geladene Energie&lt;br /&gt;
;todayBatInSum: 	Summe der am aktuellen Tag in alle Batterien geladene Energie&lt;br /&gt;
;todayBatOut_XX: 	die am aktuellen Tag aus der Batterie XX entnommene Energie&lt;br /&gt;
;todayBatOutSum: 	Summe der am aktuellen Tag aus allen Batterien entnommene Energie&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Manche Angaben sind im Setup des Moduls optional, d.h. sie müssen nicht zwingend beim Setup angegeben werden. Allerdings sind diese Angaben für die Erstellung eines zusätzlichen Readings unter Umständen Voraussetzung. Es empfiehlt sich deshalb bei Setup so viele Informationen wie möglich zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
So ist zum Beispiel für die sinnvolle Erstellung der Informationen &#039;&#039;&#039;todayBatInSum&#039;&#039;&#039; und &#039;&#039;&#039;todayBatOutSum&#039;&#039;&#039; (Readings special_todayBatInSum und special_todayBatOutSum) das Vorhandensein der Schlüssel &#039;&#039;intotal&#039;&#039; und &#039;&#039;outtotal&#039;&#039; im Attribut setupBatteryDevXX notwendig (Beispiel):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupBatteryDev01 MQTT2_cerboGX_c0619ab34e08_battery &lt;br /&gt;
                              pin=BatIn:W pout=BatOut:W charge=SOC_value intotal=BatInTotal:Wh outtotal=BatOutTotal:Wh &lt;br /&gt;
                              cap=InstalledCapacity_Wh:Wh asynchron=1 show=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Fehlersuche ==&lt;br /&gt;
Das Modul SolarForecast ist sehr komplex und es die verschiedensten Datenquellen ausgewertet, zusammengeführt und daraus Ergebnisse berechnet und/oder visualisiert. Wird etwas nicht wie erwartet durch das Modul geliefert, können die Ursachen vielfältig sein. Natürlich kann ein Fehler im Modulcode vorliegen, oftmals gibt es aber andere Ursachen.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgenden Hinweise sollen Hilfe zur Selbsthilfe geben und sind eine Zusammenfassung von realen Fällen die mit dem beschriebenen Wegen und Verfahren gelöst wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die erwartete erzeugte PV-Energie ist im Modul zu gering und wird im Balkendiagramm nicht angezeigt === &lt;br /&gt;
&lt;br /&gt;
Die erzeugte PV-Energie wird nicht richtig angezeigt: Am Vormittag sind keine Werte vorhanden und, wenn dann etwas kommt, ist die Anzeige zu gering. Für 13 und 14 Uhr wurden ca. 5.000Wh erwartet (im Vergleich mit den Daten aus einer anderen Auswertungsquelle). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lösungsweg:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Aus dem List des Devices wurden die für den Fall wesentlichen Readings herausgezogen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVforecast 152 Wh&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVforecast 1400 Wh&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVforecast 2500 Wh&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVforecast 4392 Wh&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVforecast 4000 Wh&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVreal 300 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVforecast 6415 Wh&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVreal 3200 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVforecast 5629 Wh&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVreal 2700 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVforecast 3958 Wh&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVreal 900 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVforecast 945 Wh&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVreal 500 Wh&lt;br /&gt;
   &lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour18_PVforecast 59 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man sieht dass bis 12:00 keine erzeugte Energie vom WR gemeldet wird. Deswegen wird in der Balkengrafik nichts dargestellt. Auch danach bleibt die registrierte PV-Energie hinter den Erwartungen zurück. Zuständig für die Lieferung der PV-Energie an das Modul ist das Reading im Schlüssel:&lt;br /&gt;
&lt;br /&gt;
 setupInverterDev01 SH10rt pv=Total_DC_Power:W &amp;lt;mark&amp;gt;etotal=Total_Export_Energy_from_PV:kWh&amp;lt;/mark&amp;gt; capacity=10000 strings=Hauptdach,Flachdach&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Welche Änderungen es zwischen den Stunden gab, sieht man mit einem &amp;quot;get ... pvHistory XX&amp;quot; (&amp;quot;XX&amp;quot; steht für das Datum, d.h. den Tag, z.B. 02). &amp;lt;br&amp;gt;&lt;br /&gt;
Hier ein Beispiel für die Stunden 10 (9:00 - 9:59) und 11 (10:00 - 10:59). &amp;lt;br&amp;gt;&lt;br /&gt;
Wichtig ist hier der Key etotali01 für den ersten Inverter. Die Differenz zwischen den Werten beider Stunden ist die in der Stunde erzeugte Energie (hier 380 Wh). Diese 380 Wh findest du auch im Key pvrl01 als PVReal für diese Stunde. Das Modul rechnet intern immer mit Wh, kWh werden vorher in Wh umgerechnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
10 =&amp;gt; pvfc: 365, pvrl: 530, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63364714&amp;lt;/mark&amp;gt;, etotali02: 3044110, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;pvrl01: 380&amp;lt;/mark&amp;gt;, pvrl02: 150, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 574, con: 518, gcons: 22, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 1, feedprice: 0.1269&lt;br /&gt;
&lt;br /&gt;
            DoN: 1, sunaz: 137, sunalt: 12&lt;br /&gt;
&lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
      11 =&amp;gt; pvfc: 2966, pvrl: 1862, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63365094&amp;lt;/mark&amp;gt;, etotali02: 3044260, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            pvrl01: 1392, pvrl02: 470, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 774, con: 609, gcons: 25, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 4, feedprice: 0.1269&lt;br /&gt;
           &lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
D.h. wenn zwischen den beiden Stunden keine Differenzen zu finden sind, liegt es sehr wahrscheinlich am Input des Readings:&lt;br /&gt;
&lt;br /&gt;
 etotal=Total_Export_Energy_from_PV:kWh&lt;br /&gt;
&lt;br /&gt;
welches sich in den ersten Stunden nicht ändert und danach auch nur wenig.&lt;br /&gt;
&lt;br /&gt;
Man kann mit dem Attribut:&lt;br /&gt;
&lt;br /&gt;
 ctrlDebug=collectData&lt;br /&gt;
&lt;br /&gt;
die Datensammlung verfolgen (leider entstehen viele Daten im Log). Man sieht welche Werte von dem Inverter/Reading geliefert werden:&lt;br /&gt;
 &lt;br /&gt;
 ....&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; collect Inverter 01 data - device: STP_5000, delivery: default =&amp;gt;&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; pv: 0 W, &amp;lt;mark&amp;gt;etotal: 63378810 Wh&amp;lt;/mark&amp;gt;&lt;br /&gt;
 ....&lt;br /&gt;
&lt;br /&gt;
Dieser Wert muß bei PV Erzeugung kontinuierlich hochzählen. Wenn nicht, muss das angegebene Reading, d.h. die Quelle überprüft werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ergebnis der Prüfung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tatsächlich wurde ein Reading benutzt, das ungeeignet war: Statt &amp;quot;Total_PV_Generation&amp;quot; wurde &amp;quot;Total_export_energy_from_PV&amp;quot; genutzt. In diesem Reading wurde immer die in die Batterie gespeicherte Energie von der gesamten erzeugten Energie abgezogen. Daher war auch vormittags alles 0, da in dieser Periode alle PV-Energie in die Batterie geladen wurde bzw. in weiteren Stunden ein Anteil der dann bei dem PV-Erzeugungswert fehlte.&lt;br /&gt;
&lt;br /&gt;
Nachdem die Ursache beseitigt war, zeigt SolarForecast wieder die erwarteten PV-Erzeugungswerte an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Konfigurationsbeispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Visualisierung solare Vorhersage und reale Erzeugung ===&lt;br /&gt;
&lt;br /&gt;
Zu Beginn jedes neuen Tages gegen 00:00 Uhr werden durch das SolarForecast Device Events für die initiale PV Prognose des kommenden Tages erstellt.&lt;br /&gt;
Der Readingteil dieser Events heißt&lt;br /&gt;
&lt;br /&gt;
 AllPVforecastsToEvent&lt;br /&gt;
&lt;br /&gt;
Die Uhrzeiten der Events sind so aufbereitet und können direkt geloggt werden um sie in einen SVG Plot zu integrieren.&lt;br /&gt;
Im SolarForecast Device ist dieses Reading nicht sichtbar, nur die Events werden erstellt.&lt;br /&gt;
&lt;br /&gt;
Die meteorologischen Bedingungen verändern sich über den Tag permanent. Je nach gewählter Strahlungsdatenquelle (eine API oder DWD Device) erfolgt eine mehr oder weniger dynamische Anpassung der Prognose an die sich verändernde Umwelt.&lt;br /&gt;
&lt;br /&gt;
Aktuelle Prognosedaten sowie die reale PV Erzeugung der vergangenen Stunde können über die Readings&lt;br /&gt;
&lt;br /&gt;
 LastHourPVforecast&lt;br /&gt;
 LastHourPVreal&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-10-20 134050.png|right|thumb|400px|Übersicht solare Vorhersage]]&lt;br /&gt;
geloggt werden. &lt;br /&gt;
&lt;br /&gt;
Werden alle drei Werte in einem SVG kombiniert, kann die Entwicklung der Prognose über den Tag und die Beziehung von Prognose zu realer PV Erzeugnung pro Stunde visualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Für das rechts abgebildete Beispiel des Plots aus einer Datenbank &amp;quot;LogDBShort&amp;quot; sieht das gplot-File wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Created by FHEM/98_SVG.pm, 2024-03-08 15:05:31&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;TL&amp;gt;&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid&lt;br /&gt;
set ylabel &amp;quot;Wh&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Wh&amp;quot;&lt;br /&gt;
set yrange [0:7500]&lt;br /&gt;
set y2range [0:7500]&lt;br /&gt;
&lt;br /&gt;
#LogDBShort SolCast:LastHourPVforecast:::&lt;br /&gt;
#LogDBShort SolCast:LastHourPVreal:::&lt;br /&gt;
#LogDBShort SolCast:AllPVforecastsToEvent:::&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;aktuelle PV Vorhersage&#039; ls l6fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;reale PV Erzeugung&#039; ls l2fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;initiale PV Vorhersage&#039; ls l4 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; In manchen Fällen werden die Vorhersagewerte im SVG-Plot nicht angezeigt wenn FileLog verwendet wird. Ein Setzen des Attribute &amp;quot;fixedrange=3days +1&amp;quot; im SVG löst das Problem. Die Definition des SVG-Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_LogDBShort_SolCast SVG LogDBShort:SVG_LogDBShort_SolCast:HISTORY&lt;br /&gt;
attr SVG_LogDBShort_SolCast fixedrange 3days +1&lt;br /&gt;
attr SVG_LogDBShort_SolCast room Energie-&amp;gt;SolarPrognose&lt;br /&gt;
attr SVG_LogDBShort_SolCast sortby 2&lt;br /&gt;
attr SVG_LogDBShort_SolCast title &amp;quot;Übersicht solare Vorhersage&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Technisch bedingt werden an einem Tag X kurz nach 00:00 Uhr die am Vortag für den Tag X erzeugten Events aktualisiert. Diese Daten erzeugen in der Datenbank einen zweiten Satz an Daten mit dem gleichen Timestamp was für die Anzeige unvorteilhaft ist. &lt;br /&gt;
Um nur die aktualisierten Events von &#039;&#039;&#039;AllPVforecastsToEvent&#039;&#039;&#039; in der Datenbank zu erhalten, bietet sich ein DbRep-Device an. Die nachfolgende Vorschlagsdefinition kann per at-Device jeden Tag kurz vor Mitternacht (z.B. 23:57:10) ausgeführt werden. Es werden immer die in der Vergangenheit geschriebenen (veralteten) Daten aus der Datenbank gelöscht, doppelte Datesätze vermieden und immer die aktuellste initiale Prognose gespeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.Del.AllPVforecastsToEvent DbRep LogDBShort&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent alias Löschen Readings AllPVforecastsToEvent des Folgetages&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent comment ermöglicht dass die Readings AllPVforecastsToEvent am Folgetag wieder neu und aktuell geschrieben werden können&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent devStateIcon initialized:control_3dot_hor_s connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent disable 0&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent event-on-update-reading state&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent icon edit_delete&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent showproctime 1&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent device TYPE=SolarForecast&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_begin next_day_begin&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_end next_day_end&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das angegebene DbLog-Device &#039;&#039;&#039;LogDBShort&#039;&#039;&#039; ist natürlich anzupassen.&lt;br /&gt;
&lt;br /&gt;
Das at-Device zum Starten der Datenbankbereinigung sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define At.Del.AllPVforecastsToEvent at *23:58:10 set Rep.Del.AllPVforecastsToEvent delEntries&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent alias Start Löschen Readings AllPVforecastsToEventn LogDBShort&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent icon clock&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich sind auch hier die eigenen Devicenamen entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
Ab SolarForecast Version 1.51.7 kann die Eventerzeugung für bestimmte SVG Plot-Typen optimiert werden. &amp;lt;br&amp;gt; &lt;br /&gt;
Die Aktivierung dieser Optimierungen ist in der Online Hilfe zum Attribut &#039;&#039;&#039;plantControl-&amp;gt;genPVforecastsToEvent&#039;&#039;&#039; beschrieben. Bei Nutzung des Attributes plantControl-&amp;gt;genPVforecastsToEvent ist ebenfalls das Attribut &#039;&#039;&#039;event-on-update-reading=AllPVforecastsToEvent&#039;&#039;&#039; zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispielkonfiguration 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;
Bitte dabei diese DWD-Version aus dem [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter Contrib] von DS_Starter dazu nutzen&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|55_DWD_OpenData.pm&lt;br /&gt;
|136.2 KB ​&lt;br /&gt;
|29260  &lt;br /&gt;
|DS_Starter&lt;br /&gt;
|55_DWD_OpenData: contrib 1.17.7&lt;br /&gt;
|}&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 downloadTimeout 120&lt;br /&gt;
attr DWD comment Im DWD Wetterdevice verwendet Solarforecast : \&lt;br /&gt;
TTT,Neff,RR1c,ww,SunUp,SunRise,SunSet \&lt;br /&gt;
zusätzlich ist jedoch auch noch Rad1h notwendig \&lt;br /&gt;
wenn dieses DWD-Device als Strahlungsdevice genutzt wird.\&lt;br /&gt;
Die Station 10418 (Lüdenscheid) überträgt aktuell am 09.03.2025 (noch) Rad1h.\&lt;br /&gt;
attr DWD downloadTimeout 120&lt;br /&gt;
attr DWD forecastDays 7&lt;br /&gt;
attr DWD forecastProperties SunUp, SunRise, SunSet, Rad1h, R101, RR1c, TTT, Tx, Tn, Tg, DD, FX1, RR6c, R600, RRhc, Rh00, ww, wwd, Neff&lt;br /&gt;
attr DWD forecastRefresh 1&lt;br /&gt;
attr DWD forecastResolution 1&lt;br /&gt;
attr DWD forecastStation 10418&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 fc_description  -(state fc_time)&lt;br /&gt;
attr DWD verbose 2&lt;br /&gt;
&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;
defmod InverterDummy dummy&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;
defmod 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 feedinPrice 0.08&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 powerCost 0.25&lt;br /&gt;
attr SMA_Energymeter room 015_Zaehler,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;
defmod 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;
attr BatteryDummy userReadings total_pac, power_out, power_in, chargestatus, bat_rated_capacity, bat_loadtotal, bat_unloadtotal&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;
defmod N.PV.TotalConsumption.Dum.Energy notify SMA_Energymeter:Saldo_Wirkleistung:.* {\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung_2 Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&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;MB_USRW610_004&amp;quot;,&amp;quot;Power_Sum__W&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;
fhem &amp;quot;setreading InverterDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(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;
#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;
 # Batterie-total_pac  InverterDummy\&lt;br /&gt;
my $wert7 = sprintf(&amp;quot;%.3f&amp;quot;,((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy bat_rated_capacity &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert7));;\&lt;br /&gt;
 # möglicher Aufruf einer Batterie-Bebladung-Routine....SMABatteryChargewithTibber();;\&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;
defmod Forecast SolarForecast&lt;br /&gt;
attr Forecast DbLogExclude .*&lt;br /&gt;
attr Forecast DbLogInclude Current_BatCharge999&lt;br /&gt;
attr Forecast affectBatteryPreferredCharge 30&lt;br /&gt;
attr Forecast affectConsForecastLastDays 31&lt;br /&gt;
attr Forecast affect70percentRule 0&lt;br /&gt;
attr Forecast comment &amp;quot;wget -qO ./FHEM/76_SolarForecast.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/76_SolarForecast.pm&amp;quot;\&lt;br /&gt;
&amp;quot;wget -qO ./FHEM/55_DWD_OpenData.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/55_DWD_OpenData.pm&amp;quot;\&lt;br /&gt;
&amp;quot;13.01.2025 mit der Version 76_SolarForecast.pm:v1.43.2-s29518/2025-01-12&amp;quot;&lt;br /&gt;
attr Forecast graphicHeaderOwnspec PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal Verbrauch&amp;amp;nbsp;;bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast  Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest FCU-Erzeugung&amp;amp;nbsp;;:Current_PP01\&lt;br /&gt;
attr Forecast consumer01 FBDECT_fbahahttp_11657_0127183 icon=scene_washing_machine@orange type=washingmachine power=10 swstate:state notbefore=09 notafter=20 pcurr=power:W:3 etotal=energy:Wh interruptable=1 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer02 FBDECT_fbahahttp_E8_DF_70_07_3E_57 icon=light_floor_lamp@orange type=other power=15 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer03 FBDECT_fbahahttp_E8_DF_70_07_42_0B icon=raspberrypi@orange type=other power=8 swstate:state pcurr=power:W:1 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer04 FBDECT_fbahahttp_11657_0067275 icon=springbrunnen_icon@orange type=other power=50 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer05 FBDECT_fbahahttp_34_31_C4_D4_31_37 icon=sani_domestic_waterworks@orange type=other power=10 swstate:state pcurr=power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer06 tuya_local_bf5037060f450bdbd4rl0q icon=scene_clothes_dryer@orange type=dryer power=10 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer07 tuya_local_bfac44fb487476efd1vhdu icon=weather_sunset@orange type=noSchedule power=5 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumerControl adviceIcon=light_light_dim_100@gold&lt;br /&gt;
attr Forecast consumerControl showLegend=icon_top&lt;br /&gt;
attr Forecast consumerControl detailLink=1&lt;br /&gt;
attr Forecast ctrlAIdataStorageDuration 1825&lt;br /&gt;
attr Forecast ctrlAIshiftTrainStart 2&lt;br /&gt;
attr Forecast ctrlBatSocManagement01 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlBatSocManagement02 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlDebug none&lt;br /&gt;
attr Forecast plantControl genPVdeviation=continuously&lt;br /&gt;
attr Forecast plantControl cycleInterval=15&lt;br /&gt;
attr Forecast ctrlNextDayForecastReadings 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24&lt;br /&gt;
attr Forecast ctrlNextHoursSoCForecastReadings 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23&lt;br /&gt;
attr Forecast ctrlSpecialReadings BatPowerIn_Sum,BatPowerOut_Sum,SunHours_Remain,SunMinutes_Remain,allStringsFullfilled,conForecastTillNextSunrise,currentAPIinterval,currentRunMtsConsumer_01,currentRunMtsConsumer_02,currentRunMtsConsumer_03,currentRunMtsConsumer_04,currentRunMtsConsumer_05,currentRunMtsConsumer_06,currentRunMtsConsumer_07,dayAfterTomorrowPVforecast,daysUntilBatteryCare_01,daysUntilBatteryCare_02,lastretrieval_time,lastretrieval_timestamp,response_message,runTimeAvgDayConsumer_01,runTimeAvgDayConsumer_02,runTimeAvgDayConsumer_03,runTimeAvgDayConsumer_04,runTimeAvgDayConsumer_05,runTimeAvgDayConsumer_06,runTimeAvgDayConsumer_07,runTimeCentralTask,runTimeLastAPIAnswer,runTimeLastAPIProc,runTimeTrainAI,todayBatIn_01,todayBatIn_02,todayBatOut_01,todayBatOut_02,todayConForecastTillSunset,todayConsumptionForecast,todayDoneAPIcalls,todayDoneAPIrequests,todayGridConsumption,todayGridFeedIn,todayMaxAPIcalls,todayRemainingAPIcalls,todayRemainingAPIrequests&lt;br /&gt;
attr Forecast disable 0&lt;br /&gt;
attr Forecast event-min-interval .*:1800&lt;br /&gt;
attr Forecast event-on-change-reading .*&lt;br /&gt;
attr Forecast flowGraphicControl animate=1 consumerdist=80 h2consumerdist=50 shiftx=0  shifty=0 showconsumer=1 showconsumerdummy=1 showconsumerpower=1 showconsumerremaintime=0 size=400 strokewidth=12&lt;br /&gt;
attr Forecast graphicBeam1Color 3C14FF&lt;br /&gt;
attr Forecast graphicBeam1Content pvReal&lt;br /&gt;
attr Forecast graphicBeam2Color 19FF29&lt;br /&gt;
attr Forecast graphicBeam2Content pvForecast&lt;br /&gt;
attr Forecast graphicBeam3Color D60924&lt;br /&gt;
attr Forecast graphicBeam3Content batsocforecast_02&lt;br /&gt;
attr Forecast graphicBeam3FontColor FFFF0D&lt;br /&gt;
attr Forecast graphicBeam4Color FFFF1F&lt;br /&gt;
attr Forecast graphicBeam4Content batsocforecast_01&lt;br /&gt;
attr Forecast graphicBeam4FontColor 000000&lt;br /&gt;
attr Forecast graphicBeamHeightLevel1 200&lt;br /&gt;
attr Forecast graphicBeamHeightLevel2 200&lt;br /&gt;
attr Forecast graphicHeaderDetail all&lt;br /&gt;
attr Forecast graphicHeaderOwnspec #PV\&lt;br /&gt;
PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal\&lt;br /&gt;
PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast\&lt;br /&gt;
PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast\&lt;br /&gt;
:\&lt;br /&gt;
#\&lt;br /&gt;
AutarkyRate:Current_AutarkyRate\&lt;br /&gt;
Überschuss:Current_Surplus\&lt;br /&gt;
aktueller&amp;amp;nbsp;;Netzbezug:Current_GridConsumption\&lt;br /&gt;
:\&lt;br /&gt;
#Verbrauch\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenuntergang:special_todayConForecastTillSunset\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie01\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_01\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_01\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_01\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_01\&lt;br /&gt;
#Batterie01_tmp\&lt;br /&gt;
Current_PowerBatIn_01:Current_PowerBatIn_01\&lt;br /&gt;
Current_PowerBatOut_01:Current_PowerBatOut_01\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie02\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_02\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_02\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_02\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_02\&lt;br /&gt;
#Batterie02_tmp\&lt;br /&gt;
Current_PowerBatIn_02:Current_PowerBatIn_02\&lt;br /&gt;
Current_PowerBatOut_02:Current_PowerBatOut_02\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Settings\&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto \&lt;br /&gt;
Wetter:graphicShowWeather\&lt;br /&gt;
History:graphicHistoryHour\&lt;br /&gt;
ShowNight:graphicShowNight\&lt;br /&gt;
Debug:ctrlDebug\&lt;br /&gt;
FCU-Modus:FCU-Betriebsmodus@FCU&lt;br /&gt;
attr Forecast graphicHistoryHour 4&lt;br /&gt;
attr Forecast graphicHourCount 24&lt;br /&gt;
attr Forecast graphicLayoutType double&lt;br /&gt;
attr Forecast graphicShowDiff top&lt;br /&gt;
attr Forecast graphicShowNight 1&lt;br /&gt;
attr Forecast graphicShowWeather 1&lt;br /&gt;
attr Forecast group Energy Meter&lt;br /&gt;
attr Forecast room 020_PV,Energie&lt;br /&gt;
attr Forecast setupBatteryDev01 SBS25 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupBatteryDev02 SBS25_2 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupInverterDev01 SB25 pv=total_pac:kW etotal=etotal:kWh capacity=2500 strings=GarageSE limit=70&lt;br /&gt;
attr Forecast setupInverterDev02 SB30 pv=total_pac:kW etotal=etotal:kWh capacity=3000 strings=GarageNW,HausNW limit=70&lt;br /&gt;
attr Forecast setupInverterDev03 SB40 pv=total_pac:kW etotal=etotal:kWh capacity=4000 strings=HausSE1,HausSE2,HausSW limit=70&lt;br /&gt;
attr Forecast setupInverterStrings GarageSE,GarageNW,HausNW,HausSW,HausSE1,HausSE2&lt;br /&gt;
attr Forecast setupMeterDev SMA_Energymeter gcon=Bezug_Wirkleistung:W contotal=Bezug_Wirkleistung_Zaehler:kWh gfeedin=Einspeisung_Wirkleistung:W feedtotal=Einspeisung_Wirkleistung_Zaehler:kWh conprice=0.25:€ feedprice=0.08123:€&lt;br /&gt;
attr Forecast setupOtherProducer01 icon=Heizung_FCU_green@red MB_USRW610_004 pcurr=Power_L1__W:W etotal=Energy_L1_import__kWh:kWh&lt;br /&gt;
attr Forecast setupRadiationAPI DWD&lt;br /&gt;
attr Forecast setupStringPeak GarageSE=2.75 GarageNW=3.200 HausNW=2.230 HausSW=2.230 HausSE1=2.200 HausSE2=2.200&lt;br /&gt;
attr Forecast setupWeatherDev1 DWD&lt;br /&gt;
attr Forecast stateFormat Current_PV&lt;br /&gt;
attr Forecast userReadings Current_BatCharge999 {((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))) / ( (ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0) * 1000)  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0)*1000))*100}&lt;br /&gt;
attr Forecast verbose 2&lt;br /&gt;
&lt;br /&gt;
setstate Forecast 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .FCU_FCU-Betriebsmodus 2&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_ctrlDebug none&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicHistoryHour 4&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowNight 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowWeather 1&lt;br /&gt;
setstate Forecast 2025-01-13 08:24:25 .associatedWith SMA_Energymeter FBDECT_fbahahttp_11657_0127183 FBDECT_fbahahttp_E8_DF_70_07_3E_57 FBDECT_fbahahttp_E8_DF_70_07_42_0B FBDECT_fbahahttp_11657_0067275 FBDECT_fbahahttp_34_31_C4_D4_31_37 tuya_local_bf5037060f450bdbd4rl0q tuya_local_bfac44fb487476efd1vhdu SBS25 SBS25_2 SB25 SB30 SB40 DWD MB_USRW610_004&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .lastupdateForecastValues 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .pvCorrectionFactor_Auto_Soll on_complex_ai&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .signaldone_01 done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .signaldone_02 done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .signaldone_03 done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .signaldone_04 done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .signaldone_05 done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .signaldone_06 done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .signaldone_07 done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .signaldone_08 done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .signaldone_09 done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .signaldone_10 done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .signaldone_11 done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .signaldone_12 done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .signaldone_13 done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .signaldone_14 done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .signaldone_15 done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .signaldone_16 done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .signaldone_17 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .signaldone_18 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_01 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_02 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_01 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_02 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_AutarkyRate 83 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 Current_BatCharge999 10&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_01 12 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_02 8 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Consumption 626 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridConsumption 2 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridFeedIn 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PP_01 746.0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PV 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_01 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_02 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_01 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_02 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumption 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumptionRate 0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Surplus 120 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourGridconsumptionReal 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_ConsumptionForecast 2944 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayConsumptionForecast 3609 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_01 272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PPreal_01 748 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PPreal_01 787 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_01 271 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PPreal_01 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PPreal_01 745 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_01 267 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PPreal_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_01 255 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PPreal_01 752 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_01 226 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_01 50 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PPreal_01 681 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_02 233 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_01 845 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridConsumption 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_01 37 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_02 90 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_01 351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_02 188 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridConsumption 447 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVforecast 127 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridConsumption 1650 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVforecast 478 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVreal 26 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridConsumption 513 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVforecast 868 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVreal 97 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridConsumption 576 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVforecast 1157 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVreal 320 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_01 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_02 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridConsumption 1272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridFeedIn 7 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVforecast 1238 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVreal 945 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_01 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_02 53 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridConsumption 955 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridFeedIn 31 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PPreal_01 562 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVforecast 1168 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVreal 1410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_01 703 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_02 500 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_01 22 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_02 18 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridConsumption 32 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridFeedIn 71 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PPreal_01 777 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVreal 1416 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_01 296 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_02 70 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_01 74 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_02 258 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridConsumption 13 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridFeedIn 17 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PPreal_01 732 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVforecast 880 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVreal 1051 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_01 47 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_02 126 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_01 102 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_02 75 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridConsumption 15 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridFeedIn 23 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PPreal_01 771 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVforecast 117 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVreal 86 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_02 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_02 67 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridConsumption 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridFeedIn 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PPreal_01 723 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_01 349 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_02 124 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_01 73 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_02 450 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridConsumption 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridFeedIn 6 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PPreal_01 671 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecastTime 2025-01-13 14:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVdeviation 30.17 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVforecast 7663 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVreal 5351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunRise 08:28&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunSet 16:46&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_ConsumptionForecast 17043 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour05_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour06_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour07_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour08_PVforecast 10 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour09_PVforecast 161 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour10_PVforecast 275 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour11_PVforecast 532 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour12_PVforecast 730 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour13_PVforecast 1252 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour14_PVforecast 818 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour15_PVforecast 1465 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour16_PVforecast 303 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour17_PVforecast 20 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour18_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour19_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour20_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour21_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour22_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour23_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour24_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_PVforecast 5566 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunRise 08:27&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunSet 16:47&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01 name=&#039;_Waschmaschine&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_start 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_stop 14.01.2025 11:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02 name=&#039;_Esszimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_currentPower 15.3 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03 name=&#039;_FCU&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_currentPower 7.15 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04 name=&#039;_Brunnen&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05 name=&#039;_Zisterne&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06 name=&#039;SW Trockner&#039; state=&#039;unknown&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_stop 14.01.2025 08:30:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07 name=&#039;SW Urlaubslicht-Wohnzimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;noSchedule&#039; info=&#039;von extern umgeschaltet&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 nextCycletime 18:54:09&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 pvCorrectionFactor_10 0.53 (automatic - old factor: 1.00, Sun Alt range: 5, Cloud range: 75, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 pvCorrectionFactor_11 0.56 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 70, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 pvCorrectionFactor_12 0.64 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 pvCorrectionFactor_13 0.88 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 pvCorrectionFactor_14 1.10 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 50, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 pvCorrectionFactor_15 1.01 (automatic - old factor: 1.06, Sun Alt range: 15, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 pvCorrectionFactor_16 1.09 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 45, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 pvCorrectionFactor_17 0.28 (automatic - old factor: 0.52, Sun Alt range: 0, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 pvCorrectionFactor_Auto on_complex_ai&lt;br /&gt;
setstate Forecast 2024-10-30 19:42:19 setupStringAzimuth GarageSE=-55 GarageNW=125 HausNW=125 HausSW=35 HausSE1=-55 HausSE2=-55&lt;br /&gt;
setstate Forecast 2024-10-30 19:37:38 setupStringDeclination GarageSE=40 GarageNW=40 HausNW=50 HausSW=50 HausSE1=50 HausSE2=50&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerIn_Sum 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerOut_Sum 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunHours_Remain 0.00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunMinutes_Remain 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_allStringsFullfilled 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_conForecastTillNextSunrise 9467 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentAPIinterval 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_01 132 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_02 184 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_03 329512 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_04 200 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_05 27 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_06 193 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_07 106 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_dayAfterTomorrowPVforecast 7344 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_01 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_02 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_time 2025-01-13 18:53:54&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_timestamp 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_response_message success&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_01 545.94 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_02 382.10 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_03 1430.13 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_04 262.05 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_05 28.80 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_06 622.63 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_07 276.51 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeCentralTask 0.3744&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIAnswer -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIProc -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeTrainAI 1.2529&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_01 3683.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_02 1617.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_01 2287.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_02 1057.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConForecastTillSunset 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 special_todayConsumptionForecast_01 509 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 special_todayConsumptionForecast_02 499 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 special_todayConsumptionForecast_03 501 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 special_todayConsumptionForecast_04 511 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 special_todayConsumptionForecast_05 503 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 special_todayConsumptionForecast_06 495 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 special_todayConsumptionForecast_07 504 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 special_todayConsumptionForecast_08 561 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 special_todayConsumptionForecast_09 768 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 special_todayConsumptionForecast_10 783 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 special_todayConsumptionForecast_11 692 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 special_todayConsumptionForecast_12 791 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 special_todayConsumptionForecast_13 910 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 special_todayConsumptionForecast_14 1022 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 special_todayConsumptionForecast_15 965 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 special_todayConsumptionForecast_16 812 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 special_todayConsumptionForecast_17 884 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 special_todayConsumptionForecast_18 928 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_19 874 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_20 763 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_21 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_22 765 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_23 643 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_24 601 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIcalls 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIrequests 4532&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridConsumption 5500.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridFeedIn 178.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayMaxAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIrequests n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 state updated&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So sollte es dann als Ergebnis aussehen:&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13.png|zentriert|mini|Ergebnis nach kompletter Einrichtung]]&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13 Teil II.png|alternativtext=Unterer Teil der Anzeige|zentriert|mini]]&lt;br /&gt;
&lt;br /&gt;
== Praxisbeispiele und Lösungsansätze für Steuerungen ==&lt;br /&gt;
=== Fallstudie: Trockner darf pausiert werden, wenn nicht genug PV-Überschuss vorhanden ist, soll aber nach spätestens X Stunden fertig sein ===&lt;br /&gt;
Für diese Aufgabenstellung sind mehrere Schlüssel essentiell wichtig, &#039;&#039;&#039;power&#039;&#039;&#039;, &#039;&#039;&#039;mintime&#039;&#039;&#039;, &#039;&#039;&#039;mode&#039;&#039;&#039; und &#039;&#039;&#039;interruptable&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Die Bedingung, dass der Trockner nach spätestens X Stunden fertig sein soll, steht in einem Widerspruch zu der Möglichkeit den Trockner bei zu wenig PV-Überschuss unterbrechen zu können. Im Extremfall könnte nach dem Start die gesamte Planungszeit ungenügender Überschuss vorliegen und der Trockner nicht arbeiten. Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; (in Minuten) wird nun wie folgt angesetzt:&lt;br /&gt;
&lt;br /&gt;
 mintime = 2,5 x &amp;lt;gewöhnliche Betriebszeit für einen Trockengang (mneed, z.B. 120)&amp;gt; = 300 Minuten&lt;br /&gt;
&lt;br /&gt;
Das bedeutet, der Trockner wird nach 300 Minuten Laufzeit abgeschaltet werden bzw. vom Netz getrennt. Der Trockenvorgang wird natürlich bereits nach 120 Minuten beendet sein, sofern nach Start keine Unterbrechnung des Vorganges erfolgte. Wurde der Vorgang unterbrochen, soll der Trockner innerhalb &lt;br /&gt;
&lt;br /&gt;
 X+120 bis X+300 &lt;br /&gt;
&lt;br /&gt;
fertig sein. &lt;br /&gt;
&lt;br /&gt;
Demnach ist die ausgeführte Laufzeit des Trockners permanent zu überwachen, zu summieren (rtsum) und die notwendige Restzeit (mneed - rtsum) mit der noch verbleibenden Restzeit (mrest) bis zur geplanten Abschaltung des Consumers zu vergleichen. Ist der Consumer gestartet, wird die Laufzeit in der pvHistory für jede Stunde des Tages im Schlüssel &#039;&#039;minutescsmXX&#039;&#039; (XX = Consumernummer) aufgezeichnet und kann darüber ausgewertet werden. Somit ist:&lt;br /&gt;
&lt;br /&gt;
 msum = for (01 .. 24) {Summe von minutescsmXX} des aktuellen Tages&lt;br /&gt;
&lt;br /&gt;
Solange die Bedingung &lt;br /&gt;
&lt;br /&gt;
 mrest &amp;gt;= (mneed - msum)&lt;br /&gt;
&lt;br /&gt;
zutrifft, darf der Trockner unterbrochen werden, anderenfalls darf er nicht mehr unterbrochen werden da die Restzeit evtl. nicht ausreichen könnte um den Vorgang abzuschließen. Für die Planung des Trockners wird der Consumer wie gewöhnlich nach dem Bedarf im Modul registriert. Für die Steuerung der Unterbrechbarkeit wird noch ein Code erstellt, welcher im Trockner-Device &#039;&#039;Dryerdev&#039;&#039; das Reading &#039;&#039;SF_Int&#039;&#039; zur Unterbrechnungssteuerung verwaltet. Dieses Reading wird dem Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; übergeben. Für das Beispiel wird der Consumer &#039;07&#039; verwendet, es kann natürlich jede andere freie Nummer verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Dryerdev:Trockner&lt;br /&gt;
                        icon=scene_cloves_dryer type=dryer power=2000 mode=must mintime=300 &lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic asynchron=1&lt;br /&gt;
                        interruptable=Dryerdev:SF_Int:1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Kombination &#039;&#039;&#039;auto=automatic&#039;&#039;&#039; eröffnet die Möglickeit, in der Consumer-Legende den Trockner-Start zusätzlich manuell freizugeben oder zu verbieten. &lt;br /&gt;
&lt;br /&gt;
Im nachfolgenden Code werden modulinterne Subroutinen verwendet. Diese sind inklusive dem Paket &#039;&#039;FHEM::SolarForecast::&#039;&#039; anzugeben. Die erstellte Subroutine wird in die 99_mySolarForecastUtils.pm eingefügt. Die Datei 99_mySolarForecastUtils.pm wird vorher von 99_myUtils.pm kopiert und enthält für die Übersichtlichkeit nur Routinen für SolarForecast.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Trocknersteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub dryControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # gewöhlich benötigte Zeit für &lt;br /&gt;
                                                                                  # einen Trockengang, z.B. 120 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $dryer     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename des Trockners&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Trockner-Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit des Trockners&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      my $dhash = $defs{$dryer};&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 1, 0);                        # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 0, 0);                        # keine Interrupt-Freigabe&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die gewöhnliche Laufzeit des Trockners für einen Trockenvorgang (120 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::dryControl ($name, &#039;07&#039;, 120);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Fallstudie: Umwälzpumpe Pool soll X Stunden am Tag laufen. Ist kein PV-Überschuß vorhanden, müssen die X Stunden/Tag trotzdem erreicht werden ===&lt;br /&gt;
&lt;br /&gt;
Die Vorgehensweise ähnelt der Fallstudie zuvor. Verändernd kommt hinzu, dass der Planungszeitraum bewusst sehr lang angesetzt wird mit der Option, den Zyklus des Consumers vorfristig zu beenden sobald die Laufzeit von X Stunden am Tag erreicht ist. &lt;br /&gt;
Im folgenden Beispiel soll die Pumpe 5 Stunden am Tag (300 Minuten) laufen und dabei mögliche PV-Überschüsse ausnutzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Pump:Zirkulationspumpe&lt;br /&gt;
                        icon=sani_pump type=other power=50 mode=must mintime=780 notafter=09&lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic &lt;br /&gt;
                        interruptable=1 swoffcond=Pump:SF_Abort:1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit dieser Registrierung wird die Pumpe ca. 09 Uhr täglich starten. Wenn kein bzw. ungenügender PV-Überschuß vorhanden ist, erfolgt eine Unterbrechung nach dem Start. Ist genügender PV-Überschuß (wieder) vorhanden, erfolgt keine Unterbrechnung (mehr). Zusätzlich wird über den Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; eine vorfristige Beendigung veranlasst, sobald die gewünschte Tageslaufzeit erreicht ist.&lt;br /&gt;
&lt;br /&gt;
Zur Verwaltung des Schlüssels &#039;&#039;interruptable&#039;&#039; und des Readings &#039;&#039;SF_Abort&#039;&#039; verwenden wir eine leicht veränderte Subroutine aus dem vorhergehenden Fallbeispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Pumpensteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub pumpControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # Soll-Pumpenzeit, z.B. 300 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $pump      = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename der Pumpe&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;);&lt;br /&gt;
  my $intbl     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;interruptable&#039;, 1); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
  my $dhash     = $defs{$pump};&lt;br /&gt;
&lt;br /&gt;
  readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 0, 0);                                # default keine Zyklusbeendigung&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Pumpen Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit der Pumpe&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
     &lt;br /&gt;
      if ($msum &amp;gt;= $mneed) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 1, 0);                       # vorfristige Zyklusbeendigung&lt;br /&gt;
          return;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=1&amp;quot;) if(!$intbl);  # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=0&amp;quot;) if($intbl);   # keine Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Befehl &#039;&#039;attrKeyVal&#039;&#039; setzt den Schlüssel &#039;&#039;interruptable&#039;&#039; im Attribut &#039;&#039;consumer07&#039;&#039; dynamisch. Diese Strukturänderung wird automatisch im System gespeichert, sofern &#039;&#039;global-&amp;gt;autosave=1&#039;&#039; gesetzt ist. Diese Einstellung ist der FHEM default.  &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die Mindestlaufzeit der Umwälzpumpe (300 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::pumpControl ($name, &#039;07&#039;, 300);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamische Ladestromsteuerung eines Victron MultiPlus II Chargers mit Pylontech Batterie ===&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;
&lt;br /&gt;
 set &amp;lt;Device&amp;gt; MaxChargeCurrent &amp;lt;Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
eingestellt bzw. variiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Modul bietet dem Nutzer die Möglichkeit in dem Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltene Code wird am Ende jedes Zyklus (siehe Attribut &#039;&#039;plantControl-&amp;gt;cycleInterval&#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;
&lt;br /&gt;
&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 $mppt1   = &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common&#039;;              # SmartLoader Device&lt;br /&gt;
  my $maxcspc = 105;                        # max. Ladesollstrom (A) nominal&lt;br /&gt;
  my $spcorr  = 0.9;                        # Korrekturfaktor Überschuss 90%&lt;br /&gt;
  my $sch     = 0.25;                       # Verkürzungsfaktor Zeit bis Vollladung vor Sunset             &lt;br /&gt;
  &lt;br /&gt;
  my $cclvl0  = 15;                         # Ladestrom Level 0 max. 5  A (240 W) pro WR  (720  W)&lt;br /&gt;
  my $cclvl1  = 27;                         # Ladestrom Level 1 max. 9  A (432 W) pro WR  (1296 W)&lt;br /&gt;
  my $cclvl2  = 54;                         # Ladestrom Level 2 max. 18 A (864 W) pro WR  (2592 W)&lt;br /&gt;
  my $cclvl3  = 81;                         # Ladestrom Level 3 max. 27 A (1296 W) pro WR (3888 W)&lt;br /&gt;
  ###############&lt;br /&gt;
  &lt;br /&gt;
  my $cofc   = ReadingsNum ($name,  &#039;special_todayConForecastTillSunset&#039;, 0);&lt;br /&gt;
  my $pvfc   = ReadingsNum ($name,  &#039;RestOfDayPVforecast&#039;, 0);&lt;br /&gt;
  my $cpv    = ReadingsNum ($name,  &#039;Current_PV&#039;,          0);&lt;br /&gt;
  my $mppt1c = ReadingsNum ($mppt1, &#039;DC_0_Current_value&#039;,  0);             # Load I MPPT1 (max. 44 A)&lt;br /&gt;
  my $ssts   = CurrentVal  ($hash,  &#039;sunsetTodayTs&#039;,        0);&lt;br /&gt;
  my $srts   = CurrentVal  ($hash,  &#039;sunriseTodayTs&#039;,       0);&lt;br /&gt;
  my $sdiff  = ($ssts - $srts) / 3600;                                     # Sonnengang heute in h &lt;br /&gt;
  &lt;br /&gt;
  my $solh   = ReadingsNum ($name, &#039;special_SunHours_Remain&#039;, 0);          # h bis SunSet&lt;br /&gt;
  $solh      = $solh - ($sdiff * $sch);                                    # h bis SunSet - X&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;              # Ah Bat bis SOC&lt;br /&gt;
  $ahrem     = sprintf &amp;quot;%.0f&amp;quot;, $ahrem;&lt;br /&gt;
  &lt;br /&gt;
  my $fcdiff = ($pvfc - $cofc) * $spcorr;     # Korrektur d. noch prognostizierten Überschussenergie &lt;br /&gt;
  $fcdiff    = $fcdiff &amp;lt; 0 ? 0 : $fcdiff;     # Wh&lt;br /&gt;
  &lt;br /&gt;
  my $loadcur = $maxcspc;&lt;br /&gt;
  &lt;br /&gt;
  if ($cpv &amp;amp;&amp;amp; $solh &amp;amp;&amp;amp; $ahrem &amp;amp;&amp;amp; $fcdiff &amp;gt; $ahrem) {  # Ladeanforderung und Überschuss übersteigt &lt;br /&gt;
                                                      # Lademenge&lt;br /&gt;
      my $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($ahrem / $solh);    # A = Ah / h -&amp;gt; A Soll Schätzung&lt;br /&gt;
&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Battery charging process should be completed }.&lt;br /&gt;
                      qq{in &amp;gt;$solh&amp;lt; hours});&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; raw Target charging current: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($cspc - $mppt1c);      # SmartLoader IST berücksichtigen&lt;br /&gt;
	  &lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Charge Current minus MPPT load Current &amp;gt;$mppt1c&amp;lt;: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $loadcur = $cspc &amp;lt;= 0       ? 0       :     # nur MPPT Ladung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl0 ? $cclvl0 :     # Übergangsbereich&lt;br /&gt;
                 $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;
	  Log3 ($name, 3, qq{$name - userFn -&amp;gt; MaxChargeCurrent calculated: $loadcur});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent&#039;,       $loadcur.&#039; A&#039;,          1);&lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_HoursUntilChargeFinish&#039;, sprintf (&amp;quot;%.2f&amp;quot;,$solh), 1);&lt;br /&gt;
  CommandSet           (undef, &amp;quot;$vebus MaxChargeCurrent $loadcur&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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. 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;special_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;special_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;Verkürzungsfaktor Zeit bis Vollladung vor Sunset&#039;&#039;) reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche mindest Ladestromstärke ermittelt.&lt;br /&gt;
&lt;br /&gt;
&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 auch während der MQTT Intergration 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;
=== Poolheizung in Abhängigkeit von vorhandenem Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren) ===&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;consumer01&#039;&#039; wird beispielhaft wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr Forecast consumer01 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;&lt;br /&gt;
&lt;br /&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. &lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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, einen 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 Überschuss 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;. &lt;br /&gt;
&lt;br /&gt;
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;
=== PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) ===&lt;br /&gt;
[[Datei:Screenshot 2025-08-04 104835.png|mini|Darstellung der PV-Vorhersage in evcc auf Basis der SolarForecast-Daten]]&lt;br /&gt;
[https://evcc.io evcc] ist ein Energie-Management-System, mit dem u.a. Überschussladen von Elektroautos möglich ist. Hier ist beschreiben, wie die PV-Vorhersage von SolarForecast per API von evcc abgerufen wird.&lt;br /&gt;
&lt;br /&gt;
Lege im SolarForecast-Device ein User-Reading mit dem Namen forecast_json an. Es wandelt die Forecast-Werte in JSON und ins UTC-Zeitformat um, so dass evcc die Daten verwenden kann:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
forecast_json {&lt;br /&gt;
&lt;br /&gt;
    use strict;&lt;br /&gt;
    use warnings;&lt;br /&gt;
    use JSON;&lt;br /&gt;
    use DateTime;&lt;br /&gt;
    use DateTime::Format::Strptime;&lt;br /&gt;
&lt;br /&gt;
    my $hour = 0;&lt;br /&gt;
    my @output;&lt;br /&gt;
&lt;br /&gt;
    # Parser für Datum mit CET/CEST&lt;br /&gt;
    my $parser = DateTime::Format::Strptime-&amp;gt;new(&lt;br /&gt;
        pattern   =&amp;gt; &#039;%Y-%m-%d %H:%M:%S&#039;,&lt;br /&gt;
        time_zone =&amp;gt; &#039;Europe/Berlin&#039;,&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    # Alle NextHour-Daten durchsuchen&lt;br /&gt;
    while ($hour &amp;lt; 100) {&lt;br /&gt;
        my $hour_str = sprintf(&#039;NextHour%02d&#039;, $hour);&lt;br /&gt;
        my $start_str = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;starttime&#039;, &#039;na&#039;); &lt;br /&gt;
        my $pvfc = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;pvfc&#039;, &#039;na&#039;);&lt;br /&gt;
&lt;br /&gt;
        # Schleife beenden, wenn keine Werte mehr vorhanden sind&lt;br /&gt;
        last if $start_str eq &#039;na&#039; or $pvfc eq &#039;na&#039;;&lt;br /&gt;
&lt;br /&gt;
        # parse und konvertiere Zeit&lt;br /&gt;
        my $start_dt = $parser-&amp;gt;parse_datetime($start_str);&lt;br /&gt;
        my $end_dt   = $start_dt-&amp;gt;clone-&amp;gt;add(hours =&amp;gt; 1);&lt;br /&gt;
&lt;br /&gt;
        # nach UTC konvertieren&lt;br /&gt;
        $start_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
        $end_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $start_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            end   =&amp;gt; $end_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            value =&amp;gt; 0 + $pvfc,&lt;br /&gt;
        };&lt;br /&gt;
        &lt;br /&gt;
        $hour++;&lt;br /&gt;
    }  &lt;br /&gt;
&lt;br /&gt;
    # Ausgabe als JSON&lt;br /&gt;
    my $json = JSON-&amp;gt;new-&amp;gt;utf8-&amp;gt;pretty-&amp;gt;encode(\@output);&lt;br /&gt;
    return $json;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Kommunikation von FHEM zu evcc läuft über den integrierten FHEM-Webserver, der die JSON-Daten aus dem Reading forecast_json veröffentlicht. Dazu wird in FHEM eine separate Webinstanz auf einem neuen Port erstellt, die ohne [[CsrfToken-HowTo|CSFR-Token]] (Achtung, Auswirkungen auf die Sicherheit beachten!) und nur von localhost aufrufbar ist (Voraussetzung: evcc läuft auf derselben Maschine wie FHEM):&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
defmod WEBapi FHEMWEB 8089&lt;br /&gt;
attr WEBapi csrfToken none&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;In der [https://docs.evcc.io/docs/tariffs#pv-vorhersage evcc-Konfig unter tariffs] steht die Quelle für die Solar-Vorhersage. Der FHEM-Befehl {ReadingsVal(&#039;solarforecast_dev&#039;,&#039;forecast_json&#039;,&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;)} wird encoded und in die uri eingetragen. Trage statt solarforecast_dev den passenden Namen deines SolarForecast-Device ein. evcc holt die Daten dann regelmäßig ab.&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
solar:&lt;br /&gt;
  type: custom&lt;br /&gt;
  interval: 20m    &lt;br /&gt;
  forecast:&lt;br /&gt;
    source: http&lt;br /&gt;
    uri: http://localhost:8089/fhem?cmd=%7BReadingsVal%28%27solarforecast_dev%27%2C%27forecast_json%27%2C%27%27%29%7D&amp;amp;XHR=1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Zur Verbesserung der Sicherheit kann das neue WEBapi Device auch ein [[CsrfToken-HowTo#csrfToken festlegen|festes CSFR-Token]] verwenden. Dieses Token muss dann in der evcc-Konfiguration an die uri mittels &amp;amp;fwcsrf=&amp;lt;festes token&amp;gt; angehängt werden.&lt;br /&gt;
&lt;br /&gt;
== weiterführende Links ==&lt;br /&gt;
* Forenthema &amp;quot;{{Link2Forum|Topic=137058|LinkText=76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support}}&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;
* Photovoltaik Ingenieurbüro Junge: https://www.ing-büro-junge.de/html/photovoltaik.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung&amp;diff=40303</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=40303"/>
		<updated>2025-08-04T11:33:03Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Hinweis|Die vorliegende Wiki-Seite befindet sich im Aufbau.}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Solarprognose und Verbrauchersteuerung&lt;br /&gt;
|ModType=d&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 Prognosewerte können die SolCast API, OpenMeteo API, Forecast.Solar API, Victron VRM Portal API oder alternativ DWD Stahlungswerte-Stationen verwendet werden&lt;br /&gt;
&lt;br /&gt;
::* optionale KI Unterstützung der PV-Prognose bei Verwendung von geeigneten Solar-API&#039;s&lt;br /&gt;
&lt;br /&gt;
::* es wird sowohl die Erzeugungsprognose als auch eine Verbrauchsprognose sowie SoC Prognose (bei Batterie-Integration) erstellt&lt;br /&gt;
&lt;br /&gt;
::* Wetterdaten werden über DWD Wetter-Stationen oder verschiedene API integriert. Es können verschiedene API zur Gewinnung von Solar- und Wetterdaten kombiniert werden. &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 FHEM-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 Integration von bis zu 4 Inverter und Smartloader (DC-DC Batterieladegeräte) ist möglich&lt;br /&gt;
&lt;br /&gt;
::* eine Integration von bis zu 3 nicht PV-Energieerzeugern wie BHKW, Windrädern oder Notstromaggregaten ist möglich&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;
::* Einbindung von bis zu drei Batteriespeichersystemen&lt;br /&gt;
&lt;br /&gt;
::* Bereitstellung von Leitwerten zur optimalen Einstellung/Steuerung von Batteriespeichersystemen&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 Benutzererlebnis 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;
Das Wiki gibt allgemeingültige und teilweise sehr spezifische bzw. tiefgehende Informationen und Handlungsempfehlungen zum SolarForecast Modul. Die dargestellten Informationen beziehen sich auf den zum Zeitpunkt der Wiki-Erstellung vorhandenen Entwicklungsstand des Moduls. Durch die stetige Weiterentwicklung können sich Abweichungen zum beschriebenen Inhalt ergeben oder zur Obsoleszenz dieser Inhalte führen. &lt;br /&gt;
&lt;br /&gt;
Vergleiche deshalb die Informationen immer mit der aktuellen Befehls-Referenz zum Modul!&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Ein SolarForecast Device wird mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 define &amp;lt;Name&amp;gt; SolarForecast &lt;br /&gt;
&lt;br /&gt;
angelegt. Nach der Definition wird der User durch einen Dialog geführt, der einige unerlässliche Einstellungen abfragt und in den entsprechenden Attributen und Readings persistiert. Alle Attribute und Readings die eine Einstellung der Anlage bewirken, sind mit dem Präfix &amp;quot;setup&amp;quot; versehen. &lt;br /&gt;
&lt;br /&gt;
Die Verwendung von setup-Readings gestattet es die Anlagenparameter dynamisch im Betrieb zu verändern. So kann mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringAzimuth   bzw.&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringDeclination &lt;br /&gt;
&lt;br /&gt;
die Ausrichtung und der Neigungswinkel der PV-Module ständig angepasst werden, was zum Beispiel bei einer dem Sonnenstand nachgeführten Anlage von Bedeutung ist.&lt;br /&gt;
&lt;br /&gt;
Die abgefragten Einstellungen während des Dialoges sind ausführlich in den entsprechenden Attributen bzw. Set-Kommandos erläutert. Die benötigten Informationen sind anhängig von der gewählten Prognose-API und können im Umfang variieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 213257.png|right|thumb|400px|Anlagenprüfung über Drucktaste in der Kopfgrafik]]&lt;br /&gt;
&lt;br /&gt;
Sobald alle verlangten Einstellungen vorgenommen sind, sollte eine Anlagenprüfung mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; plantConfiguration check&lt;br /&gt;
&lt;br /&gt;
oder über die angebotene Drucktaste in der Grafik durchgeführt werden. Es wird eine Plausibilitätsprüfung vorgenommen und das Ergebnis sowie eventuelle Hinweise bzw. Fehler ausgegeben.&lt;br /&gt;
Die Prüfung kann beliebig wiederholt werden und sollte sich bei jeder Einstellungsänderung der Anlage durchgeführt werden. Dadurch wird die Wahrscheinlichkeit von fehlerhaften Einstellungen minimiert.&lt;br /&gt;
&lt;br /&gt;
Neben den grundlegenden Einstellungen können im Device weitere sekundäre Anlagenkomponenten wie Batteriesystem(e) (Attribut setupBatteryDev1 - setupBatteryDev3), weitere Wetter-Devices (Attribut setupWeatherDev1 - setupWeatherDev3) oder sonstige Erzeuger (z.B. BHKW, Winderzeugung, Notstromaggregat) integriert werden (Attribut setupOtherProducer01 - setupOtherProducer03).&lt;br /&gt;
&lt;br /&gt;
Die verlangten Parameter der Anlage werden in der Online-Hilfe umfassend beschrieben und deren Funktion erschließt sich zum größten Teil selbst. Dennoch soll nachfolgend auf einige Punkte im Zusammenhang der Einrichtung eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Hinweise zur Struktur der Attribute ===&lt;br /&gt;
&lt;br /&gt;
Durch die umfangreichen Funktionen des Moduls würde bei Nutzung der im FHEM herkömmlich vorhandenen Attributstruktur die Anzahl der benötigten Attribute extrem stark steigen und nicht sinnvoll genutzt werden können. Deshalb gibt es neben den &#039;&#039;gewöhnlichen&#039;&#039; Attributen mit einfachen Werteauswahlmöglichkeiten oder Eingaben (z.B. ctrlDebug, ctrlSpecialReadings) sogenannte &#039;&#039;zusammengesetzte&#039;&#039; Attribute, deren Inhalt durch &#039;&#039;&#039;Schlüssel=Wert Paare&#039;&#039;&#039; gebildet wird und dadurch deutlich mehr Funktionen und Informationen transportieren als ein gewöhnliches Attribut.&lt;br /&gt;
&lt;br /&gt;
Für zusammengesetzte Attribute besteht die zusätzliche Möglichkeit, gewünschte Änderungen der Schlüssel=Wert Paare selektiv vornehmen zu können, ohne das gesamte Attribut aufrufen und ändern zu müssen. Die Vorgang, der vor allem für programmtechnische Manipulationen gedacht ist, kann durch eine Set-Funktion ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; attrKeyVal &amp;lt;Attribut&amp;gt; [&amp;lt;Gerät&amp;gt;] &amp;lt;Schlüssel=Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiele für zusammengesetzte Attribute sind:&lt;br /&gt;
&lt;br /&gt;
* aiControl&lt;br /&gt;
* plantControl&lt;br /&gt;
* setup* Attribute&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktionen der Attribute werden durch einen Präfix geclustert und so inhaltlich, aber vor allem auch in der Attribute Drop-Down Liste, strukturiert dargestellt.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der &#039;&#039;&#039;Präfixe&#039;&#039;&#039; sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ai&#039;&#039;&#039; - Steuerungsfunktionen für KI (z.B. aiControl)&lt;br /&gt;
* &#039;&#039;&#039;consumer&#039;&#039;&#039; - Registrierung und Einstellungen für Verbraucher (z.B. consumer02, consumerControl)&lt;br /&gt;
* &#039;&#039;&#039;ctrl&#039;&#039;&#039; - Steuerungsfunktion allgemeiner Art (z.B. ctrlDebug, ctrlSpecialReadings, ctrlUserExitFn)&lt;br /&gt;
* &#039;&#039;&#039;flowGraphic&#039;&#039;&#039; - Einstellungen für die Energieflußgrafik (z.B. flowGraphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphic&#039;&#039;&#039; - Einstellung für die Grafik allgemein (z.B. graphicSelect, graphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphicBeam&#039;&#039;&#039; -  Einstellungen bestimmte Balkeneigenschaften in der Balkengrafik (z.B. graphicBeamHeightLevel1)&lt;br /&gt;
* &#039;&#039;&#039;plant&#039;&#039;&#039; - übergreifende Einstellungen betreffend der gesamten PV-Anlage bzw. des SolarForecast-Devices (z.B. plantControl)&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039; - Registrierung von Geräten in der Gesamtanlage und Einstellung deren Eigenschaften (Inverter, Zähler, Batterien usw.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Einrichtung der Wechselrichter mit setupInverterDevXX ===&lt;br /&gt;
&lt;br /&gt;
Mit den Attributen setupInverterDev01 bis setupInverterDevXX werden die vorhandenen Wechselrichter der Anlage registriert.&lt;br /&gt;
Das Modul unterscheidet verschiedene Wechselrichter-Typen, die sich durch ihre Arbeitsweise innerhalb der Anlage unterscheiden. Die Schlüssel=Wert Paare in den Attributen können mehrzeilig organisiert werden. Das erleichtert die Übersicht wenn viele dieser Parameter eingegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;PV-Wechselrichter: Es ist der Standard Wechselrichter in einer PV-Anlage. An ihn sind die Solarzellen bzw. Strings angeschlossen. Die zugeordneten Strings können mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ohne diese Angabe werden diesem Gerät alle definierten Strings (siehe Attribut &#039;&#039;setupInverterStrings&#039;&#039;) zugeordnet. Der Wechselrichter liefert seine Energie in das Hausnetz. Alternativ kann mit der Angabe &#039;&#039;&#039;feed=grid&#039;&#039;&#039; die Funktion des Wechselrichters geändert werden. Diese Angabe sagt aus, dass dieser Wechselrichter ausschließlich in das öffentliche Netz einspeist.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel-Setup eines PV-Wechselrichters (SMA STP):&lt;br /&gt;
&lt;br /&gt;
 STP_5000 pvIn=string_1_pdc:kW pvOut=total_pac:kW etotal=etotal:kWh capacity=5000 strings=Süddach asynchron=1 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Solar-Ladegeräte: Solar-Ladegeräte sind DC-DC Wandler und liefern die Energie der angeschlossenen Solarzellen nicht in das Wechselstromnetz, sondern laden direkt eine Batterie bzw. versorgen einen Batteriewechselrichter auf der Gleichstromseite. Die Funktion als Solar-Ladegerät wird mit &#039;&#039;&#039;feed=bat&#039;&#039;&#039; aktiviert, die relevanten Strings können ebenfalls mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ein Beispiel eines Solar-Ladegerätes ist ein Victron SmartSolar MPPT. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel für das Setup eines Solar-Ladegeräts (SmartSolar Charger MPPT):&lt;br /&gt;
&lt;br /&gt;
 MQTT2_cerboGX_c0619ab34e08_solarcharger_Common pv=Yield_Power_value:W etotal=Yield_System_value:kWh capacity=2080 strings=Schleppdach feed=bat synchron=0 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Batterie-Wechselrichter: Dieses Gerät hat keine angeschlossenen Solarzellen und arbeitet als DC-AC bzw. AC-DC Wandler zwischen einer Batterie (=Gleichstromquelle) und dem Wechselstrom-Hausnetz. Die Funktion als Batterie-Wechselrichter wird mit der Angabe &#039;&#039;&#039;strings=none&#039;&#039;&#039; aktiviert. Die Schlüssel &#039;&#039;etotal&#039;&#039; und &#039;&#039;pv&#039;&#039; können bei einem Batterie-Wechselrichter ohne zugeordnete Solarzellen nicht gesetzt werden. Ein Beispiel eines Batterie-Wechselrichter ist der Victron MultiPlus II.&lt;br /&gt;
&lt;br /&gt;
Ein Setup-Beispiel für einen Batterie-Wechselrichter (Victron MultiPlus II):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dc2ac=DC_IN:W&lt;br /&gt;
ac2dc=DC_OUT:W&lt;br /&gt;
capacity=7200&lt;br /&gt;
strings=none&lt;br /&gt;
icon=inverter@darkorange:inverter@grey&lt;br /&gt;
asynchron=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Eigenschaften des Wechselrichters werden durch eine Reihe von &amp;lt;Schlüssel=Wert&amp;gt; Paaren festgelegt. Auf einige dieser Paramter soll hier eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Ausgewählte Schlüssel=Wert Paare ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;pvIn=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvIn&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell zugeführte PV-Leistung bereitstellt. Der Schlüssel ist optional und dient in erster Linie dazu den entsprechenden Input-Wert in der Flußgrafik anzuzeigen sofern man das Attribut flowGraphicControl-&amp;gt;showGenerators=1 setzt. Dadurch ist auch der Eigenverbrauch des Inverters bzw. dessen Wandlungsverlust visuell abschätzbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pvOut=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvOut&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell erzeugte Leistung als positiven Wert liefert. Für einen PV-Wechselrichter (DC-&amp;gt;AC) oder Solar-Ladegerät (DC-&amp;gt;DC) ist es die erzeugte PV-Leistung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ac2dc=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter vom Hausnetz in Richtung Batterie (AC-&amp;gt;DC) wandelt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;dc2ac=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter aus einer Gleichstromquelle, d.h. einer Batterie oder einem Solar-Ladegerät, in Richtung des Hausnetzes (AC) wandelt . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;capacity=&amp;lt;max. WR-Leistung&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In dem Schlüssel &#039;&#039;capacity&#039;&#039; wird die maximal mögliche Leistung in Watt (ohne Einheit) angegeben, die der Wechselrichter lt. seinem Datenblatt in der Lage ist zu leisten. &lt;br /&gt;
&lt;br /&gt;
Die Angabe &#039;&#039;capacity&#039;&#039; hat in erster Linie die Aufgabe, die max. mögliche PV-Leistung für die Prognose zu begrenzen. Oft sind die installierten Peak-Leistungen der PV-Module höher als die angeschlossene Wechselrichter-Leistung bzw. kommt es vor, dass die KI / (korrigierte) API-Prognose über der maximal möglichen Wechselrichter-Leistung liegt. In diesen Fällen wird die Prognose auf die angegebene &#039;&#039;capacity&#039;&#039; begrenzt.&lt;br /&gt;
&lt;br /&gt;
Der Wert in diesem Schlüssel kann, wie andere Schlüssel auch, dynamisch zur Laufzeit mit dem Set-Befehl &amp;quot;[[#Hinweise zur Struktur der Attribute|set &amp;lt;Name&amp;gt; attrKeyVal ...]]&amp;quot; geändert werden. Ein Beispiel zur Anwendung ergibt sich aus folgendem Szenario.&lt;br /&gt;
&lt;br /&gt;
Gegeben sei eine Anlage die aus Solarzellen (1300 W Peak) mit einem Solar-Ladegerät mit max. 1800 W Leistung, einer Batterie und einem Batterie-Wechselrichter besteht. Die Anlage versorgt nur das Hausnetz. Eine Netzeinspeisung ist nicht vorgesehen oder nicht erlaubt.  &lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, es ist ein Tag voller Sonnenschein prognostiziert und die Batterie ist zunächst entladen. Der Haushalt verbraucht 300 W. Dann würden die PV-Module Module ihre volle Leistung von 1300 W Peak leisten können, die sich auch in der Balken-Vorhersage niederschlägt. Die Leistung wird nicht begrenzt, weil:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* sie niedriger ist als die nominale und angegebene Wechselrichter Kapazität von &#039;&#039;capacity=1800&#039;&#039;&lt;br /&gt;
* die erzeugte Energie anteilig für die Verorgung des Hauses und die Aufladung der Batterie verwendet wird&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders verhält es sich wenn nach einer gewissen Zeit die Batterie voll ist und weiterhin volle PV Leistung zur Verfügung steht. In diesem Fall würde der Haushalt seine benötigte Leistung von 300 W abnehmen, aber das Solar-Ladegerät kann keine weitere Leistung mehr abgeben, da die Batterie bereits voll geladen ist, d.h. die Anlagensteuerung würde die PV-Anlage abregeln. In diesem Fall, wenn es einen längeren Zeitraum betrifft, muß auch die Prognose PV-Energie auf 300 Wh (bzw. den durchschnittlichen Energieverbrauch des Hauses pro Stunde) begrenzt werden, damit die PV-Prognose nach unten angepasst wird und so eine realitätsnahere Prognose ermöglicht wird. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;icon=&amp;lt;aktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;][:&amp;lt;inaktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Jeder Wechselrichter wird im Standard durch ein Icon getrennt nach Tag und Nacht, d.h. je nach Aktiv-Status und Inaktiv-Status, symbolisiert.&lt;br /&gt;
&lt;br /&gt;
;Tag bzw. Aktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Sonnensymbol im Standard verwendet. Batterie-Wechselrichter verwenden ein gefärbtes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
;Nacht bzw. Inaktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Symbol der aktuellen Mondphasen im Standard verwendet. Batterie-Wechselrichter verwenden ein ausgegrautes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie angegeben, kann man für Tag und Nacht jeweils ein Wunsch-Icon, wenn gewünscht mit einer alternativen Färbung, auswählen.&lt;br /&gt;
&lt;br /&gt;
 icon=inverter@darkorange:inverter@gray&lt;br /&gt;
&lt;br /&gt;
Soll nur das Icon für die Nacht bzw. Inaktivät geändert werden, kann dies in dieser Form angegeben werden:&lt;br /&gt;
&lt;br /&gt;
 icon=:inverter@gray  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(beachte den führenden &#039;:&#039;)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Der integrierte SolarForecast Grafikbereich ==&lt;br /&gt;
Das SolarForecast Modul beinhaltet eine Grafikdarstellung die sich in mehrere Bereiche gliedert. Diese Bereiche können über Attribute ein- bzw. ausgeblendet sowie die Inhalte festgelegt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 223545.png|right|thumb|400px|Bereiche der integrierten Grafik]]&lt;br /&gt;
&lt;br /&gt;
Der nebenstehende Screenshot gibt die Gliederung der Grafikbereiche wieder:&lt;br /&gt;
&lt;br /&gt;
 1 - der Kopfbereich (Graphic Header)&lt;br /&gt;
 2 - durch den Nutzer selbst definierbarer Inhalt (Graphic Header Own Specification) als Teil des Kopfbereiches&lt;br /&gt;
 3 - Bereich Verbraucherdarstellung (Consumer Legend)&lt;br /&gt;
 4 - Bereich Balkengrafik (Beam Graphic)&lt;br /&gt;
 5 - Energieflußgrafik (Flow Graphic)&lt;br /&gt;
&lt;br /&gt;
Jeder dieser Bereiche hat spezifische Steuerungsattribute zur Anpassung des Verhaltens und ggf. des Inhalts.&lt;br /&gt;
&lt;br /&gt;
=== 1 - Der Grafik Kopfbereich ===&lt;br /&gt;
Im Kopfbereich befinden sich fest verankerte Informationen zur verwendeten Vorhersage-API sowie deren Status, Informationen zum Sonnenaufgang und Sonnenuntergang, dem aktuellen Gesamtstatus des SolarForecast Devices, Abweichungskennzahlen der PV Vorhersage sowie weitere Kennzeichen zur Verfügung.&lt;br /&gt;
Über zwei Drucktasten kann eine Anlagenprüfung durchgeführt und in den Spportthread des Moduls im FHEM Forum abgesprungen werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;graphicHeaderShow&#039;&#039;&#039; kann der gesamte Kopfbereich 1 und 2 (nutzereigener Teilbereich) ausgeblendet werden. Wird der Kopbereich ausgeblendet, ist es hilfreich mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;showLink&#039;&#039;&#039; einen Link zur Detailgrafik einzufügen da der in der Kopfgrafik integrierte Link in diesem Fall nicht mehr zur Verfügung steht. &lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;graphicHeaderDetail&#039;&#039;&#039; definiert welche Bereiche des Grafikkopfes angezeigt werden sollen. Es kann die Anzeige des Energieverbrauches, der PV-Erzeugung und der vom Nutzer selbst definierte Inhalt miteinander frei kombiniert werden.&lt;br /&gt;
&lt;br /&gt;
=== 2 - Der Bereich mit selbst definierbarem Inhalt (Graphic Header Own Specification) ===&lt;br /&gt;
In diesem Bereich kann der User beliebige Readings, Set-Kommandos und Attribute des SolarForecast Devices oder anderer Devices, die sich im gleichen FHEM-System wie das SolarForecast Device befinden, anzeigen lassen.&lt;br /&gt;
&lt;br /&gt;
Dieser Bereich ist als Tabelle mit einer beliebigen Anzahl von Zeilen organisiert. Jede Zeile beinhaltet ein Kommentarfeld und vier Nutzfelder zur Darstellung ausgewähler Werte + Label. Der Bereich bzw. der Inhalt des Bereiches wird mit dem Attribut &#039;&#039;&#039;graphicHeaderOwnspec&#039;&#039;&#039; definiert.  &lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt ein real gesetztes graphicHeaderOwnspec Attribut. Die Leerzeilen sind nicht notwendig, erhöhen aber die Lesbarkeit der Struktur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
Autarkierate:Current_AutarkyRate&lt;br /&gt;
PV&amp;amp;nbsp;übermorgen:special_dayAfterTomorrowPVforecast&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;Sunset:special_todayConForecastTillSunset&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;nächsten&amp;amp;nbsp;Sunrise:special_conForecastTillNextSunrise&lt;br /&gt;
&lt;br /&gt;
#Batterie&lt;br /&gt;
BatteryLive&amp;amp;nbsp;Status:userFn_BatLive_State&lt;br /&gt;
SoC&amp;amp;nbsp;Limit:Settings_CGwacs_BatteryLife_MinimumSocLimit_value@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SoC&amp;amp;nbsp;Ist:SOC_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
SOC&amp;amp;nbsp;Optimum:Battery_OptimumTargetSoC&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
aktuelle&amp;amp;nbsp;Ladung:userFn_Bat_EnergyState&lt;br /&gt;
Verfügbar:userFn_BatLive_UsableEnergy&lt;br /&gt;
benötigte&amp;amp;nbsp;Ladeenergie:userFn_Bat_EnergyRemain&lt;br /&gt;
Ladefreigabe:Battery_ChargeRecommended&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
akt.&amp;amp;nbsp;DC&amp;amp;nbsp;Strom:DC_Current_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
Restladezeit&amp;amp;nbsp;Ziel:userFn_Bat_HoursUntilChargeFinish&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Soll:userFn_Bat_MaxChargeCurrent_set&lt;br /&gt;
:&lt;br /&gt;
&lt;br /&gt;
#Settings&lt;br /&gt;
Batterie&amp;amp;nbsp;Lademanagement:userFn_BatteryChargeManagement&lt;br /&gt;
SoC&amp;amp;nbsp;Management:userFn_BatterySoCManagement&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Ist:MaxChargeCurrent@MQTT2_cerboGX_c0619ab34e08_vebus&lt;br /&gt;
SmartSolar&amp;lt;br&amp;gt;Einspeisung:OvervoltageFeedIn@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
MPII&amp;amp;nbsp;Limit&amp;lt;br&amp;gt;Einspeisung&amp;amp;nbsp;(W):MaxFeedInPower@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SOC&amp;amp;nbsp;Limit&amp;amp;nbsp;Soll:MinimumSocLimit@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Verbr.&amp;amp;nbsp;Neuplanung:consumerNewPlanning&lt;br /&gt;
Wetteranzeige:graphicShowWeather &lt;br /&gt;
&lt;br /&gt;
Anzeige&amp;amp;nbsp;Nachtstunden:graphicShowNight&lt;br /&gt;
hist.&amp;amp;nbsp;Stunden:graphicHistoryHour&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto&lt;br /&gt;
Victron&amp;amp;nbsp;BatteryLife&amp;lt;br&amp;gt;(1=an,10=aus):BatteryLife@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Debug:ctrlDebu&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Kommentarfeld am Beginn einer Zeile wird durch ein &#039;&#039;&#039;#&#039;&#039;&#039; gekennzeichnet. Folgt dem # ein String, wird dieser String als Kommentarangabe gewertet und in der Grafik ausgegeben. Ein leeres Kommentarfeld wird lediglich durch ein # gefolgt von einem Leerzeichen oder NL beschrieben:&lt;br /&gt;
&lt;br /&gt;
 #:&amp;lt;Text&amp;gt;  (bzw nur # für einen &#039;leeren&#039; Titel)&lt;br /&gt;
&lt;br /&gt;
Ein Netzfeld bzw. ein Datensatz wird durch die Angabe von einem Label und dem darzustellenden Wert getrennt durch &#039;:&#039; definiert:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Label&amp;gt;:&amp;lt;Reading, Attribut oder Set-Kommando&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das System erkennt selbständig, ob es sich bei der Angabe um ein Reading, Attribut oder ein Set-Kommando handelt. Sollen Readings, Set-Kommandos und Attribute anderer Devices als dem SolarForecast-Device angezeigt werden, kann dies einfach durch Zusatz von&lt;br /&gt;
&lt;br /&gt;
 ....@&amp;lt;Device-Name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
an den Parameter erreicht werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-12-05 203916.png|right|thumb|400px|Darstellung eigener Grafikbereich]]&lt;br /&gt;
Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten &amp;quot;Wh&amp;quot; bzw. &amp;quot;kWh&amp;quot; werden entsprechend der Einstellung des Attributs &#039;&#039;&#039;graphicEnergyUnit&#039;&#039;&#039; umgerechnet. Im Label sind Leerzeichen durch &amp;quot;&amp;amp;amp;nbsp;&amp;quot; einzufügen, ein Zeilenumbruch durch &amp;quot;&amp;amp;lt;br&amp;amp;gt;&amp;quot;. Ein leeres Feld in einer Zeile wird durch &amp;quot;:&amp;quot; ohne eine weitere Angabe erzeugt.&lt;br /&gt;
&lt;br /&gt;
Die nebenstehende Abbildung zeigt die reale Darstellung der oben angegebenen Struktur im Attribut graphicHeaderOwnspec.&lt;br /&gt;
&lt;br /&gt;
==== Formatierung der Inhalte im Bereich &amp;quot;Graphic Header Own Specification&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
Die angezeigten Inhalte, wie z.B. Readingwerte, des User eigenen Bereiches (Attribut graphicHeaderOwnspec) können durch Spezifikationen im Attribut &#039;&#039;&#039;graphicHeaderOwnspecValForm&#039;&#039;&#039; manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
Die Online-Hilfe zum Attribut graphicHeaderOwnspecValForm erläutert die verfügbaren Möglichkeiten und Optionen.&lt;br /&gt;
Als Beispiel hier einige mögliche Notationen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &#039;userFn_Bat_HoursUntilChargeFinish&#039;                        =&amp;gt; &amp;quot;($VALUE).&#039; Stunden&#039;&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_battery.SOC_value&#039;             =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Settings_CGwacs_BatteryLife_MinimumSocLimit_value&#039;        =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Info_MaxChargeCurrent_value&#039;                              =&amp;gt; &amp;quot;($VALUE).&#039; A&#039;&amp;quot;,&lt;br /&gt;
  &#039;DC_Current_value&#039;                                         =&amp;gt; &amp;quot;%.0f A&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common.Regulated&#039; =&amp;gt; &amp;quot;($VALUE eq &#039;1&#039; ? &#039;Ja&#039; : &#039;Nein&#039;)&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine Besonderheit besteht bei darzustellenden Werten die die Einheiten &#039;Wh&#039; bzw. &#039;kWh&#039; besitzen. Diese Werte und Einheiten werden automatisch entsprechend des gesetzten Attributes graphicEnergyUnit umgerechnet und angezeigt.&lt;br /&gt;
&lt;br /&gt;
Soll in diesen Fällen eine automatische Formatierung umgangen werden, kann eine solche Notation verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &#039;Today_PVforecast&#039; =&amp;gt; &amp;quot;(sprintf &#039;%.1f &amp;amp;amp;nbsp;kWh&#039;, ($VALUE / 1000))&amp;quot;,&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Die Angabe von &amp;amp;amp;nbsp; vor &#039;kWh&#039; verhindert die Erkennung der Einheit und so auch die automatische Umsetzung durch das Modul. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 3 - Bereich Verbraucherdarstellung (Consumer Legend) ===&lt;br /&gt;
Dieser Grafikbereich zeigt die im Modul registrierten Verbraucher sowie deren Status und weitere Informationen an. Sind die Voraussetzungen gegeben, d.h. entsprechende Schlüssel in der ConsumerXX-Attributen gesetzt, können die Verbraucher über das Paneel manuell geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Zur Anpassung der Darstellung sind verschiedene Attribute verfügbar:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;consumerControl-&amp;gt;showLegend: Definiert die Lage bzw. Darstellungsweise der Verbraucherlegende sofern Verbraucher im SolarForecast Device registriert sind.&lt;br /&gt;
;consumerControl-&amp;gt;adviceIcon: Definiert die Art der Information über die geplanten Schaltzeiten eines Verbrauchers in der Verbraucherlegende. &lt;br /&gt;
;consumerControl-&amp;gt;detailLink: Wenn gesetzt, ist der jeweilige Verbraucher klickbar um direkt zur Detailansicht des jeweiligen Geräts auf einer neuen Browserseite zu gelangen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Standard wird das Verbraucherpaneel zwischen dem Kopfbereich und der ersten Balkengrafik Ebene dargestellt. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;showLegend&#039;&#039;&#039; und Argument &#039;&#039;&#039;icon_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_bottom&#039;&#039;&#039; kann das Verbraucherpaneel an das Ende des Grafikbereiches verschoben werden.&lt;br /&gt;
Die Verwendung von &#039;&#039;&#039;text_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_top&#039;&#039;&#039; blendet die Icon-Spalte im Verbraucherpaneel aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Screenshot 2025-02-08 093239.png|Darstellung mit consumerControl showLegend=icon_top (default)&lt;br /&gt;
File:Screenshot 2025-02-08 093646.png|Darstellung mit consumerControl showLegend=icon_bottom&lt;br /&gt;
File:Screenshot 2025-02-08 152018.png|Darstellung mit consumerControl showLegend=text_top bzw. text_bottom&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 213634.png|right|thumb|400px|]]&lt;br /&gt;
Ein Mouse-Over über das Uhrensymbol zeigt nähere Informationen zum Status, den Planungsdaten, Modus und weitere Daten des Verbrauchers. Der Schalter &amp;quot;Aus/Ein&amp;quot; visualisiert den Schaltzustand des Verbrauchers und können auch zum manuellen Schalten des Verbrauchers dienen. Voraussetzung ist, dass im consumer-Attribut die Schlüssel &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; mit den Set-Kommandos zum Schalten des Verbrauchers defininiert sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 222210.png|right|thumb|300px|]]&lt;br /&gt;
Der Auto-Schieberegler zeigt einerseits den Freigabestatus zum Schalten des Verbrauchers durch das SolarForecast Modul und kann andererseits manuell betätigt werden. Der Status des Reglers korrespondiert mit dem im zugehörigen Consumer Attribut vorhandenen Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; angegebenen Reading-Wert.&lt;br /&gt;
&lt;br /&gt;
Die Verbraucherbezeichnungen in dem Paneel können in der Standardkonfiguration angeklickt werden um direkt zur Detailansicht des Devices zu gelangen. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;detailLink&#039;&#039;&#039; kann der Link zur Detailansicht deaktiviert werden.&lt;br /&gt;
&lt;br /&gt;
Das Uhrensymbol kann mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;adviceIcon&#039;&#039;&#039; geändert und/oder dessen Farbe angepasst, sowie einen Informationstext statt eines Icons angezeigt werden. &lt;br /&gt;
&lt;br /&gt;
=== 4 - Bereich Balkengrafik (Beam Graphic) ===&lt;br /&gt;
&lt;br /&gt;
Die Balkengrafik des Moduls ist ein wesentliches Visualisierungshilfsmittel. Im Auslieferungszustand existiert eine Balkengrafikebene, die &#039;&#039;&#039;Ebene 1&#039;&#039;&#039;.&lt;br /&gt;
Jede Ebene kann zwei Balkendiagramme mit auswählbaren Inhalten, Farben und einstellbarem LayoutTyp darstellen. In Ebene 1 kann die Wettervorhersage eingebettet oder, bei Vorhandensein von Batteriegeräten, die zukünftigen Zeiten mit empfohlener Ladefreigabe und SoC-Prognose eingeblendet werden. &lt;br /&gt;
&lt;br /&gt;
Welche Daten in welchen Zeiträumen dargestellt werden sollen, die Bestimmung des Layouts, die Gestaltung der Balken und einiges mehr wird durch Attribute gesteuert. Ein Teil dieser Einstellungen wird über das zusammengesetzete Attribut &#039;&#039;&#039;graphicControl-&amp;gt;&#039;Schlüssel&#039;=&#039;Wert&#039;&#039;&#039;&#039; eingestellt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;grundsätzliche Layout Definitionen&#039;&#039;&#039;&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204342.png|right|thumb|400px|Standardanzeige mit Wetter-Icons, gesetzen Attributen graphicBeam1Color=D4C177, graphicHistoryHour=11]]&lt;br /&gt;
&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingTop:Legt den Platz in px im Balkendiagramm fest, der zwischen dem oberen Rand der jeweiligen Balkengrafik Ebene und der ersten Text- oder Iconreihe dieser Ebene eingefügt wird.&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingBottom:Legt den Platz in px im Balkendiagramm fest, der zwischen der letzten Text- oder Iconreihe der jeweiligen Balkengrafik Ebene und dem unteren Rand dieser Ebene eingefügt wird. &lt;br /&gt;
;graphicControl-&amp;gt;layoutType:Layout-Optionen zur grundlegenden Gestaltung der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourStyle:Format der Zeitangabe in der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourCount:Anzahl der darzustellenden Balken/Stunden in der Balkengrafk&lt;br /&gt;
[[Datei:Screenshot Screenshot 2025-05-21 153613.png|right|thumb|400px|Erweiterung des oberen und unteren Abstandes mit den Attributen graphicControl-&amp;gt;beamPaddingTop und graphicControl-&amp;gt;beamPaddingBottom]]&lt;br /&gt;
;graphicControl-&amp;gt;energyUnit:definiert die Einheit zur Anzeige der elektrischen Leistung in der Grafik&lt;br /&gt;
;graphicHistoryHour:Anzahl der vorangegangenen Stunden die in der Balkengrafik dargestellt werden&lt;br /&gt;
;graphicControl-&amp;gt;beamWidth:Vorgabe Breite der Balken der Balkengrafik in px (sonst automatische Bestimmung) &lt;br /&gt;
;graphicBeamHeightLevel1:Multiplikator zur Festlegung der maximalen Balkenhöhe der jeweiligen Ebene (hier Ebene 1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;Definition der Inhalte und Balkeneigenschaften&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204756.png|right|thumb|400px|Wie oben aber mit gesetzem Attribut graphicShowNight=1]]&lt;br /&gt;
;graphicBeam1Color:Farbauswahl des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2Color:Farbauswahl des sekundären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam1Content:Legt den darzustellenden Inhalt des primären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam2Content:Legt den darzustellenden Inhalt des sekundären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam1FontColor:Auswahl der Schriftfarbe des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2FontColor:Auswahl der Schriftfarbe des sekundären Balkens (Ebene 1)&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 205024.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=0 (ohne Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;zusätzliche Optionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;graphicShowNight:Anzeigen oder Verbergen der Nachtstunden in der Balkengrafik&lt;br /&gt;
;graphicShowWeather:Wettericons in der Balkengrafik anzeigen/verbergen (nur Ebene 1)&lt;br /&gt;
;graphicWeatherColor:Farbe der Wetter-Icons für die Tagesstunden&lt;br /&gt;
;graphicWeatherColorNight:Farbe der Wetter-Icons für die Nachtstunden&lt;br /&gt;
;graphicShowDiff:Zusätzliche Anzeige der Differenz &amp;quot;&amp;lt;primärer Balkeninhalt&amp;gt; - &amp;lt;sekundärer Balkeninhalt&amp;gt;&amp;quot; im Kopf- oder Fußbereich der Balkengrafik&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die genaue Beschreibung und deren Optionen sind der aktuellen Online-Hilfe zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Für alle Ebenen gilt:&#039;&#039;&#039; Ein Attribut mit einer ungeraden Balkennummer (z.B. graphicBeam1Content) bezieht sich immer auf den primären Balken, ein Attribut mit einer geraden Balkennummer (z.B. graphicBeam2Content) bezieht sich immer auf den sekundären Balken.&lt;br /&gt;
&lt;br /&gt;
Die Balken haben, wie die meisten Elemente in der Balkengrafik, eine Mouse-Over Eigenschaft welche relevante Informationen zu den dargestellten Werten anzeigt. &lt;br /&gt;
&lt;br /&gt;
Sind die Nachtunden mit &#039;&#039;&#039;graphicShowNight&#039;&#039;&#039; ausgeblendet, werden keine Balken angezeigt sofern es keine Werte anzuzeigen gibt. Sollten dennoch Werte ungleich 0 anzuzeigen sein, werden diese Werte auch trotz ausgeblendeter Nachstunden angezeigt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 2 ====&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 211741.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=01 (mit Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 2&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam3Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam4Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 4 für Balken 4) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wetter-Icons können nur in Ebene 1 integriert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 2 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 2 gibt, eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgende Ebene.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 3 ====&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 3&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam5Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam6Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 5 für Balken 5) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 3 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 3 gibt, ist eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgenden Ebenen, d.h. auch auf die Ebene 3.&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 5 - Die Energieflußgrafik (Flow Graphic) ===&lt;br /&gt;
[[Datei:Screenshot 2025-02-13 213424.png|right|thumb|400px|Energieflußgrafik mit Verbrauchern in der Nachtdarstellung (Mondphasen) nach Sonnenuntergang]]&lt;br /&gt;
&lt;br /&gt;
Die Energieflußgrafik stellt die registrierten Erzeuger, Batterien, Netzzugänge und Verbraucher strukturiert in mehreren Ebenen dar:&lt;br /&gt;
&lt;br /&gt;
;Ebene 1: In der oberen Ebene befinden sich die PV-Generatoren, Smart-Loader sowie sonstigen Erzeuger &lt;br /&gt;
;Ebene 2: Die mittlere Ebene organisiert den Zugang zum öffentlichen Netz, dem Hausknoten, dem Batterieknoten sowie einem Dummy-Verbraucher (Lampensymbol) für den Energieverbrauch des Hauses der keinem der registrierten Verbraucher zugeordnet werden kann.&lt;br /&gt;
;Ebene 3: In der unteren Ebene werden die registrierten Verbraucher dargestellt. Unterhalb der Verbrauchersymbole werden der aktuelle Verbrauch (bzw. der On/Off-Zustand) sowie darunter die Restlaufzeit (Minuten) des Verbrauchers, sofern er durch das Modul geplant und gestartet wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Position und Gestaltung der Grafikelemente ist umfangreich über das Attribut &#039;&#039;&#039;flowGraphicControl&#039;&#039;&#039; und den darin verfügbaren Schlüsseln einstellbar.&lt;br /&gt;
Die Bedeutung der Schlüssel ist in der Online-Hilfe zum Attribut mit einem Beispiel beschrieben. &lt;br /&gt;
&lt;br /&gt;
Darüber hinaus enthalten die Setup-Attribute &#039;&#039;&#039;setupInverterDevXX&#039;&#039;&#039;, &#039;&#039;&#039;setupOtherProducerXX&#039;&#039;&#039; und &#039;&#039;&#039;consumerXX&#039;&#039;&#039; weitere Einstellungsmöglichkeiten um deren Icons und Färbungen in der Flußgrafik individuell einstellen zu können. So sind zum Beispiel die Icons der PV-Inverter und deren Färbung mit dem Schlüssel &#039;&#039;&#039;icon&#039;&#039;&#039; der setupInverterDevXX-Attribute in Abhängigkeit von Tag und Nacht separat definierbar.&lt;br /&gt;
&lt;br /&gt;
In den Verbraucher-Attributen ist mit dem Schlüssel &#039;&#039;&#039;noshow&#039;&#039;&#039; die Sichtbarkeit in der Flußgrafik definierbar.&lt;br /&gt;
&lt;br /&gt;
Generell steuert das Attribut &#039;&#039;&#039;graphicSelect&#039;&#039;&#039; die Ein- bzw. Ausblendung der gesamten Flußgrafik.&lt;br /&gt;
&lt;br /&gt;
== Die Verbrauchsprognose ==&lt;br /&gt;
Im Gegensatz zu der PV Prognose gibt es keine API oder andere externen Datenquellen die für die Verbrauchsprognose herangezogen werden könnten.&lt;br /&gt;
&lt;br /&gt;
Zum Zweck der Verbrauchsermittlung verwendet das Modul die Meterdaten aus dem Attribut &#039;&#039;setupMeterDev&#039;&#039; sowie den weiteren setup-Attributen &#039;&#039;setupInverterDevXX&#039;&#039;. &lt;br /&gt;
Sind auch andere Erzeuger (BHKW, Windanlagen, etc.) bzw. eine Batterie vorhanden, sind ebenfalls die Attribute &#039;&#039;setupOtherProducerXX&#039;&#039; bzw. &#039;&#039;setupBatteryDev&#039;&#039; für die Berechnung des Hausverbrauchs relevant. In diesen Attributen gibt es die Schlüssel &#039;&#039;*total&#039;&#039; die teilweise optional sind. Für die Verbrauchsprognose bilden sie jedoch die Berechnungsgrundlage und sind deswegen für diese Funktionalität wichtig anzugeben.&lt;br /&gt;
&lt;br /&gt;
Die Verbrauchswerte werden stundengenau erfasst und im Datenspeicher &#039;&#039;pvHistory&#039;&#039; für 31 Tage, sowie im Datenspeicher &#039;&#039;pvCircular&#039;&#039; 210 Tage gespeichert. Die beiden Datenspeicher übernehmen unterschiedliche Aufgaben im Rahmen der Prognoseerstellung. Auf Grundlage der gespeicherten und somit historischen Verbrauchswerte erstellt das Modul eine Prognose für die kommende Zeit.&lt;br /&gt;
&lt;br /&gt;
Mit dem Kommando &lt;br /&gt;
&lt;br /&gt;
   &amp;quot;get ... pvHistory [Tag]&amp;quot; &lt;br /&gt;
&lt;br /&gt;
wird der Inhalt aufgelistet. Die Schlüssel &#039;&#039;confc&#039;&#039;, &#039;&#039;con&#039;&#039; und &#039;&#039;gcon&#039;&#039; zeigen die Verbrauchsprognose, den Verbrauch und den Netzbezug der jeweiligen Stunde des gewählten Tages.&lt;br /&gt;
Die Stunde &amp;quot;99&amp;quot; zeigt die Summen dieser Schlüsssel für den Tag:&lt;br /&gt;
&lt;br /&gt;
      99 =&amp;gt; etotal: , pvfc: 782, pvrl: 0, rad1h: -&lt;br /&gt;
            confc: 14540, con: 13873, gcon: 13873, gfeedin: 0&lt;br /&gt;
            batintotal: , batin: 0, batouttotal: , batout: 0&lt;br /&gt;
            batmaxsoc: -, batsetsoc: -&lt;br /&gt;
            wid: , wcc: , wrp: , pvcorrf: , dayname: So&lt;br /&gt;
            cyclescsm01: 0&lt;br /&gt;
            cyclescsm02: 0&lt;br /&gt;
            cyclescsm03: 0&lt;br /&gt;
            cyclescsm04: 1, hourscsme04: 0.00&lt;br /&gt;
            cyclescsm05: 0&lt;br /&gt;
            cyclescsm06: 0&lt;br /&gt;
            cyclescsm07: 1, hourscsme07: 0.00&lt;br /&gt;
            cyclescsm08: 1, hourscsme08: 0.00&lt;br /&gt;
            cyclescsm09: 1, hourscsme09: 0.03 &lt;br /&gt;
&lt;br /&gt;
In dem Beispiel wurden für den Tag 14540 Wh Verbrauch prognostiziert, 13873 Wh tatsächlich verbraucht und davon 13873 Wh aus dem Netz bezogen. Leider war an diesem Tag keinerlei PV Ertrag vorhanden, was man auch an dem Schlüssel &#039;&#039;pvrl&#039;&#039; erkennen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Inhalt des pvCircular-Speichers kann mit dem Befehl  &lt;br /&gt;
&lt;br /&gt;
     &amp;quot;get ... pvCircular [Tag]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Das nachfolgende Beispiel zeigt die Ausgabe für die Tagesstunde 23:&lt;br /&gt;
&lt;br /&gt;
 23 =&amp;gt; pvapifc: 0, pvaifc: -, pvfc: 0, aihit: 0, pvrl: 0&lt;br /&gt;
       batin01: 0, batin02: -, batin03: -&lt;br /&gt;
       batout01: 619, batout02: -, batout03: -&lt;br /&gt;
       confc: 650, gcon: 23, gfeedin: 0, wcc: 40, rr1c: 0.00&lt;br /&gt;
       temp: -6.00, wid: 100, wtxt: Bewölkungsentwicklung nicht beobachtet&lt;br /&gt;
       pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
       ... &lt;br /&gt;
       con_all =&amp;gt; Sa  @ 617 762&lt;br /&gt;
                  Di  @ 693 645&lt;br /&gt;
                  Mo  @ 620 679&lt;br /&gt;
                  So  @ 669 666 636&lt;br /&gt;
                  Mi  @ 701 626&lt;br /&gt;
                  Do  @ 612 642&lt;br /&gt;
                  Fr  @ 615 606&lt;br /&gt;
&lt;br /&gt;
Der Schüssel &#039;&#039;con_all&#039;&#039; enthält einen Hash aus Arrays die für jeden Wochentag (Mo..So) bis zu 30 Verbrauchswerte (in Wh) für die angezeigte Stunde speichern. Wie hier erkennbar ist, wurden an den drei vergangenen Sonntagen jweils 669 Wh, 666 Wh bzw. 636 Wh in der Stunde 23 (22:00-22:59) verbraucht.&lt;br /&gt;
Der Median aus diesen Werten geht in die Verbrauchsprognose ein. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wochentagsnamen Mo..So sind von den installierten Locales auf Betriebsystemebene abhängig. Ist keine deutsche locale installiert, werden die englischen Wochentagsnamen Mon..Sun verwendet. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Wie wird der Verbrauch des Hauses ermittelt und gespeichert? ===&lt;br /&gt;
Die Verbrauchsdaten des Hauses werden auf Stundenbasis ermittelt und gespeichert. Das &amp;quot;Haus&amp;quot; steht als Synonym aller im Kontext des Solarforecast Devices zusammengeführten Inverter (setupInverterDevXX), sonstigen Erzeuger (setupOtherProducerXX), Netzanschlüsse (setupMeterDev), Verbraucher (consumerXX) und Batterien (setupBatteryDev).&lt;br /&gt;
&lt;br /&gt;
Alle diese Daten werden durch das Modul mit jedem ausgeführten Zyklus (Attribut plantControl-&amp;gt;cycleInterval) und, wenn ein Event eines als &#039;asynchron&#039; definierten Devices auftritt, gesammelt und daraus permanent ein aktualisierter Verbrauch berechnet. Die Berechnung beschreibt folgende Formel:&lt;br /&gt;
&lt;br /&gt;
 PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung - Verbrauch = 0&lt;br /&gt;
&lt;br /&gt;
bzw.&lt;br /&gt;
 &lt;br /&gt;
 Verbrauch (Wh) = PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung&lt;br /&gt;
            con = PV           + PP                 - GridIn          + GridCon   - BatIn          + BatOut&lt;br /&gt;
&lt;br /&gt;
Die PV-Erzeugung beinhaltet die Summe aller durch die angegebnen Inverter (setupInverterDev01 .. setupInverterDevXX) erzeugten Energien. Die &amp;quot;sonstige Erzeugung&amp;quot; summiert sich aus den Werten aller angegebenen Producer (setupOtherProducer01 .. setupOtherProducerXX). Der Verbrauch wird durch die registrierten Geräte consumerXX teilweise direkt erfasst, ist aber grundsätzlich unvollständig da nicht alle Verbrauchswerte im &amp;quot;Haus&amp;quot; gemessen und durch das Modul erfasst werden können.&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel zeigt das Ergebnis bei 300 Wh PV-Erzeugung und gleichzeitige 500 Wh Netzbezug:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 300 + 0 - 0 + 500 - 0 + 0 = 800 Wh&lt;br /&gt;
&lt;br /&gt;
Bei 1300Wh PV-Erzeugung, 100 Wh Netzeinspeisung sowie 200 Wh Batterieladung ergibt sich der Verbrauch zu:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 1300 + 0 - 100 + 0 - 200 + 0 = 1000 Wh&lt;br /&gt;
&lt;br /&gt;
Ohne Erzeugung, aber mit der Energielieferung von 500 Wh aus der Batterie, 800 Wh Netzbezug (mit einem Anteil Batterienachladung aus dem Netz von 200 Wh) sieht die Verbrauchsrechnung wie folgt aus: &lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 0 + 0 - 0 + 800 - 200 + 500 = 1100 Wh&lt;br /&gt;
&lt;br /&gt;
Der so ermittelte Verbrauchsert wird mit jedem Zyklus in der pvHistory im Schlüssel &amp;quot;con&amp;quot; gespeichert. Man kann sich die gespeicherten Werte mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;name&amp;gt; pvHistory [&amp;lt;Tag&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Nachfolgendes Beispiel zeigt einen Datensatz für die Stunde 8 eines Tages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      08 =&amp;gt; pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotali01: 62940734, etotali02: 2928860, etotali03: -&lt;br /&gt;
            pvrl01: 0, pvrl02: 0, pvrl03: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 630, con: 962, gcons: 962, conprice: 0.2958&lt;br /&gt;
            gfeedin: 0, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 120, sunalt: -3&lt;br /&gt;
            batintotal: 3713815.07742543, batouttotal: 3604468.26993988, batin: 0, batout: 0&lt;br /&gt;
            wid: 161, wcc: 89, rr1c: 0.00, pvcorrf: 0.27/0.00 temp: 7.40, &lt;br /&gt;
            csmt01: 110996.12, csme01: 32.1399999999994, minutescsm01: 30&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 2513.67, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1581293.6, csme04: 136.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 1662.17, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 90.53, csme06: 0, minutescsm06: 0&lt;br /&gt;
            csmt07: 39.75, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 38050, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 131627, csme09: 33.2000000000116, minutescsm09: 39&lt;br /&gt;
            minutescsm10: 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Schlüssel &amp;quot;con&amp;quot; ist der gespeicherte Verbrauch von 962 Wh ersichtlich.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit bekommt man mit dem Attribut &#039;&#039;ctrlDebug=collectData&#039;&#039; einen Einblick in die Verbrauchsermittlung bei jedem Zyklus und kann so die Eingangswerte und das daraus resultierende Ergebnis im FHEM Log nachverfolgen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
2024.11.28 11:38:20.080 1: SolCast DEBUG&amp;gt; EnergyConsumption input -&amp;gt; PV: 96, PP: 0, GridIn: 0, GridCon: 582, BatIn: 5, BatOut: 0&lt;br /&gt;
2024.11.28 11:38:20.081 1: SolCast DEBUG&amp;gt; EnergyConsumption result -&amp;gt; 673 Wh&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie wird die Verbrauchsprognose erstellt? ===&lt;br /&gt;
&lt;br /&gt;
Aus den gespeicherten con-Werten (Verbrauchsdaten) der pvCircular (Schlüssel con_all) sowie Einträgen der pvHistory wird der Median der historischen Tage ermittelt und für den kommenden Tag bzw. die kommen Stunden zur Prognose angewendet. Dabei geht per default jeder verfügbare historische Tag gleichberechtigt in die Prognose ein. Mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039; kann festgelegt werden, dass nur gleiche Wochentage (Mo..So) für die Prognose verwendet werden. Hierbei spielt die Vermutung, dass das Verbrauchsverhalten eine gewisse Korrelation zum Wochentag hat, eine Rolle. &lt;br /&gt;
&lt;br /&gt;
Verwendet man die Einstellung consForecastIdentWeekdays=1, hat es sich als vorteilhaft erwiesen, das Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays&#039;&#039;&#039; auf einen niedrigeren Wert als den Default zu setzen. Eine Einstellung auf &#039;8&#039; zum Beispiel verwendet den Median der gleichen Wochentage der vergangenenen 8 Wochen. Dadurch wird nicht zu weit in die Vergangenheit verzweigt und so eine langsame Veränderung des Verbrauchsmedian, zum Beispiel hervorgerufen durch den Übergang vom Winter in das Frühjahr hinein, abgebildet.&lt;br /&gt;
&lt;br /&gt;
Weiteren Einfluß auf die Verbrauchsprognose kann mit dem Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; im Consumerattribut genommen werden. Insbesondere bei der unregelmäßigen Nutzung von Verbrauchern mit hoher Leistung kann die Projektion der aufgezeichneten historischen Werte in die Prognose zu unverhältnismäßig hohen Verbrauchswerwartunden führen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Möglicherweise führt in Fällen die Verwendung eine der nachfolgenden Optionen zu einem besseren Ergebnis:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;1 -&#039;&#039;&#039; die allgemeine Verbrauchsprognose wird um die gespeicherten Energieverbrauchsanteile reduziert.&lt;br /&gt;
* &#039;&#039;&#039;2 -&#039;&#039;&#039; wie bei &#039;1&#039;, jedoch gehen die Planungsdaten des Verbrauchers bei der Prognose der kommenden Stunden wieder mit ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;&#039;exconfc&#039;&#039;&#039; in einem der Consumer verwendet, sollte&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays=4&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
eingestellt werden. Hintergrund ist, dass die Verbrauchsanteile der jeweiligen Verbraucher nur maximal 31 Tage in der pvHistory verfügbar sind. Für längere Zeiträume stehen nur Gesamtsummen des Verbrauchs in der pvCircular zu Verfügung.  &lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=1&#039;&#039;&#039; werden die in der Historie aufgezeichneten Verbrauchsbestandteile aus einer Prognose herausgerechnet. Konkret werden die in der pvHistory aufgezeichneten Verbrauchsbestandteile für die relevante Stunde ermittelt und daraus ein Durchschnitt gebildet der vom Prognosewert subtrahiert wird. Mit dem Attributwert plantControl-&amp;gt;consForecastIdentWeekdays=1 werden wiederum nur identische Wochentage (Mo .. So) zusammengefasst.&lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=2&#039;&#039;&#039; erfolgt ebenso die Eliminierung des Verbrauchsanteils, es wird jedoch auf die Planungsdaten für diesen Verbraucher zugegriffen und die geplanten Energieanteile wiederum der Verbrauchsprognose für die kommenden Stunden hinzugerechnet.&lt;br /&gt;
&lt;br /&gt;
In beiden Anwendungsfällen ist es notwendig, dass dem Modul durch die Angabe entsprechender Readings der Energieverbrauch im Setup des Consumers bekannt gemacht wird damit diese Energieanteile registriert werden können. Allgemein funktioniert die Verbrauchsprognose gut wenn Verbrauchsprozesse regelmäßig in einem wiederkehrenden Zeitraster ablaufen, der Verbrauch durch persönliche Rituale bestimmt ist. So zum Beispiel könnte am Dienstag und Samstag gewöhnlich die Waschmaschine laufen, das E-Auto täglich aufgeladen werden und gebügelt wird oft am Sonntag Nachmittag.&lt;br /&gt;
&lt;br /&gt;
Unregelmäßige Nutzung, vor allem vom Großverbrauchern, lässt sich nur sehr schwer und ungenügend auf zukünftige Verbrauchsprognosen projizieren.&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis der Prognose wird im Kopf der Grafik in der Zeile &#039;&#039;Verbrauch&#039;&#039; sowie in diversen Readings wie &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RestOfDayConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den Rest des Tages)&lt;br /&gt;
* &#039;&#039;&#039;NextHours_Sum04_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für die nächsten 4 Stunden)&lt;br /&gt;
* &#039;&#039;&#039;Tomorrow_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den kommenden Tag)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
angezeigt.&lt;br /&gt;
&lt;br /&gt;
Weitere Aggregationen kann man sich über das Attribut &#039;&#039;&#039;ctrlStatisticReadings&#039;&#039;&#039; bei Bedarf zuschalten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;conForecastTillNextSunrise&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
* &#039;&#039;&#039;todayConForecastTillSunset&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
* &#039;&#039;&#039;todayConsumptionForecast&#039;&#039;&#039; - Verbrauchsprognose aufgesplittet pro Stunde des aktuellen Tages (01-24) &lt;br /&gt;
 &lt;br /&gt;
==== Debugging der Verbrauchsprognose ====&lt;br /&gt;
Um sich einen Einblick über die Erstellung der Verbrauchsprognose zu verschaffen, bietet sich die Einschaltung von:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
an. Mit diesem gesetzten Attribut wird die Erstellung der Prognose im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; ################### Start Consumption forecast ###################&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; Basics - installed locale: de_DE.UTF-8, used scheme: DE&lt;br /&gt;
2025.02.27 19:52:00.064 1: SolCast DEBUG&amp;gt; process Today dayname: Do, Tomorrow dayname: Fr&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 01 - 74.43 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 10 - 290.77 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 24 - 660.70 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 20, hod: 07 - 459.93 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;07&#039; register for exclude day 20, hod: 02 - 0.33 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 30, hod: 08 - 264.78 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next Hours (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; excl. hist 74 Wh for Hour 01, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; estimated cons of Hour 01: 436 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; excl. hist 0 Wh for Hour 02, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 02: 428 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 03: 458 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 04: 503 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 05: 489 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 06: 482 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; excl. hist 460 Wh for Hour 07, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 07: 274 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 265 Wh for Hour 08, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 08: 441 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 09: 558 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 291 Wh for Hour 10, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 10: 443 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 11: 881 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 12: 794 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 13: 840 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 14: 660 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 15: 812 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 16: 752 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 17: 597 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 18: 652 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 19: 634 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 20: 628 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 21: 713 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 22: 596 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 23: 629 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; excl. hist 661 Wh for Hour 24, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons of Hour 24: 660 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons Tomorrow: 16848 Wh, Individual hourly values considered: 72, exclude: 0 Wh (avg of 0 entities)&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Store Consumption forecast values (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour00&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;20&#039; confc: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour01&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;21&#039; confc: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour02&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;22&#039; confc: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour03&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;23&#039; confc: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store &#039;NextHour04&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;24&#039; confc: 660&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour05&#039; hod &#039;01&#039; confc: 436, confcEx: 436&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour06&#039; hod &#039;02&#039; confc: 428, confcEx: 428&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour07&#039; hod &#039;03&#039; confc: 458, confcEx: 458&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour08&#039; hod &#039;04&#039; confc: 503, confcEx: 503&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour09&#039; hod &#039;05&#039; confc: 489, confcEx: 489&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour10&#039; hod &#039;06&#039; confc: 482, confcEx: 482&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour11&#039; hod &#039;07&#039; confc: 274, confcEx: 274&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour12&#039; hod &#039;08&#039; confc: 441, confcEx: 441&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour13&#039; hod &#039;09&#039; confc: 558, confcEx: 558&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour14&#039; hod &#039;10&#039; confc: 443, confcEx: 443&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour15&#039; hod &#039;11&#039; confc: 881, confcEx: 881&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour16&#039; hod &#039;12&#039; confc: 794, confcEx: 794&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour17&#039; hod &#039;13&#039; confc: 840, confcEx: 840&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour18&#039; hod &#039;14&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour19&#039; hod &#039;15&#039; confc: 812, confcEx: 812&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour20&#039; hod &#039;16&#039; confc: 752, confcEx: 752&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour21&#039; hod &#039;17&#039; confc: 597, confcEx: 597&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour22&#039; hod &#039;18&#039; confc: 652, confcEx: 652&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour23&#039; hod &#039;19&#039; confc: 634, confcEx: 634&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour24&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour25&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour26&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour27&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour28&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; consumption calculated - day: 27, hod: 20, con: 574 Wh&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; write pvCircular consumption - hod: 99, todayConsumption: 11210 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe startet mit &#039;&#039;&amp;quot;Start Consumption forecast&#039;&#039;&amp;quot;, es werden die zu exkludierenden historischen Daten für jeden Consumer bzgl. jedem Tag (day) und Stunde des Tages (hod) getrennt registriert. Diese Werte werden durch die gespeicherte Einträge in der pvHistory (max. 31 historische Tage) geliefert. &lt;br /&gt;
&lt;br /&gt;
Im nächsten Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next Hours (new median)&amp;quot;&#039;&#039; werden die Prognosen für die nächsten Stunden kalkuliert und die zuvor registrierten Excludes angewendet. Die Prognose für den kommenden Tag ist im Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next day (new median)&amp;quot;&#039;&#039; protokolliert. Die Prognose für den kommenden Tag ist nicht einfach die Summe der Prognose der nächsten Stunden, denn in den kommenden Stunden werden auch die verfügbaren Planungen der Consumer einbezogen. Für den kommenden Tag können diese Werte unter Umständen nicht einbezogen werden da sie zum Zeitpunkt X noch nicht verfügbar sind.&lt;br /&gt;
&lt;br /&gt;
Im Abschnitt &#039;&#039;&amp;quot;Store Consumption forecast values (new median)&amp;quot;&#039;&#039; erscheinen die effektiv gespeicherten Werte. Diese sind die Grandlage für die grafische Darstellung sowie weiteren Kalkulationen.&lt;br /&gt;
&lt;br /&gt;
=== Wie kann eine fehlerhafte Verbrauchsprognose korrigiert werden? ===&lt;br /&gt;
Wie im vorherigen Abschnitt beschrieben, wird die Prognose aus den gespeicherten &amp;quot;con&amp;quot;-Werten der vergangenen Tage (bzw. Stunden) abgeleitet. &lt;br /&gt;
Grundsätzlich muß zunächst sichergestellt werden, dass die auszulesenden Readings der angegebenen Energiezähler sowie deren Einheiten! korrekt eingestellt sind. Das gilt ebenfalls für die registrierten Verbraucher im Modul.&lt;br /&gt;
&lt;br /&gt;
Für einen ersten Überblick bietet sich das Debug Attribut an zu setzen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
Beispielausgabe des Debug:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2024.09.21 13:28:27.041 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day ###################&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;01&amp;lt; considering possible exclusions: 14082&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;08&amp;lt; considering possible exclusions: 16446&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;15&amp;lt; considering possible exclusions: 14568&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;25&amp;lt; considering possible exclusions: 15522&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; estimated Consumption for tomorrow: 15154, days for avg: 4&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next hours ###################&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 14 -&amp;gt; 850 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 14 -&amp;gt; 643 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 14 -&amp;gt; 590 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 14 -&amp;gt; 522 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 13:00:00, confc: 651, days for avg: 4, hist. consumption registered consumers: 560.97&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 15 -&amp;gt; 720 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 15 -&amp;gt; 743 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 15 -&amp;gt; 897 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 15 -&amp;gt; 557 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 14:00:00, confc: 729, days for avg: 4, hist. consumption registered consumers: 620.97&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 16 -&amp;gt; 676 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 16 -&amp;gt; 790 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 16 -&amp;gt; 785 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 16 -&amp;gt; 581 Wh&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 15:00:00, confc: 708, days for avg: 4, hist. consumption registered consumers: 647.29&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 17 -&amp;gt; 622 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 17 -&amp;gt; 639 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 17 -&amp;gt; 646 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 17 -&amp;gt; 572 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 16:00:00, confc: 619, days for avg: 4, hist. consumption registered consumers: 618.30&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 18 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 18 -&amp;gt; 614 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 18 -&amp;gt; 580 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 18 -&amp;gt; 480 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 17:00:00, confc: 567, days for avg: 4, hist. consumption registered consumers: 583.41&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 19 -&amp;gt; 615 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 19 -&amp;gt; 1659 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 19 -&amp;gt; 597 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 19 -&amp;gt; 618 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 18:00:00, confc: 872, days for avg: 4, hist. consumption registered consumers: 636.97&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 20 -&amp;gt; 611 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 20 -&amp;gt; 1124 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 20 -&amp;gt; 546 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 20 -&amp;gt; 479 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 19:00:00, confc: 690, days for avg: 4, hist. consumption registered consumers: 578.87&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 21 -&amp;gt; 1474 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 21 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 21 -&amp;gt; 619 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 21 -&amp;gt; 433 Wh&lt;br /&gt;
2024.09.21 13:28:27.058 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Im ersten Teil wird die erwartete Consumption für den nächsten Tag unter Berücksichtigung möglicher Ausschlüsse von Verbrauchern ausgegeben. Ausschlüsse von Verbrauchern ergeben sich wenn in dem Verbraucherattribut der Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; gesetzt ist. Er besagt, dass die Verbrauchswerte des Verbrauchers in eine zukünftige Prognose nicht eingehen sollen. Zum Beispiel wenn ein Verbraucher mit sehr hohen Verbrauchswerten nur sporadisch eingesetzt wird und dadurch die Prognose stark verfälschen würde. Es ist auch zu sehen, dass bedingt durch das Attribut &#039;&#039;&#039;affectConsForecastIdentWeekdays = 1&#039;&#039;&#039; nur die historischen Tage 01, 08, 15 und 25 berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Teil wird die berechnete Erwartung für die nächsten Stunden ausgegeben. &lt;br /&gt;
Zur Beschreibung der Fehlersuche gehen wir davon aus, dass die Prognose von 780 Wh am 2024-09-21 20:00:00 zu hoch erscheint weil am Tag &amp;quot;07&amp;quot; ein Wert von 1474 Wh gespeichert ist:&lt;br /&gt;
&lt;br /&gt;
 SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt geben wir die historischen Werte für den Tag 07 aus:&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;Name&amp;gt; pvHistory 07&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz interessiert die Stunde 21. Sie resultiert aus der obigen Angabe &amp;quot;starttime: xxxx-xx-xx 20:00:00&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      21 =&amp;gt; etotal: 64354660, pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 496, con: 1474, gcons: 23, conprice: 0.2958&lt;br /&gt;
            gfeedin: 5, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 289, sunalt: -8&lt;br /&gt;
            batintotal: 3064096.92456668, batouttotal: 2958021.37946804, batin: 0, batout: 1460&lt;br /&gt;
            wid: 101, wcc: 20, rr1c: 0.00, pvcorrf: 1.00/-temp: 26.00, &lt;br /&gt;
            csmt01: 64262.43, csme01: 28.8099999999977, minutescsm01: 25&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 0, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1389417.4, csme04: 94.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 0, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 290.15, csme06: 6.66999999999996, minutescsm06: 54&lt;br /&gt;
            csmt07: 0, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 32800, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 103987.8, csme09: 38, minutescsm09: 43&lt;br /&gt;
            csmt10: 9151.24999999783, csme10: 3.99999999997999, minutescsm10: 60&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz sind die Energieverbrauchsanteile der im Device registrierten Verbraucher mit dem Schlüssel &amp;quot;csmeXX&amp;quot; gespeichert. Dabei ist &amp;quot;XX&amp;quot; die Verbrauchernummer. In dem Beispiel existieren die Anteile csme01 und csme03 - csme10. Keiner dieser Verbraucher hat einen auffälligen Verbrauchswert gespeichert, d.h. die Messung der Verbraucher scheidet als Problemquelle aus. Wäre ein unverhältmismäßig hoher Verbrauch bei einem der Verbraucher feststellbar, müssten die Schlüssel &#039;&#039;&#039;pcurr&#039;&#039;&#039; und &#039;&#039;&#039;etotal&#039;&#039;&#039; im consumerXX-Attribut geprüft, sowie die Datenlieferung des Consumerdevices selbst geprüft werden.  &lt;br /&gt;
&lt;br /&gt;
Es wurde offensichtlich ein hoher Verbrauch von einem nicht registrierten Verbraucher verursacht oder durch die Übertragung eines Meßfehlers des Devices, angegeben im Attribut &#039;&#039;&#039;setupMeterDev&#039;&#039;&#039;, in das SolarForecast Device übertragen. Eine weitere Analyse ist an dieser Stelle nicht möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Behebung des falschen Wertes kann ein Reset der gespeicherten Consumption der relevanten Stunde durchgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; reset consumptionHistory 07 21&lt;br /&gt;
&lt;br /&gt;
== Modulinterne Datenstrukturen ==&lt;br /&gt;
Das Modul speichert die verschiedenen historischen und aktuellen Daten wie PV-Prognose, Witterungsdaten (Regen, Bewölkung), Strahlungsdaten, Einspeisung, Bezug, reale Erzeugungsdaten und vieles mehr zur Laufzeit im Arbeitsspeicher. Dadurch ist die Verarbeitung dieser Daten im Vergleich zu Lesevorgängen aus dem Filesystem bzw. einer Datenbank sehr performant. Allerdings würden diese Daten bei einem FHEM Absturz bzw. bei einem regulären Shutdown verlorengehen.&lt;br /&gt;
&lt;br /&gt;
Deswegen werden die relevanten Daten regelmäßig in Dateien gesichert und bei Bedarf wiederhergestellt. Diese Dateien befinden sich im Verzeichnis &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; und heißen &#039;&#039;&#039;.*_SolarForecast_.*&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Die Daten werden in jedem Zyklus der Zentralschleife (CentralTask) gesammelt bzw. berechnet. Der Zyklus wird mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;cycleInterval&#039;&#039;&#039; eingestellt.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit können diese Daten über get-Kommandos abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvHistory [Tag]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der pvHistory Datenspeicher enthält die vergangenen Kennwerte der letzten 31 Tage mit einer Genauigkeit von einer Stunde. Es werden die Prognosewerte für Erzeugung und Verbrauch, die realen Werte für Erzeugung und Verbrauch sowie ebenso die Laufzeiten jedes einzelnen Verbrauchers (Consumer) festgehalten. Für jeden Tag gibt es die Stunde &amp;quot;99&amp;quot; die eine Summierung der Stundenwerte des Tages bzw. Sonderschlüssel enthält.&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf lässt sich mit dem Befehl &amp;quot;set ... reset pvHistory&amp;quot; der gesamte Inhalt des Speichers löschen (nicht empfohlen). Selektiver funktioniert die Datenlöschung mit &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt;&amp;quot; (Daten eines bestimmten Tages löschen) bzw. &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt; &amp;lt;Stunde&amp;gt;&amp;quot; (Daten der Stunde  eines bestimmten Tages löschen). Die letzten beiden Kommandos müssen über die Kommandozeile im Browser ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvCircular &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Ringspeicher enthält Daten der letzten 24 Stunden sowie fortwährend berechnete Werte wie Korrekturfaktoren der PV-Erzeugung und Prognosequalität.&lt;br /&gt;
Neue Stundenwerte des Tages überschreiben die gespeicherten Schüssel des vorangegangenen Tages sofern es sich nicht um fortwährend berechnete Werte handelt. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... nextHours&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Speicher enthält sämtliche Prognosewerte der kommenden Stunden beginnend mit der aktuellen Stunde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... radiationApiData&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Abhängig von der ausgewählten Strahlungsdaten API enthält dieser Speicher die von der API gelieferten Rohdaten sowie evtl. weitere für die Funktion benötigte Daten wie API-Keys, Response Messages, Anzahl der API Abruf und weitere.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valCurrent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Struktur wird nicht regelmäßig im Filesystem gespeichert und enthält immer aktuell gesammelte oder berechnete/gelieferte Daten wie z.B. die Autarkierate, letze Laufzeit der Zentralschleife (CentralTask), Zeit des Sonnenauf- und untergangs sowie weitere Betriebsdaten. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valConsumerMaster [XX]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zeigt die Daten der aktuell im SolarForecast Device registrierten Verbraucher. Mit der Nummer &#039;&#039;&#039;XX&#039;&#039;&#039; kann ein bestimmter Verbraucher angesprungen werden. Die Nummer korrespondiert mit dem entsprechenden &#039;&#039;&#039;consumerXX&#039;&#039;&#039; Attribut.&lt;br /&gt;
Neben anderen Betriebs- und Energiedaten werden insbesondere folgende Daten ermittelt, die für die zukünftige Planung der Verbraucherschaltzeiten relevant sind:&lt;br /&gt;
&lt;br /&gt;
* epieces - prognostizierte Energiescheiben pro Betriebsstunde &lt;br /&gt;
&lt;br /&gt;
Ausgehend von gespeicherten historischen Verbrauchsdaten des Verbrauchers wird der Energieverbrauch des Verbrauchers in seiner ersten Betriebsstunde prognostiziert, was insbesondere für die Planung der optimalen Startzeit des Verbrauchers in Bezug zu der prognostizierten PV Energie und den Verbrauchswerten weiterer vorhandener bzw. zu planender Verbraucher Berücksichtigung findet. Weitere Informationen zur Verbrauchersteuerung in diesem  [[#Verbrauchersteuerung_-_Registrieren_und_visualisieren_von_Verbrauchern|Abschnitt]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Schnittstelle für Modulautoren bzw. eigenen Code ===&lt;br /&gt;
&lt;br /&gt;
Die im vorherigen Artikel beschriebenen internen Datenstrukturen können durch externen Code abgefragt und ausgewertet werden.&lt;br /&gt;
Dazu stehen die folgenden Funktionen zur Verfügung. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]BatteryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Bn&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valBattery&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CurrentVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valCurrent&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]InverterVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valInverter&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ProducerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valProducer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]HistoryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Day&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvHistory&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CircularVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvCircular&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]NexthoursVal (&#039;&amp;lt;Name&amp;gt;&#039;, &amp;lt;nhr&amp;gt;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... nextHours&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ConsumerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valConsumerMaster&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]RadiationAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;DateTime&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... radiationApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]WeatherAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;TimeCode&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... weatherApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StatusAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;QTag&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... statusApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StringVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valStrings&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Angabe des Packages (FHEM::SolarForecast::) ist nur notwendig wenn die Funktionen von außerhalb des SolarForecast-Devices aufgerufen werden. Innerhalb des Devices (Code-Ausführung im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039;) kann darauf verzichtet werden.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der Platzhalter sind:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     &amp;lt;Name&amp;gt;     - Name des SolarForecast Devices&lt;br /&gt;
     &amp;lt;Day&amp;gt;      - abzufragender Tag (01 - 31)&lt;br /&gt;
     &amp;lt;Bn&amp;gt;       - Batterie Nummer (01, 02, ...)&lt;br /&gt;
     &amp;lt;DateTime&amp;gt; - Startzeit der Form YYYY-MM-DD hh:00:00&lt;br /&gt;
     &amp;lt;TimeCode&amp;gt; - Zeitwert der Form fcX_XX (z.B. fc1_19)&lt;br /&gt;
     &amp;lt;APIname&amp;gt;  - Hauptname der API gemäß setupWeatherDev1 (z.B. OpenMeteo)&lt;br /&gt;
     &amp;lt;String&amp;gt;   - Name des PV-Modulstrings wie im Attribut &#039;setupInverterStrings&#039;&lt;br /&gt;
     &amp;lt;QTag&amp;gt;     - Question Tag, z.B. &#039;?All&#039;&lt;br /&gt;
     &amp;lt;Nr&amp;gt;       - laufende Nummer des Verbrauchers / Gerätes (01, 02, 03, 04,...)&lt;br /&gt;
     &amp;lt;HoD&amp;gt;      - abzufragende Stunde (01 - 24, 99)&lt;br /&gt;
     &amp;lt;nhr&amp;gt;      - nächste Stunde (NextHour00, NextHour01,...)&lt;br /&gt;
     &amp;lt;Key&amp;gt;      - der abzufragende Schlüssel &lt;br /&gt;
     &amp;lt;default&amp;gt;  - def default-Rückgabewert&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Auswerten von internen Arrays ===&lt;br /&gt;
&lt;br /&gt;
Die meisten der internen Datenstrukturen liefern bei der Abfrage einen einfachen String oder numerischen Wert der ausgewertet werden kann. Es gibt allerdings auch intern gespeicherte Wertelisten. Werden die Listenstrukturen mit den oben beschriebenen Befehlen abgefragt, wird eine Referenz auf die Liste geliefert sofern sie vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
Um auf die Werte einer solchen Liste zuzugreifen, ist am Beispiel des Arrays &#039;&#039;surplusslidereg&#039;&#039; aus dem Current-Speicher (get ... valCurrent) dargestellt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
my $splref = CurrentVal ($name, &#039;surplusslidereg&#039;, &#039;.&#039;);&lt;br /&gt;
my $spser  = ref $splref eq &#039;ARRAY&#039; ? join &#039; &#039;, @{$splref} : undef;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Variable $spser enthält bei Vorhandensein der Liste einen String, der die Listenelemente von &#039;surplusslidereg&#039; durch Leerzeichen getrennt enthält.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backup und Wiederherstellung der Moduldaten ==&lt;br /&gt;
Neben der Datenhaltung in den Attributen und Readings des SolarForecast Devices, erzeugt jedes SolarForecast Device Dateien im Verzeichnis  &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; mit folgenden Inhalten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PVH_SolarForecast_&amp;lt;name&amp;gt;        - PV History&lt;br /&gt;
PVC_SolarForecast_&amp;lt;name&amp;gt;        - PV Circular&lt;br /&gt;
PVCfg_SolarForecast_&amp;lt;name&amp;gt;      - PV Anlagenkonfiguration&lt;br /&gt;
PVCsm_SolarForecast_&amp;lt;name&amp;gt;      - Consumer Status&lt;br /&gt;
ScApi_SolarForecast_&amp;lt;name&amp;gt;      - Strahlungswerte aus verwendeter API&lt;br /&gt;
StatApi_SolarForecast_&amp;lt;name&amp;gt;    - Statusdaten der verwendeten API&#039;s&lt;br /&gt;
WeatherApi_SolarForecast_&amp;lt;name&amp;gt; - Wetterdaten der gewählten Wetter-API (außer DWD-Device)&lt;br /&gt;
AItra_SolarForecast_&amp;lt;name&amp;gt;      - KI Entscheidungsquelle (trainierte Daten)&lt;br /&gt;
AIraw_SolarForecast_&amp;lt;name&amp;gt;      - KI Input Daten = Raw Trainigsdaten&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nach Ausprägung und eingesetzten Features des SolarForecast Devices sind alle oder nur ein Teil dieser Dateien vorhanden. Dabei ist &#039;&#039;&#039;&amp;lt;name&amp;gt;&#039;&#039;&#039; der Name des SolarForecast Devices.&lt;br /&gt;
&lt;br /&gt;
Bei einem Filebackup des FHEM-Servers ist darauf zu achten, dass diese Dateien in dem Backup enthalten sind. Der Inhalt der Dateien ist nicht statisch, sondern kann sich dynamisch aktualisieren. Um im Bedarfsfall einen aktuellen Datenstand zu haben, ist mindestens ein tägliches Backup dieser Dateien empfehlenswert. Eventuell auch öfter mit Hilfe einer Versionierung welche z.B. immer die letzten 3 Versionen aufbewahrt.&lt;br /&gt;
&lt;br /&gt;
Beim Start von FHEM werden bestimmte Dateien automatisch gelesen und in das SolarForecast Device importiert. &lt;br /&gt;
Der Vorgang ist mit verbose=3 im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2023.10.02 09:57:07.967 3: SolCast6 - cached data &amp;quot;pvHistory&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.969 3: SolCast6 - cached data &amp;quot;pvCircular&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;consumerMaster&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;radiationApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;statusApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;weatherApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.974 3: SolCast6 - cached data &amp;quot;aiTrainedData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.976 3: SolCast6 - cached data &amp;quot;aiRawData&amp;quot; restored&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bestimmte Betriebsdaten, wie z.B. die witterungsabhängigen Korrekturfaktoren (circular) oder die KI-Daten (aitrained/airaw), bauen sich über die Zeit immer granularer auf und stellen einen wertvollen Datenbestand dar.&lt;br /&gt;
&lt;br /&gt;
Wird das SolarForecast Device gelöscht und anschließend wieder neu mit dem gleichen Namen definiert, können die bisher verfügbaren Daten sehr einfach wiederhergestellt werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. starten von FHEM (bestimmte Daten werden automatisch importiert)&lt;br /&gt;
* 5. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Soll das neue SolarForecast Device mit einem anderen Namen oder weitere SolarForecast Devices erstellt werden, welche die Betriebsdaten des primären Devices verwenden sollen, ist wie folgt vorzugehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. umbenenen der Dateien, wobei &amp;lt;name&amp;gt; durch den Namen des neuen SolarForecast Devices ersetzt wird&lt;br /&gt;
* 5. starten von FHEM (die Daten werden automatisch importiert)&lt;br /&gt;
* 6. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn sich die SolarForecast Devices hinsichtlich ihres Models oder der integrierten Consumer unterscheiden, sind die Dateien &amp;quot;PVCsm_SolarForecast_&amp;lt;name&amp;gt; &amp;quot; , &amp;quot;ScApi_SolarForecast_&amp;lt;name&amp;gt;&amp;quot; von dem Verfahren auszuschließen.&lt;br /&gt;
&lt;br /&gt;
== Batterieintegration und -steuerung ==&lt;br /&gt;
&lt;br /&gt;
=== Wie eine Batterie eingebunden wird ===&lt;br /&gt;
Wie immer muß die Batterieanlage zunächst mit einem für die Batterie spezifischen FHEM-Device in FHEM definiert sein.&lt;br /&gt;
In diesem Device werden Readings erwartet die folgende Werte bereitstellen:&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieentladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die installierte Batteriekapazität liefert (&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; dieser Schlüssel ist für die Aktivierung des Batterie SOC-Managements und die grafische Anzeige des SOC wesentlich!)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Lade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Entlade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* Reading welches den aktuellen Ladezustand (SOC in Prozent) liefert (optional)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Batterie, bzw. das Batteriedevice wird mit dem Attribut &#039;&#039;&#039;setupBatteryDev&#039;&#039;&#039; im SolarForecast Device registriert. Die Syntax des Attributes ist in  der Online-Hilfe zum Attribut umfassend erläutert. &lt;br /&gt;
Auch wenn manche Readings optional sind, wird empfohlen alle Werte bereitzustellen um alle Batterie-Funktionen im Modul nutzen zu können. Durch die Weiterentwicklung des Moduls können optionale Readings später auch obligatorisch werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Visualisierung der Batterie in der Balkengrafik ====&lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;setupBatteryDevXX&#039;&#039;&#039; verfügt über den Schlüssel &#039;&#039;&#039;show&#039;&#039;&#039;, mit dem die Einblendung des bzw. der Batteriesymbole in den Ebenen der Balkengrafik gesteuert werden kann:&lt;br /&gt;
[[Datei:Screenshot 2025-02-23 192002.png|right|thumb|400px|Einblendung der Batterieleiste und Darstellung des Batterie-SoC als Balkencontent in der zweiten Ebene]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 0 - keine Anzeige des Gerätes (default)&lt;br /&gt;
* 1 - Anzeige des Gerätes in der Balkengrafik Ebene 1&lt;br /&gt;
* 2 - Anzeige des Gerätes in der Balkengrafik Ebene 2 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Symbole und die Farbgebung der Batterie(n) können mittels des Schlüssels &#039;&#039;&#039;icon&#039;&#039;&#039; verändert werden. Die Online-Hilfe gibt weitere Informationen zur Ausgestaltung. &lt;br /&gt;
&lt;br /&gt;
In der Batteriedarstellung wird das Symbol der aktuellen Stunde hervorgehoben. Ein Mouse-Over zeigt wesentliche Betriebszustände der Batterie. Die Batteriesymbole vergangener Stunden zeigen mit einem Mouse-Over die erreichten SoC (State of Charge) Stände. Die kommenden Stunden visualisieren die folgenden Prognosen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der prognostizierte SoC unter Berücksichtigung der PV-Prognose und der [[#Aktivierung_des_Batterie_SOC-Managements|Batteriesteuerung]] sofern sie im Modul aktiviert ist.&lt;br /&gt;
* eine Freigabe bzw. Empfehlung der Batterieladung zur [[#Unterstützung_eines_netzdienlichen_Verhaltens|Unterstützung eines netzdienlichen Verhaltens]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Neben der Einblendung der Batterieleiste über der Balkengrafik selbst können bestimmte Batteriekennwerte als Balkeninhalt dargestellt werden. Die Auswahl erfolgt über das Attribut &#039;&#039;&#039;graphicBeamXContent&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Aktivierung des Batterie SOC- und Lade-Managements ===&lt;br /&gt;
Das integrierte SOC- und Lade-Management verfolgt insbesondere zwei Ziele: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* den Ladezustand der Batterie(n) zu optmimieren, was besonders in den Monaten mit geringerer PV-Erzeugung einen wertvollen Beitrag zur Erhöhung der Autarkierate und Batteriepflege leisten kann&lt;br /&gt;
 &lt;br /&gt;
* eine PV-Prognose und Verbrauch optimierte Beladungssteuerung, die in den Monaten mit hoher PV-Erzeugung hilft eine evtl. Abregelung der Anlage zu verhindern, die Batterie ausgewogen über den Tag zu laden und ein netzdienliches Verhalten zu unterstützen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese beiden Aspekte der Batteriesteuerung werden in den folgenden Abschnitten beschrieben. Sind mehrere Batterien installiert, kann die Steuerung getrennt für jede einzelne Batterie aktiviert und eingestellt werden. Dabei ist zu beachten, dass vom Modul nur Signale und Readings bereitgestellt werden, die durch eine entsprechende Routine ausgewertet werden können um spezifische Befehle zur Umsetzung der Steuerung an das Batteriesystem zu senden. &lt;br /&gt;
 &lt;br /&gt;
Für eine Aktivierung des Managements muß zunächst das Batterie-Device wie im vorigen Abschnitt im SolarForecast Device registriert werden.&lt;br /&gt;
Das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; aktiviert die im Modul integrierte SOC- und Lade-Management Routine: &lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; ctrlBatSocManagement01 lowSoc=&amp;lt;Wert&amp;gt; upSoC=&amp;lt;Wert&amp;gt; [maxSoC=&amp;lt;Wert&amp;gt;] [careCycle=&amp;lt;Wert&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
Die einzelnen Schlüssel werden der Kalkulationsroutine als Steuerungsparameter übergeben und bedeuten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;lowSoc:unterer Mindest-SoC, die Batterie wird nicht tiefer als dieser Wert entladen (muß &amp;gt; 0 sein). Dieser Wert kann zum Beispiel dazu dienen, stets eine Mindestenergiemenge für den Fall eines Stromausfalls im öffentlichen Netz in den Batterien vorzuhalten.&lt;br /&gt;
&lt;br /&gt;
;upSoC:oberer Mindest-SoC, Der übliche Wert des optimalen SoC bewegt sich in Perioden mit hohen PV-Überschuß tendenziell zwischen &#039;lowSoC&#039; und &#039;upSoC&#039;, in Perioden mit geringer PV-Ausbeute bzw. geringem PV Energieüberschuß bewegt sich der optimale SoC tendenziell zwischen &#039;upSoC&#039; und &#039;maxSoC&#039;. Die Einstellung von upSoC=50 für ein ausgewogenes Verhalten kann als guter Startwert dienen.&lt;br /&gt;
&lt;br /&gt;
;maxSoC:maximaler Mindest-SoC, d.h. der SoC Wert der mindestens im Abstand von &#039;careCycle&#039; Tagen erreicht werden muß um den Ladungsausgleich im Speicherverbund auszuführen. Die Angabe ist optional (muß &amp;lt;= 100 sein, default: 95)&lt;br /&gt;
&lt;br /&gt;
;careCycle:maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens &#039;maxSoC&#039; auftreten darf. Die Angabe ist optional. (default: 20)&lt;br /&gt;
&lt;br /&gt;
;loadAbort: definiert eine vom Anwender gewünnschte Bedingung für einen generellen Ladeabbruch und Wiederfreigabe der Lademöglichkeit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle Werte sind ganze Zahlen in %. Dabei gilt: &lt;br /&gt;
&lt;br /&gt;
 lowSoc &amp;lt; upSoC &amp;lt; maxSoC&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====  Erläuterung der Batterie-Steuerungsreadings ==== &lt;br /&gt;
&lt;br /&gt;
Für die Steuerung des Batteriesystems gibt es im SolarForecast einen Satz an Readings, die unterschiedliche Zustände signalisieren und für entsprechende Steuerungsaufgaben bezüglich der Batteriesysteme eingesetzt werden können. In den nachfolgenden Abschnitten werden diese Zusammenhänge noch dataillierter beschrieben.&lt;br /&gt;
&lt;br /&gt;
;Hinweis: SolarForecast stellt lediglich Steuerungsinformationen zur Verfügung. Die Umsetzung des Eingriffs in das Batteriesystem erfolgt durch den Anwender selbst über entsprechende Skripte. In den thematischen Abschnitten werden Beispiele für solche Steuerungsskripte vorgestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle erstellten Readings gelten für ein Batteriesystem, es können mehrere Batteriesysteme in SolarForecast integriert sein. Die Endung &#039;&#039;XX&#039;&#039; der Readings beschreibt die Nummer des Batteriesystems und korrespondiert mit der Endung des entsprechenden Attributes &#039;&#039;ctrlBatSocManagementXX&#039;&#039; bzw. &#039;&#039;setupBatteryDevXX&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Battery_OptimumTargetSoC_XX: Mit den im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; hinterlegten Parametern unter Berücksichtigung von PV- und Verbrauchsprognosen wird ein optimaler SOC-Wert errechnet. Dieser Wert dient zur Einstellung des unteren SOC des Batteriesystems.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeRequest_XX: Dieses Reading signalisiert mit 1 eine Anforderung zur Zwangsladung der Batterie um die Batterie vor Schäden zu schützen (wenn der SOC unter ctrlBatSocManagementXX-&amp;gt;lowSoc gefallen ist) oder wenn der aktuelle SOC unter den berechneten Mindest-SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeUnrestricted_XX: Dieses Reading kann den Wert &#039;&#039;&#039;0&#039;&#039;&#039; oder &#039;&#039;&#039;1&#039;&#039;&#039; einnehmen. Ist der Inhalt 0, sollte die Batterie nur geladen werden, wenn der im Attribut &#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039; definierte Wert überschritten wird. Ist der Inhalt 1, sollte die Batterie mit der vollen zur Verfügung stehenden Ladeleistung angesteuert werden, um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeAbort_XX: Im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; kann mit dem Schlüssel &#039;&#039;loadAbort&#039;&#039; eine Bedingung definiert werden, bei deren Eintritt die Ladung der Batterie abgebrochen werden soll. In diesem Fall wird &#039;&#039;Battery_ChargeAbort_XX=1&#039;&#039; gesetzt. Mit einem entsprechenden Befehl kann der Anwender das Batteriesystem anweisen den Ladevorgang abzubrechen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Nutzung des Batterie SOC-Management ====&lt;br /&gt;
&lt;br /&gt;
Oftmals wird durch die Anlagenhersteller ein hoher statischer SOC eingestellt bzw. empfohlen, der eine längere Verharrungszeit auf einem tiefen SOC-Wert verhindern soll. Allerdings wechseln sich in auch in den Herbst-, Frühlings- und Wintermonaten Zeiten mit wenig PV-Erzeugung mit Phasen stärkerer Solarstrahlung bei klarem Himmel und Sonnenschein ab.&lt;br /&gt;
&lt;br /&gt;
Ein statischer SOC würde dazu führen, dass in den erwähnten Phasen zuviel Energie in das öffentliche Netz eingespeist wird. Dies soll verhindert werden da die wertvolle Energie besser im eigenen Netz gespeichert und in Dunkelphasen verwendet werden kann. Andererseits soll die Batterie nicht zu lange auf einem tiefen SOC verbleiben und außerdem in gewissen Abständen auf einen so hohen SOC geladen werden der den internen Zellausgleich ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Die SOC Kalkulationsroutine des Moduls errechnet unter Berücksichtigung des prognostizierten PV-Ertrages der kommenden Tage, des aktuellen SOC und der im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; (nachfolgend beschrieben) angegebenen Steuerparameter den Vorschlag für eine optimale SOC-Einstellung. Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert.&lt;br /&gt;
&lt;br /&gt;
Durch das Modul selbst findet keine Steuerung der Batterie statt. Es stellt entsprechende Readings zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen SoC.&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SoC unter den optimalen SoC gefallen ist. In diesem Fall sollte die Batterie, unter Umständen mit Netzstrom, zwangsgeladen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Readings können zur Steuerung des SoC (State of Charge) sowie zur Steuerung des verwendeten Ladestroms der Batterie verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ermittlung des optimalen SOC erfolgt nach folgender Logik:&lt;br /&gt;
&lt;br /&gt;
# 	Ausgehend von &#039;lowSoc&#039; wird der Mindest-SoC kurz vor Sonnenuntergang um 5% inkrementiert sofern am laufenden Tag &#039;maxSoC&#039; nicht erreicht wurde und die PV-Prognose keinen hinreichenden Ertrag des kommenden Tages vorhersagt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Wird &#039;maxSoC&#039; (wieder) erreicht, wird Mindest-SoC um 5%, aber nicht tiefer als &#039;lowSoc&#039;, verringert. Ist der berechnete Mindest-SoC größer als &#039;upSoc&#039;, wird der Mindest-SoC auf &#039;upSoc&#039; gesetzt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#   Mindest-SoC wird soweit verringert, dass die prognostizierte PV Energie des aktuellen bzw. des folgenden Tages von der Batterie aufgenommen werden kann. Mindest-SoC wird typisch auf &#039;upSoc&#039; und nicht tiefer als &#039;lowSoc&#039; verringert.  &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Das Modul erfasst den letzten Zeitpunkt am &#039;maxSoC&#039;-Level, um eine Ladung auf &#039;maxSoC&#039; mindestens alle &#039;careCycle&#039; Tage zu realisieren. Zu diesem Zweck wird der optimierte SoC in Abhängigkeit der Resttage bis zum nächsten &#039;careCycle&#039; Zeitpunkt derart verändert, dass durch eine tägliche 5% SoC-Steigerung &#039;maxSoC&#039; am &#039;careCycle&#039; Zeitpunkt rechnerisch erreicht wird. Wird zwischenzeitlich &#039;maxSoC&#039; erreicht, beginnt der &#039;careCycle&#039; Zeitraum erneut. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im fünften Schritt werden die Grenzen &#039;lowSoc&#039; und &#039;upSoc&#039; berücksichtigt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im letzten Schritt erfolgt Generierung des Readings &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; zur Signalisierung einer eventuell empfohlenen Zwangsladung auf den berechneten Min-SoC. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei sehr wenig Erzeugungungsprognose, d.h. wenn sich der berechnete Min-SoC oberhalb von &#039;upSoC&#039; bewegt, wird &#039;upSoC&#039; eingestellt. Liegt der berechnete Min-SoC unterhalb von &#039;upSoC&#039;, ist jedoch größer als &#039;lowSoC&#039;, wird der berechnete SOC im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; eingestellt. Somit eignet sich die Angabe im Schlüssel &#039;upSoC&#039; um in Zeiten geringer Solarenergieerzeugung die Batterie für eine Notstromerzeugung auf mindestens diesem Wert zu halten. Sollte die PV-Prognose kurzfristig einen größeren Ertrag vorhersagen als die Batterie durch die Einhaltung von &#039;upSoC&#039; aufnehmen kann, wird der Min-SoC unter &#039;upSoC&#039; abgesenkt um möglichst allen PV-Überschuß in der Batterie zu speichern und somit dem Eigenverbrauch zuzuführen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der berechnete Mindest-SoC ist immer nur ein unterer Grenzwert. Die Batterie kann durch Ladevorgänge natürlich jederzeit einen höheren als den im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; dargestellten optimalen SoC haben. Der optimale SoC sollte nicht unterschritten werden um die oben genannten Zusammenhänge abbilden zu können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Die dynamische SOC Steuerung mit Umsetzungsbeispiel =====&lt;br /&gt;
Das Modul bietet eine Unterstützung zur automatisierten Einstellung eines optimalen SoC Wertes.&lt;br /&gt;
&lt;br /&gt;
Ziel ist es, den Minimum SoC in Abhängigkeit der zu erwartenden Solarerträge des aktuellen und des folgenden Tages so einzustellen, dass der prognostizierte Solarertrag von der Batterie aufgenommen werden kann. Die Einspeisung in das öffentliche Netz soll minimiert werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin soll ein unterer SoC nicht unterschritten, sowie ein oberer Minimum SoC im Normalfall nicht überschritten werden. Der obere Grenzwert stellt sicher, dass die Batterie mindestens bis zu diesem Wert wieder entladen werden kann. Dadurch bleibt innerhalb der Batterie immer genügend Kapazität verfügbar um unvorhergesehene PV Energie aufnehmen zu können.&lt;br /&gt;
&lt;br /&gt;
Aktiviert wird die Unterstützung der Batteriesteuerung durch das Setzen des Attributes &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; z.B. mit diesen Angaben:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagementXX lowSoc=x upSoC=x maxSoC=x careCycle=x &lt;br /&gt;
&lt;br /&gt;
so zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=98 careCycle=20&lt;br /&gt;
&lt;br /&gt;
Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert. &lt;br /&gt;
Ist dieses Attribut gesetzt, werden Steuerungs-Readings erstellt, die der Nutzer auswerten und seine Batterieanlage z.B. via notify oder DOIF steuern kann. &amp;lt;bR&amp;gt;&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen Mindest-SoC.&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SOC unter den optimalen SOC bzw. minimalen SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
Die Schlüssel &#039;&#039;&#039;lowSoc&#039;&#039;&#039; und &#039;&#039;&#039;upSoC&#039;&#039;&#039; sind die unteren und oberen Grenzen, zwischen denen sich der Minimum SoC im normalen Betrieb bewegen soll.&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;maxSoC&#039;&#039;&#039; stellt eine Ladungsgrenze dar, die mindestens alle X (careCycle) Tage erreicht werden soll. Zu diesem Zweck errechnet das Modul die Anzahl der nötigen Erhöhungen der Minimum Batterieladung von 5% pro Tag um ausgehend vom aktuellen SoC-Level. Der resultierende Minimum SoC Wert wird entsprechend angepasst. Wurde der einstellte maxSoC Level erreicht, startet der Wartungszyklus (careCycle) erneut. &amp;lt;br&amp;gt;&lt;br /&gt;
Der maxSoC in Verbindung mit dem durch &#039;&#039;&#039;careCycle&#039;&#039;&#039; definierten Zyklus soll sicherstellen, dass der Batterieverbund in regelmäßigen Abständen einen Ladungsausgleich vollziehen kann. &lt;br /&gt;
&lt;br /&gt;
Durch die Modullogik erfolgt eine 5 protentige Anhebung des Minimum SoC wenn am Vortag maxSoC nicht erreicht wurde. Die Anhebung erfolgt aber nicht über upSoC. upSoC ist die obere Grenze des Minimum SoC. Wird am Vortag mindestens die maxSoC Ladung erreicht, verringert sich der Minimum SoC wieder schrittweise um 5%, aber nicht tiefer als lowSoc.&lt;br /&gt;
&lt;br /&gt;
Ergänzt wird die Logik noch um die PV Vorhersage. Dabei wird die obige Minimum SoC Berechnung um die Erwartung der PV Erwartung am aktuellen und folgenden Tag korrigiert. Das bedeutet, dass der Minimum SoC z.B. von heute 50% auf 10% abgesenkt und dadurch die gespeicherte Energie dem Haushalt zugeführt wird, wenn am heutigen oder kommenden Tag eine entsprechende PV Energie zu erwarten ist um die Batterie wieder vollständig zu zuladen.&lt;br /&gt;
Dadurch ist immer genügend &amp;quot;Freiplatz&amp;quot; in der Batterie und andererseits hat die Batterie in langen Dunkelphasen eine Reserve für einen eventuellen Stromausfall (falls der abgesichert werden soll) und wird vor einem dauerhaften tiefen SoC geschützt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Umsetzungsbeispiel =====&lt;br /&gt;
&lt;br /&gt;
Wie das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; genutzt werden kann, wird am Beispiel einer Victron Batterieanlage gezeigt. Die Anlage wird durch Cerbo GX Gerät gesteuert. Der Cerbo GX ist per MQTT2 in FHEM eingebunden. Umgesetzt ist die Steuerung der Batterie &#039;01&#039;, d.h. die Angabe &#039;XX&#039; ist durch &#039;01&#039; ersetzt.&lt;br /&gt;
&lt;br /&gt;
Die folgende kleine Logik ist in einem &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; File eingebaut und wird regelmäßig mit&lt;br /&gt;
&lt;br /&gt;
 batSocChargeMgmnt (&#039;&amp;lt;Name SolarForecast Device&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
aufgerufen. Der Aufruf erfolgt durch Angabe der Routine im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; des SolarForecast Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
  # Hinweis: die Zeichen &#039;::&#039; vor der Routine sind durch das SolarForecast Package bedingt&lt;br /&gt;
  ::batSocChargeMgmnt ($name);&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Routine wird dadurch automatisch am Ende jedes Zyklus (siehe Attribut plantControl-&amp;gt;cycleInterval) ausgeführt.&lt;br /&gt;
Um die SOC Managementfunktion nach Bedarf ein- bzw. ausschalten zu können wird zunächst im SolarForecast Device ein userattr zur Steuerung der SOC-Logik angelegt:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; userattr userFn_BatterySoCManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
Die Perl Routine &#039;&#039;&#039;batSocChargeMgmnt&#039;&#039;&#039; ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#  Batterie SOC und Max. Ladestrom Management&lt;br /&gt;
############################################################################&lt;br /&gt;
sub batSocChargeMgmnt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vebus   = &#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;;                            # Victron Vebus Device&lt;br /&gt;
  my $vicsets = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                         # Victron Einstellungen&lt;br /&gt;
&lt;br /&gt;
  my $maxcspc = 105;                                                           # max. Ladestrom (A) Victron MPII Verbund&lt;br /&gt;
  my $actmcc  = ReadingsNum ($vebus, &#039;MaxChargeCurrent&#039;, undef);               # akt. Ladestromeinstellung&lt;br /&gt;
  my $load    = $actmcc // $maxcspc;                                           # Soll-Ladestrom (A)&lt;br /&gt;
&lt;br /&gt;
  ## Battery SoC Management&lt;br /&gt;
  ###########################&lt;br /&gt;
  my $ubsm = AttrVal ($name, &#039;userFn_BatterySoCManagement&#039;, &#039;aus&#039;); &lt;br /&gt;
  &lt;br /&gt;
  if ($ubsm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name,    &#039;Battery_ChargeRequest_01&#039;,     0);&lt;br /&gt;
    my $csoc = ReadingsNum ($vicsets, &#039;MinimumSocLimit&#039;,             10);      # akt. SoC&lt;br /&gt;
    my $osoc = ReadingsNum ($name,    &#039;Battery_OptimumTargetSoC_01&#039;, 10);      # Soll-SoC&lt;br /&gt;
    my $surp = ReadingsNum ($name,    &#039;Current_Surplus&#039;,              0);      # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if ($csoc != $osoc) {&lt;br /&gt;
      CommandSet (undef, &amp;quot;$vicsets MinimumSocLimit $osoc&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn SoCMgmnt -&amp;gt; MinimumSocLimit in $vicsets set to $osoc %});&lt;br /&gt;
    }&lt;br /&gt;
	                                           &lt;br /&gt;
    if ($bcrq &amp;amp;&amp;amp; $surp &amp;lt; 1000) {                                              # max. Strom b. Battery_ChargeRequest &lt;br /&gt;
      $load = 21;&lt;br /&gt;
    }&lt;br /&gt;
	else {&lt;br /&gt;
	  $load = $maxcspc;&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Batterie Einstellung MaxChargeCurrent&lt;br /&gt;
  ##########################################&lt;br /&gt;
  if ($load != $actmcc) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$vebus MaxChargeCurrent $load&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
    Log3 ($name, 3, qq{$name - userFn ChargeMgmnt -&amp;gt; MaxChargeCurrent in $vebus set }.&lt;br /&gt;
                    qq{from old $actmcc A to $load A});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent_set&#039;, $load, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist im SolarForecast Device das Reading  &#039;&#039;&#039;Battery_ChargeRequest_01&#039;&#039;&#039; gesetzt, ist der aktuelle SOC kleiner als der optimale SOC und die Batterie wird (eventuell aus dem öffentlichen Netz) geladen. Das kann automatisch durch den Cerbo GX bzw. in anderen Anlagen durch einen entsprechenden Befehl erfolgen.&lt;br /&gt;
Damit die Netzbeladung nicht mit der vollen Ladestromstärke geschieht, wird der Ladestrom auf den gewünschten Wert (hier 21 A -&amp;gt; ca. 1000 W bei einem 48V System) reduziert sofern kein oder zu wenig PV-Überschuß vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== weitere mögliche Aspekte der SOC- und Batterieladesteuerung ====&lt;br /&gt;
&lt;br /&gt;
SolarForecast liefert durch seine internen Logiken bereits sehr hilfreiche Signale zur Steuerung von Batteriesystemen in Form von Readings an. Abhängig von den individuellen Möglichkeiten der vorhandenen Anlage käme zum Beispiel zusätzlich zu einer Steurung des optimalen SOC oder der Zeitfenster für die Batterieaufladung auch eine Steuerung des Ladestroms bzw. der verwendeten Ladeleistung in Betracht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hintergründe:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Das Laden eines Akkus mit möglichst gleichbleibender und geringer Leistung wirkt sich positiv auf dessen Langlebigkeit aus, was u.a. auch daran liegt, dass der Temperaturstreß im Akku bei langsamer Energiezuführung nur gering ist.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom führt zu einem geringen Absacken der Akkuspannung beim (ggf, temporären) Abschalten des Ladestroms, was sich positiv auf die SOC-Schätzung auswirkt.&lt;br /&gt;
    &lt;br /&gt;
* Ein geringer Ladestrom führt, insb. bei Nutzung passiver Balancer (sind in den Akku-Systemen üblicherweise verbaut), zu einer geringen Differenz zwischen den einzelnen Zellspannungen und damit zu einer besseren Kapazitätsausnutzung eins Akkus.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom kann zu einem zeitlich punktgenauen Zielfüllstand (im Winter 100%, ansonsten natürlich weniger) am Ende des Tages führen.&lt;br /&gt;
    &lt;br /&gt;
* Eine geringer Ladestrom führt auch zu geringen Leitungsverlusten, da der Strom quadratisch zu den Leitungsverlusten beiträgt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann auch die Verweildauer oder die Begrenzung des SOC, auf den die Batterie maximal geladen werden soll, Gegenstand von Optimierungen sein.&lt;br /&gt;
&lt;br /&gt;
Die häufig zu findende Empfehlung, Akkus nicht zu lange bei einem SOC von 100% verweilen zu lassen, liegt weniger an dem SOC als solchem, sondern daran, dass &#039;&#039;SOC=100%&#039;&#039; üblicherweise dadurch ermittelt wird, dass eine Zelle im Akku einen Spannungsschwellenwert überschreitet, der – würde dieser Schwellenwert zeitlich länger überschritten sein – zu einer Schädigung des Akkus führen könnte. Schädlich sind insbesondere häufige Nachladevorgänge bei Werten um die 100% SOC, da Zellen dann ja häufiger und damit - integral gesehen - auch länger den o.g. Schwellenwert überschreiten.&lt;br /&gt;
&lt;br /&gt;
Einige Akku-Hersteller, z.B. BYD, haben auf o.g, Grund in der (neueren) Firmware Ihrer Systeme einen SOC-Threshold (bei BYD liegt dieser bei 95%) eingebaut. Dieser Wert muss nach einem erreichten SOC von 100% unterschritten  werden, bevor überhaupt eine weitere Ladung erfolgt. Insbesondere in der dunklen Jahreszeit kann es daher sinnvoll sein, den Akku unter Verwendung von PV-Leistung so zu füllen, dass dieser möglichst nur einmal vor Einbruch der Dunkelheit auf &#039;&#039;SOC=100%&#039;&#039; geladen wird. Hierbei sollte darauf geachtet werden, dass der Ladeschlussstrom des jeweiligen Systems nicht unterschritten wird. &lt;br /&gt;
&lt;br /&gt;
SolarForecast unterstützt die oben betrachtete Batteriesteuerung durch die optionale Angabe von &#039;&#039;&#039;loadAbort&#039;&#039;&#039; im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039;. Das in diesem Kontext erstellte Reading &#039;&#039;&#039;Battery_ChargeAbort_XX&#039;&#039;&#039; stellt die auswertbaren Steuerungsinformationen zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== PV-Prognose und Verbrauch optimierte Beladungssteuerung unter Berücksichtigung einer Wirkleistungsbegrenzung ====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-04-25 143910.png|right|thumb|400px|Batterie Popup &amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Batterie geladen. sobald PV-Überschuß vorhanden ist ohne eine Prognose zu berücksichtigen. Dadurch sind die Batterien im Sommer unter Umständen schon um 10-12 Uhr voll geladen und die Anlage liefert ihre mehr oder weniger volle Energie (je nach Ausrichtung) in das öffentliche Netz. Dann könnte es zu einer Begrenzung der PV-Leistung durch einen Schwellenwert (z.B. 70%-Regelung) oder eventuell Zwangsabregelung durch den Netzbetreiber kommen.&lt;br /&gt;
&lt;br /&gt;
Hintergrund dieser Erweiterung ist das Bestreben, eine optimale Unterstützung bei der Maximierung des Eigenverbrauchs zu geben und einen Beitrag zur Netzstabilität zu leisten.&lt;br /&gt;
Das Ziel der Beladungssteuerung der Batterie ist es, die Ladung der Batterie über den Tag verteilt so zu steuern, dass die Batterie erst dann geladen wird, wenn durch den PV-Überschuß eine Netzeinspeisung erfolgen würde bzw. ein Grenzwert erreicht werden würde, der zu einer Abregelung der PV-Anlage führen könnte.&lt;br /&gt;
Es kann auch zu einer Zwangsabregelung durch den Netzbetreiber führen, was vermieden werden soll.&lt;br /&gt;
 &lt;br /&gt;
Die interne Kalkulationslogik erstellt zu diesem Zweck ein Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039;.&lt;br /&gt;
Dieses Reading gibt dem User ein Signal, ob zu der aktuellen Stunde der Ladevorgang der Batterie freigegeben (1) oder nicht freigegeben werden sollte (0). Die Freigabe zur Ladung bedeutet dass:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; die Batterie mit ihrer vollen Ladeleistung angesteuert werden sollte um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=0&#039;&#039;&#039; die Batterie nur geladen werden sollte wenn der im Attribut plantControl-&amp;gt;feedinPowerLimit definierte Wert überschritten wird&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ist keine Freigabe zur Ladung vorhanden, kann bzw. sollte dennoch eine Ladung der Batterie vorgenommen werden, sofern eine über dem im &amp;lt;br&amp;gt;&lt;br /&gt;
Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limit liegende Einspeiseleistung vorhanden ist. In diesem Status sollte die Batterie nur mit der Differenzleistung von vorhandener Einspeiseleistung und dem gesetzen Einspeiselimit geladen werden und damit das gesetzte Einspeiselimit einhalten ohne die Anlage abzuregeln. Ist die Batterie in einer Balkengrafikebene dargestellt, wird im Mouse-Over Popup die Battrie mit &#039;&#039;&amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;&#039;&#039; gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Möglichkeiten der Batteriesteuerung sind stark von der individuellen Anlage abhängig und können hier nicht beschrieben werden. Ein Umsetzungsbeispiel mit einer Victron-Anlage mit Pylontech Batterie ist weiter unten dargestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Aktivierung und Arbeitsweise =====&lt;br /&gt;
&lt;br /&gt;
Die implementierte Logik zur optimierten Batterie Beladungssteuerung wird aktiviert, wenn folgende Kriterien erfüllt sind: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;capacity&#039;&#039;&#039; in den setupInverterDevXX Atributen ist gesetzt&lt;br /&gt;
* das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; für die jeweilige Batterie ist gesetzt&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;cap&#039;&#039;&#039; im Attribut setupBatteryDevXX der jeweiligen Batterie ist gesetzt&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Die Logik arbeitet wie folgt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Der resultierende Schwellenwert der Wirkleistungsbegrenzung: der Gesamtanlage wird durch die Auswertung der in den Inverter-Attributen setupInverterDevXX  gesetzen Schlüssel limit (optional) und capacity ermittelt. Inverter mit gesetztem Schlüssel feed = grid (deren Energie wird ausschließlich in das öffentlich Netz eingespeist) werden von der Betrachtung in diesem Kontext ausgeschlossen.&lt;br /&gt;
&lt;br /&gt;
;Die benötigte Beladung bis zu maxSoC (im Attribut setupBatteryDevXX) : wird ermittelt und mit der zu erwartenden PV Tagesprognose in Beziehung gesetzt. Sofern die PV-Erzeugung abzgl. Verbrauch noch nicht das Wirkleistungbegrenzungs-Limit erreicht UND noch genügend PV-Überschuß für eine Ladung auf &#039;&#039;maxSoC&#039;&#039; im Laufe der kommenden Stunden des Tages zu erwarten ist, bleibt das Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 0&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
;Wird das Wirkleistungbegrenzungs-Limit erreicht/überschritten und/oder die PV-Überschußprognose: zzgl. eines Sicherheitspuffers unterschritten, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 1&#039;&#039;&#039; gesetzt. Der User kann darauf reagieren und den Batterie Ladevorgang aktivieren. Die Möglichkeiten der Aktivierung sind natürlich von der installierten Anlage abhängig. Das SolarForecast Device greift nicht in die Batteriesteuerung direkt ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders ausgedrückt erfolgt immer dann eine Ladefreigabe, wenn einer der nachfolgenden Sachverhalte &#039;&#039;wahr&#039;&#039; ist:&lt;br /&gt;
&lt;br /&gt;
- die benötigte Ladeenergie (aller installierten Batterien) &amp;gt;= PV-Restüberschuß des Tages (Reading RestOfDayPVforecast) zzgl. Sicherheitsaufschlag&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- der Zeitpunkt des PV-Erzeugungszenit des laufenden Tages überschritten ist (Reading Today_MaxPVforecastTime)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn die aktuelle PV Leistung &amp;gt;= einer eventuellen Wechselrichter-Leistungsbegrenzung ist (Summe aller WR-Begrenzungen)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn das BatSoc-Management _nicht_ aktiviert ist (nicht alle oben genannten Aktivierungskriterien erfüllt sind)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind mehrere Batterien installiert und durch das Management einer Batterie die Einhaltung der genannten Kriterien bzw. Sachverhalte erwirkt wird, bleiben die weiteren Batterien im Modus Ladefreigabe (Battery_ChargeUnrestricted_XX=1).  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Umsetzungsbeispiel Batterie Ladesteuerung mit Victron GX Venus über den Grid Setpoint =====&lt;br /&gt;
&lt;br /&gt;
Ziel der Steuerung ist es abhängig vom Wert des Readings Battery_ChargeUnrestricted_XX (z.B. Battery_ChargeUnrestricted_01) die Ladung des angeschlossenen Batteriesystems zu aktivieren bzw. zu deaktivieren.&lt;br /&gt;
Das vorliegende Beispiel soll umzusetzen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 0 -&amp;gt; Batterie nicht aufladen bzw. nur laden wenn Einspeiselimit überschritten (Attribut plantControl-&amp;gt;feedinPowerLimit)&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 1 -&amp;gt; Batterie aufladen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Grid Setpoint ist ein Parameter in den Victron Systemeinstellungen. Das Victron System wird den eingestellten Grid Setpoint versuchen einzuhalten und bei einem positiven Wert Energie aus dem Netz beziehen bzw. bei einem negativen Grid Setpoint Energie in das Netz einspeisen.&lt;br /&gt;
&lt;br /&gt;
Normalerweise wird das Victron System die erzeugte PV Energie zunächst zur Deckung des Hausverbrauchs verwenden, ist dann noch ein PV Überschuß vorhanden, die Batterien aufladen und bei weiter vohandenen PV Überschuß diese Energie in das öffentliche Netz einspeisen sofern dem System eine Einspeisung erlaubt ist. Anderenfalls werden die Wechselrichter oder MPPT Smartloader heruntergeregelt bzw. limitiert. &lt;br /&gt;
&lt;br /&gt;
In der Standardeinstellung ist beim Victron System ein Grid Setpoint von ca. 20 bis 50 Watt, d.h. das System strebt danach diese Vorgabe zu erfüllen zieht ständig Energie in diesem Bereich aus dem öffentlich Netz von einem gelegentlichen Überschwingen der Regelung abgesehen. Damit ein eventueller PV Überschuß nicht zum Laden der Batterie verwendet, sondern statt dessen in das öffentliche Netz eingespeist wird, muß der Grid Setpoint um diesen Betrag abgesenkt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-24 114403.png|right|thumb|400px|Integration des Grid Setpoint-Managements in den Own_Spec-Bereich]]&lt;br /&gt;
&lt;br /&gt;
Damit man später per Attribut bzw. über den [[#Formatierung_der_Inhalte_im_Bereich_&amp;quot;Graphic_Header_Own_Specification&amp;quot;|Own_Spec-Bereich]] die automatische Ladesteuerung über den Grid Setpoint ein- bzw. ausschalten kann, legen wir ein userattr an:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 userattr &amp;lt;Name&amp;gt; userFn_GridSetpointManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin sind einige Vorbereitungen im Device MQTT2_cerboGX_c0619ab34e08_settings vorzunehmen. Dieses Device ist im vorliegenden Beispiel ein in FHEM vorhandenes MQTT2_DEVICE, über das die Victron CerboGX Einstellungen zugreifbar sowie einstellbar sind. Die Vorgehensweise zur Erstellung des MQTT2_DEVICE ist hier nicht beschrieben und wird vorausgesetzt.&lt;br /&gt;
&lt;br /&gt;
Damit ein entsprechender Set-Befehl zur Einstellung des Grid Setpoints vorhanden ist, werden folgende Attribute gesetzt:&lt;br /&gt;
&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings jsonMap Settings_CGwacs_AcPowerSetPoint_value:GridSetpoint&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings setList GridSetpoint W/c0619ab34e08/settings/0/Settings/CGwacs/AcPowerSetPoint {&amp;quot;value&amp;quot;:$EVTPART1}&lt;br /&gt;
&lt;br /&gt;
Nach dieser Attributierung kann mit einem &amp;quot;&#039;&#039;set MQTT2_cerboGX_c0619ab34e08_settings GridSetpoint &amp;lt;Wert&amp;gt;&#039;&#039;&amp;quot; der Grid Setpoint eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Das Attribut userFn_GridSetpointManagement kann nun im Perl Code ausgewertet werden um das Grid Setpoint-Management ein- bzw. auszuschalten.&lt;br /&gt;
Der nachfolgende Code wird in die Datei &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; eingefügt. Ist diese Datei nicht vorhanden, legen wir sie vorab als Kopie der ausgelieferten 99_myUtils.pm an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Steuerung Start/Stop der Batterieladung über den Victron Grid Setpoint&lt;br /&gt;
############################################################################&lt;br /&gt;
sub gridSetpointMgmt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vicsets   = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                               # Device Victron Einstellungen&lt;br /&gt;
  my $gspdef    = 20;                                                                  # Default Einstellung des Grid Setpoint&lt;br /&gt;
  my $targetgsp = $gspdef;                                                             # Voreinstellung Grid Setpoint&lt;br /&gt;
  my $neggspmax = FHEM::SolarForecast::CurrentVal ($name, &#039;feedinPowerLimit&#039;, 5000);   # max. gewünschte Einspeiseleistung in Watt&lt;br /&gt;
  $neggspmax    = $neggspmax * -1;&lt;br /&gt;
  my $gspm      = AttrVal ($name, &#039;userFn_GridSetpointManagement&#039;, &#039;aus&#039;);             # Freischaltung des Grid Setpoint-Managements&lt;br /&gt;
  my $curgsp    = ReadingsNum ($vicsets, &#039;GridSetpoint&#039;,         $gspdef);             # aktuelle Einstellung Grid Setpoint&lt;br /&gt;
  &lt;br /&gt;
  if ($gspm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name, &#039;Battery_ChargeUnrestricted_01&#039;, 0);         # Ladefreigabe (1 -&amp;gt; Bat Ladefreigabe)&lt;br /&gt;
    my $surp = ReadingsNum ($name, &#039;Current_Surplus&#039;,               0);         # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if (!$bcrq) {                                                               # Grid Setpoint absenken wenn keine .. &lt;br /&gt;
        $targetgsp = $gspdef - $surp;                                           # ..Batterie Ladefreigabe&lt;br /&gt;
        $targetgsp = $neggspmax if($targetgsp &amp;lt; $neggspmax);                    # Begrenzung der Einspeiseleistung&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($curgsp != $targetgsp) {&lt;br /&gt;
	  fhem (&amp;quot;set $vicsets GridSetpoint $targetgsp&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn gridSetpointMgmt -&amp;gt; GridSetpoint in $vicsets set to $targetgsp});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Victron_GridSetpoint_set&#039;, $targetgsp, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Vergleich des Setpoints mit der Vorgabe von &#039;&#039;$neggspmax&#039;&#039; dient dazu die maximale Einspeiseleistung in das öffentliche Netz zu begrenzen. Ist diese Grenze erreicht, wird der noch verbleibende Überschuß in die Batterie geladen. Dadurch wird eine Abregelung der Anlage vermieden wenn der Schwellenwert &#039;&#039;$neggspmax&#039;&#039;erreicht ist sofern die Batterie aufnahmefähig ist und nicht voll geladen ist. &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::gridSetpointMgmt  ($name);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zum Management des automatischen Grid Setpoint und der Anzeige des eingestellten Wertes wird das Attribut und die Readinganzeige in den Own_Spec-Bereich eingebunden, z.B.:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; graphicHeaderOwnspec  #Settings&lt;br /&gt;
                                   SetPoint&amp;amp;nbsp;Management:userFn_GridSetpointManagement&lt;br /&gt;
                                   Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Unterstützung eines netzdienlichen Verhaltens ====&lt;br /&gt;
&lt;br /&gt;
Der Steuerungsprozess der Batterieanlage leistet insgesamt einen kleinen Beitrag zur Netzstabilität, indem die Speicherladung in den Zeitraum der meisten prognostizierten Überschußeinspeisung gelegt wird. Im Sommer kann sich dieser Zeitraum in die Zeit nach dem Maxmimum des prognostizierten PV-Überschusses verlagern, wenn auch danach noch genügend Überschußenergie zu Volladung der Batterie prognostiziert wird. In dem Zusammenhang sollte im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; ein Einspeiselimit gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zur Verdeutlichung soll das Beispiel dienen:&lt;br /&gt;
&lt;br /&gt;
* die Batterie ist zu 60% geladen &lt;br /&gt;
* der User hat upSoC=40 eingestellt&lt;br /&gt;
* der User hat maxSoC=90 eingestellt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Am Vormittag ist genügend Sonne vohanden, das Maximumum der Energie über die Zeit wird aber noch erwartet. &lt;br /&gt;
Zu diesem Zeitpunkt wird das Reading  &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039; auf den Wert &amp;quot;0&amp;quot; gesetzt. Durch den Nutzer erfolgt daraufhin, zum Beipiel über ein Notify, ein anlagenspezifischer Befehl &amp;quot;Ladestop&amp;quot; an die Batterieanlage. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ab diesem Moment wird:&lt;br /&gt;
&lt;br /&gt;
# die Batterie nicht geladen&lt;br /&gt;
# die erzeugte PV-Energie dem Haushalt zur Verfügung gestellt bzw. der verbleibende Überschuß eingespeist, sofern der Überschuß unterhalb des im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limits liegt.&lt;br /&gt;
# ein eventuell über dem Limit &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; vorhandener Überschuß in die Batterie geladen und so die Netzlast verringert sowie die Batterie schonend geladen. (dieser Punkt trifft in den Monaten mit wenig PV-Erzeugung eher nicht zu)  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig liefert die Batterie Energie an das Hausnetz und wird von 60% bis maximal einem SoC-Wert entladen, der durch die [[#Die_dynamische_SOC_Steuerung_mit_Umsetzungsbeispiel|dynamische SOC Steuerung]] bestimmt wird. Dazu muß diese Steuerung natürlich implementiert sein. Sofern der berechnete SoC größer als upSoC ist, wird der maximale Entladungs-SoC auf upSoC gesetzt. &lt;br /&gt;
&lt;br /&gt;
Zusätzlich überprüft das Modul permanent bei jedem Zyklus die Differenz des aktuell vorhandenen SoC zum eingestellten maxSoC.&lt;br /&gt;
Sie soll nicht größer sein um mit dem (noch) zu erwartenden PV-überschuß des Tages der eingestellte maxSoC bzw. dessen Nähe wahrscheinlich erreicht werden kann. &lt;br /&gt;
Sollte der Differenz-Grenzwert erreicht sein, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; gesetzt und der Nutzer sollte dann über einen geeigneten Befehl seine Anlage in den Modus &amp;quot;Laden&amp;quot; umschalten.&lt;br /&gt;
Dieser Vorgang kann beliebig oft während des Tages alternieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Nutzung von batteryTrigger ===&lt;br /&gt;
Ergänzt werden die Möglichkeiten durch das set-Kommando: &lt;br /&gt;
&lt;br /&gt;
 batteryTrigger &amp;lt;1on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;1off&amp;gt;=&amp;lt;Wert&amp;gt; [&amp;lt;2on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;2off&amp;gt;=&amp;lt;Wert&amp;gt; ...] &lt;br /&gt;
&lt;br /&gt;
Das Kommando setzt Triggerpunkte bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %).&lt;br /&gt;
&lt;br /&gt;
Der verwendete SoC wird als resultierender SoC als Summe der aktuellen Ladung aller registrierten Batterie-Geräte im Verhältnis zur installierten Gesamtkapazität gebildet. Das bedeutet, dass alle einzelnen Batterie-Geräte als ein gemeinsamer Cluster betrachtet werden. &lt;br /&gt;
&lt;br /&gt;
Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise definiert werden.&lt;br /&gt;
Überschreiten die letzten drei SoC-Messungen eine definierte Xon-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = on&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
Unterschreiten die letzten drei SoC-Messungen eine definierte Xoff-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = off&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
&lt;br /&gt;
Der Inhalt der Readings kann durch ein User-Programm oder, bei Erzeugung von entsprechenden Events, mittels notify-Device ausgewertet werden um bei Eintreten eines definierten Ereignisses entsprechende Reaktionen auszulösen. Das kann zum Beispiel die Freigabe eines Heizstabes oberhalb eines bestimmten SOC sein oder ein Entladeverbot der Batterie unterhalb eines SOC-Wertes um Reserven für einen eventuellen Stromausfall zu behalten.&lt;br /&gt;
&lt;br /&gt;
Damit die Batterietrigger dynamisch geändert werden können, ist die Einstellung als Set-Kommando und nicht als Attribut ausgeführt.   &lt;br /&gt;
&lt;br /&gt;
Alle Triggerpunkte können mit dem set-Befehl:&lt;br /&gt;
&lt;br /&gt;
 reset batteryTriggerSet&lt;br /&gt;
&lt;br /&gt;
wieder gelöscht werden.&lt;br /&gt;
&lt;br /&gt;
== Verbrauchersteuerung - Registrieren und visualisieren 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;
Die Eigenschaften und das Schaltverhalten wird durch die Angabe der verfügbaren Schlüssel gesteuert. Die Möglichkeiten sind sehr umfangreich. Die nachfolgenden Abschnitte beschreiben die Verwendung am Beispiel oft vorkommender bzw. nachgefragter Sachverhalte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die Phasen der Verbrauchersteuerung ===&lt;br /&gt;
&lt;br /&gt;
Jeder Zyklus eines Verbrauchers durchläuft im Modul die folgenden Phasen:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Planung&#039;&#039;&#039; der Aktivzeiten des Verbrauchers, d.h. wann der Verbraucher geplant eingeschaltet sowie geplant ausgeschaltet wird und damit der Zyklus beendet wird.&lt;br /&gt;
# &#039;&#039;&#039;Start&#039;&#039;&#039; des Zyklus, d.h. Einschalten des Verbrauchers entsprechend der Planungsdaten sofern weitere, in den Consumer-Schlüsseln definierbare Rahmenbedingungen das Einschalten nicht verhindern (z.B. kein oder zu wenig PV-Energieerzeugung / PV-Überschuss)&lt;br /&gt;
# &#039;&#039;&#039;Permanente Überprüfung von&#039;&#039;&#039; eventuell vorhandenen &#039;&#039;&#039;Interruptbedingungen&#039;&#039;&#039; die den Verbraucher temporär ausschalten und, sofern die Interruptbedingung nicht mehr vorliegt, den Verbraucher wieder einschalten und so den gestarteten Zyklus fortsetzen.&lt;br /&gt;
#  &#039;&#039;&#039;Beendigung&#039;&#039;&#039; der Zyklus. Die Beendigung erfolgt entweder (normalerweise) wenn die geplante Endezeit der Zyklus erreicht ist oder eine optionale Endebedingung erfüllt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Steuerung der Phasen ====&lt;br /&gt;
Der Ablauf der Phasen kann durch verschiedene Schlüssel-Wert Paare beeinflusst und gesteuert werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; kann eine &#039;&#039;&#039;zusätzliche externe Bedingung&#039;&#039;&#039; definiert werden um den Einschaltvorgang des Consumers freizugeben. Ist die Bedingung (Regex) nicht erfüllt, erfolgt kein Einschalten des Verbrauchers auch wenn die sonstigen Voraussetzungen wie Zeitplanung, on-Schlüssel, auto-Mode und aktuelle PV-Leistung gegeben sind. Es erfolgt somit eine &#039;&#039;&#039;UND-Verknüpfung&#039;&#039;&#039; des Schlüssels swoncond mit den Planungsdaten und weiteren Einschaltbedingungen.&lt;br /&gt;
&lt;br /&gt;
Der optionale Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; definiert eine &#039;&#039;&#039;vorrangige Ausschaltbedingung&#039;&#039;&#039; (Regex). Sobald diese Bedingung erfüllt ist, wird der Consumer ausgeschaltet auch wenn die geplante Endezeit (consumerXX_planned_stop) noch nicht erreicht ist (&#039;&#039;&#039;ODER-Verknüpfung&#039;&#039;&#039;). Weitere Bedingungen wie off-Schlüssel und auto-Mode müssen zum automatischen Ausschalten erfüllt sein.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; kann während der geplanten Einschaltzeit eine automatische Unterbrechung sowie Wiedereinschaltung des Verbrauchers vorgenommen werden. Der Verbraucher wird temporär ausgeschaltet (interrupted) und wieder eingeschaltet (continued) wenn die Interrupt-Bedingung nicht mehr vorliegt. Die verbleibende Laufzeit wird durch einen Interrupt nicht beeinflusst! &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;power&#039;&#039;&#039; gibt die nominale Leistungsaufnahme des Verbrauchers gemäß seines Datenblattes an. Dieser Wert wird verwendet um die Schaltzeiten des Verbrauchers zu planen und das Schalten in Abhängigkeit des tatsächlichen PV-Überschusses zum Einplanungszeitpunkt zu steuern. Ist &#039;&#039;&#039;power=0&#039;&#039;&#039; gesetzt, wird der Verbraucher unabhängig von einem zum Zeitpunkt des Zyklus-Start eventuell nicht ausreichend vorhandenem PV-Überschuss wie geplant eingeschaltet und somit der Zyklus gestartet.&lt;br /&gt;
&lt;br /&gt;
Durch die Schlüssel &#039;&#039;&#039;notbefore&#039;&#039;&#039; und &#039;&#039;&#039;notafter&#039;&#039;&#039; kann der Startzeitpunkt des Verbrauchers so gesteuert werden, dass der Start des Zyklus nicht vor bzw. nach der angegebenen Zeit eingeplant wird. Diese Steuerung bezieht sich auf die &#039;&#039;Planung&#039;&#039;, d.h. der eigentliche Start des Verbrauchers kann sich unter Umständen durch vorhandene Rahmenbedingungen verzögern. &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; legt die geplanten Einschaltzeit, d.h. die Laufzeit des Zyklus fest. Der Name &#039;&#039;&#039;mintime&#039;&#039;&#039; ist nicht als MInimum-Zeit zu deuten, sondern beschreibt die angegebene Zeit in Minuten die der Zyklus dauern soll.&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist optional, da sich die Standard-Laufzeit des Verbrauchers von dessen Typ abgeleitet wird. Diese Standard Laufzeiten sind:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|dryer&lt;br /&gt;
|90 Minten&lt;br /&gt;
|-&lt;br /&gt;
|dishwasher&lt;br /&gt;
|180 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|washingmachine&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|heater&lt;br /&gt;
|240 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|charger&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|other&lt;br /&gt;
|60 Minuten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Der Verbraucher wurde nicht gestartet obwohl die Startzeit der Einplanung erreicht wurde ===&lt;br /&gt;
&lt;br /&gt;
Wenn die Startzeit des Consumers entsprechend der Einplanung erreicht oder überschritten ist, wird der Consumer eingeschaltet wenn die weiteren Voraussetzungen wahr sind:&lt;br /&gt;
&lt;br /&gt;
* es ist aktuell ein PV-Überschuss vorhanden und der PV-Überschuss deckt die kalkulierten Leistungsaufnahme des Verbrauchers ab. Mit den Schlüsseln &#039;&#039;&#039;power&#039;&#039;&#039; und &#039;&#039;&#039;spignorecond&#039;&#039;&#039; kann die Einschaltung trotz fehlendem PV-Überschuss ermöglicht werden. &lt;br /&gt;
&lt;br /&gt;
* die Angabe im Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; ist wahr (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* das Schalten ist über den Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; freigegeben (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* im Schlüssel &#039;&#039;&#039;on&#039;&#039;&#039; ist ein valides Einschaltkommando hinterlegt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind diese zusätzlichen Bedingungen nicht erfüllt, erfolgt kein Start des eingeplanten Zyklus. Der Verbraucher verbleibt in diesem Fall weiterhin im Status &#039;&#039;planned&#039;&#039; oder &#039;&#039;suspended&#039;&#039;. Die Startbedingungen werden regelmäßig reviewed und der Consumer gestartet sobald alle Startbedingungen wahr sind bzw. Start verhindernde Bedingungen entfallen sind. &lt;br /&gt;
&lt;br /&gt;
Dieser Vorgang erfolgt bis das geplante Ende des Verbaucherzyklus erreicht ist oder die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; zutrifft. Sobald die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; wahr ist, wird der gesamte Planungszyklus des Consumers beendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Kann manuell / automatisiert in den Planungszyklus eines Verbrauchers eingegriffen werden? ===&lt;br /&gt;
&lt;br /&gt;
Die Einplanung und die darauf aufbauenden Schaltprozesse laufen gemäß den hinterlegten Schlüsseloptionen im Modul automatatisch ab ohne dass ein Eingriff durch den Anwender erfolgen muß.&lt;br /&gt;
&lt;br /&gt;
Dennoch kann es gewünscht sein eine Neuplanung oder eine Sofortplanung eines Consumers vorzunehmen weil der Bedarf dazu besteht. Zu diesem Zweck stehen die Set-Kommandos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* consumerNewPlanning &lt;br /&gt;
&lt;br /&gt;
* consumerImmediatePlanning &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
zur Verfügung. &lt;br /&gt;
Beide Befehle initiieren die Consumer-Neuplanung, wobei mit dem Befehl &#039;&#039;consumerImmediatePlanning&#039;&#039; die eventuell im consumerXX Attribut gesetzten Schlüssel notbefore, notafter bzw. mode werden nicht beachtet werden. Dagenen beachtet der Befehl &#039;&#039;consumerNewPlanning&#039;&#039; alle definierten Schlüsseloptionen und dient gewöhnlich dazu einen abgeschlossenen Verbraucherzyklus wiederholt ausführen zu lassen weil die aktuelle Witterungslage dazu geeignet ist. &lt;br /&gt;
&lt;br /&gt;
Ein Anwendungsbeispiel dafür ist zum Beispiel die Ausführung von mehreren Waschmaschinen-Zyklen an einem langen, sonnigen Sommertag.&lt;br /&gt;
Diese beiden Set-Befehle können zum Beispiel über ein auf einen Schalter/Taster reagierendes Notify oder DOIF Device ausgeführt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung eines Verbrauchers mit getrennten Geräten für Messung und Schalten ===&lt;br /&gt;
&lt;br /&gt;
Es existieren in FHEM Geräte, die über verschiedene Kanäle für unterschiedliche Aufgaben verfügen. Diese Kanäle werden jeweils in einem gesonderten Device abgebildet. HomeMatic oder readingsProxy sind Beispiele für solche Varianten.&lt;br /&gt;
&lt;br /&gt;
Um solche Verbraucher einzubinden gibt es im consumerXX Attribut den Schlüssel &#039;&#039;&#039;switchdev&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Bei der Registrierung gibt man als Consumerdevice das Gerät für die Messung an und im Schüssel switchdev das entsprechende FHEM-Device, welches für die Schaltvorgänge benutzt wird. &lt;br /&gt;
Ist switchdev angegeben, beziehen sich die weiteren Schlüssel on, off, swstate, auto und asynchron auf dieses Gerät.&lt;br /&gt;
&lt;br /&gt;
In dem nachfolgenden Beispiel (Homematic) ist &#039;&#039;eg.az.fridge_Pwr&#039;&#039; FHEM Device für die Energiemessung. Die Schlüssel &#039;&#039;pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; geben Readings in diesem Device an damit SolarForecast den Verbrauch und die Energiemengen auslesen kann. Demgegenüber ist im Schlüssel &#039;&#039;switchdev&#039;&#039; das zugehörige Schalter-Device der Kombination angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eg.az.fridge_Pwr&lt;br /&gt;
type=noSchedule switchdev=eg.az.fridge_Sw power=0 icon=fridge pcurr=power:W:5 etotal=energyCalc:Wh &lt;br /&gt;
swstate=state:on:off auto=automatic&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung von Verbrauchern ohne Zeitplanung und aktivem Schalten ===&lt;br /&gt;
Manchmal besteht der Wunsch, Verbraucher in SolarForecast zu integrieren um lediglich folgende Sachverhalte abzubilden:&lt;br /&gt;
&lt;br /&gt;
* Visualisierung des Schaltstatus in der Consumer Legende und/oder der Energieflußgrafik&lt;br /&gt;
* Darstellung des aktuellen Energieverbrauchs in der Energieflußgrafik&lt;br /&gt;
* Erfassung der (externen) Schaltzeiten, d.h. der Zeiten der Gerätenutzung sowie der Verbrauchsdaten um deren Einfluß bei den Planungszeiten anderer Geräte durch SolarForecast berücksichtigen zu lassen&lt;br /&gt;
&lt;br /&gt;
In solchen Fällen werden bei der Registrierung die Schlüssel &#039;&#039;swstate, pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; zur Erfassung der Schaltzustände und der Energieverbrauchs angegeben, jedoch zur Verhinderung der Zeitplanung durch SolarForecast der Schlüssel &#039;&#039;&#039;type=noSchedule&#039;&#039;&#039; gesetzt sowie die Schlüssel &#039;&#039;on&#039;&#039; und &#039;&#039;off&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt eine mögliche Registrierung eines Zwischensteckers (Shelly) zur Erfassung der Daten eines Gefrierschrankes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Shelly.shellyplug4&lt;br /&gt;
type=noSchedule power=65 asynchron=1&lt;br /&gt;
icon=gefrierschrank &lt;br /&gt;
swstate=state:.*on.*:.*off.* &lt;br /&gt;
pcurr=relay_0_power:W:5 etotal=relay_0_energy_Wh:Wh&lt;br /&gt;
&amp;lt;/pre&amp;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;
&lt;br /&gt;
 Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off&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;
&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;
&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. Alternativ kann die Berücksichtigung des zwangsweisen PV Überschuss mit dem Schlüssel &amp;quot;spignorecond&amp;quot; im Consumer-Attribut ausgesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== zusätzliche Readings bzw. Erzeugung von statistischen Readings ==&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den zahlreichen im Modul per Standard erzeugten Readings kann der Anwender weitere Readings generieren lassen.&lt;br /&gt;
Diese zusätzlichen Readings geben entweder einen bestimmten Sachverhalt (Laufzeit, Status der API-Abfragen, etc.) oder einen statistischen Wert, z.B. die Batterieentladung des aktuellen Tages, wieder.&lt;br /&gt;
&lt;br /&gt;
Die zusätzlich erstellten Readings sind durch den Präfix &#039;&#039;&#039;special_&#039;&#039;&#039; im Device gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Diese zusätzlichen Informationen können durch das Setzen einer oder mehrerer Kennzeichen im Attribut &#039;&#039;&#039;ctrlSpecialReadings&#039;&#039;&#039; erzeugt werden. Die mögliche Auswahl wird je nach Bedarf ausgebaut und umfasst zum aktuellen Zeitpunkt (07.02.2025) diese Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;BatPowerIn_Sum: 	die Summe der momentanen Batterieladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;BatPowerOut_Sum: 	die Summe der momentanen Batterieentladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;allStringsFullfilled: 	Erfüllungsstatus der fehlerfreien Generierung aller Strings&lt;br /&gt;
;conForecastTillNextSunrise: 	Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
;currentAPIinterval: 	das aktuelle Abrufintervall der gewählten Strahlungsdaten-API in Sekunden&lt;br /&gt;
;currentRunMtsConsumer_XX: 	die Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; seit dem letzten Einschalten. (letzter Laufzyklus)&lt;br /&gt;
;dayAfterTomorrowPVforecast: 	liefert die Vorhersage der PV Erzeugung für Übermorgen (sofern verfügbar) ohne Autokorrektur (Rohdaten).&lt;br /&gt;
;daysUntilBatteryCare_XX: 	Tage bis zur nächsten Batterie XX Pflege (Erreichen der Ladung &#039;maxSoC&#039; aus Attribut ctrlBatSocManagementXX)&lt;br /&gt;
;lastretrieval_time: 	der letzte Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;lastretrieval_timestamp: 	der Timestamp der letzen Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;response_message: 	die letzte Statusmeldung der gewählten Strahlungsdaten-API&lt;br /&gt;
;runTimeAvgDayConsumer_XX: 	die durchschnittliche Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; an einem Tag&lt;br /&gt;
;runTimeCentralTask: 	die Laufzeit des letzten SolarForecast Intervalls (Gesamtprozess) in Sekunden&lt;br /&gt;
;runTimeTrainAI: 	die Laufzeit des letzten KI Trainingszyklus in Sekunden&lt;br /&gt;
;runTimeLastAPIAnswer: 	die letzte Antwortzeit des Strahlungsdaten-API Abrufs auf einen Request in Sekunden&lt;br /&gt;
;runTimeLastAPIProc: 	die letzte Prozesszeit zur Verarbeitung der empfangenen Strahlungsdaten-API Daten&lt;br /&gt;
;SunMinutes_Remain: 	die verbleibenden Minuten bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;SunHours_Remain: 	die verbleibenden Stunden bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;todayConsumptionForecast: 	Verbrauchsprognose pro Stunde des aktuellen Tages (01-24)&lt;br /&gt;
;todayConForecastTillSunset: 	Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
;todayDoneAPIcalls: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Calls&lt;br /&gt;
;todayDoneAPIrequests: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Requests&lt;br /&gt;
;todayConsumption: 	der gesamte Energieverbrauch (Wh) des Hauses am aktuellen Tag&lt;br /&gt;
;todayGridConsumption: 	die aus dem öffentlichen Netz bezogene Energie am aktuellen Tag&lt;br /&gt;
;todayGridFeedIn: 	die in das öffentliche Netz eingespeiste PV Energie am aktuellen Tag&lt;br /&gt;
;todayMaxAPIcalls: 	die maximal mögliche Anzahl Strahlungsdaten-API Calls. Ein Call kann mehrere API Requests enthalten.&lt;br /&gt;
;todayRemainingAPIcalls: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Calls&lt;br /&gt;
;todayRemainingAPIrequests: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Requests&lt;br /&gt;
;todayBatIn_XX: 	die am aktuellen Tag in die Batterie XX geladene Energie&lt;br /&gt;
;todayBatInSum: 	Summe der am aktuellen Tag in alle Batterien geladene Energie&lt;br /&gt;
;todayBatOut_XX: 	die am aktuellen Tag aus der Batterie XX entnommene Energie&lt;br /&gt;
;todayBatOutSum: 	Summe der am aktuellen Tag aus allen Batterien entnommene Energie&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Manche Angaben sind im Setup des Moduls optional, d.h. sie müssen nicht zwingend beim Setup angegeben werden. Allerdings sind diese Angaben für die Erstellung eines zusätzlichen Readings unter Umständen Voraussetzung. Es empfiehlt sich deshalb bei Setup so viele Informationen wie möglich zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
So ist zum Beispiel für die sinnvolle Erstellung der Informationen &#039;&#039;&#039;todayBatInSum&#039;&#039;&#039; und &#039;&#039;&#039;todayBatOutSum&#039;&#039;&#039; (Readings special_todayBatInSum und special_todayBatOutSum) das Vorhandensein der Schlüssel &#039;&#039;intotal&#039;&#039; und &#039;&#039;outtotal&#039;&#039; im Attribut setupBatteryDevXX notwendig (Beispiel):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupBatteryDev01 MQTT2_cerboGX_c0619ab34e08_battery &lt;br /&gt;
                              pin=BatIn:W pout=BatOut:W charge=SOC_value intotal=BatInTotal:Wh outtotal=BatOutTotal:Wh &lt;br /&gt;
                              cap=InstalledCapacity_Wh:Wh asynchron=1 show=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Fehlersuche ==&lt;br /&gt;
Das Modul SolarForecast ist sehr komplex und es die verschiedensten Datenquellen ausgewertet, zusammengeführt und daraus Ergebnisse berechnet und/oder visualisiert. Wird etwas nicht wie erwartet durch das Modul geliefert, können die Ursachen vielfältig sein. Natürlich kann ein Fehler im Modulcode vorliegen, oftmals gibt es aber andere Ursachen.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgenden Hinweise sollen Hilfe zur Selbsthilfe geben und sind eine Zusammenfassung von realen Fällen die mit dem beschriebenen Wegen und Verfahren gelöst wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die erwartete erzeugte PV-Energie ist im Modul zu gering und wird im Balkendiagramm nicht angezeigt === &lt;br /&gt;
&lt;br /&gt;
Die erzeugte PV-Energie wird nicht richtig angezeigt: Am Vormittag sind keine Werte vorhanden und, wenn dann etwas kommt, ist die Anzeige zu gering. Für 13 und 14 Uhr wurden ca. 5.000Wh erwartet (im Vergleich mit den Daten aus einer anderen Auswertungsquelle). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lösungsweg:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Aus dem List des Devices wurden die für den Fall wesentlichen Readings herausgezogen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVforecast 152 Wh&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVforecast 1400 Wh&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVforecast 2500 Wh&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVforecast 4392 Wh&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVforecast 4000 Wh&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVreal 300 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVforecast 6415 Wh&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVreal 3200 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVforecast 5629 Wh&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVreal 2700 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVforecast 3958 Wh&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVreal 900 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVforecast 945 Wh&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVreal 500 Wh&lt;br /&gt;
   &lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour18_PVforecast 59 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man sieht dass bis 12:00 keine erzeugte Energie vom WR gemeldet wird. Deswegen wird in der Balkengrafik nichts dargestellt. Auch danach bleibt die registrierte PV-Energie hinter den Erwartungen zurück. Zuständig für die Lieferung der PV-Energie an das Modul ist das Reading im Schlüssel:&lt;br /&gt;
&lt;br /&gt;
 setupInverterDev01 SH10rt pv=Total_DC_Power:W &amp;lt;mark&amp;gt;etotal=Total_Export_Energy_from_PV:kWh&amp;lt;/mark&amp;gt; capacity=10000 strings=Hauptdach,Flachdach&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Welche Änderungen es zwischen den Stunden gab, sieht man mit einem &amp;quot;get ... pvHistory XX&amp;quot; (&amp;quot;XX&amp;quot; steht für das Datum, d.h. den Tag, z.B. 02). &amp;lt;br&amp;gt;&lt;br /&gt;
Hier ein Beispiel für die Stunden 10 (9:00 - 9:59) und 11 (10:00 - 10:59). &amp;lt;br&amp;gt;&lt;br /&gt;
Wichtig ist hier der Key etotali01 für den ersten Inverter. Die Differenz zwischen den Werten beider Stunden ist die in der Stunde erzeugte Energie (hier 380 Wh). Diese 380 Wh findest du auch im Key pvrl01 als PVReal für diese Stunde. Das Modul rechnet intern immer mit Wh, kWh werden vorher in Wh umgerechnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
10 =&amp;gt; pvfc: 365, pvrl: 530, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63364714&amp;lt;/mark&amp;gt;, etotali02: 3044110, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;pvrl01: 380&amp;lt;/mark&amp;gt;, pvrl02: 150, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 574, con: 518, gcons: 22, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 1, feedprice: 0.1269&lt;br /&gt;
&lt;br /&gt;
            DoN: 1, sunaz: 137, sunalt: 12&lt;br /&gt;
&lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
      11 =&amp;gt; pvfc: 2966, pvrl: 1862, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63365094&amp;lt;/mark&amp;gt;, etotali02: 3044260, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            pvrl01: 1392, pvrl02: 470, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 774, con: 609, gcons: 25, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 4, feedprice: 0.1269&lt;br /&gt;
           &lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
D.h. wenn zwischen den beiden Stunden keine Differenzen zu finden sind, liegt es sehr wahrscheinlich am Input des Readings:&lt;br /&gt;
&lt;br /&gt;
 etotal=Total_Export_Energy_from_PV:kWh&lt;br /&gt;
&lt;br /&gt;
welches sich in den ersten Stunden nicht ändert und danach auch nur wenig.&lt;br /&gt;
&lt;br /&gt;
Man kann mit dem Attribut:&lt;br /&gt;
&lt;br /&gt;
 ctrlDebug=collectData&lt;br /&gt;
&lt;br /&gt;
die Datensammlung verfolgen (leider entstehen viele Daten im Log). Man sieht welche Werte von dem Inverter/Reading geliefert werden:&lt;br /&gt;
 &lt;br /&gt;
 ....&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; collect Inverter 01 data - device: STP_5000, delivery: default =&amp;gt;&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; pv: 0 W, &amp;lt;mark&amp;gt;etotal: 63378810 Wh&amp;lt;/mark&amp;gt;&lt;br /&gt;
 ....&lt;br /&gt;
&lt;br /&gt;
Dieser Wert muß bei PV Erzeugung kontinuierlich hochzählen. Wenn nicht, muss das angegebene Reading, d.h. die Quelle überprüft werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ergebnis der Prüfung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tatsächlich wurde ein Reading benutzt, das ungeeignet war: Statt &amp;quot;Total_PV_Generation&amp;quot; wurde &amp;quot;Total_export_energy_from_PV&amp;quot; genutzt. In diesem Reading wurde immer die in die Batterie gespeicherte Energie von der gesamten erzeugten Energie abgezogen. Daher war auch vormittags alles 0, da in dieser Periode alle PV-Energie in die Batterie geladen wurde bzw. in weiteren Stunden ein Anteil der dann bei dem PV-Erzeugungswert fehlte.&lt;br /&gt;
&lt;br /&gt;
Nachdem die Ursache beseitigt war, zeigt SolarForecast wieder die erwarteten PV-Erzeugungswerte an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Konfigurationsbeispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Visualisierung solare Vorhersage und reale Erzeugung ===&lt;br /&gt;
&lt;br /&gt;
Zu Beginn jedes neuen Tages gegen 00:00 Uhr werden durch das SolarForecast Device Events für die initiale PV Prognose des kommenden Tages erstellt.&lt;br /&gt;
Der Readingteil dieser Events heißt&lt;br /&gt;
&lt;br /&gt;
 AllPVforecastsToEvent&lt;br /&gt;
&lt;br /&gt;
Die Uhrzeiten der Events sind so aufbereitet und können direkt geloggt werden um sie in einen SVG Plot zu integrieren.&lt;br /&gt;
Im SolarForecast Device ist dieses Reading nicht sichtbar, nur die Events werden erstellt.&lt;br /&gt;
&lt;br /&gt;
Die meteorologischen Bedingungen verändern sich über den Tag permanent. Je nach gewählter Strahlungsdatenquelle (eine API oder DWD Device) erfolgt eine mehr oder weniger dynamische Anpassung der Prognose an die sich verändernde Umwelt.&lt;br /&gt;
&lt;br /&gt;
Aktuelle Prognosedaten sowie die reale PV Erzeugung der vergangenen Stunde können über die Readings&lt;br /&gt;
&lt;br /&gt;
 LastHourPVforecast&lt;br /&gt;
 LastHourPVreal&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-10-20 134050.png|right|thumb|400px|Übersicht solare Vorhersage]]&lt;br /&gt;
geloggt werden. &lt;br /&gt;
&lt;br /&gt;
Werden alle drei Werte in einem SVG kombiniert, kann die Entwicklung der Prognose über den Tag und die Beziehung von Prognose zu realer PV Erzeugnung pro Stunde visualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Für das rechts abgebildete Beispiel des Plots aus einer Datenbank &amp;quot;LogDBShort&amp;quot; sieht das gplot-File wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Created by FHEM/98_SVG.pm, 2024-03-08 15:05:31&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;TL&amp;gt;&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid&lt;br /&gt;
set ylabel &amp;quot;Wh&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Wh&amp;quot;&lt;br /&gt;
set yrange [0:7500]&lt;br /&gt;
set y2range [0:7500]&lt;br /&gt;
&lt;br /&gt;
#LogDBShort SolCast:LastHourPVforecast:::&lt;br /&gt;
#LogDBShort SolCast:LastHourPVreal:::&lt;br /&gt;
#LogDBShort SolCast:AllPVforecastsToEvent:::&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;aktuelle PV Vorhersage&#039; ls l6fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;reale PV Erzeugung&#039; ls l2fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;initiale PV Vorhersage&#039; ls l4 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; In manchen Fällen werden die Vorhersagewerte im SVG-Plot nicht angezeigt wenn FileLog verwendet wird. Ein Setzen des Attribute &amp;quot;fixedrange=3days +1&amp;quot; im SVG löst das Problem. Die Definition des SVG-Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_LogDBShort_SolCast SVG LogDBShort:SVG_LogDBShort_SolCast:HISTORY&lt;br /&gt;
attr SVG_LogDBShort_SolCast fixedrange 3days +1&lt;br /&gt;
attr SVG_LogDBShort_SolCast room Energie-&amp;gt;SolarPrognose&lt;br /&gt;
attr SVG_LogDBShort_SolCast sortby 2&lt;br /&gt;
attr SVG_LogDBShort_SolCast title &amp;quot;Übersicht solare Vorhersage&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Technisch bedingt werden an einem Tag X kurz nach 00:00 Uhr die am Vortag für den Tag X erzeugten Events aktualisiert. Diese Daten erzeugen in der Datenbank einen zweiten Satz an Daten mit dem gleichen Timestamp was für die Anzeige unvorteilhaft ist. &lt;br /&gt;
Um nur die aktualisierten Events von &#039;&#039;&#039;AllPVforecastsToEvent&#039;&#039;&#039; in der Datenbank zu erhalten, bietet sich ein DbRep-Device an. Die nachfolgende Vorschlagsdefinition kann per at-Device jeden Tag kurz vor Mitternacht (z.B. 23:57:10) ausgeführt werden. Es werden immer die in der Vergangenheit geschriebenen (veralteten) Daten aus der Datenbank gelöscht, doppelte Datesätze vermieden und immer die aktuellste initiale Prognose gespeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.Del.AllPVforecastsToEvent DbRep LogDBShort&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent alias Löschen Readings AllPVforecastsToEvent des Folgetages&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent comment ermöglicht dass die Readings AllPVforecastsToEvent am Folgetag wieder neu und aktuell geschrieben werden können&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent devStateIcon initialized:control_3dot_hor_s connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent disable 0&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent event-on-update-reading state&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent icon edit_delete&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent showproctime 1&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent device TYPE=SolarForecast&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_begin next_day_begin&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_end next_day_end&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das angegebene DbLog-Device &#039;&#039;&#039;LogDBShort&#039;&#039;&#039; ist natürlich anzupassen.&lt;br /&gt;
&lt;br /&gt;
Das at-Device zum Starten der Datenbankbereinigung sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define At.Del.AllPVforecastsToEvent at *23:58:10 set Rep.Del.AllPVforecastsToEvent delEntries&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent alias Start Löschen Readings AllPVforecastsToEventn LogDBShort&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent icon clock&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich sind auch hier die eigenen Devicenamen entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
Ab SolarForecast Version 1.51.7 kann die Eventerzeugung für bestimmte SVG Plot-Typen optimiert werden. &amp;lt;br&amp;gt; &lt;br /&gt;
Die Aktivierung dieser Optimierungen ist in der Online Hilfe zum Attribut &#039;&#039;&#039;plantControl-&amp;gt;genPVforecastsToEvent&#039;&#039;&#039; beschrieben. Bei Nutzung des Attributes plantControl-&amp;gt;genPVforecastsToEvent ist ebenfalls das Attribut &#039;&#039;&#039;event-on-update-reading=AllPVforecastsToEvent&#039;&#039;&#039; zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispielkonfiguration 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;
Bitte dabei diese DWD-Version aus dem [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter Contrib] von DS_Starter dazu nutzen&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|55_DWD_OpenData.pm&lt;br /&gt;
|136.2 KB ​&lt;br /&gt;
|29260  &lt;br /&gt;
|DS_Starter&lt;br /&gt;
|55_DWD_OpenData: contrib 1.17.7&lt;br /&gt;
|}&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 downloadTimeout 120&lt;br /&gt;
attr DWD comment Im DWD Wetterdevice verwendet Solarforecast : \&lt;br /&gt;
TTT,Neff,RR1c,ww,SunUp,SunRise,SunSet \&lt;br /&gt;
zusätzlich ist jedoch auch noch Rad1h notwendig \&lt;br /&gt;
wenn dieses DWD-Device als Strahlungsdevice genutzt wird.\&lt;br /&gt;
Die Station 10418 (Lüdenscheid) überträgt aktuell am 09.03.2025 (noch) Rad1h.\&lt;br /&gt;
attr DWD downloadTimeout 120&lt;br /&gt;
attr DWD forecastDays 7&lt;br /&gt;
attr DWD forecastProperties SunUp, SunRise, SunSet, Rad1h, R101, RR1c, TTT, Tx, Tn, Tg, DD, FX1, RR6c, R600, RRhc, Rh00, ww, wwd, Neff&lt;br /&gt;
attr DWD forecastRefresh 1&lt;br /&gt;
attr DWD forecastResolution 1&lt;br /&gt;
attr DWD forecastStation 10418&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 fc_description  -(state fc_time)&lt;br /&gt;
attr DWD verbose 2&lt;br /&gt;
&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;
defmod InverterDummy dummy&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;
defmod 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 feedinPrice 0.08&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 powerCost 0.25&lt;br /&gt;
attr SMA_Energymeter room 015_Zaehler,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;
defmod 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;
attr BatteryDummy userReadings total_pac, power_out, power_in, chargestatus, bat_rated_capacity, bat_loadtotal, bat_unloadtotal&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;
defmod N.PV.TotalConsumption.Dum.Energy notify SMA_Energymeter:Saldo_Wirkleistung:.* {\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung_2 Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&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;MB_USRW610_004&amp;quot;,&amp;quot;Power_Sum__W&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;
fhem &amp;quot;setreading InverterDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(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;
#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;
 # Batterie-total_pac  InverterDummy\&lt;br /&gt;
my $wert7 = sprintf(&amp;quot;%.3f&amp;quot;,((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy bat_rated_capacity &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert7));;\&lt;br /&gt;
 # möglicher Aufruf einer Batterie-Bebladung-Routine....SMABatteryChargewithTibber();;\&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;
defmod Forecast SolarForecast&lt;br /&gt;
attr Forecast DbLogExclude .*&lt;br /&gt;
attr Forecast DbLogInclude Current_BatCharge999&lt;br /&gt;
attr Forecast affectBatteryPreferredCharge 30&lt;br /&gt;
attr Forecast affectConsForecastLastDays 31&lt;br /&gt;
attr Forecast affect70percentRule 0&lt;br /&gt;
attr Forecast comment &amp;quot;wget -qO ./FHEM/76_SolarForecast.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/76_SolarForecast.pm&amp;quot;\&lt;br /&gt;
&amp;quot;wget -qO ./FHEM/55_DWD_OpenData.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/55_DWD_OpenData.pm&amp;quot;\&lt;br /&gt;
&amp;quot;13.01.2025 mit der Version 76_SolarForecast.pm:v1.43.2-s29518/2025-01-12&amp;quot;&lt;br /&gt;
attr Forecast graphicHeaderOwnspec PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal Verbrauch&amp;amp;nbsp;;bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast  Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest FCU-Erzeugung&amp;amp;nbsp;;:Current_PP01\&lt;br /&gt;
attr Forecast consumer01 FBDECT_fbahahttp_11657_0127183 icon=scene_washing_machine@orange type=washingmachine power=10 swstate:state notbefore=09 notafter=20 pcurr=power:W:3 etotal=energy:Wh interruptable=1 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer02 FBDECT_fbahahttp_E8_DF_70_07_3E_57 icon=light_floor_lamp@orange type=other power=15 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer03 FBDECT_fbahahttp_E8_DF_70_07_42_0B icon=raspberrypi@orange type=other power=8 swstate:state pcurr=power:W:1 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer04 FBDECT_fbahahttp_11657_0067275 icon=springbrunnen_icon@orange type=other power=50 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer05 FBDECT_fbahahttp_34_31_C4_D4_31_37 icon=sani_domestic_waterworks@orange type=other power=10 swstate:state pcurr=power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer06 tuya_local_bf5037060f450bdbd4rl0q icon=scene_clothes_dryer@orange type=dryer power=10 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer07 tuya_local_bfac44fb487476efd1vhdu icon=weather_sunset@orange type=noSchedule power=5 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumerControl adviceIcon=light_light_dim_100@gold&lt;br /&gt;
attr Forecast consumerControl showLegend=icon_top&lt;br /&gt;
attr Forecast consumerControl detailLink=1&lt;br /&gt;
attr Forecast ctrlAIdataStorageDuration 1825&lt;br /&gt;
attr Forecast ctrlAIshiftTrainStart 2&lt;br /&gt;
attr Forecast ctrlBatSocManagement01 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlBatSocManagement02 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlDebug none&lt;br /&gt;
attr Forecast plantControl genPVdeviation=continuously&lt;br /&gt;
attr Forecast plantControl cycleInterval=15&lt;br /&gt;
attr Forecast ctrlNextDayForecastReadings 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24&lt;br /&gt;
attr Forecast ctrlNextHoursSoCForecastReadings 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23&lt;br /&gt;
attr Forecast ctrlSpecialReadings BatPowerIn_Sum,BatPowerOut_Sum,SunHours_Remain,SunMinutes_Remain,allStringsFullfilled,conForecastTillNextSunrise,currentAPIinterval,currentRunMtsConsumer_01,currentRunMtsConsumer_02,currentRunMtsConsumer_03,currentRunMtsConsumer_04,currentRunMtsConsumer_05,currentRunMtsConsumer_06,currentRunMtsConsumer_07,dayAfterTomorrowPVforecast,daysUntilBatteryCare_01,daysUntilBatteryCare_02,lastretrieval_time,lastretrieval_timestamp,response_message,runTimeAvgDayConsumer_01,runTimeAvgDayConsumer_02,runTimeAvgDayConsumer_03,runTimeAvgDayConsumer_04,runTimeAvgDayConsumer_05,runTimeAvgDayConsumer_06,runTimeAvgDayConsumer_07,runTimeCentralTask,runTimeLastAPIAnswer,runTimeLastAPIProc,runTimeTrainAI,todayBatIn_01,todayBatIn_02,todayBatOut_01,todayBatOut_02,todayConForecastTillSunset,todayConsumptionForecast,todayDoneAPIcalls,todayDoneAPIrequests,todayGridConsumption,todayGridFeedIn,todayMaxAPIcalls,todayRemainingAPIcalls,todayRemainingAPIrequests&lt;br /&gt;
attr Forecast disable 0&lt;br /&gt;
attr Forecast event-min-interval .*:1800&lt;br /&gt;
attr Forecast event-on-change-reading .*&lt;br /&gt;
attr Forecast flowGraphicControl animate=1 consumerdist=80 h2consumerdist=50 shiftx=0  shifty=0 showconsumer=1 showconsumerdummy=1 showconsumerpower=1 showconsumerremaintime=0 size=400 strokewidth=12&lt;br /&gt;
attr Forecast graphicBeam1Color 3C14FF&lt;br /&gt;
attr Forecast graphicBeam1Content pvReal&lt;br /&gt;
attr Forecast graphicBeam2Color 19FF29&lt;br /&gt;
attr Forecast graphicBeam2Content pvForecast&lt;br /&gt;
attr Forecast graphicBeam3Color D60924&lt;br /&gt;
attr Forecast graphicBeam3Content batsocforecast_02&lt;br /&gt;
attr Forecast graphicBeam3FontColor FFFF0D&lt;br /&gt;
attr Forecast graphicBeam4Color FFFF1F&lt;br /&gt;
attr Forecast graphicBeam4Content batsocforecast_01&lt;br /&gt;
attr Forecast graphicBeam4FontColor 000000&lt;br /&gt;
attr Forecast graphicBeamHeightLevel1 200&lt;br /&gt;
attr Forecast graphicBeamHeightLevel2 200&lt;br /&gt;
attr Forecast graphicHeaderDetail all&lt;br /&gt;
attr Forecast graphicHeaderOwnspec #PV\&lt;br /&gt;
PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal\&lt;br /&gt;
PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast\&lt;br /&gt;
PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast\&lt;br /&gt;
:\&lt;br /&gt;
#\&lt;br /&gt;
AutarkyRate:Current_AutarkyRate\&lt;br /&gt;
Überschuss:Current_Surplus\&lt;br /&gt;
aktueller&amp;amp;nbsp;;Netzbezug:Current_GridConsumption\&lt;br /&gt;
:\&lt;br /&gt;
#Verbrauch\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenuntergang:special_todayConForecastTillSunset\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie01\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_01\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_01\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_01\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_01\&lt;br /&gt;
#Batterie01_tmp\&lt;br /&gt;
Current_PowerBatIn_01:Current_PowerBatIn_01\&lt;br /&gt;
Current_PowerBatOut_01:Current_PowerBatOut_01\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie02\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_02\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_02\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_02\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_02\&lt;br /&gt;
#Batterie02_tmp\&lt;br /&gt;
Current_PowerBatIn_02:Current_PowerBatIn_02\&lt;br /&gt;
Current_PowerBatOut_02:Current_PowerBatOut_02\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Settings\&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto \&lt;br /&gt;
Wetter:graphicShowWeather\&lt;br /&gt;
History:graphicHistoryHour\&lt;br /&gt;
ShowNight:graphicShowNight\&lt;br /&gt;
Debug:ctrlDebug\&lt;br /&gt;
FCU-Modus:FCU-Betriebsmodus@FCU&lt;br /&gt;
attr Forecast graphicHistoryHour 4&lt;br /&gt;
attr Forecast graphicHourCount 24&lt;br /&gt;
attr Forecast graphicLayoutType double&lt;br /&gt;
attr Forecast graphicShowDiff top&lt;br /&gt;
attr Forecast graphicShowNight 1&lt;br /&gt;
attr Forecast graphicShowWeather 1&lt;br /&gt;
attr Forecast group Energy Meter&lt;br /&gt;
attr Forecast room 020_PV,Energie&lt;br /&gt;
attr Forecast setupBatteryDev01 SBS25 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupBatteryDev02 SBS25_2 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupInverterDev01 SB25 pv=total_pac:kW etotal=etotal:kWh capacity=2500 strings=GarageSE limit=70&lt;br /&gt;
attr Forecast setupInverterDev02 SB30 pv=total_pac:kW etotal=etotal:kWh capacity=3000 strings=GarageNW,HausNW limit=70&lt;br /&gt;
attr Forecast setupInverterDev03 SB40 pv=total_pac:kW etotal=etotal:kWh capacity=4000 strings=HausSE1,HausSE2,HausSW limit=70&lt;br /&gt;
attr Forecast setupInverterStrings GarageSE,GarageNW,HausNW,HausSW,HausSE1,HausSE2&lt;br /&gt;
attr Forecast setupMeterDev SMA_Energymeter gcon=Bezug_Wirkleistung:W contotal=Bezug_Wirkleistung_Zaehler:kWh gfeedin=Einspeisung_Wirkleistung:W feedtotal=Einspeisung_Wirkleistung_Zaehler:kWh conprice=0.25:€ feedprice=0.08123:€&lt;br /&gt;
attr Forecast setupOtherProducer01 icon=Heizung_FCU_green@red MB_USRW610_004 pcurr=Power_L1__W:W etotal=Energy_L1_import__kWh:kWh&lt;br /&gt;
attr Forecast setupRadiationAPI DWD&lt;br /&gt;
attr Forecast setupStringPeak GarageSE=2.75 GarageNW=3.200 HausNW=2.230 HausSW=2.230 HausSE1=2.200 HausSE2=2.200&lt;br /&gt;
attr Forecast setupWeatherDev1 DWD&lt;br /&gt;
attr Forecast stateFormat Current_PV&lt;br /&gt;
attr Forecast userReadings Current_BatCharge999 {((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))) / ( (ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0) * 1000)  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0)*1000))*100}&lt;br /&gt;
attr Forecast verbose 2&lt;br /&gt;
&lt;br /&gt;
setstate Forecast 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .FCU_FCU-Betriebsmodus 2&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_ctrlDebug none&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicHistoryHour 4&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowNight 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowWeather 1&lt;br /&gt;
setstate Forecast 2025-01-13 08:24:25 .associatedWith SMA_Energymeter FBDECT_fbahahttp_11657_0127183 FBDECT_fbahahttp_E8_DF_70_07_3E_57 FBDECT_fbahahttp_E8_DF_70_07_42_0B FBDECT_fbahahttp_11657_0067275 FBDECT_fbahahttp_34_31_C4_D4_31_37 tuya_local_bf5037060f450bdbd4rl0q tuya_local_bfac44fb487476efd1vhdu SBS25 SBS25_2 SB25 SB30 SB40 DWD MB_USRW610_004&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .lastupdateForecastValues 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .pvCorrectionFactor_Auto_Soll on_complex_ai&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .signaldone_01 done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .signaldone_02 done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .signaldone_03 done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .signaldone_04 done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .signaldone_05 done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .signaldone_06 done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .signaldone_07 done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .signaldone_08 done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .signaldone_09 done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .signaldone_10 done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .signaldone_11 done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .signaldone_12 done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .signaldone_13 done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .signaldone_14 done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .signaldone_15 done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .signaldone_16 done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .signaldone_17 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .signaldone_18 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_01 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_02 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_01 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_02 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_AutarkyRate 83 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 Current_BatCharge999 10&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_01 12 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_02 8 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Consumption 626 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridConsumption 2 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridFeedIn 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PP_01 746.0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PV 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_01 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_02 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_01 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_02 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumption 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumptionRate 0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Surplus 120 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourGridconsumptionReal 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_ConsumptionForecast 2944 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayConsumptionForecast 3609 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_01 272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PPreal_01 748 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PPreal_01 787 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_01 271 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PPreal_01 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PPreal_01 745 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_01 267 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PPreal_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_01 255 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PPreal_01 752 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_01 226 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_01 50 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PPreal_01 681 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_02 233 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_01 845 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridConsumption 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_01 37 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_02 90 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_01 351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_02 188 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridConsumption 447 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVforecast 127 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridConsumption 1650 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVforecast 478 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVreal 26 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridConsumption 513 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVforecast 868 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVreal 97 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridConsumption 576 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVforecast 1157 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVreal 320 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_01 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_02 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridConsumption 1272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridFeedIn 7 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVforecast 1238 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVreal 945 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_01 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_02 53 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridConsumption 955 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridFeedIn 31 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PPreal_01 562 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVforecast 1168 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVreal 1410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_01 703 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_02 500 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_01 22 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_02 18 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridConsumption 32 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridFeedIn 71 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PPreal_01 777 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVreal 1416 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_01 296 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_02 70 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_01 74 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_02 258 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridConsumption 13 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridFeedIn 17 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PPreal_01 732 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVforecast 880 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVreal 1051 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_01 47 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_02 126 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_01 102 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_02 75 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridConsumption 15 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridFeedIn 23 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PPreal_01 771 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVforecast 117 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVreal 86 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_02 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_02 67 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridConsumption 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridFeedIn 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PPreal_01 723 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_01 349 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_02 124 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_01 73 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_02 450 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridConsumption 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridFeedIn 6 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PPreal_01 671 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecastTime 2025-01-13 14:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVdeviation 30.17 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVforecast 7663 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVreal 5351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunRise 08:28&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunSet 16:46&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_ConsumptionForecast 17043 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour05_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour06_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour07_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour08_PVforecast 10 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour09_PVforecast 161 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour10_PVforecast 275 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour11_PVforecast 532 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour12_PVforecast 730 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour13_PVforecast 1252 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour14_PVforecast 818 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour15_PVforecast 1465 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour16_PVforecast 303 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour17_PVforecast 20 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour18_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour19_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour20_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour21_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour22_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour23_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour24_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_PVforecast 5566 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunRise 08:27&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunSet 16:47&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01 name=&#039;_Waschmaschine&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_start 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_stop 14.01.2025 11:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02 name=&#039;_Esszimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_currentPower 15.3 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03 name=&#039;_FCU&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_currentPower 7.15 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04 name=&#039;_Brunnen&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05 name=&#039;_Zisterne&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06 name=&#039;SW Trockner&#039; state=&#039;unknown&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_stop 14.01.2025 08:30:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07 name=&#039;SW Urlaubslicht-Wohnzimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;noSchedule&#039; info=&#039;von extern umgeschaltet&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 nextCycletime 18:54:09&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 pvCorrectionFactor_10 0.53 (automatic - old factor: 1.00, Sun Alt range: 5, Cloud range: 75, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 pvCorrectionFactor_11 0.56 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 70, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 pvCorrectionFactor_12 0.64 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 pvCorrectionFactor_13 0.88 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 pvCorrectionFactor_14 1.10 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 50, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 pvCorrectionFactor_15 1.01 (automatic - old factor: 1.06, Sun Alt range: 15, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 pvCorrectionFactor_16 1.09 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 45, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 pvCorrectionFactor_17 0.28 (automatic - old factor: 0.52, Sun Alt range: 0, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 pvCorrectionFactor_Auto on_complex_ai&lt;br /&gt;
setstate Forecast 2024-10-30 19:42:19 setupStringAzimuth GarageSE=-55 GarageNW=125 HausNW=125 HausSW=35 HausSE1=-55 HausSE2=-55&lt;br /&gt;
setstate Forecast 2024-10-30 19:37:38 setupStringDeclination GarageSE=40 GarageNW=40 HausNW=50 HausSW=50 HausSE1=50 HausSE2=50&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerIn_Sum 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerOut_Sum 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunHours_Remain 0.00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunMinutes_Remain 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_allStringsFullfilled 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_conForecastTillNextSunrise 9467 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentAPIinterval 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_01 132 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_02 184 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_03 329512 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_04 200 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_05 27 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_06 193 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_07 106 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_dayAfterTomorrowPVforecast 7344 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_01 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_02 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_time 2025-01-13 18:53:54&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_timestamp 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_response_message success&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_01 545.94 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_02 382.10 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_03 1430.13 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_04 262.05 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_05 28.80 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_06 622.63 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_07 276.51 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeCentralTask 0.3744&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIAnswer -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIProc -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeTrainAI 1.2529&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_01 3683.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_02 1617.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_01 2287.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_02 1057.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConForecastTillSunset 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 special_todayConsumptionForecast_01 509 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 special_todayConsumptionForecast_02 499 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 special_todayConsumptionForecast_03 501 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 special_todayConsumptionForecast_04 511 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 special_todayConsumptionForecast_05 503 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 special_todayConsumptionForecast_06 495 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 special_todayConsumptionForecast_07 504 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 special_todayConsumptionForecast_08 561 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 special_todayConsumptionForecast_09 768 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 special_todayConsumptionForecast_10 783 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 special_todayConsumptionForecast_11 692 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 special_todayConsumptionForecast_12 791 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 special_todayConsumptionForecast_13 910 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 special_todayConsumptionForecast_14 1022 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 special_todayConsumptionForecast_15 965 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 special_todayConsumptionForecast_16 812 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 special_todayConsumptionForecast_17 884 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 special_todayConsumptionForecast_18 928 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_19 874 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_20 763 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_21 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_22 765 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_23 643 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_24 601 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIcalls 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIrequests 4532&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridConsumption 5500.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridFeedIn 178.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayMaxAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIrequests n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 state updated&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So sollte es dann als Ergebnis aussehen:&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13.png|zentriert|mini|Ergebnis nach kompletter Einrichtung]]&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13 Teil II.png|alternativtext=Unterer Teil der Anzeige|zentriert|mini]]&lt;br /&gt;
&lt;br /&gt;
== Praxisbeispiele und Lösungsansätze für Steuerungen ==&lt;br /&gt;
=== Fallstudie: Trockner darf pausiert werden, wenn nicht genug PV-Überschuss vorhanden ist, soll aber nach spätestens X Stunden fertig sein ===&lt;br /&gt;
Für diese Aufgabenstellung sind mehrere Schlüssel essentiell wichtig, &#039;&#039;&#039;power&#039;&#039;&#039;, &#039;&#039;&#039;mintime&#039;&#039;&#039;, &#039;&#039;&#039;mode&#039;&#039;&#039; und &#039;&#039;&#039;interruptable&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Die Bedingung, dass der Trockner nach spätestens X Stunden fertig sein soll, steht in einem Widerspruch zu der Möglichkeit den Trockner bei zu wenig PV-Überschuss unterbrechen zu können. Im Extremfall könnte nach dem Start die gesamte Planungszeit ungenügender Überschuss vorliegen und der Trockner nicht arbeiten. Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; (in Minuten) wird nun wie folgt angesetzt:&lt;br /&gt;
&lt;br /&gt;
 mintime = 2,5 x &amp;lt;gewöhnliche Betriebszeit für einen Trockengang (mneed, z.B. 120)&amp;gt; = 300 Minuten&lt;br /&gt;
&lt;br /&gt;
Das bedeutet, der Trockner wird nach 300 Minuten Laufzeit abgeschaltet werden bzw. vom Netz getrennt. Der Trockenvorgang wird natürlich bereits nach 120 Minuten beendet sein, sofern nach Start keine Unterbrechnung des Vorganges erfolgte. Wurde der Vorgang unterbrochen, soll der Trockner innerhalb &lt;br /&gt;
&lt;br /&gt;
 X+120 bis X+300 &lt;br /&gt;
&lt;br /&gt;
fertig sein. &lt;br /&gt;
&lt;br /&gt;
Demnach ist die ausgeführte Laufzeit des Trockners permanent zu überwachen, zu summieren (rtsum) und die notwendige Restzeit (mneed - rtsum) mit der noch verbleibenden Restzeit (mrest) bis zur geplanten Abschaltung des Consumers zu vergleichen. Ist der Consumer gestartet, wird die Laufzeit in der pvHistory für jede Stunde des Tages im Schlüssel &#039;&#039;minutescsmXX&#039;&#039; (XX = Consumernummer) aufgezeichnet und kann darüber ausgewertet werden. Somit ist:&lt;br /&gt;
&lt;br /&gt;
 msum = for (01 .. 24) {Summe von minutescsmXX} des aktuellen Tages&lt;br /&gt;
&lt;br /&gt;
Solange die Bedingung &lt;br /&gt;
&lt;br /&gt;
 mrest &amp;gt;= (mneed - msum)&lt;br /&gt;
&lt;br /&gt;
zutrifft, darf der Trockner unterbrochen werden, anderenfalls darf er nicht mehr unterbrochen werden da die Restzeit evtl. nicht ausreichen könnte um den Vorgang abzuschließen. Für die Planung des Trockners wird der Consumer wie gewöhnlich nach dem Bedarf im Modul registriert. Für die Steuerung der Unterbrechbarkeit wird noch ein Code erstellt, welcher im Trockner-Device &#039;&#039;Dryerdev&#039;&#039; das Reading &#039;&#039;SF_Int&#039;&#039; zur Unterbrechnungssteuerung verwaltet. Dieses Reading wird dem Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; übergeben. Für das Beispiel wird der Consumer &#039;07&#039; verwendet, es kann natürlich jede andere freie Nummer verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Dryerdev:Trockner&lt;br /&gt;
                        icon=scene_cloves_dryer type=dryer power=2000 mode=must mintime=300 &lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic asynchron=1&lt;br /&gt;
                        interruptable=Dryerdev:SF_Int:1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Kombination &#039;&#039;&#039;auto=automatic&#039;&#039;&#039; eröffnet die Möglickeit, in der Consumer-Legende den Trockner-Start zusätzlich manuell freizugeben oder zu verbieten. &lt;br /&gt;
&lt;br /&gt;
Im nachfolgenden Code werden modulinterne Subroutinen verwendet. Diese sind inklusive dem Paket &#039;&#039;FHEM::SolarForecast::&#039;&#039; anzugeben. Die erstellte Subroutine wird in die 99_mySolarForecastUtils.pm eingefügt. Die Datei 99_mySolarForecastUtils.pm wird vorher von 99_myUtils.pm kopiert und enthält für die Übersichtlichkeit nur Routinen für SolarForecast.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Trocknersteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub dryControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # gewöhlich benötigte Zeit für &lt;br /&gt;
                                                                                  # einen Trockengang, z.B. 120 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $dryer     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename des Trockners&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Trockner-Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit des Trockners&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      my $dhash = $defs{$dryer};&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 1, 0);                        # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 0, 0);                        # keine Interrupt-Freigabe&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die gewöhnliche Laufzeit des Trockners für einen Trockenvorgang (120 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::dryControl ($name, &#039;07&#039;, 120);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Fallstudie: Umwälzpumpe Pool soll X Stunden am Tag laufen. Ist kein PV-Überschuß vorhanden, müssen die X Stunden/Tag trotzdem erreicht werden ===&lt;br /&gt;
&lt;br /&gt;
Die Vorgehensweise ähnelt der Fallstudie zuvor. Verändernd kommt hinzu, dass der Planungszeitraum bewusst sehr lang angesetzt wird mit der Option, den Zyklus des Consumers vorfristig zu beenden sobald die Laufzeit von X Stunden am Tag erreicht ist. &lt;br /&gt;
Im folgenden Beispiel soll die Pumpe 5 Stunden am Tag (300 Minuten) laufen und dabei mögliche PV-Überschüsse ausnutzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Pump:Zirkulationspumpe&lt;br /&gt;
                        icon=sani_pump type=other power=50 mode=must mintime=780 notafter=09&lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic &lt;br /&gt;
                        interruptable=1 swoffcond=Pump:SF_Abort:1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit dieser Registrierung wird die Pumpe ca. 09 Uhr täglich starten. Wenn kein bzw. ungenügender PV-Überschuß vorhanden ist, erfolgt eine Unterbrechung nach dem Start. Ist genügender PV-Überschuß (wieder) vorhanden, erfolgt keine Unterbrechnung (mehr). Zusätzlich wird über den Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; eine vorfristige Beendigung veranlasst, sobald die gewünschte Tageslaufzeit erreicht ist.&lt;br /&gt;
&lt;br /&gt;
Zur Verwaltung des Schlüssels &#039;&#039;interruptable&#039;&#039; und des Readings &#039;&#039;SF_Abort&#039;&#039; verwenden wir eine leicht veränderte Subroutine aus dem vorhergehenden Fallbeispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Pumpensteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub pumpControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # Soll-Pumpenzeit, z.B. 300 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $pump      = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename der Pumpe&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;);&lt;br /&gt;
  my $intbl     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;interruptable&#039;, 1); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
  my $dhash     = $defs{$pump};&lt;br /&gt;
&lt;br /&gt;
  readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 0, 0);                                # default keine Zyklusbeendigung&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Pumpen Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit der Pumpe&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
     &lt;br /&gt;
      if ($msum &amp;gt;= $mneed) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 1, 0);                       # vorfristige Zyklusbeendigung&lt;br /&gt;
          return;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=1&amp;quot;) if(!$intbl);  # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=0&amp;quot;) if($intbl);   # keine Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Befehl &#039;&#039;attrKeyVal&#039;&#039; setzt den Schlüssel &#039;&#039;interruptable&#039;&#039; im Attribut &#039;&#039;consumer07&#039;&#039; dynamisch. Diese Strukturänderung wird automatisch im System gespeichert, sofern &#039;&#039;global-&amp;gt;autosave=1&#039;&#039; gesetzt ist. Diese Einstellung ist der FHEM default.  &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die Mindestlaufzeit der Umwälzpumpe (300 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::pumpControl ($name, &#039;07&#039;, 300);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamische Ladestromsteuerung eines Victron MultiPlus II Chargers mit Pylontech Batterie ===&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;
&lt;br /&gt;
 set &amp;lt;Device&amp;gt; MaxChargeCurrent &amp;lt;Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
eingestellt bzw. variiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Modul bietet dem Nutzer die Möglichkeit in dem Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltene Code wird am Ende jedes Zyklus (siehe Attribut &#039;&#039;plantControl-&amp;gt;cycleInterval&#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;
&lt;br /&gt;
&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 $mppt1   = &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common&#039;;              # SmartLoader Device&lt;br /&gt;
  my $maxcspc = 105;                        # max. Ladesollstrom (A) nominal&lt;br /&gt;
  my $spcorr  = 0.9;                        # Korrekturfaktor Überschuss 90%&lt;br /&gt;
  my $sch     = 0.25;                       # Verkürzungsfaktor Zeit bis Vollladung vor Sunset             &lt;br /&gt;
  &lt;br /&gt;
  my $cclvl0  = 15;                         # Ladestrom Level 0 max. 5  A (240 W) pro WR  (720  W)&lt;br /&gt;
  my $cclvl1  = 27;                         # Ladestrom Level 1 max. 9  A (432 W) pro WR  (1296 W)&lt;br /&gt;
  my $cclvl2  = 54;                         # Ladestrom Level 2 max. 18 A (864 W) pro WR  (2592 W)&lt;br /&gt;
  my $cclvl3  = 81;                         # Ladestrom Level 3 max. 27 A (1296 W) pro WR (3888 W)&lt;br /&gt;
  ###############&lt;br /&gt;
  &lt;br /&gt;
  my $cofc   = ReadingsNum ($name,  &#039;special_todayConForecastTillSunset&#039;, 0);&lt;br /&gt;
  my $pvfc   = ReadingsNum ($name,  &#039;RestOfDayPVforecast&#039;, 0);&lt;br /&gt;
  my $cpv    = ReadingsNum ($name,  &#039;Current_PV&#039;,          0);&lt;br /&gt;
  my $mppt1c = ReadingsNum ($mppt1, &#039;DC_0_Current_value&#039;,  0);             # Load I MPPT1 (max. 44 A)&lt;br /&gt;
  my $ssts   = CurrentVal  ($hash,  &#039;sunsetTodayTs&#039;,        0);&lt;br /&gt;
  my $srts   = CurrentVal  ($hash,  &#039;sunriseTodayTs&#039;,       0);&lt;br /&gt;
  my $sdiff  = ($ssts - $srts) / 3600;                                     # Sonnengang heute in h &lt;br /&gt;
  &lt;br /&gt;
  my $solh   = ReadingsNum ($name, &#039;special_SunHours_Remain&#039;, 0);          # h bis SunSet&lt;br /&gt;
  $solh      = $solh - ($sdiff * $sch);                                    # h bis SunSet - X&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;              # Ah Bat bis SOC&lt;br /&gt;
  $ahrem     = sprintf &amp;quot;%.0f&amp;quot;, $ahrem;&lt;br /&gt;
  &lt;br /&gt;
  my $fcdiff = ($pvfc - $cofc) * $spcorr;     # Korrektur d. noch prognostizierten Überschussenergie &lt;br /&gt;
  $fcdiff    = $fcdiff &amp;lt; 0 ? 0 : $fcdiff;     # Wh&lt;br /&gt;
  &lt;br /&gt;
  my $loadcur = $maxcspc;&lt;br /&gt;
  &lt;br /&gt;
  if ($cpv &amp;amp;&amp;amp; $solh &amp;amp;&amp;amp; $ahrem &amp;amp;&amp;amp; $fcdiff &amp;gt; $ahrem) {  # Ladeanforderung und Überschuss übersteigt &lt;br /&gt;
                                                      # Lademenge&lt;br /&gt;
      my $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($ahrem / $solh);    # A = Ah / h -&amp;gt; A Soll Schätzung&lt;br /&gt;
&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Battery charging process should be completed }.&lt;br /&gt;
                      qq{in &amp;gt;$solh&amp;lt; hours});&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; raw Target charging current: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($cspc - $mppt1c);      # SmartLoader IST berücksichtigen&lt;br /&gt;
	  &lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Charge Current minus MPPT load Current &amp;gt;$mppt1c&amp;lt;: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $loadcur = $cspc &amp;lt;= 0       ? 0       :     # nur MPPT Ladung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl0 ? $cclvl0 :     # Übergangsbereich&lt;br /&gt;
                 $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;
	  Log3 ($name, 3, qq{$name - userFn -&amp;gt; MaxChargeCurrent calculated: $loadcur});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent&#039;,       $loadcur.&#039; A&#039;,          1);&lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_HoursUntilChargeFinish&#039;, sprintf (&amp;quot;%.2f&amp;quot;,$solh), 1);&lt;br /&gt;
  CommandSet           (undef, &amp;quot;$vebus MaxChargeCurrent $loadcur&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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. 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;special_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;special_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;Verkürzungsfaktor Zeit bis Vollladung vor Sunset&#039;&#039;) reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche mindest Ladestromstärke ermittelt.&lt;br /&gt;
&lt;br /&gt;
&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 auch während der MQTT Intergration 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;
=== Poolheizung in Abhängigkeit von vorhandenem Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren) ===&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;consumer01&#039;&#039; wird beispielhaft wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr Forecast consumer01 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;&lt;br /&gt;
&lt;br /&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. &lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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, einen 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 Überschuss 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;. &lt;br /&gt;
&lt;br /&gt;
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;
=== PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) ===&lt;br /&gt;
[[Datei:Screenshot 2025-08-04 104835.png|mini|Darstellung der PV-Vorhersage in evcc auf Basis der SolarForecast-Daten]]&lt;br /&gt;
[https://evcc.io evcc] ist ein Energie-Management-System, mit dem u.a. Überschussladen von Elektroautos möglich ist. Hier ist beschreiben, wie die PV-Vorhersage von SolarForecast per API an evcc gesendet wird.&lt;br /&gt;
&lt;br /&gt;
Lege im SolarForecast-Device ein User-Reading mit dem Namen forecast_json an. Es wandelt die Forecast-Werte in JSON und ins UTC-Zeitformat um, so dass evcc die Daten verwenden kann:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
forecast_json {&lt;br /&gt;
&lt;br /&gt;
    use strict;&lt;br /&gt;
    use warnings;&lt;br /&gt;
    use JSON;&lt;br /&gt;
    use DateTime;&lt;br /&gt;
    use DateTime::Format::Strptime;&lt;br /&gt;
&lt;br /&gt;
    my $hour = 0;&lt;br /&gt;
    my @output;&lt;br /&gt;
&lt;br /&gt;
    # Parser für Datum mit CET/CEST&lt;br /&gt;
    my $parser = DateTime::Format::Strptime-&amp;gt;new(&lt;br /&gt;
        pattern   =&amp;gt; &#039;%Y-%m-%d %H:%M:%S&#039;,&lt;br /&gt;
        time_zone =&amp;gt; &#039;Europe/Berlin&#039;,&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    # Alle NextHour-Daten durchsuchen&lt;br /&gt;
    while ($hour &amp;lt; 100) {&lt;br /&gt;
        my $hour_str = sprintf(&#039;NextHour%02d&#039;, $hour);&lt;br /&gt;
        my $start_str = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;starttime&#039;, &#039;na&#039;); &lt;br /&gt;
        my $pvfc = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;pvfc&#039;, &#039;na&#039;);&lt;br /&gt;
&lt;br /&gt;
        # Schleife beenden, wenn keine Werte mehr vorhanden sind&lt;br /&gt;
        last if $start_str eq &#039;na&#039; or $pvfc eq &#039;na&#039;;&lt;br /&gt;
&lt;br /&gt;
        # parse und konvertiere Zeit&lt;br /&gt;
        my $start_dt = $parser-&amp;gt;parse_datetime($start_str);&lt;br /&gt;
        my $end_dt   = $start_dt-&amp;gt;clone-&amp;gt;add(hours =&amp;gt; 1);&lt;br /&gt;
&lt;br /&gt;
        # nach UTC konvertieren&lt;br /&gt;
        $start_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
        $end_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $start_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            end   =&amp;gt; $end_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            value =&amp;gt; 0 + $pvfc,&lt;br /&gt;
        };&lt;br /&gt;
        &lt;br /&gt;
        $hour++;&lt;br /&gt;
    }  &lt;br /&gt;
&lt;br /&gt;
    # Ausgabe als JSON&lt;br /&gt;
    my $json = JSON-&amp;gt;new-&amp;gt;utf8-&amp;gt;pretty-&amp;gt;encode(\@output);&lt;br /&gt;
    return $json;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Kommunikation von FHEM zu evcc läuft über den integrierten FHEM-Webserver, der die JSON-Daten aus dem Reading forecast_json veröffentlicht. Dazu wird in FHEM eine separate Webinstanz auf einem neuen Port erstellt, die ohne [[CsrfToken-HowTo|CSFR-Token]] (Achtung, Auswirkungen auf die Sicherheit beachten!) und nur von localhost aufrufbar ist (Voraussetzung: evcc läuft auf derselben Maschine wie FHEM):&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
defmod WEBapi FHEMWEB 8089&lt;br /&gt;
attr WEBapi csrfToken none&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;In der [https://docs.evcc.io/docs/tariffs#pv-vorhersage evcc-Konfig unter tariffs] steht die Quelle für die Solar-Vorhersage. Der FHEM-Befehl {ReadingsVal(&#039;solarforecast_dev&#039;,&#039;forecast_json&#039;,&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;)} wird encoded und in die uri eingetragen. Trage statt solarforecast_dev den passenden Namen deines SolarForecast-Device ein. evcc holt die Daten dann regelmäßig ab.&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
solar:&lt;br /&gt;
  type: custom&lt;br /&gt;
  interval: 20m    &lt;br /&gt;
  forecast:&lt;br /&gt;
    source: http&lt;br /&gt;
    uri: http://localhost:8089/fhem?cmd=%7BReadingsVal%28%27solarforecast_dev%27%2C%27forecast_json%27%2C%27%27%29%7D&amp;amp;XHR=1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Zur Verbesserung der Sicherheit kann das neue WEBapi Device auch ein [[CsrfToken-HowTo#csrfToken festlegen|festes CSFR-Token]] verwenden. Dieses Token muss dann in der evcc-Konfiguration an die uri mittels &amp;amp;fwcsrf=&amp;lt;festes token&amp;gt; angehängt werden.&lt;br /&gt;
&lt;br /&gt;
== weiterführende Links ==&lt;br /&gt;
* Forenthema &amp;quot;{{Link2Forum|Topic=137058|LinkText=76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support}}&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;
* Photovoltaik Ingenieurbüro Junge: https://www.ing-büro-junge.de/html/photovoltaik.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung&amp;diff=40302</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=40302"/>
		<updated>2025-08-04T10:25:05Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Hinweis|Die vorliegende Wiki-Seite befindet sich im Aufbau.}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Solarprognose und Verbrauchersteuerung&lt;br /&gt;
|ModType=d&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 Prognosewerte können die SolCast API, OpenMeteo API, Forecast.Solar API, Victron VRM Portal API oder alternativ DWD Stahlungswerte-Stationen verwendet werden&lt;br /&gt;
&lt;br /&gt;
::* optionale KI Unterstützung der PV-Prognose bei Verwendung von geeigneten Solar-API&#039;s&lt;br /&gt;
&lt;br /&gt;
::* es wird sowohl die Erzeugungsprognose als auch eine Verbrauchsprognose sowie SoC Prognose (bei Batterie-Integration) erstellt&lt;br /&gt;
&lt;br /&gt;
::* Wetterdaten werden über DWD Wetter-Stationen oder verschiedene API integriert. Es können verschiedene API zur Gewinnung von Solar- und Wetterdaten kombiniert werden. &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 FHEM-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 Integration von bis zu 4 Inverter und Smartloader (DC-DC Batterieladegeräte) ist möglich&lt;br /&gt;
&lt;br /&gt;
::* eine Integration von bis zu 3 nicht PV-Energieerzeugern wie BHKW, Windrädern oder Notstromaggregaten ist möglich&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;
::* Einbindung von bis zu drei Batteriespeichersystemen&lt;br /&gt;
&lt;br /&gt;
::* Bereitstellung von Leitwerten zur optimalen Einstellung/Steuerung von Batteriespeichersystemen&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 Benutzererlebnis 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;
Das Wiki gibt allgemeingültige und teilweise sehr spezifische bzw. tiefgehende Informationen und Handlungsempfehlungen zum SolarForecast Modul. Die dargestellten Informationen beziehen sich auf den zum Zeitpunkt der Wiki-Erstellung vorhandenen Entwicklungsstand des Moduls. Durch die stetige Weiterentwicklung können sich Abweichungen zum beschriebenen Inhalt ergeben oder zur Obsoleszenz dieser Inhalte führen. &lt;br /&gt;
&lt;br /&gt;
Vergleiche deshalb die Informationen immer mit der aktuellen Befehls-Referenz zum Modul!&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Ein SolarForecast Device wird mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 define &amp;lt;Name&amp;gt; SolarForecast &lt;br /&gt;
&lt;br /&gt;
angelegt. Nach der Definition wird der User durch einen Dialog geführt, der einige unerlässliche Einstellungen abfragt und in den entsprechenden Attributen und Readings persistiert. Alle Attribute und Readings die eine Einstellung der Anlage bewirken, sind mit dem Präfix &amp;quot;setup&amp;quot; versehen. &lt;br /&gt;
&lt;br /&gt;
Die Verwendung von setup-Readings gestattet es die Anlagenparameter dynamisch im Betrieb zu verändern. So kann mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringAzimuth   bzw.&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringDeclination &lt;br /&gt;
&lt;br /&gt;
die Ausrichtung und der Neigungswinkel der PV-Module ständig angepasst werden, was zum Beispiel bei einer dem Sonnenstand nachgeführten Anlage von Bedeutung ist.&lt;br /&gt;
&lt;br /&gt;
Die abgefragten Einstellungen während des Dialoges sind ausführlich in den entsprechenden Attributen bzw. Set-Kommandos erläutert. Die benötigten Informationen sind anhängig von der gewählten Prognose-API und können im Umfang variieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 213257.png|right|thumb|400px|Anlagenprüfung über Drucktaste in der Kopfgrafik]]&lt;br /&gt;
&lt;br /&gt;
Sobald alle verlangten Einstellungen vorgenommen sind, sollte eine Anlagenprüfung mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; plantConfiguration check&lt;br /&gt;
&lt;br /&gt;
oder über die angebotene Drucktaste in der Grafik durchgeführt werden. Es wird eine Plausibilitätsprüfung vorgenommen und das Ergebnis sowie eventuelle Hinweise bzw. Fehler ausgegeben.&lt;br /&gt;
Die Prüfung kann beliebig wiederholt werden und sollte sich bei jeder Einstellungsänderung der Anlage durchgeführt werden. Dadurch wird die Wahrscheinlichkeit von fehlerhaften Einstellungen minimiert.&lt;br /&gt;
&lt;br /&gt;
Neben den grundlegenden Einstellungen können im Device weitere sekundäre Anlagenkomponenten wie Batteriesystem(e) (Attribut setupBatteryDev1 - setupBatteryDev3), weitere Wetter-Devices (Attribut setupWeatherDev1 - setupWeatherDev3) oder sonstige Erzeuger (z.B. BHKW, Winderzeugung, Notstromaggregat) integriert werden (Attribut setupOtherProducer01 - setupOtherProducer03).&lt;br /&gt;
&lt;br /&gt;
Die verlangten Parameter der Anlage werden in der Online-Hilfe umfassend beschrieben und deren Funktion erschließt sich zum größten Teil selbst. Dennoch soll nachfolgend auf einige Punkte im Zusammenhang der Einrichtung eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Hinweise zur Struktur der Attribute ===&lt;br /&gt;
&lt;br /&gt;
Durch die umfangreichen Funktionen des Moduls würde bei Nutzung der im FHEM herkömmlich vorhandenen Attributstruktur die Anzahl der benötigten Attribute extrem stark steigen und nicht sinnvoll genutzt werden können. Deshalb gibt es neben den &#039;&#039;gewöhnlichen&#039;&#039; Attributen mit einfachen Werteauswahlmöglichkeiten oder Eingaben (z.B. ctrlDebug, ctrlSpecialReadings) sogenannte &#039;&#039;zusammengesetzte&#039;&#039; Attribute, deren Inhalt durch &#039;&#039;&#039;Schlüssel=Wert Paare&#039;&#039;&#039; gebildet wird und dadurch deutlich mehr Funktionen und Informationen transportieren als ein gewöhnliches Attribut.&lt;br /&gt;
&lt;br /&gt;
Für zusammengesetzte Attribute besteht die zusätzliche Möglichkeit, gewünschte Änderungen der Schlüssel=Wert Paare selektiv vornehmen zu können, ohne das gesamte Attribut aufrufen und ändern zu müssen. Die Vorgang, der vor allem für programmtechnische Manipulationen gedacht ist, kann durch eine Set-Funktion ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; attrKeyVal &amp;lt;Attribut&amp;gt; [&amp;lt;Gerät&amp;gt;] &amp;lt;Schlüssel=Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiele für zusammengesetzte Attribute sind:&lt;br /&gt;
&lt;br /&gt;
* aiControl&lt;br /&gt;
* plantControl&lt;br /&gt;
* setup* Attribute&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktionen der Attribute werden durch einen Präfix geclustert und so inhaltlich, aber vor allem auch in der Attribute Drop-Down Liste, strukturiert dargestellt.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der &#039;&#039;&#039;Präfixe&#039;&#039;&#039; sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ai&#039;&#039;&#039; - Steuerungsfunktionen für KI (z.B. aiControl)&lt;br /&gt;
* &#039;&#039;&#039;consumer&#039;&#039;&#039; - Registrierung und Einstellungen für Verbraucher (z.B. consumer02, consumerControl)&lt;br /&gt;
* &#039;&#039;&#039;ctrl&#039;&#039;&#039; - Steuerungsfunktion allgemeiner Art (z.B. ctrlDebug, ctrlSpecialReadings, ctrlUserExitFn)&lt;br /&gt;
* &#039;&#039;&#039;flowGraphic&#039;&#039;&#039; - Einstellungen für die Energieflußgrafik (z.B. flowGraphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphic&#039;&#039;&#039; - Einstellung für die Grafik allgemein (z.B. graphicSelect, graphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphicBeam&#039;&#039;&#039; -  Einstellungen bestimmte Balkeneigenschaften in der Balkengrafik (z.B. graphicBeamHeightLevel1)&lt;br /&gt;
* &#039;&#039;&#039;plant&#039;&#039;&#039; - übergreifende Einstellungen betreffend der gesamten PV-Anlage bzw. des SolarForecast-Devices (z.B. plantControl)&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039; - Registrierung von Geräten in der Gesamtanlage und Einstellung deren Eigenschaften (Inverter, Zähler, Batterien usw.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Einrichtung der Wechselrichter mit setupInverterDevXX ===&lt;br /&gt;
&lt;br /&gt;
Mit den Attributen setupInverterDev01 bis setupInverterDevXX werden die vorhandenen Wechselrichter der Anlage registriert.&lt;br /&gt;
Das Modul unterscheidet verschiedene Wechselrichter-Typen, die sich durch ihre Arbeitsweise innerhalb der Anlage unterscheiden. Die Schlüssel=Wert Paare in den Attributen können mehrzeilig organisiert werden. Das erleichtert die Übersicht wenn viele dieser Parameter eingegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;PV-Wechselrichter: Es ist der Standard Wechselrichter in einer PV-Anlage. An ihn sind die Solarzellen bzw. Strings angeschlossen. Die zugeordneten Strings können mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ohne diese Angabe werden diesem Gerät alle definierten Strings (siehe Attribut &#039;&#039;setupInverterStrings&#039;&#039;) zugeordnet. Der Wechselrichter liefert seine Energie in das Hausnetz. Alternativ kann mit der Angabe &#039;&#039;&#039;feed=grid&#039;&#039;&#039; die Funktion des Wechselrichters geändert werden. Diese Angabe sagt aus, dass dieser Wechselrichter ausschließlich in das öffentliche Netz einspeist.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel-Setup eines PV-Wechselrichters (SMA STP):&lt;br /&gt;
&lt;br /&gt;
 STP_5000 pvIn=string_1_pdc:kW pvOut=total_pac:kW etotal=etotal:kWh capacity=5000 strings=Süddach asynchron=1 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Solar-Ladegeräte: Solar-Ladegeräte sind DC-DC Wandler und liefern die Energie der angeschlossenen Solarzellen nicht in das Wechselstromnetz, sondern laden direkt eine Batterie bzw. versorgen einen Batteriewechselrichter auf der Gleichstromseite. Die Funktion als Solar-Ladegerät wird mit &#039;&#039;&#039;feed=bat&#039;&#039;&#039; aktiviert, die relevanten Strings können ebenfalls mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ein Beispiel eines Solar-Ladegerätes ist ein Victron SmartSolar MPPT. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel für das Setup eines Solar-Ladegeräts (SmartSolar Charger MPPT):&lt;br /&gt;
&lt;br /&gt;
 MQTT2_cerboGX_c0619ab34e08_solarcharger_Common pv=Yield_Power_value:W etotal=Yield_System_value:kWh capacity=2080 strings=Schleppdach feed=bat synchron=0 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Batterie-Wechselrichter: Dieses Gerät hat keine angeschlossenen Solarzellen und arbeitet als DC-AC bzw. AC-DC Wandler zwischen einer Batterie (=Gleichstromquelle) und dem Wechselstrom-Hausnetz. Die Funktion als Batterie-Wechselrichter wird mit der Angabe &#039;&#039;&#039;strings=none&#039;&#039;&#039; aktiviert. Die Schlüssel &#039;&#039;etotal&#039;&#039; und &#039;&#039;pv&#039;&#039; können bei einem Batterie-Wechselrichter ohne zugeordnete Solarzellen nicht gesetzt werden. Ein Beispiel eines Batterie-Wechselrichter ist der Victron MultiPlus II.&lt;br /&gt;
&lt;br /&gt;
Ein Setup-Beispiel für einen Batterie-Wechselrichter (Victron MultiPlus II):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dc2ac=DC_IN:W&lt;br /&gt;
ac2dc=DC_OUT:W&lt;br /&gt;
capacity=7200&lt;br /&gt;
strings=none&lt;br /&gt;
icon=inverter@darkorange:inverter@grey&lt;br /&gt;
asynchron=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Eigenschaften des Wechselrichters werden durch eine Reihe von &amp;lt;Schlüssel=Wert&amp;gt; Paaren festgelegt. Auf einige dieser Paramter soll hier eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Ausgewählte Schlüssel=Wert Paare ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;pvIn=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvIn&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell zugeführte PV-Leistung bereitstellt. Der Schlüssel ist optional und dient in erster Linie dazu den entsprechenden Input-Wert in der Flußgrafik anzuzeigen sofern man das Attribut flowGraphicControl-&amp;gt;showGenerators=1 setzt. Dadurch ist auch der Eigenverbrauch des Inverters bzw. dessen Wandlungsverlust visuell abschätzbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pvOut=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvOut&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell erzeugte Leistung als positiven Wert liefert. Für einen PV-Wechselrichter (DC-&amp;gt;AC) oder Solar-Ladegerät (DC-&amp;gt;DC) ist es die erzeugte PV-Leistung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ac2dc=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter vom Hausnetz in Richtung Batterie (AC-&amp;gt;DC) wandelt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;dc2ac=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter aus einer Gleichstromquelle, d.h. einer Batterie oder einem Solar-Ladegerät, in Richtung des Hausnetzes (AC) wandelt . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;capacity=&amp;lt;max. WR-Leistung&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In dem Schlüssel &#039;&#039;capacity&#039;&#039; wird die maximal mögliche Leistung in Watt (ohne Einheit) angegeben, die der Wechselrichter lt. seinem Datenblatt in der Lage ist zu leisten. &lt;br /&gt;
&lt;br /&gt;
Die Angabe &#039;&#039;capacity&#039;&#039; hat in erster Linie die Aufgabe, die max. mögliche PV-Leistung für die Prognose zu begrenzen. Oft sind die installierten Peak-Leistungen der PV-Module höher als die angeschlossene Wechselrichter-Leistung bzw. kommt es vor, dass die KI / (korrigierte) API-Prognose über der maximal möglichen Wechselrichter-Leistung liegt. In diesen Fällen wird die Prognose auf die angegebene &#039;&#039;capacity&#039;&#039; begrenzt.&lt;br /&gt;
&lt;br /&gt;
Der Wert in diesem Schlüssel kann, wie andere Schlüssel auch, dynamisch zur Laufzeit mit dem Set-Befehl &amp;quot;[[#Hinweise zur Struktur der Attribute|set &amp;lt;Name&amp;gt; attrKeyVal ...]]&amp;quot; geändert werden. Ein Beispiel zur Anwendung ergibt sich aus folgendem Szenario.&lt;br /&gt;
&lt;br /&gt;
Gegeben sei eine Anlage die aus Solarzellen (1300 W Peak) mit einem Solar-Ladegerät mit max. 1800 W Leistung, einer Batterie und einem Batterie-Wechselrichter besteht. Die Anlage versorgt nur das Hausnetz. Eine Netzeinspeisung ist nicht vorgesehen oder nicht erlaubt.  &lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, es ist ein Tag voller Sonnenschein prognostiziert und die Batterie ist zunächst entladen. Der Haushalt verbraucht 300 W. Dann würden die PV-Module Module ihre volle Leistung von 1300 W Peak leisten können, die sich auch in der Balken-Vorhersage niederschlägt. Die Leistung wird nicht begrenzt, weil:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* sie niedriger ist als die nominale und angegebene Wechselrichter Kapazität von &#039;&#039;capacity=1800&#039;&#039;&lt;br /&gt;
* die erzeugte Energie anteilig für die Verorgung des Hauses und die Aufladung der Batterie verwendet wird&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders verhält es sich wenn nach einer gewissen Zeit die Batterie voll ist und weiterhin volle PV Leistung zur Verfügung steht. In diesem Fall würde der Haushalt seine benötigte Leistung von 300 W abnehmen, aber das Solar-Ladegerät kann keine weitere Leistung mehr abgeben, da die Batterie bereits voll geladen ist, d.h. die Anlagensteuerung würde die PV-Anlage abregeln. In diesem Fall, wenn es einen längeren Zeitraum betrifft, muß auch die Prognose PV-Energie auf 300 Wh (bzw. den durchschnittlichen Energieverbrauch des Hauses pro Stunde) begrenzt werden, damit die PV-Prognose nach unten angepasst wird und so eine realitätsnahere Prognose ermöglicht wird. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;icon=&amp;lt;aktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;][:&amp;lt;inaktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Jeder Wechselrichter wird im Standard durch ein Icon getrennt nach Tag und Nacht, d.h. je nach Aktiv-Status und Inaktiv-Status, symbolisiert.&lt;br /&gt;
&lt;br /&gt;
;Tag bzw. Aktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Sonnensymbol im Standard verwendet. Batterie-Wechselrichter verwenden ein gefärbtes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
;Nacht bzw. Inaktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Symbol der aktuellen Mondphasen im Standard verwendet. Batterie-Wechselrichter verwenden ein ausgegrautes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie angegeben, kann man für Tag und Nacht jeweils ein Wunsch-Icon, wenn gewünscht mit einer alternativen Färbung, auswählen.&lt;br /&gt;
&lt;br /&gt;
 icon=inverter@darkorange:inverter@gray&lt;br /&gt;
&lt;br /&gt;
Soll nur das Icon für die Nacht bzw. Inaktivät geändert werden, kann dies in dieser Form angegeben werden:&lt;br /&gt;
&lt;br /&gt;
 icon=:inverter@gray  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(beachte den führenden &#039;:&#039;)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Der integrierte SolarForecast Grafikbereich ==&lt;br /&gt;
Das SolarForecast Modul beinhaltet eine Grafikdarstellung die sich in mehrere Bereiche gliedert. Diese Bereiche können über Attribute ein- bzw. ausgeblendet sowie die Inhalte festgelegt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 223545.png|right|thumb|400px|Bereiche der integrierten Grafik]]&lt;br /&gt;
&lt;br /&gt;
Der nebenstehende Screenshot gibt die Gliederung der Grafikbereiche wieder:&lt;br /&gt;
&lt;br /&gt;
 1 - der Kopfbereich (Graphic Header)&lt;br /&gt;
 2 - durch den Nutzer selbst definierbarer Inhalt (Graphic Header Own Specification) als Teil des Kopfbereiches&lt;br /&gt;
 3 - Bereich Verbraucherdarstellung (Consumer Legend)&lt;br /&gt;
 4 - Bereich Balkengrafik (Beam Graphic)&lt;br /&gt;
 5 - Energieflußgrafik (Flow Graphic)&lt;br /&gt;
&lt;br /&gt;
Jeder dieser Bereiche hat spezifische Steuerungsattribute zur Anpassung des Verhaltens und ggf. des Inhalts.&lt;br /&gt;
&lt;br /&gt;
=== 1 - Der Grafik Kopfbereich ===&lt;br /&gt;
Im Kopfbereich befinden sich fest verankerte Informationen zur verwendeten Vorhersage-API sowie deren Status, Informationen zum Sonnenaufgang und Sonnenuntergang, dem aktuellen Gesamtstatus des SolarForecast Devices, Abweichungskennzahlen der PV Vorhersage sowie weitere Kennzeichen zur Verfügung.&lt;br /&gt;
Über zwei Drucktasten kann eine Anlagenprüfung durchgeführt und in den Spportthread des Moduls im FHEM Forum abgesprungen werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;graphicHeaderShow&#039;&#039;&#039; kann der gesamte Kopfbereich 1 und 2 (nutzereigener Teilbereich) ausgeblendet werden. Wird der Kopbereich ausgeblendet, ist es hilfreich mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;showLink&#039;&#039;&#039; einen Link zur Detailgrafik einzufügen da der in der Kopfgrafik integrierte Link in diesem Fall nicht mehr zur Verfügung steht. &lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;graphicHeaderDetail&#039;&#039;&#039; definiert welche Bereiche des Grafikkopfes angezeigt werden sollen. Es kann die Anzeige des Energieverbrauches, der PV-Erzeugung und der vom Nutzer selbst definierte Inhalt miteinander frei kombiniert werden.&lt;br /&gt;
&lt;br /&gt;
=== 2 - Der Bereich mit selbst definierbarem Inhalt (Graphic Header Own Specification) ===&lt;br /&gt;
In diesem Bereich kann der User beliebige Readings, Set-Kommandos und Attribute des SolarForecast Devices oder anderer Devices, die sich im gleichen FHEM-System wie das SolarForecast Device befinden, anzeigen lassen.&lt;br /&gt;
&lt;br /&gt;
Dieser Bereich ist als Tabelle mit einer beliebigen Anzahl von Zeilen organisiert. Jede Zeile beinhaltet ein Kommentarfeld und vier Nutzfelder zur Darstellung ausgewähler Werte + Label. Der Bereich bzw. der Inhalt des Bereiches wird mit dem Attribut &#039;&#039;&#039;graphicHeaderOwnspec&#039;&#039;&#039; definiert.  &lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt ein real gesetztes graphicHeaderOwnspec Attribut. Die Leerzeilen sind nicht notwendig, erhöhen aber die Lesbarkeit der Struktur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
Autarkierate:Current_AutarkyRate&lt;br /&gt;
PV&amp;amp;nbsp;übermorgen:special_dayAfterTomorrowPVforecast&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;Sunset:special_todayConForecastTillSunset&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;nächsten&amp;amp;nbsp;Sunrise:special_conForecastTillNextSunrise&lt;br /&gt;
&lt;br /&gt;
#Batterie&lt;br /&gt;
BatteryLive&amp;amp;nbsp;Status:userFn_BatLive_State&lt;br /&gt;
SoC&amp;amp;nbsp;Limit:Settings_CGwacs_BatteryLife_MinimumSocLimit_value@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SoC&amp;amp;nbsp;Ist:SOC_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
SOC&amp;amp;nbsp;Optimum:Battery_OptimumTargetSoC&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
aktuelle&amp;amp;nbsp;Ladung:userFn_Bat_EnergyState&lt;br /&gt;
Verfügbar:userFn_BatLive_UsableEnergy&lt;br /&gt;
benötigte&amp;amp;nbsp;Ladeenergie:userFn_Bat_EnergyRemain&lt;br /&gt;
Ladefreigabe:Battery_ChargeRecommended&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
akt.&amp;amp;nbsp;DC&amp;amp;nbsp;Strom:DC_Current_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
Restladezeit&amp;amp;nbsp;Ziel:userFn_Bat_HoursUntilChargeFinish&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Soll:userFn_Bat_MaxChargeCurrent_set&lt;br /&gt;
:&lt;br /&gt;
&lt;br /&gt;
#Settings&lt;br /&gt;
Batterie&amp;amp;nbsp;Lademanagement:userFn_BatteryChargeManagement&lt;br /&gt;
SoC&amp;amp;nbsp;Management:userFn_BatterySoCManagement&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Ist:MaxChargeCurrent@MQTT2_cerboGX_c0619ab34e08_vebus&lt;br /&gt;
SmartSolar&amp;lt;br&amp;gt;Einspeisung:OvervoltageFeedIn@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
MPII&amp;amp;nbsp;Limit&amp;lt;br&amp;gt;Einspeisung&amp;amp;nbsp;(W):MaxFeedInPower@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SOC&amp;amp;nbsp;Limit&amp;amp;nbsp;Soll:MinimumSocLimit@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Verbr.&amp;amp;nbsp;Neuplanung:consumerNewPlanning&lt;br /&gt;
Wetteranzeige:graphicShowWeather &lt;br /&gt;
&lt;br /&gt;
Anzeige&amp;amp;nbsp;Nachtstunden:graphicShowNight&lt;br /&gt;
hist.&amp;amp;nbsp;Stunden:graphicHistoryHour&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto&lt;br /&gt;
Victron&amp;amp;nbsp;BatteryLife&amp;lt;br&amp;gt;(1=an,10=aus):BatteryLife@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Debug:ctrlDebu&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Kommentarfeld am Beginn einer Zeile wird durch ein &#039;&#039;&#039;#&#039;&#039;&#039; gekennzeichnet. Folgt dem # ein String, wird dieser String als Kommentarangabe gewertet und in der Grafik ausgegeben. Ein leeres Kommentarfeld wird lediglich durch ein # gefolgt von einem Leerzeichen oder NL beschrieben:&lt;br /&gt;
&lt;br /&gt;
 #:&amp;lt;Text&amp;gt;  (bzw nur # für einen &#039;leeren&#039; Titel)&lt;br /&gt;
&lt;br /&gt;
Ein Netzfeld bzw. ein Datensatz wird durch die Angabe von einem Label und dem darzustellenden Wert getrennt durch &#039;:&#039; definiert:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Label&amp;gt;:&amp;lt;Reading, Attribut oder Set-Kommando&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das System erkennt selbständig, ob es sich bei der Angabe um ein Reading, Attribut oder ein Set-Kommando handelt. Sollen Readings, Set-Kommandos und Attribute anderer Devices als dem SolarForecast-Device angezeigt werden, kann dies einfach durch Zusatz von&lt;br /&gt;
&lt;br /&gt;
 ....@&amp;lt;Device-Name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
an den Parameter erreicht werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-12-05 203916.png|right|thumb|400px|Darstellung eigener Grafikbereich]]&lt;br /&gt;
Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten &amp;quot;Wh&amp;quot; bzw. &amp;quot;kWh&amp;quot; werden entsprechend der Einstellung des Attributs &#039;&#039;&#039;graphicEnergyUnit&#039;&#039;&#039; umgerechnet. Im Label sind Leerzeichen durch &amp;quot;&amp;amp;amp;nbsp;&amp;quot; einzufügen, ein Zeilenumbruch durch &amp;quot;&amp;amp;lt;br&amp;amp;gt;&amp;quot;. Ein leeres Feld in einer Zeile wird durch &amp;quot;:&amp;quot; ohne eine weitere Angabe erzeugt.&lt;br /&gt;
&lt;br /&gt;
Die nebenstehende Abbildung zeigt die reale Darstellung der oben angegebenen Struktur im Attribut graphicHeaderOwnspec.&lt;br /&gt;
&lt;br /&gt;
==== Formatierung der Inhalte im Bereich &amp;quot;Graphic Header Own Specification&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
Die angezeigten Inhalte, wie z.B. Readingwerte, des User eigenen Bereiches (Attribut graphicHeaderOwnspec) können durch Spezifikationen im Attribut &#039;&#039;&#039;graphicHeaderOwnspecValForm&#039;&#039;&#039; manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
Die Online-Hilfe zum Attribut graphicHeaderOwnspecValForm erläutert die verfügbaren Möglichkeiten und Optionen.&lt;br /&gt;
Als Beispiel hier einige mögliche Notationen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &#039;userFn_Bat_HoursUntilChargeFinish&#039;                        =&amp;gt; &amp;quot;($VALUE).&#039; Stunden&#039;&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_battery.SOC_value&#039;             =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Settings_CGwacs_BatteryLife_MinimumSocLimit_value&#039;        =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Info_MaxChargeCurrent_value&#039;                              =&amp;gt; &amp;quot;($VALUE).&#039; A&#039;&amp;quot;,&lt;br /&gt;
  &#039;DC_Current_value&#039;                                         =&amp;gt; &amp;quot;%.0f A&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common.Regulated&#039; =&amp;gt; &amp;quot;($VALUE eq &#039;1&#039; ? &#039;Ja&#039; : &#039;Nein&#039;)&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine Besonderheit besteht bei darzustellenden Werten die die Einheiten &#039;Wh&#039; bzw. &#039;kWh&#039; besitzen. Diese Werte und Einheiten werden automatisch entsprechend des gesetzten Attributes graphicEnergyUnit umgerechnet und angezeigt.&lt;br /&gt;
&lt;br /&gt;
Soll in diesen Fällen eine automatische Formatierung umgangen werden, kann eine solche Notation verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &#039;Today_PVforecast&#039; =&amp;gt; &amp;quot;(sprintf &#039;%.1f &amp;amp;amp;nbsp;kWh&#039;, ($VALUE / 1000))&amp;quot;,&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Die Angabe von &amp;amp;amp;nbsp; vor &#039;kWh&#039; verhindert die Erkennung der Einheit und so auch die automatische Umsetzung durch das Modul. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 3 - Bereich Verbraucherdarstellung (Consumer Legend) ===&lt;br /&gt;
Dieser Grafikbereich zeigt die im Modul registrierten Verbraucher sowie deren Status und weitere Informationen an. Sind die Voraussetzungen gegeben, d.h. entsprechende Schlüssel in der ConsumerXX-Attributen gesetzt, können die Verbraucher über das Paneel manuell geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Zur Anpassung der Darstellung sind verschiedene Attribute verfügbar:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;consumerControl-&amp;gt;showLegend: Definiert die Lage bzw. Darstellungsweise der Verbraucherlegende sofern Verbraucher im SolarForecast Device registriert sind.&lt;br /&gt;
;consumerControl-&amp;gt;adviceIcon: Definiert die Art der Information über die geplanten Schaltzeiten eines Verbrauchers in der Verbraucherlegende. &lt;br /&gt;
;consumerControl-&amp;gt;detailLink: Wenn gesetzt, ist der jeweilige Verbraucher klickbar um direkt zur Detailansicht des jeweiligen Geräts auf einer neuen Browserseite zu gelangen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Standard wird das Verbraucherpaneel zwischen dem Kopfbereich und der ersten Balkengrafik Ebene dargestellt. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;showLegend&#039;&#039;&#039; und Argument &#039;&#039;&#039;icon_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_bottom&#039;&#039;&#039; kann das Verbraucherpaneel an das Ende des Grafikbereiches verschoben werden.&lt;br /&gt;
Die Verwendung von &#039;&#039;&#039;text_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_top&#039;&#039;&#039; blendet die Icon-Spalte im Verbraucherpaneel aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Screenshot 2025-02-08 093239.png|Darstellung mit consumerControl showLegend=icon_top (default)&lt;br /&gt;
File:Screenshot 2025-02-08 093646.png|Darstellung mit consumerControl showLegend=icon_bottom&lt;br /&gt;
File:Screenshot 2025-02-08 152018.png|Darstellung mit consumerControl showLegend=text_top bzw. text_bottom&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 213634.png|right|thumb|400px|]]&lt;br /&gt;
Ein Mouse-Over über das Uhrensymbol zeigt nähere Informationen zum Status, den Planungsdaten, Modus und weitere Daten des Verbrauchers. Der Schalter &amp;quot;Aus/Ein&amp;quot; visualisiert den Schaltzustand des Verbrauchers und können auch zum manuellen Schalten des Verbrauchers dienen. Voraussetzung ist, dass im consumer-Attribut die Schlüssel &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; mit den Set-Kommandos zum Schalten des Verbrauchers defininiert sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 222210.png|right|thumb|300px|]]&lt;br /&gt;
Der Auto-Schieberegler zeigt einerseits den Freigabestatus zum Schalten des Verbrauchers durch das SolarForecast Modul und kann andererseits manuell betätigt werden. Der Status des Reglers korrespondiert mit dem im zugehörigen Consumer Attribut vorhandenen Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; angegebenen Reading-Wert.&lt;br /&gt;
&lt;br /&gt;
Die Verbraucherbezeichnungen in dem Paneel können in der Standardkonfiguration angeklickt werden um direkt zur Detailansicht des Devices zu gelangen. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;detailLink&#039;&#039;&#039; kann der Link zur Detailansicht deaktiviert werden.&lt;br /&gt;
&lt;br /&gt;
Das Uhrensymbol kann mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;adviceIcon&#039;&#039;&#039; geändert und/oder dessen Farbe angepasst, sowie einen Informationstext statt eines Icons angezeigt werden. &lt;br /&gt;
&lt;br /&gt;
=== 4 - Bereich Balkengrafik (Beam Graphic) ===&lt;br /&gt;
&lt;br /&gt;
Die Balkengrafik des Moduls ist ein wesentliches Visualisierungshilfsmittel. Im Auslieferungszustand existiert eine Balkengrafikebene, die &#039;&#039;&#039;Ebene 1&#039;&#039;&#039;.&lt;br /&gt;
Jede Ebene kann zwei Balkendiagramme mit auswählbaren Inhalten, Farben und einstellbarem LayoutTyp darstellen. In Ebene 1 kann die Wettervorhersage eingebettet oder, bei Vorhandensein von Batteriegeräten, die zukünftigen Zeiten mit empfohlener Ladefreigabe und SoC-Prognose eingeblendet werden. &lt;br /&gt;
&lt;br /&gt;
Welche Daten in welchen Zeiträumen dargestellt werden sollen, die Bestimmung des Layouts, die Gestaltung der Balken und einiges mehr wird durch Attribute gesteuert. Ein Teil dieser Einstellungen wird über das zusammengesetzete Attribut &#039;&#039;&#039;graphicControl-&amp;gt;&#039;Schlüssel&#039;=&#039;Wert&#039;&#039;&#039;&#039; eingestellt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;grundsätzliche Layout Definitionen&#039;&#039;&#039;&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204342.png|right|thumb|400px|Standardanzeige mit Wetter-Icons, gesetzen Attributen graphicBeam1Color=D4C177, graphicHistoryHour=11]]&lt;br /&gt;
&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingTop:Legt den Platz in px im Balkendiagramm fest, der zwischen dem oberen Rand der jeweiligen Balkengrafik Ebene und der ersten Text- oder Iconreihe dieser Ebene eingefügt wird.&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingBottom:Legt den Platz in px im Balkendiagramm fest, der zwischen der letzten Text- oder Iconreihe der jeweiligen Balkengrafik Ebene und dem unteren Rand dieser Ebene eingefügt wird. &lt;br /&gt;
;graphicControl-&amp;gt;layoutType:Layout-Optionen zur grundlegenden Gestaltung der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourStyle:Format der Zeitangabe in der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourCount:Anzahl der darzustellenden Balken/Stunden in der Balkengrafk&lt;br /&gt;
[[Datei:Screenshot Screenshot 2025-05-21 153613.png|right|thumb|400px|Erweiterung des oberen und unteren Abstandes mit den Attributen graphicControl-&amp;gt;beamPaddingTop und graphicControl-&amp;gt;beamPaddingBottom]]&lt;br /&gt;
;graphicControl-&amp;gt;energyUnit:definiert die Einheit zur Anzeige der elektrischen Leistung in der Grafik&lt;br /&gt;
;graphicHistoryHour:Anzahl der vorangegangenen Stunden die in der Balkengrafik dargestellt werden&lt;br /&gt;
;graphicControl-&amp;gt;beamWidth:Vorgabe Breite der Balken der Balkengrafik in px (sonst automatische Bestimmung) &lt;br /&gt;
;graphicBeamHeightLevel1:Multiplikator zur Festlegung der maximalen Balkenhöhe der jeweiligen Ebene (hier Ebene 1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;Definition der Inhalte und Balkeneigenschaften&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204756.png|right|thumb|400px|Wie oben aber mit gesetzem Attribut graphicShowNight=1]]&lt;br /&gt;
;graphicBeam1Color:Farbauswahl des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2Color:Farbauswahl des sekundären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam1Content:Legt den darzustellenden Inhalt des primären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam2Content:Legt den darzustellenden Inhalt des sekundären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam1FontColor:Auswahl der Schriftfarbe des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2FontColor:Auswahl der Schriftfarbe des sekundären Balkens (Ebene 1)&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 205024.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=0 (ohne Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;zusätzliche Optionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;graphicShowNight:Anzeigen oder Verbergen der Nachtstunden in der Balkengrafik&lt;br /&gt;
;graphicShowWeather:Wettericons in der Balkengrafik anzeigen/verbergen (nur Ebene 1)&lt;br /&gt;
;graphicWeatherColor:Farbe der Wetter-Icons für die Tagesstunden&lt;br /&gt;
;graphicWeatherColorNight:Farbe der Wetter-Icons für die Nachtstunden&lt;br /&gt;
;graphicShowDiff:Zusätzliche Anzeige der Differenz &amp;quot;&amp;lt;primärer Balkeninhalt&amp;gt; - &amp;lt;sekundärer Balkeninhalt&amp;gt;&amp;quot; im Kopf- oder Fußbereich der Balkengrafik&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die genaue Beschreibung und deren Optionen sind der aktuellen Online-Hilfe zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Für alle Ebenen gilt:&#039;&#039;&#039; Ein Attribut mit einer ungeraden Balkennummer (z.B. graphicBeam1Content) bezieht sich immer auf den primären Balken, ein Attribut mit einer geraden Balkennummer (z.B. graphicBeam2Content) bezieht sich immer auf den sekundären Balken.&lt;br /&gt;
&lt;br /&gt;
Die Balken haben, wie die meisten Elemente in der Balkengrafik, eine Mouse-Over Eigenschaft welche relevante Informationen zu den dargestellten Werten anzeigt. &lt;br /&gt;
&lt;br /&gt;
Sind die Nachtunden mit &#039;&#039;&#039;graphicShowNight&#039;&#039;&#039; ausgeblendet, werden keine Balken angezeigt sofern es keine Werte anzuzeigen gibt. Sollten dennoch Werte ungleich 0 anzuzeigen sein, werden diese Werte auch trotz ausgeblendeter Nachstunden angezeigt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 2 ====&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 211741.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=01 (mit Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 2&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam3Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam4Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 4 für Balken 4) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wetter-Icons können nur in Ebene 1 integriert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 2 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 2 gibt, eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgende Ebene.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 3 ====&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 3&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam5Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam6Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 5 für Balken 5) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 3 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 3 gibt, ist eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgenden Ebenen, d.h. auch auf die Ebene 3.&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 5 - Die Energieflußgrafik (Flow Graphic) ===&lt;br /&gt;
[[Datei:Screenshot 2025-02-13 213424.png|right|thumb|400px|Energieflußgrafik mit Verbrauchern in der Nachtdarstellung (Mondphasen) nach Sonnenuntergang]]&lt;br /&gt;
&lt;br /&gt;
Die Energieflußgrafik stellt die registrierten Erzeuger, Batterien, Netzzugänge und Verbraucher strukturiert in mehreren Ebenen dar:&lt;br /&gt;
&lt;br /&gt;
;Ebene 1: In der oberen Ebene befinden sich die PV-Generatoren, Smart-Loader sowie sonstigen Erzeuger &lt;br /&gt;
;Ebene 2: Die mittlere Ebene organisiert den Zugang zum öffentlichen Netz, dem Hausknoten, dem Batterieknoten sowie einem Dummy-Verbraucher (Lampensymbol) für den Energieverbrauch des Hauses der keinem der registrierten Verbraucher zugeordnet werden kann.&lt;br /&gt;
;Ebene 3: In der unteren Ebene werden die registrierten Verbraucher dargestellt. Unterhalb der Verbrauchersymbole werden der aktuelle Verbrauch (bzw. der On/Off-Zustand) sowie darunter die Restlaufzeit (Minuten) des Verbrauchers, sofern er durch das Modul geplant und gestartet wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Position und Gestaltung der Grafikelemente ist umfangreich über das Attribut &#039;&#039;&#039;flowGraphicControl&#039;&#039;&#039; und den darin verfügbaren Schlüsseln einstellbar.&lt;br /&gt;
Die Bedeutung der Schlüssel ist in der Online-Hilfe zum Attribut mit einem Beispiel beschrieben. &lt;br /&gt;
&lt;br /&gt;
Darüber hinaus enthalten die Setup-Attribute &#039;&#039;&#039;setupInverterDevXX&#039;&#039;&#039;, &#039;&#039;&#039;setupOtherProducerXX&#039;&#039;&#039; und &#039;&#039;&#039;consumerXX&#039;&#039;&#039; weitere Einstellungsmöglichkeiten um deren Icons und Färbungen in der Flußgrafik individuell einstellen zu können. So sind zum Beispiel die Icons der PV-Inverter und deren Färbung mit dem Schlüssel &#039;&#039;&#039;icon&#039;&#039;&#039; der setupInverterDevXX-Attribute in Abhängigkeit von Tag und Nacht separat definierbar.&lt;br /&gt;
&lt;br /&gt;
In den Verbraucher-Attributen ist mit dem Schlüssel &#039;&#039;&#039;noshow&#039;&#039;&#039; die Sichtbarkeit in der Flußgrafik definierbar.&lt;br /&gt;
&lt;br /&gt;
Generell steuert das Attribut &#039;&#039;&#039;graphicSelect&#039;&#039;&#039; die Ein- bzw. Ausblendung der gesamten Flußgrafik.&lt;br /&gt;
&lt;br /&gt;
== Die Verbrauchsprognose ==&lt;br /&gt;
Im Gegensatz zu der PV Prognose gibt es keine API oder andere externen Datenquellen die für die Verbrauchsprognose herangezogen werden könnten.&lt;br /&gt;
&lt;br /&gt;
Zum Zweck der Verbrauchsermittlung verwendet das Modul die Meterdaten aus dem Attribut &#039;&#039;setupMeterDev&#039;&#039; sowie den weiteren setup-Attributen &#039;&#039;setupInverterDevXX&#039;&#039;. &lt;br /&gt;
Sind auch andere Erzeuger (BHKW, Windanlagen, etc.) bzw. eine Batterie vorhanden, sind ebenfalls die Attribute &#039;&#039;setupOtherProducerXX&#039;&#039; bzw. &#039;&#039;setupBatteryDev&#039;&#039; für die Berechnung des Hausverbrauchs relevant. In diesen Attributen gibt es die Schlüssel &#039;&#039;*total&#039;&#039; die teilweise optional sind. Für die Verbrauchsprognose bilden sie jedoch die Berechnungsgrundlage und sind deswegen für diese Funktionalität wichtig anzugeben.&lt;br /&gt;
&lt;br /&gt;
Die Verbrauchswerte werden stundengenau erfasst und im Datenspeicher &#039;&#039;pvHistory&#039;&#039; für 31 Tage, sowie im Datenspeicher &#039;&#039;pvCircular&#039;&#039; 210 Tage gespeichert. Die beiden Datenspeicher übernehmen unterschiedliche Aufgaben im Rahmen der Prognoseerstellung. Auf Grundlage der gespeicherten und somit historischen Verbrauchswerte erstellt das Modul eine Prognose für die kommende Zeit.&lt;br /&gt;
&lt;br /&gt;
Mit dem Kommando &lt;br /&gt;
&lt;br /&gt;
   &amp;quot;get ... pvHistory [Tag]&amp;quot; &lt;br /&gt;
&lt;br /&gt;
wird der Inhalt aufgelistet. Die Schlüssel &#039;&#039;confc&#039;&#039;, &#039;&#039;con&#039;&#039; und &#039;&#039;gcon&#039;&#039; zeigen die Verbrauchsprognose, den Verbrauch und den Netzbezug der jeweiligen Stunde des gewählten Tages.&lt;br /&gt;
Die Stunde &amp;quot;99&amp;quot; zeigt die Summen dieser Schlüsssel für den Tag:&lt;br /&gt;
&lt;br /&gt;
      99 =&amp;gt; etotal: , pvfc: 782, pvrl: 0, rad1h: -&lt;br /&gt;
            confc: 14540, con: 13873, gcon: 13873, gfeedin: 0&lt;br /&gt;
            batintotal: , batin: 0, batouttotal: , batout: 0&lt;br /&gt;
            batmaxsoc: -, batsetsoc: -&lt;br /&gt;
            wid: , wcc: , wrp: , pvcorrf: , dayname: So&lt;br /&gt;
            cyclescsm01: 0&lt;br /&gt;
            cyclescsm02: 0&lt;br /&gt;
            cyclescsm03: 0&lt;br /&gt;
            cyclescsm04: 1, hourscsme04: 0.00&lt;br /&gt;
            cyclescsm05: 0&lt;br /&gt;
            cyclescsm06: 0&lt;br /&gt;
            cyclescsm07: 1, hourscsme07: 0.00&lt;br /&gt;
            cyclescsm08: 1, hourscsme08: 0.00&lt;br /&gt;
            cyclescsm09: 1, hourscsme09: 0.03 &lt;br /&gt;
&lt;br /&gt;
In dem Beispiel wurden für den Tag 14540 Wh Verbrauch prognostiziert, 13873 Wh tatsächlich verbraucht und davon 13873 Wh aus dem Netz bezogen. Leider war an diesem Tag keinerlei PV Ertrag vorhanden, was man auch an dem Schlüssel &#039;&#039;pvrl&#039;&#039; erkennen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Inhalt des pvCircular-Speichers kann mit dem Befehl  &lt;br /&gt;
&lt;br /&gt;
     &amp;quot;get ... pvCircular [Tag]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Das nachfolgende Beispiel zeigt die Ausgabe für die Tagesstunde 23:&lt;br /&gt;
&lt;br /&gt;
 23 =&amp;gt; pvapifc: 0, pvaifc: -, pvfc: 0, aihit: 0, pvrl: 0&lt;br /&gt;
       batin01: 0, batin02: -, batin03: -&lt;br /&gt;
       batout01: 619, batout02: -, batout03: -&lt;br /&gt;
       confc: 650, gcon: 23, gfeedin: 0, wcc: 40, rr1c: 0.00&lt;br /&gt;
       temp: -6.00, wid: 100, wtxt: Bewölkungsentwicklung nicht beobachtet&lt;br /&gt;
       pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
       ... &lt;br /&gt;
       con_all =&amp;gt; Sa  @ 617 762&lt;br /&gt;
                  Di  @ 693 645&lt;br /&gt;
                  Mo  @ 620 679&lt;br /&gt;
                  So  @ 669 666 636&lt;br /&gt;
                  Mi  @ 701 626&lt;br /&gt;
                  Do  @ 612 642&lt;br /&gt;
                  Fr  @ 615 606&lt;br /&gt;
&lt;br /&gt;
Der Schüssel &#039;&#039;con_all&#039;&#039; enthält einen Hash aus Arrays die für jeden Wochentag (Mo..So) bis zu 30 Verbrauchswerte (in Wh) für die angezeigte Stunde speichern. Wie hier erkennbar ist, wurden an den drei vergangenen Sonntagen jweils 669 Wh, 666 Wh bzw. 636 Wh in der Stunde 23 (22:00-22:59) verbraucht.&lt;br /&gt;
Der Median aus diesen Werten geht in die Verbrauchsprognose ein. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wochentagsnamen Mo..So sind von den installierten Locales auf Betriebsystemebene abhängig. Ist keine deutsche locale installiert, werden die englischen Wochentagsnamen Mon..Sun verwendet. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Wie wird der Verbrauch des Hauses ermittelt und gespeichert? ===&lt;br /&gt;
Die Verbrauchsdaten des Hauses werden auf Stundenbasis ermittelt und gespeichert. Das &amp;quot;Haus&amp;quot; steht als Synonym aller im Kontext des Solarforecast Devices zusammengeführten Inverter (setupInverterDevXX), sonstigen Erzeuger (setupOtherProducerXX), Netzanschlüsse (setupMeterDev), Verbraucher (consumerXX) und Batterien (setupBatteryDev).&lt;br /&gt;
&lt;br /&gt;
Alle diese Daten werden durch das Modul mit jedem ausgeführten Zyklus (Attribut plantControl-&amp;gt;cycleInterval) und, wenn ein Event eines als &#039;asynchron&#039; definierten Devices auftritt, gesammelt und daraus permanent ein aktualisierter Verbrauch berechnet. Die Berechnung beschreibt folgende Formel:&lt;br /&gt;
&lt;br /&gt;
 PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung - Verbrauch = 0&lt;br /&gt;
&lt;br /&gt;
bzw.&lt;br /&gt;
 &lt;br /&gt;
 Verbrauch (Wh) = PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung&lt;br /&gt;
            con = PV           + PP                 - GridIn          + GridCon   - BatIn          + BatOut&lt;br /&gt;
&lt;br /&gt;
Die PV-Erzeugung beinhaltet die Summe aller durch die angegebnen Inverter (setupInverterDev01 .. setupInverterDevXX) erzeugten Energien. Die &amp;quot;sonstige Erzeugung&amp;quot; summiert sich aus den Werten aller angegebenen Producer (setupOtherProducer01 .. setupOtherProducerXX). Der Verbrauch wird durch die registrierten Geräte consumerXX teilweise direkt erfasst, ist aber grundsätzlich unvollständig da nicht alle Verbrauchswerte im &amp;quot;Haus&amp;quot; gemessen und durch das Modul erfasst werden können.&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel zeigt das Ergebnis bei 300 Wh PV-Erzeugung und gleichzeitige 500 Wh Netzbezug:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 300 + 0 - 0 + 500 - 0 + 0 = 800 Wh&lt;br /&gt;
&lt;br /&gt;
Bei 1300Wh PV-Erzeugung, 100 Wh Netzeinspeisung sowie 200 Wh Batterieladung ergibt sich der Verbrauch zu:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 1300 + 0 - 100 + 0 - 200 + 0 = 1000 Wh&lt;br /&gt;
&lt;br /&gt;
Ohne Erzeugung, aber mit der Energielieferung von 500 Wh aus der Batterie, 800 Wh Netzbezug (mit einem Anteil Batterienachladung aus dem Netz von 200 Wh) sieht die Verbrauchsrechnung wie folgt aus: &lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 0 + 0 - 0 + 800 - 200 + 500 = 1100 Wh&lt;br /&gt;
&lt;br /&gt;
Der so ermittelte Verbrauchsert wird mit jedem Zyklus in der pvHistory im Schlüssel &amp;quot;con&amp;quot; gespeichert. Man kann sich die gespeicherten Werte mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;name&amp;gt; pvHistory [&amp;lt;Tag&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Nachfolgendes Beispiel zeigt einen Datensatz für die Stunde 8 eines Tages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      08 =&amp;gt; pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotali01: 62940734, etotali02: 2928860, etotali03: -&lt;br /&gt;
            pvrl01: 0, pvrl02: 0, pvrl03: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 630, con: 962, gcons: 962, conprice: 0.2958&lt;br /&gt;
            gfeedin: 0, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 120, sunalt: -3&lt;br /&gt;
            batintotal: 3713815.07742543, batouttotal: 3604468.26993988, batin: 0, batout: 0&lt;br /&gt;
            wid: 161, wcc: 89, rr1c: 0.00, pvcorrf: 0.27/0.00 temp: 7.40, &lt;br /&gt;
            csmt01: 110996.12, csme01: 32.1399999999994, minutescsm01: 30&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 2513.67, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1581293.6, csme04: 136.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 1662.17, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 90.53, csme06: 0, minutescsm06: 0&lt;br /&gt;
            csmt07: 39.75, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 38050, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 131627, csme09: 33.2000000000116, minutescsm09: 39&lt;br /&gt;
            minutescsm10: 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Schlüssel &amp;quot;con&amp;quot; ist der gespeicherte Verbrauch von 962 Wh ersichtlich.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit bekommt man mit dem Attribut &#039;&#039;ctrlDebug=collectData&#039;&#039; einen Einblick in die Verbrauchsermittlung bei jedem Zyklus und kann so die Eingangswerte und das daraus resultierende Ergebnis im FHEM Log nachverfolgen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
2024.11.28 11:38:20.080 1: SolCast DEBUG&amp;gt; EnergyConsumption input -&amp;gt; PV: 96, PP: 0, GridIn: 0, GridCon: 582, BatIn: 5, BatOut: 0&lt;br /&gt;
2024.11.28 11:38:20.081 1: SolCast DEBUG&amp;gt; EnergyConsumption result -&amp;gt; 673 Wh&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie wird die Verbrauchsprognose erstellt? ===&lt;br /&gt;
&lt;br /&gt;
Aus den gespeicherten con-Werten (Verbrauchsdaten) der pvCircular (Schlüssel con_all) sowie Einträgen der pvHistory wird der Median der historischen Tage ermittelt und für den kommenden Tag bzw. die kommen Stunden zur Prognose angewendet. Dabei geht per default jeder verfügbare historische Tag gleichberechtigt in die Prognose ein. Mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039; kann festgelegt werden, dass nur gleiche Wochentage (Mo..So) für die Prognose verwendet werden. Hierbei spielt die Vermutung, dass das Verbrauchsverhalten eine gewisse Korrelation zum Wochentag hat, eine Rolle. &lt;br /&gt;
&lt;br /&gt;
Verwendet man die Einstellung consForecastIdentWeekdays=1, hat es sich als vorteilhaft erwiesen, das Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays&#039;&#039;&#039; auf einen niedrigeren Wert als den Default zu setzen. Eine Einstellung auf &#039;8&#039; zum Beispiel verwendet den Median der gleichen Wochentage der vergangenenen 8 Wochen. Dadurch wird nicht zu weit in die Vergangenheit verzweigt und so eine langsame Veränderung des Verbrauchsmedian, zum Beispiel hervorgerufen durch den Übergang vom Winter in das Frühjahr hinein, abgebildet.&lt;br /&gt;
&lt;br /&gt;
Weiteren Einfluß auf die Verbrauchsprognose kann mit dem Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; im Consumerattribut genommen werden. Insbesondere bei der unregelmäßigen Nutzung von Verbrauchern mit hoher Leistung kann die Projektion der aufgezeichneten historischen Werte in die Prognose zu unverhältnismäßig hohen Verbrauchswerwartunden führen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Möglicherweise führt in Fällen die Verwendung eine der nachfolgenden Optionen zu einem besseren Ergebnis:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;1 -&#039;&#039;&#039; die allgemeine Verbrauchsprognose wird um die gespeicherten Energieverbrauchsanteile reduziert.&lt;br /&gt;
* &#039;&#039;&#039;2 -&#039;&#039;&#039; wie bei &#039;1&#039;, jedoch gehen die Planungsdaten des Verbrauchers bei der Prognose der kommenden Stunden wieder mit ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;&#039;exconfc&#039;&#039;&#039; in einem der Consumer verwendet, sollte&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays=4&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
eingestellt werden. Hintergrund ist, dass die Verbrauchsanteile der jeweiligen Verbraucher nur maximal 31 Tage in der pvHistory verfügbar sind. Für längere Zeiträume stehen nur Gesamtsummen des Verbrauchs in der pvCircular zu Verfügung.  &lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=1&#039;&#039;&#039; werden die in der Historie aufgezeichneten Verbrauchsbestandteile aus einer Prognose herausgerechnet. Konkret werden die in der pvHistory aufgezeichneten Verbrauchsbestandteile für die relevante Stunde ermittelt und daraus ein Durchschnitt gebildet der vom Prognosewert subtrahiert wird. Mit dem Attributwert plantControl-&amp;gt;consForecastIdentWeekdays=1 werden wiederum nur identische Wochentage (Mo .. So) zusammengefasst.&lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=2&#039;&#039;&#039; erfolgt ebenso die Eliminierung des Verbrauchsanteils, es wird jedoch auf die Planungsdaten für diesen Verbraucher zugegriffen und die geplanten Energieanteile wiederum der Verbrauchsprognose für die kommenden Stunden hinzugerechnet.&lt;br /&gt;
&lt;br /&gt;
In beiden Anwendungsfällen ist es notwendig, dass dem Modul durch die Angabe entsprechender Readings der Energieverbrauch im Setup des Consumers bekannt gemacht wird damit diese Energieanteile registriert werden können. Allgemein funktioniert die Verbrauchsprognose gut wenn Verbrauchsprozesse regelmäßig in einem wiederkehrenden Zeitraster ablaufen, der Verbrauch durch persönliche Rituale bestimmt ist. So zum Beispiel könnte am Dienstag und Samstag gewöhnlich die Waschmaschine laufen, das E-Auto täglich aufgeladen werden und gebügelt wird oft am Sonntag Nachmittag.&lt;br /&gt;
&lt;br /&gt;
Unregelmäßige Nutzung, vor allem vom Großverbrauchern, lässt sich nur sehr schwer und ungenügend auf zukünftige Verbrauchsprognosen projizieren.&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis der Prognose wird im Kopf der Grafik in der Zeile &#039;&#039;Verbrauch&#039;&#039; sowie in diversen Readings wie &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RestOfDayConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den Rest des Tages)&lt;br /&gt;
* &#039;&#039;&#039;NextHours_Sum04_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für die nächsten 4 Stunden)&lt;br /&gt;
* &#039;&#039;&#039;Tomorrow_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den kommenden Tag)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
angezeigt.&lt;br /&gt;
&lt;br /&gt;
Weitere Aggregationen kann man sich über das Attribut &#039;&#039;&#039;ctrlStatisticReadings&#039;&#039;&#039; bei Bedarf zuschalten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;conForecastTillNextSunrise&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
* &#039;&#039;&#039;todayConForecastTillSunset&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
* &#039;&#039;&#039;todayConsumptionForecast&#039;&#039;&#039; - Verbrauchsprognose aufgesplittet pro Stunde des aktuellen Tages (01-24) &lt;br /&gt;
 &lt;br /&gt;
==== Debugging der Verbrauchsprognose ====&lt;br /&gt;
Um sich einen Einblick über die Erstellung der Verbrauchsprognose zu verschaffen, bietet sich die Einschaltung von:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
an. Mit diesem gesetzten Attribut wird die Erstellung der Prognose im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; ################### Start Consumption forecast ###################&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; Basics - installed locale: de_DE.UTF-8, used scheme: DE&lt;br /&gt;
2025.02.27 19:52:00.064 1: SolCast DEBUG&amp;gt; process Today dayname: Do, Tomorrow dayname: Fr&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 01 - 74.43 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 10 - 290.77 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 24 - 660.70 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 20, hod: 07 - 459.93 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;07&#039; register for exclude day 20, hod: 02 - 0.33 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 30, hod: 08 - 264.78 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next Hours (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; excl. hist 74 Wh for Hour 01, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; estimated cons of Hour 01: 436 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; excl. hist 0 Wh for Hour 02, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 02: 428 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 03: 458 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 04: 503 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 05: 489 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 06: 482 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; excl. hist 460 Wh for Hour 07, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 07: 274 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 265 Wh for Hour 08, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 08: 441 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 09: 558 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 291 Wh for Hour 10, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 10: 443 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 11: 881 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 12: 794 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 13: 840 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 14: 660 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 15: 812 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 16: 752 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 17: 597 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 18: 652 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 19: 634 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 20: 628 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 21: 713 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 22: 596 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 23: 629 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; excl. hist 661 Wh for Hour 24, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons of Hour 24: 660 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons Tomorrow: 16848 Wh, Individual hourly values considered: 72, exclude: 0 Wh (avg of 0 entities)&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Store Consumption forecast values (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour00&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;20&#039; confc: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour01&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;21&#039; confc: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour02&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;22&#039; confc: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour03&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;23&#039; confc: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store &#039;NextHour04&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;24&#039; confc: 660&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour05&#039; hod &#039;01&#039; confc: 436, confcEx: 436&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour06&#039; hod &#039;02&#039; confc: 428, confcEx: 428&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour07&#039; hod &#039;03&#039; confc: 458, confcEx: 458&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour08&#039; hod &#039;04&#039; confc: 503, confcEx: 503&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour09&#039; hod &#039;05&#039; confc: 489, confcEx: 489&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour10&#039; hod &#039;06&#039; confc: 482, confcEx: 482&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour11&#039; hod &#039;07&#039; confc: 274, confcEx: 274&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour12&#039; hod &#039;08&#039; confc: 441, confcEx: 441&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour13&#039; hod &#039;09&#039; confc: 558, confcEx: 558&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour14&#039; hod &#039;10&#039; confc: 443, confcEx: 443&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour15&#039; hod &#039;11&#039; confc: 881, confcEx: 881&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour16&#039; hod &#039;12&#039; confc: 794, confcEx: 794&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour17&#039; hod &#039;13&#039; confc: 840, confcEx: 840&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour18&#039; hod &#039;14&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour19&#039; hod &#039;15&#039; confc: 812, confcEx: 812&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour20&#039; hod &#039;16&#039; confc: 752, confcEx: 752&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour21&#039; hod &#039;17&#039; confc: 597, confcEx: 597&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour22&#039; hod &#039;18&#039; confc: 652, confcEx: 652&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour23&#039; hod &#039;19&#039; confc: 634, confcEx: 634&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour24&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour25&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour26&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour27&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour28&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; consumption calculated - day: 27, hod: 20, con: 574 Wh&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; write pvCircular consumption - hod: 99, todayConsumption: 11210 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe startet mit &#039;&#039;&amp;quot;Start Consumption forecast&#039;&#039;&amp;quot;, es werden die zu exkludierenden historischen Daten für jeden Consumer bzgl. jedem Tag (day) und Stunde des Tages (hod) getrennt registriert. Diese Werte werden durch die gespeicherte Einträge in der pvHistory (max. 31 historische Tage) geliefert. &lt;br /&gt;
&lt;br /&gt;
Im nächsten Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next Hours (new median)&amp;quot;&#039;&#039; werden die Prognosen für die nächsten Stunden kalkuliert und die zuvor registrierten Excludes angewendet. Die Prognose für den kommenden Tag ist im Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next day (new median)&amp;quot;&#039;&#039; protokolliert. Die Prognose für den kommenden Tag ist nicht einfach die Summe der Prognose der nächsten Stunden, denn in den kommenden Stunden werden auch die verfügbaren Planungen der Consumer einbezogen. Für den kommenden Tag können diese Werte unter Umständen nicht einbezogen werden da sie zum Zeitpunkt X noch nicht verfügbar sind.&lt;br /&gt;
&lt;br /&gt;
Im Abschnitt &#039;&#039;&amp;quot;Store Consumption forecast values (new median)&amp;quot;&#039;&#039; erscheinen die effektiv gespeicherten Werte. Diese sind die Grandlage für die grafische Darstellung sowie weiteren Kalkulationen.&lt;br /&gt;
&lt;br /&gt;
=== Wie kann eine fehlerhafte Verbrauchsprognose korrigiert werden? ===&lt;br /&gt;
Wie im vorherigen Abschnitt beschrieben, wird die Prognose aus den gespeicherten &amp;quot;con&amp;quot;-Werten der vergangenen Tage (bzw. Stunden) abgeleitet. &lt;br /&gt;
Grundsätzlich muß zunächst sichergestellt werden, dass die auszulesenden Readings der angegebenen Energiezähler sowie deren Einheiten! korrekt eingestellt sind. Das gilt ebenfalls für die registrierten Verbraucher im Modul.&lt;br /&gt;
&lt;br /&gt;
Für einen ersten Überblick bietet sich das Debug Attribut an zu setzen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
Beispielausgabe des Debug:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2024.09.21 13:28:27.041 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day ###################&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;01&amp;lt; considering possible exclusions: 14082&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;08&amp;lt; considering possible exclusions: 16446&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;15&amp;lt; considering possible exclusions: 14568&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;25&amp;lt; considering possible exclusions: 15522&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; estimated Consumption for tomorrow: 15154, days for avg: 4&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next hours ###################&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 14 -&amp;gt; 850 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 14 -&amp;gt; 643 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 14 -&amp;gt; 590 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 14 -&amp;gt; 522 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 13:00:00, confc: 651, days for avg: 4, hist. consumption registered consumers: 560.97&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 15 -&amp;gt; 720 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 15 -&amp;gt; 743 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 15 -&amp;gt; 897 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 15 -&amp;gt; 557 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 14:00:00, confc: 729, days for avg: 4, hist. consumption registered consumers: 620.97&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 16 -&amp;gt; 676 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 16 -&amp;gt; 790 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 16 -&amp;gt; 785 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 16 -&amp;gt; 581 Wh&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 15:00:00, confc: 708, days for avg: 4, hist. consumption registered consumers: 647.29&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 17 -&amp;gt; 622 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 17 -&amp;gt; 639 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 17 -&amp;gt; 646 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 17 -&amp;gt; 572 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 16:00:00, confc: 619, days for avg: 4, hist. consumption registered consumers: 618.30&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 18 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 18 -&amp;gt; 614 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 18 -&amp;gt; 580 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 18 -&amp;gt; 480 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 17:00:00, confc: 567, days for avg: 4, hist. consumption registered consumers: 583.41&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 19 -&amp;gt; 615 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 19 -&amp;gt; 1659 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 19 -&amp;gt; 597 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 19 -&amp;gt; 618 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 18:00:00, confc: 872, days for avg: 4, hist. consumption registered consumers: 636.97&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 20 -&amp;gt; 611 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 20 -&amp;gt; 1124 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 20 -&amp;gt; 546 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 20 -&amp;gt; 479 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 19:00:00, confc: 690, days for avg: 4, hist. consumption registered consumers: 578.87&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 21 -&amp;gt; 1474 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 21 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 21 -&amp;gt; 619 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 21 -&amp;gt; 433 Wh&lt;br /&gt;
2024.09.21 13:28:27.058 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Im ersten Teil wird die erwartete Consumption für den nächsten Tag unter Berücksichtigung möglicher Ausschlüsse von Verbrauchern ausgegeben. Ausschlüsse von Verbrauchern ergeben sich wenn in dem Verbraucherattribut der Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; gesetzt ist. Er besagt, dass die Verbrauchswerte des Verbrauchers in eine zukünftige Prognose nicht eingehen sollen. Zum Beispiel wenn ein Verbraucher mit sehr hohen Verbrauchswerten nur sporadisch eingesetzt wird und dadurch die Prognose stark verfälschen würde. Es ist auch zu sehen, dass bedingt durch das Attribut &#039;&#039;&#039;affectConsForecastIdentWeekdays = 1&#039;&#039;&#039; nur die historischen Tage 01, 08, 15 und 25 berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Teil wird die berechnete Erwartung für die nächsten Stunden ausgegeben. &lt;br /&gt;
Zur Beschreibung der Fehlersuche gehen wir davon aus, dass die Prognose von 780 Wh am 2024-09-21 20:00:00 zu hoch erscheint weil am Tag &amp;quot;07&amp;quot; ein Wert von 1474 Wh gespeichert ist:&lt;br /&gt;
&lt;br /&gt;
 SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt geben wir die historischen Werte für den Tag 07 aus:&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;Name&amp;gt; pvHistory 07&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz interessiert die Stunde 21. Sie resultiert aus der obigen Angabe &amp;quot;starttime: xxxx-xx-xx 20:00:00&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      21 =&amp;gt; etotal: 64354660, pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 496, con: 1474, gcons: 23, conprice: 0.2958&lt;br /&gt;
            gfeedin: 5, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 289, sunalt: -8&lt;br /&gt;
            batintotal: 3064096.92456668, batouttotal: 2958021.37946804, batin: 0, batout: 1460&lt;br /&gt;
            wid: 101, wcc: 20, rr1c: 0.00, pvcorrf: 1.00/-temp: 26.00, &lt;br /&gt;
            csmt01: 64262.43, csme01: 28.8099999999977, minutescsm01: 25&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 0, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1389417.4, csme04: 94.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 0, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 290.15, csme06: 6.66999999999996, minutescsm06: 54&lt;br /&gt;
            csmt07: 0, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 32800, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 103987.8, csme09: 38, minutescsm09: 43&lt;br /&gt;
            csmt10: 9151.24999999783, csme10: 3.99999999997999, minutescsm10: 60&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz sind die Energieverbrauchsanteile der im Device registrierten Verbraucher mit dem Schlüssel &amp;quot;csmeXX&amp;quot; gespeichert. Dabei ist &amp;quot;XX&amp;quot; die Verbrauchernummer. In dem Beispiel existieren die Anteile csme01 und csme03 - csme10. Keiner dieser Verbraucher hat einen auffälligen Verbrauchswert gespeichert, d.h. die Messung der Verbraucher scheidet als Problemquelle aus. Wäre ein unverhältmismäßig hoher Verbrauch bei einem der Verbraucher feststellbar, müssten die Schlüssel &#039;&#039;&#039;pcurr&#039;&#039;&#039; und &#039;&#039;&#039;etotal&#039;&#039;&#039; im consumerXX-Attribut geprüft, sowie die Datenlieferung des Consumerdevices selbst geprüft werden.  &lt;br /&gt;
&lt;br /&gt;
Es wurde offensichtlich ein hoher Verbrauch von einem nicht registrierten Verbraucher verursacht oder durch die Übertragung eines Meßfehlers des Devices, angegeben im Attribut &#039;&#039;&#039;setupMeterDev&#039;&#039;&#039;, in das SolarForecast Device übertragen. Eine weitere Analyse ist an dieser Stelle nicht möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Behebung des falschen Wertes kann ein Reset der gespeicherten Consumption der relevanten Stunde durchgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; reset consumptionHistory 07 21&lt;br /&gt;
&lt;br /&gt;
== Modulinterne Datenstrukturen ==&lt;br /&gt;
Das Modul speichert die verschiedenen historischen und aktuellen Daten wie PV-Prognose, Witterungsdaten (Regen, Bewölkung), Strahlungsdaten, Einspeisung, Bezug, reale Erzeugungsdaten und vieles mehr zur Laufzeit im Arbeitsspeicher. Dadurch ist die Verarbeitung dieser Daten im Vergleich zu Lesevorgängen aus dem Filesystem bzw. einer Datenbank sehr performant. Allerdings würden diese Daten bei einem FHEM Absturz bzw. bei einem regulären Shutdown verlorengehen.&lt;br /&gt;
&lt;br /&gt;
Deswegen werden die relevanten Daten regelmäßig in Dateien gesichert und bei Bedarf wiederhergestellt. Diese Dateien befinden sich im Verzeichnis &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; und heißen &#039;&#039;&#039;.*_SolarForecast_.*&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Die Daten werden in jedem Zyklus der Zentralschleife (CentralTask) gesammelt bzw. berechnet. Der Zyklus wird mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;cycleInterval&#039;&#039;&#039; eingestellt.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit können diese Daten über get-Kommandos abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvHistory [Tag]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der pvHistory Datenspeicher enthält die vergangenen Kennwerte der letzten 31 Tage mit einer Genauigkeit von einer Stunde. Es werden die Prognosewerte für Erzeugung und Verbrauch, die realen Werte für Erzeugung und Verbrauch sowie ebenso die Laufzeiten jedes einzelnen Verbrauchers (Consumer) festgehalten. Für jeden Tag gibt es die Stunde &amp;quot;99&amp;quot; die eine Summierung der Stundenwerte des Tages bzw. Sonderschlüssel enthält.&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf lässt sich mit dem Befehl &amp;quot;set ... reset pvHistory&amp;quot; der gesamte Inhalt des Speichers löschen (nicht empfohlen). Selektiver funktioniert die Datenlöschung mit &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt;&amp;quot; (Daten eines bestimmten Tages löschen) bzw. &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt; &amp;lt;Stunde&amp;gt;&amp;quot; (Daten der Stunde  eines bestimmten Tages löschen). Die letzten beiden Kommandos müssen über die Kommandozeile im Browser ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvCircular &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Ringspeicher enthält Daten der letzten 24 Stunden sowie fortwährend berechnete Werte wie Korrekturfaktoren der PV-Erzeugung und Prognosequalität.&lt;br /&gt;
Neue Stundenwerte des Tages überschreiben die gespeicherten Schüssel des vorangegangenen Tages sofern es sich nicht um fortwährend berechnete Werte handelt. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... nextHours&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Speicher enthält sämtliche Prognosewerte der kommenden Stunden beginnend mit der aktuellen Stunde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... radiationApiData&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Abhängig von der ausgewählten Strahlungsdaten API enthält dieser Speicher die von der API gelieferten Rohdaten sowie evtl. weitere für die Funktion benötigte Daten wie API-Keys, Response Messages, Anzahl der API Abruf und weitere.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valCurrent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Struktur wird nicht regelmäßig im Filesystem gespeichert und enthält immer aktuell gesammelte oder berechnete/gelieferte Daten wie z.B. die Autarkierate, letze Laufzeit der Zentralschleife (CentralTask), Zeit des Sonnenauf- und untergangs sowie weitere Betriebsdaten. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valConsumerMaster [XX]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zeigt die Daten der aktuell im SolarForecast Device registrierten Verbraucher. Mit der Nummer &#039;&#039;&#039;XX&#039;&#039;&#039; kann ein bestimmter Verbraucher angesprungen werden. Die Nummer korrespondiert mit dem entsprechenden &#039;&#039;&#039;consumerXX&#039;&#039;&#039; Attribut.&lt;br /&gt;
Neben anderen Betriebs- und Energiedaten werden insbesondere folgende Daten ermittelt, die für die zukünftige Planung der Verbraucherschaltzeiten relevant sind:&lt;br /&gt;
&lt;br /&gt;
* epieces - prognostizierte Energiescheiben pro Betriebsstunde &lt;br /&gt;
&lt;br /&gt;
Ausgehend von gespeicherten historischen Verbrauchsdaten des Verbrauchers wird der Energieverbrauch des Verbrauchers in seiner ersten Betriebsstunde prognostiziert, was insbesondere für die Planung der optimalen Startzeit des Verbrauchers in Bezug zu der prognostizierten PV Energie und den Verbrauchswerten weiterer vorhandener bzw. zu planender Verbraucher Berücksichtigung findet. Weitere Informationen zur Verbrauchersteuerung in diesem  [[#Verbrauchersteuerung_-_Registrieren_und_visualisieren_von_Verbrauchern|Abschnitt]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Schnittstelle für Modulautoren bzw. eigenen Code ===&lt;br /&gt;
&lt;br /&gt;
Die im vorherigen Artikel beschriebenen internen Datenstrukturen können durch externen Code abgefragt und ausgewertet werden.&lt;br /&gt;
Dazu stehen die folgenden Funktionen zur Verfügung. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]BatteryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Bn&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valBattery&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CurrentVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valCurrent&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]InverterVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valInverter&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ProducerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valProducer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]HistoryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Day&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvHistory&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CircularVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvCircular&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]NexthoursVal (&#039;&amp;lt;Name&amp;gt;&#039;, &amp;lt;nhr&amp;gt;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... nextHours&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ConsumerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valConsumerMaster&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]RadiationAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;DateTime&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... radiationApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]WeatherAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;TimeCode&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... weatherApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StatusAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;QTag&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... statusApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StringVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valStrings&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Angabe des Packages (FHEM::SolarForecast::) ist nur notwendig wenn die Funktionen von außerhalb des SolarForecast-Devices aufgerufen werden. Innerhalb des Devices (Code-Ausführung im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039;) kann darauf verzichtet werden.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der Platzhalter sind:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     &amp;lt;Name&amp;gt;     - Name des SolarForecast Devices&lt;br /&gt;
     &amp;lt;Day&amp;gt;      - abzufragender Tag (01 - 31)&lt;br /&gt;
     &amp;lt;Bn&amp;gt;       - Batterie Nummer (01, 02, ...)&lt;br /&gt;
     &amp;lt;DateTime&amp;gt; - Startzeit der Form YYYY-MM-DD hh:00:00&lt;br /&gt;
     &amp;lt;TimeCode&amp;gt; - Zeitwert der Form fcX_XX (z.B. fc1_19)&lt;br /&gt;
     &amp;lt;APIname&amp;gt;  - Hauptname der API gemäß setupWeatherDev1 (z.B. OpenMeteo)&lt;br /&gt;
     &amp;lt;String&amp;gt;   - Name des PV-Modulstrings wie im Attribut &#039;setupInverterStrings&#039;&lt;br /&gt;
     &amp;lt;QTag&amp;gt;     - Question Tag, z.B. &#039;?All&#039;&lt;br /&gt;
     &amp;lt;Nr&amp;gt;       - laufende Nummer des Verbrauchers / Gerätes (01, 02, 03, 04,...)&lt;br /&gt;
     &amp;lt;HoD&amp;gt;      - abzufragende Stunde (01 - 24, 99)&lt;br /&gt;
     &amp;lt;nhr&amp;gt;      - nächste Stunde (NextHour00, NextHour01,...)&lt;br /&gt;
     &amp;lt;Key&amp;gt;      - der abzufragende Schlüssel &lt;br /&gt;
     &amp;lt;default&amp;gt;  - def default-Rückgabewert&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Auswerten von internen Arrays ===&lt;br /&gt;
&lt;br /&gt;
Die meisten der internen Datenstrukturen liefern bei der Abfrage einen einfachen String oder numerischen Wert der ausgewertet werden kann. Es gibt allerdings auch intern gespeicherte Wertelisten. Werden die Listenstrukturen mit den oben beschriebenen Befehlen abgefragt, wird eine Referenz auf die Liste geliefert sofern sie vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
Um auf die Werte einer solchen Liste zuzugreifen, ist am Beispiel des Arrays &#039;&#039;surplusslidereg&#039;&#039; aus dem Current-Speicher (get ... valCurrent) dargestellt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
my $splref = CurrentVal ($name, &#039;surplusslidereg&#039;, &#039;.&#039;);&lt;br /&gt;
my $spser  = ref $splref eq &#039;ARRAY&#039; ? join &#039; &#039;, @{$splref} : undef;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Variable $spser enthält bei Vorhandensein der Liste einen String, der die Listenelemente von &#039;surplusslidereg&#039; durch Leerzeichen getrennt enthält.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backup und Wiederherstellung der Moduldaten ==&lt;br /&gt;
Neben der Datenhaltung in den Attributen und Readings des SolarForecast Devices, erzeugt jedes SolarForecast Device Dateien im Verzeichnis  &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; mit folgenden Inhalten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PVH_SolarForecast_&amp;lt;name&amp;gt;        - PV History&lt;br /&gt;
PVC_SolarForecast_&amp;lt;name&amp;gt;        - PV Circular&lt;br /&gt;
PVCfg_SolarForecast_&amp;lt;name&amp;gt;      - PV Anlagenkonfiguration&lt;br /&gt;
PVCsm_SolarForecast_&amp;lt;name&amp;gt;      - Consumer Status&lt;br /&gt;
ScApi_SolarForecast_&amp;lt;name&amp;gt;      - Strahlungswerte aus verwendeter API&lt;br /&gt;
StatApi_SolarForecast_&amp;lt;name&amp;gt;    - Statusdaten der verwendeten API&#039;s&lt;br /&gt;
WeatherApi_SolarForecast_&amp;lt;name&amp;gt; - Wetterdaten der gewählten Wetter-API (außer DWD-Device)&lt;br /&gt;
AItra_SolarForecast_&amp;lt;name&amp;gt;      - KI Entscheidungsquelle (trainierte Daten)&lt;br /&gt;
AIraw_SolarForecast_&amp;lt;name&amp;gt;      - KI Input Daten = Raw Trainigsdaten&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nach Ausprägung und eingesetzten Features des SolarForecast Devices sind alle oder nur ein Teil dieser Dateien vorhanden. Dabei ist &#039;&#039;&#039;&amp;lt;name&amp;gt;&#039;&#039;&#039; der Name des SolarForecast Devices.&lt;br /&gt;
&lt;br /&gt;
Bei einem Filebackup des FHEM-Servers ist darauf zu achten, dass diese Dateien in dem Backup enthalten sind. Der Inhalt der Dateien ist nicht statisch, sondern kann sich dynamisch aktualisieren. Um im Bedarfsfall einen aktuellen Datenstand zu haben, ist mindestens ein tägliches Backup dieser Dateien empfehlenswert. Eventuell auch öfter mit Hilfe einer Versionierung welche z.B. immer die letzten 3 Versionen aufbewahrt.&lt;br /&gt;
&lt;br /&gt;
Beim Start von FHEM werden bestimmte Dateien automatisch gelesen und in das SolarForecast Device importiert. &lt;br /&gt;
Der Vorgang ist mit verbose=3 im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2023.10.02 09:57:07.967 3: SolCast6 - cached data &amp;quot;pvHistory&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.969 3: SolCast6 - cached data &amp;quot;pvCircular&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;consumerMaster&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;radiationApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;statusApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;weatherApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.974 3: SolCast6 - cached data &amp;quot;aiTrainedData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.976 3: SolCast6 - cached data &amp;quot;aiRawData&amp;quot; restored&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bestimmte Betriebsdaten, wie z.B. die witterungsabhängigen Korrekturfaktoren (circular) oder die KI-Daten (aitrained/airaw), bauen sich über die Zeit immer granularer auf und stellen einen wertvollen Datenbestand dar.&lt;br /&gt;
&lt;br /&gt;
Wird das SolarForecast Device gelöscht und anschließend wieder neu mit dem gleichen Namen definiert, können die bisher verfügbaren Daten sehr einfach wiederhergestellt werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. starten von FHEM (bestimmte Daten werden automatisch importiert)&lt;br /&gt;
* 5. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Soll das neue SolarForecast Device mit einem anderen Namen oder weitere SolarForecast Devices erstellt werden, welche die Betriebsdaten des primären Devices verwenden sollen, ist wie folgt vorzugehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. umbenenen der Dateien, wobei &amp;lt;name&amp;gt; durch den Namen des neuen SolarForecast Devices ersetzt wird&lt;br /&gt;
* 5. starten von FHEM (die Daten werden automatisch importiert)&lt;br /&gt;
* 6. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn sich die SolarForecast Devices hinsichtlich ihres Models oder der integrierten Consumer unterscheiden, sind die Dateien &amp;quot;PVCsm_SolarForecast_&amp;lt;name&amp;gt; &amp;quot; , &amp;quot;ScApi_SolarForecast_&amp;lt;name&amp;gt;&amp;quot; von dem Verfahren auszuschließen.&lt;br /&gt;
&lt;br /&gt;
== Batterieintegration und -steuerung ==&lt;br /&gt;
&lt;br /&gt;
=== Wie eine Batterie eingebunden wird ===&lt;br /&gt;
Wie immer muß die Batterieanlage zunächst mit einem für die Batterie spezifischen FHEM-Device in FHEM definiert sein.&lt;br /&gt;
In diesem Device werden Readings erwartet die folgende Werte bereitstellen:&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieentladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die installierte Batteriekapazität liefert (&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; dieser Schlüssel ist für die Aktivierung des Batterie SOC-Managements und die grafische Anzeige des SOC wesentlich!)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Lade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Entlade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* Reading welches den aktuellen Ladezustand (SOC in Prozent) liefert (optional)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Batterie, bzw. das Batteriedevice wird mit dem Attribut &#039;&#039;&#039;setupBatteryDev&#039;&#039;&#039; im SolarForecast Device registriert. Die Syntax des Attributes ist in  der Online-Hilfe zum Attribut umfassend erläutert. &lt;br /&gt;
Auch wenn manche Readings optional sind, wird empfohlen alle Werte bereitzustellen um alle Batterie-Funktionen im Modul nutzen zu können. Durch die Weiterentwicklung des Moduls können optionale Readings später auch obligatorisch werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Visualisierung der Batterie in der Balkengrafik ====&lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;setupBatteryDevXX&#039;&#039;&#039; verfügt über den Schlüssel &#039;&#039;&#039;show&#039;&#039;&#039;, mit dem die Einblendung des bzw. der Batteriesymbole in den Ebenen der Balkengrafik gesteuert werden kann:&lt;br /&gt;
[[Datei:Screenshot 2025-02-23 192002.png|right|thumb|400px|Einblendung der Batterieleiste und Darstellung des Batterie-SoC als Balkencontent in der zweiten Ebene]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 0 - keine Anzeige des Gerätes (default)&lt;br /&gt;
* 1 - Anzeige des Gerätes in der Balkengrafik Ebene 1&lt;br /&gt;
* 2 - Anzeige des Gerätes in der Balkengrafik Ebene 2 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Symbole und die Farbgebung der Batterie(n) können mittels des Schlüssels &#039;&#039;&#039;icon&#039;&#039;&#039; verändert werden. Die Online-Hilfe gibt weitere Informationen zur Ausgestaltung. &lt;br /&gt;
&lt;br /&gt;
In der Batteriedarstellung wird das Symbol der aktuellen Stunde hervorgehoben. Ein Mouse-Over zeigt wesentliche Betriebszustände der Batterie. Die Batteriesymbole vergangener Stunden zeigen mit einem Mouse-Over die erreichten SoC (State of Charge) Stände. Die kommenden Stunden visualisieren die folgenden Prognosen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der prognostizierte SoC unter Berücksichtigung der PV-Prognose und der [[#Aktivierung_des_Batterie_SOC-Managements|Batteriesteuerung]] sofern sie im Modul aktiviert ist.&lt;br /&gt;
* eine Freigabe bzw. Empfehlung der Batterieladung zur [[#Unterstützung_eines_netzdienlichen_Verhaltens|Unterstützung eines netzdienlichen Verhaltens]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Neben der Einblendung der Batterieleiste über der Balkengrafik selbst können bestimmte Batteriekennwerte als Balkeninhalt dargestellt werden. Die Auswahl erfolgt über das Attribut &#039;&#039;&#039;graphicBeamXContent&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Aktivierung des Batterie SOC- und Lade-Managements ===&lt;br /&gt;
Das integrierte SOC- und Lade-Management verfolgt insbesondere zwei Ziele: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* den Ladezustand der Batterie(n) zu optmimieren, was besonders in den Monaten mit geringerer PV-Erzeugung einen wertvollen Beitrag zur Erhöhung der Autarkierate und Batteriepflege leisten kann&lt;br /&gt;
 &lt;br /&gt;
* eine PV-Prognose und Verbrauch optimierte Beladungssteuerung, die in den Monaten mit hoher PV-Erzeugung hilft eine evtl. Abregelung der Anlage zu verhindern, die Batterie ausgewogen über den Tag zu laden und ein netzdienliches Verhalten zu unterstützen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese beiden Aspekte der Batteriesteuerung werden in den folgenden Abschnitten beschrieben. Sind mehrere Batterien installiert, kann die Steuerung getrennt für jede einzelne Batterie aktiviert und eingestellt werden. Dabei ist zu beachten, dass vom Modul nur Signale und Readings bereitgestellt werden, die durch eine entsprechende Routine ausgewertet werden können um spezifische Befehle zur Umsetzung der Steuerung an das Batteriesystem zu senden. &lt;br /&gt;
 &lt;br /&gt;
Für eine Aktivierung des Managements muß zunächst das Batterie-Device wie im vorigen Abschnitt im SolarForecast Device registriert werden.&lt;br /&gt;
Das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; aktiviert die im Modul integrierte SOC- und Lade-Management Routine: &lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; ctrlBatSocManagement01 lowSoc=&amp;lt;Wert&amp;gt; upSoC=&amp;lt;Wert&amp;gt; [maxSoC=&amp;lt;Wert&amp;gt;] [careCycle=&amp;lt;Wert&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
Die einzelnen Schlüssel werden der Kalkulationsroutine als Steuerungsparameter übergeben und bedeuten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;lowSoc:unterer Mindest-SoC, die Batterie wird nicht tiefer als dieser Wert entladen (muß &amp;gt; 0 sein). Dieser Wert kann zum Beispiel dazu dienen, stets eine Mindestenergiemenge für den Fall eines Stromausfalls im öffentlichen Netz in den Batterien vorzuhalten.&lt;br /&gt;
&lt;br /&gt;
;upSoC:oberer Mindest-SoC, Der übliche Wert des optimalen SoC bewegt sich in Perioden mit hohen PV-Überschuß tendenziell zwischen &#039;lowSoC&#039; und &#039;upSoC&#039;, in Perioden mit geringer PV-Ausbeute bzw. geringem PV Energieüberschuß bewegt sich der optimale SoC tendenziell zwischen &#039;upSoC&#039; und &#039;maxSoC&#039;. Die Einstellung von upSoC=50 für ein ausgewogenes Verhalten kann als guter Startwert dienen.&lt;br /&gt;
&lt;br /&gt;
;maxSoC:maximaler Mindest-SoC, d.h. der SoC Wert der mindestens im Abstand von &#039;careCycle&#039; Tagen erreicht werden muß um den Ladungsausgleich im Speicherverbund auszuführen. Die Angabe ist optional (muß &amp;lt;= 100 sein, default: 95)&lt;br /&gt;
&lt;br /&gt;
;careCycle:maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens &#039;maxSoC&#039; auftreten darf. Die Angabe ist optional. (default: 20)&lt;br /&gt;
&lt;br /&gt;
;loadAbort: definiert eine vom Anwender gewünnschte Bedingung für einen generellen Ladeabbruch und Wiederfreigabe der Lademöglichkeit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle Werte sind ganze Zahlen in %. Dabei gilt: &lt;br /&gt;
&lt;br /&gt;
 lowSoc &amp;lt; upSoC &amp;lt; maxSoC&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====  Erläuterung der Batterie-Steuerungsreadings ==== &lt;br /&gt;
&lt;br /&gt;
Für die Steuerung des Batteriesystems gibt es im SolarForecast einen Satz an Readings, die unterschiedliche Zustände signalisieren und für entsprechende Steuerungsaufgaben bezüglich der Batteriesysteme eingesetzt werden können. In den nachfolgenden Abschnitten werden diese Zusammenhänge noch dataillierter beschrieben.&lt;br /&gt;
&lt;br /&gt;
;Hinweis: SolarForecast stellt lediglich Steuerungsinformationen zur Verfügung. Die Umsetzung des Eingriffs in das Batteriesystem erfolgt durch den Anwender selbst über entsprechende Skripte. In den thematischen Abschnitten werden Beispiele für solche Steuerungsskripte vorgestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle erstellten Readings gelten für ein Batteriesystem, es können mehrere Batteriesysteme in SolarForecast integriert sein. Die Endung &#039;&#039;XX&#039;&#039; der Readings beschreibt die Nummer des Batteriesystems und korrespondiert mit der Endung des entsprechenden Attributes &#039;&#039;ctrlBatSocManagementXX&#039;&#039; bzw. &#039;&#039;setupBatteryDevXX&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Battery_OptimumTargetSoC_XX: Mit den im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; hinterlegten Parametern unter Berücksichtigung von PV- und Verbrauchsprognosen wird ein optimaler SOC-Wert errechnet. Dieser Wert dient zur Einstellung des unteren SOC des Batteriesystems.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeRequest_XX: Dieses Reading signalisiert mit 1 eine Anforderung zur Zwangsladung der Batterie um die Batterie vor Schäden zu schützen (wenn der SOC unter ctrlBatSocManagementXX-&amp;gt;lowSoc gefallen ist) oder wenn der aktuelle SOC unter den berechneten Mindest-SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeUnrestricted_XX: Dieses Reading kann den Wert &#039;&#039;&#039;0&#039;&#039;&#039; oder &#039;&#039;&#039;1&#039;&#039;&#039; einnehmen. Ist der Inhalt 0, sollte die Batterie nur geladen werden, wenn der im Attribut &#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039; definierte Wert überschritten wird. Ist der Inhalt 1, sollte die Batterie mit der vollen zur Verfügung stehenden Ladeleistung angesteuert werden, um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeAbort_XX: Im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; kann mit dem Schlüssel &#039;&#039;loadAbort&#039;&#039; eine Bedingung definiert werden, bei deren Eintritt die Ladung der Batterie abgebrochen werden soll. In diesem Fall wird &#039;&#039;Battery_ChargeAbort_XX=1&#039;&#039; gesetzt. Mit einem entsprechenden Befehl kann der Anwender das Batteriesystem anweisen den Ladevorgang abzubrechen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Nutzung des Batterie SOC-Management ====&lt;br /&gt;
&lt;br /&gt;
Oftmals wird durch die Anlagenhersteller ein hoher statischer SOC eingestellt bzw. empfohlen, der eine längere Verharrungszeit auf einem tiefen SOC-Wert verhindern soll. Allerdings wechseln sich in auch in den Herbst-, Frühlings- und Wintermonaten Zeiten mit wenig PV-Erzeugung mit Phasen stärkerer Solarstrahlung bei klarem Himmel und Sonnenschein ab.&lt;br /&gt;
&lt;br /&gt;
Ein statischer SOC würde dazu führen, dass in den erwähnten Phasen zuviel Energie in das öffentliche Netz eingespeist wird. Dies soll verhindert werden da die wertvolle Energie besser im eigenen Netz gespeichert und in Dunkelphasen verwendet werden kann. Andererseits soll die Batterie nicht zu lange auf einem tiefen SOC verbleiben und außerdem in gewissen Abständen auf einen so hohen SOC geladen werden der den internen Zellausgleich ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Die SOC Kalkulationsroutine des Moduls errechnet unter Berücksichtigung des prognostizierten PV-Ertrages der kommenden Tage, des aktuellen SOC und der im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; (nachfolgend beschrieben) angegebenen Steuerparameter den Vorschlag für eine optimale SOC-Einstellung. Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert.&lt;br /&gt;
&lt;br /&gt;
Durch das Modul selbst findet keine Steuerung der Batterie statt. Es stellt entsprechende Readings zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen SoC.&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SoC unter den optimalen SoC gefallen ist. In diesem Fall sollte die Batterie, unter Umständen mit Netzstrom, zwangsgeladen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Readings können zur Steuerung des SoC (State of Charge) sowie zur Steuerung des verwendeten Ladestroms der Batterie verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ermittlung des optimalen SOC erfolgt nach folgender Logik:&lt;br /&gt;
&lt;br /&gt;
# 	Ausgehend von &#039;lowSoc&#039; wird der Mindest-SoC kurz vor Sonnenuntergang um 5% inkrementiert sofern am laufenden Tag &#039;maxSoC&#039; nicht erreicht wurde und die PV-Prognose keinen hinreichenden Ertrag des kommenden Tages vorhersagt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Wird &#039;maxSoC&#039; (wieder) erreicht, wird Mindest-SoC um 5%, aber nicht tiefer als &#039;lowSoc&#039;, verringert. Ist der berechnete Mindest-SoC größer als &#039;upSoc&#039;, wird der Mindest-SoC auf &#039;upSoc&#039; gesetzt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#   Mindest-SoC wird soweit verringert, dass die prognostizierte PV Energie des aktuellen bzw. des folgenden Tages von der Batterie aufgenommen werden kann. Mindest-SoC wird typisch auf &#039;upSoc&#039; und nicht tiefer als &#039;lowSoc&#039; verringert.  &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Das Modul erfasst den letzten Zeitpunkt am &#039;maxSoC&#039;-Level, um eine Ladung auf &#039;maxSoC&#039; mindestens alle &#039;careCycle&#039; Tage zu realisieren. Zu diesem Zweck wird der optimierte SoC in Abhängigkeit der Resttage bis zum nächsten &#039;careCycle&#039; Zeitpunkt derart verändert, dass durch eine tägliche 5% SoC-Steigerung &#039;maxSoC&#039; am &#039;careCycle&#039; Zeitpunkt rechnerisch erreicht wird. Wird zwischenzeitlich &#039;maxSoC&#039; erreicht, beginnt der &#039;careCycle&#039; Zeitraum erneut. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im fünften Schritt werden die Grenzen &#039;lowSoc&#039; und &#039;upSoc&#039; berücksichtigt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im letzten Schritt erfolgt Generierung des Readings &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; zur Signalisierung einer eventuell empfohlenen Zwangsladung auf den berechneten Min-SoC. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei sehr wenig Erzeugungungsprognose, d.h. wenn sich der berechnete Min-SoC oberhalb von &#039;upSoC&#039; bewegt, wird &#039;upSoC&#039; eingestellt. Liegt der berechnete Min-SoC unterhalb von &#039;upSoC&#039;, ist jedoch größer als &#039;lowSoC&#039;, wird der berechnete SOC im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; eingestellt. Somit eignet sich die Angabe im Schlüssel &#039;upSoC&#039; um in Zeiten geringer Solarenergieerzeugung die Batterie für eine Notstromerzeugung auf mindestens diesem Wert zu halten. Sollte die PV-Prognose kurzfristig einen größeren Ertrag vorhersagen als die Batterie durch die Einhaltung von &#039;upSoC&#039; aufnehmen kann, wird der Min-SoC unter &#039;upSoC&#039; abgesenkt um möglichst allen PV-Überschuß in der Batterie zu speichern und somit dem Eigenverbrauch zuzuführen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der berechnete Mindest-SoC ist immer nur ein unterer Grenzwert. Die Batterie kann durch Ladevorgänge natürlich jederzeit einen höheren als den im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; dargestellten optimalen SoC haben. Der optimale SoC sollte nicht unterschritten werden um die oben genannten Zusammenhänge abbilden zu können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Die dynamische SOC Steuerung mit Umsetzungsbeispiel =====&lt;br /&gt;
Das Modul bietet eine Unterstützung zur automatisierten Einstellung eines optimalen SoC Wertes.&lt;br /&gt;
&lt;br /&gt;
Ziel ist es, den Minimum SoC in Abhängigkeit der zu erwartenden Solarerträge des aktuellen und des folgenden Tages so einzustellen, dass der prognostizierte Solarertrag von der Batterie aufgenommen werden kann. Die Einspeisung in das öffentliche Netz soll minimiert werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin soll ein unterer SoC nicht unterschritten, sowie ein oberer Minimum SoC im Normalfall nicht überschritten werden. Der obere Grenzwert stellt sicher, dass die Batterie mindestens bis zu diesem Wert wieder entladen werden kann. Dadurch bleibt innerhalb der Batterie immer genügend Kapazität verfügbar um unvorhergesehene PV Energie aufnehmen zu können.&lt;br /&gt;
&lt;br /&gt;
Aktiviert wird die Unterstützung der Batteriesteuerung durch das Setzen des Attributes &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; z.B. mit diesen Angaben:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagementXX lowSoc=x upSoC=x maxSoC=x careCycle=x &lt;br /&gt;
&lt;br /&gt;
so zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=98 careCycle=20&lt;br /&gt;
&lt;br /&gt;
Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert. &lt;br /&gt;
Ist dieses Attribut gesetzt, werden Steuerungs-Readings erstellt, die der Nutzer auswerten und seine Batterieanlage z.B. via notify oder DOIF steuern kann. &amp;lt;bR&amp;gt;&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen Mindest-SoC.&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SOC unter den optimalen SOC bzw. minimalen SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
Die Schlüssel &#039;&#039;&#039;lowSoc&#039;&#039;&#039; und &#039;&#039;&#039;upSoC&#039;&#039;&#039; sind die unteren und oberen Grenzen, zwischen denen sich der Minimum SoC im normalen Betrieb bewegen soll.&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;maxSoC&#039;&#039;&#039; stellt eine Ladungsgrenze dar, die mindestens alle X (careCycle) Tage erreicht werden soll. Zu diesem Zweck errechnet das Modul die Anzahl der nötigen Erhöhungen der Minimum Batterieladung von 5% pro Tag um ausgehend vom aktuellen SoC-Level. Der resultierende Minimum SoC Wert wird entsprechend angepasst. Wurde der einstellte maxSoC Level erreicht, startet der Wartungszyklus (careCycle) erneut. &amp;lt;br&amp;gt;&lt;br /&gt;
Der maxSoC in Verbindung mit dem durch &#039;&#039;&#039;careCycle&#039;&#039;&#039; definierten Zyklus soll sicherstellen, dass der Batterieverbund in regelmäßigen Abständen einen Ladungsausgleich vollziehen kann. &lt;br /&gt;
&lt;br /&gt;
Durch die Modullogik erfolgt eine 5 protentige Anhebung des Minimum SoC wenn am Vortag maxSoC nicht erreicht wurde. Die Anhebung erfolgt aber nicht über upSoC. upSoC ist die obere Grenze des Minimum SoC. Wird am Vortag mindestens die maxSoC Ladung erreicht, verringert sich der Minimum SoC wieder schrittweise um 5%, aber nicht tiefer als lowSoc.&lt;br /&gt;
&lt;br /&gt;
Ergänzt wird die Logik noch um die PV Vorhersage. Dabei wird die obige Minimum SoC Berechnung um die Erwartung der PV Erwartung am aktuellen und folgenden Tag korrigiert. Das bedeutet, dass der Minimum SoC z.B. von heute 50% auf 10% abgesenkt und dadurch die gespeicherte Energie dem Haushalt zugeführt wird, wenn am heutigen oder kommenden Tag eine entsprechende PV Energie zu erwarten ist um die Batterie wieder vollständig zu zuladen.&lt;br /&gt;
Dadurch ist immer genügend &amp;quot;Freiplatz&amp;quot; in der Batterie und andererseits hat die Batterie in langen Dunkelphasen eine Reserve für einen eventuellen Stromausfall (falls der abgesichert werden soll) und wird vor einem dauerhaften tiefen SoC geschützt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Umsetzungsbeispiel =====&lt;br /&gt;
&lt;br /&gt;
Wie das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; genutzt werden kann, wird am Beispiel einer Victron Batterieanlage gezeigt. Die Anlage wird durch Cerbo GX Gerät gesteuert. Der Cerbo GX ist per MQTT2 in FHEM eingebunden. Umgesetzt ist die Steuerung der Batterie &#039;01&#039;, d.h. die Angabe &#039;XX&#039; ist durch &#039;01&#039; ersetzt.&lt;br /&gt;
&lt;br /&gt;
Die folgende kleine Logik ist in einem &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; File eingebaut und wird regelmäßig mit&lt;br /&gt;
&lt;br /&gt;
 batSocChargeMgmnt (&#039;&amp;lt;Name SolarForecast Device&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
aufgerufen. Der Aufruf erfolgt durch Angabe der Routine im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; des SolarForecast Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
  # Hinweis: die Zeichen &#039;::&#039; vor der Routine sind durch das SolarForecast Package bedingt&lt;br /&gt;
  ::batSocChargeMgmnt ($name);&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Routine wird dadurch automatisch am Ende jedes Zyklus (siehe Attribut plantControl-&amp;gt;cycleInterval) ausgeführt.&lt;br /&gt;
Um die SOC Managementfunktion nach Bedarf ein- bzw. ausschalten zu können wird zunächst im SolarForecast Device ein userattr zur Steuerung der SOC-Logik angelegt:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; userattr userFn_BatterySoCManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
Die Perl Routine &#039;&#039;&#039;batSocChargeMgmnt&#039;&#039;&#039; ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#  Batterie SOC und Max. Ladestrom Management&lt;br /&gt;
############################################################################&lt;br /&gt;
sub batSocChargeMgmnt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vebus   = &#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;;                            # Victron Vebus Device&lt;br /&gt;
  my $vicsets = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                         # Victron Einstellungen&lt;br /&gt;
&lt;br /&gt;
  my $maxcspc = 105;                                                           # max. Ladestrom (A) Victron MPII Verbund&lt;br /&gt;
  my $actmcc  = ReadingsNum ($vebus, &#039;MaxChargeCurrent&#039;, undef);               # akt. Ladestromeinstellung&lt;br /&gt;
  my $load    = $actmcc // $maxcspc;                                           # Soll-Ladestrom (A)&lt;br /&gt;
&lt;br /&gt;
  ## Battery SoC Management&lt;br /&gt;
  ###########################&lt;br /&gt;
  my $ubsm = AttrVal ($name, &#039;userFn_BatterySoCManagement&#039;, &#039;aus&#039;); &lt;br /&gt;
  &lt;br /&gt;
  if ($ubsm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name,    &#039;Battery_ChargeRequest_01&#039;,     0);&lt;br /&gt;
    my $csoc = ReadingsNum ($vicsets, &#039;MinimumSocLimit&#039;,             10);      # akt. SoC&lt;br /&gt;
    my $osoc = ReadingsNum ($name,    &#039;Battery_OptimumTargetSoC_01&#039;, 10);      # Soll-SoC&lt;br /&gt;
    my $surp = ReadingsNum ($name,    &#039;Current_Surplus&#039;,              0);      # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if ($csoc != $osoc) {&lt;br /&gt;
      CommandSet (undef, &amp;quot;$vicsets MinimumSocLimit $osoc&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn SoCMgmnt -&amp;gt; MinimumSocLimit in $vicsets set to $osoc %});&lt;br /&gt;
    }&lt;br /&gt;
	                                           &lt;br /&gt;
    if ($bcrq &amp;amp;&amp;amp; $surp &amp;lt; 1000) {                                              # max. Strom b. Battery_ChargeRequest &lt;br /&gt;
      $load = 21;&lt;br /&gt;
    }&lt;br /&gt;
	else {&lt;br /&gt;
	  $load = $maxcspc;&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Batterie Einstellung MaxChargeCurrent&lt;br /&gt;
  ##########################################&lt;br /&gt;
  if ($load != $actmcc) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$vebus MaxChargeCurrent $load&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
    Log3 ($name, 3, qq{$name - userFn ChargeMgmnt -&amp;gt; MaxChargeCurrent in $vebus set }.&lt;br /&gt;
                    qq{from old $actmcc A to $load A});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent_set&#039;, $load, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist im SolarForecast Device das Reading  &#039;&#039;&#039;Battery_ChargeRequest_01&#039;&#039;&#039; gesetzt, ist der aktuelle SOC kleiner als der optimale SOC und die Batterie wird (eventuell aus dem öffentlichen Netz) geladen. Das kann automatisch durch den Cerbo GX bzw. in anderen Anlagen durch einen entsprechenden Befehl erfolgen.&lt;br /&gt;
Damit die Netzbeladung nicht mit der vollen Ladestromstärke geschieht, wird der Ladestrom auf den gewünschten Wert (hier 21 A -&amp;gt; ca. 1000 W bei einem 48V System) reduziert sofern kein oder zu wenig PV-Überschuß vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== weitere mögliche Aspekte der SOC- und Batterieladesteuerung ====&lt;br /&gt;
&lt;br /&gt;
SolarForecast liefert durch seine internen Logiken bereits sehr hilfreiche Signale zur Steuerung von Batteriesystemen in Form von Readings an. Abhängig von den individuellen Möglichkeiten der vorhandenen Anlage käme zum Beispiel zusätzlich zu einer Steurung des optimalen SOC oder der Zeitfenster für die Batterieaufladung auch eine Steuerung des Ladestroms bzw. der verwendeten Ladeleistung in Betracht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hintergründe:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Das Laden eines Akkus mit möglichst gleichbleibender und geringer Leistung wirkt sich positiv auf dessen Langlebigkeit aus, was u.a. auch daran liegt, dass der Temperaturstreß im Akku bei langsamer Energiezuführung nur gering ist.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom führt zu einem geringen Absacken der Akkuspannung beim (ggf, temporären) Abschalten des Ladestroms, was sich positiv auf die SOC-Schätzung auswirkt.&lt;br /&gt;
    &lt;br /&gt;
* Ein geringer Ladestrom führt, insb. bei Nutzung passiver Balancer (sind in den Akku-Systemen üblicherweise verbaut), zu einer geringen Differenz zwischen den einzelnen Zellspannungen und damit zu einer besseren Kapazitätsausnutzung eins Akkus.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom kann zu einem zeitlich punktgenauen Zielfüllstand (im Winter 100%, ansonsten natürlich weniger) am Ende des Tages führen.&lt;br /&gt;
    &lt;br /&gt;
* Eine geringer Ladestrom führt auch zu geringen Leitungsverlusten, da der Strom quadratisch zu den Leitungsverlusten beiträgt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann auch die Verweildauer oder die Begrenzung des SOC, auf den die Batterie maximal geladen werden soll, Gegenstand von Optimierungen sein.&lt;br /&gt;
&lt;br /&gt;
Die häufig zu findende Empfehlung, Akkus nicht zu lange bei einem SOC von 100% verweilen zu lassen, liegt weniger an dem SOC als solchem, sondern daran, dass &#039;&#039;SOC=100%&#039;&#039; üblicherweise dadurch ermittelt wird, dass eine Zelle im Akku einen Spannungsschwellenwert überschreitet, der – würde dieser Schwellenwert zeitlich länger überschritten sein – zu einer Schädigung des Akkus führen könnte. Schädlich sind insbesondere häufige Nachladevorgänge bei Werten um die 100% SOC, da Zellen dann ja häufiger und damit - integral gesehen - auch länger den o.g. Schwellenwert überschreiten.&lt;br /&gt;
&lt;br /&gt;
Einige Akku-Hersteller, z.B. BYD, haben auf o.g, Grund in der (neueren) Firmware Ihrer Systeme einen SOC-Threshold (bei BYD liegt dieser bei 95%) eingebaut. Dieser Wert muss nach einem erreichten SOC von 100% unterschritten  werden, bevor überhaupt eine weitere Ladung erfolgt. Insbesondere in der dunklen Jahreszeit kann es daher sinnvoll sein, den Akku unter Verwendung von PV-Leistung so zu füllen, dass dieser möglichst nur einmal vor Einbruch der Dunkelheit auf &#039;&#039;SOC=100%&#039;&#039; geladen wird. Hierbei sollte darauf geachtet werden, dass der Ladeschlussstrom des jeweiligen Systems nicht unterschritten wird. &lt;br /&gt;
&lt;br /&gt;
SolarForecast unterstützt die oben betrachtete Batteriesteuerung durch die optionale Angabe von &#039;&#039;&#039;loadAbort&#039;&#039;&#039; im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039;. Das in diesem Kontext erstellte Reading &#039;&#039;&#039;Battery_ChargeAbort_XX&#039;&#039;&#039; stellt die auswertbaren Steuerungsinformationen zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== PV-Prognose und Verbrauch optimierte Beladungssteuerung unter Berücksichtigung einer Wirkleistungsbegrenzung ====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-04-25 143910.png|right|thumb|400px|Batterie Popup &amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Batterie geladen. sobald PV-Überschuß vorhanden ist ohne eine Prognose zu berücksichtigen. Dadurch sind die Batterien im Sommer unter Umständen schon um 10-12 Uhr voll geladen und die Anlage liefert ihre mehr oder weniger volle Energie (je nach Ausrichtung) in das öffentliche Netz. Dann könnte es zu einer Begrenzung der PV-Leistung durch einen Schwellenwert (z.B. 70%-Regelung) oder eventuell Zwangsabregelung durch den Netzbetreiber kommen.&lt;br /&gt;
&lt;br /&gt;
Hintergrund dieser Erweiterung ist das Bestreben, eine optimale Unterstützung bei der Maximierung des Eigenverbrauchs zu geben und einen Beitrag zur Netzstabilität zu leisten.&lt;br /&gt;
Das Ziel der Beladungssteuerung der Batterie ist es, die Ladung der Batterie über den Tag verteilt so zu steuern, dass die Batterie erst dann geladen wird, wenn durch den PV-Überschuß eine Netzeinspeisung erfolgen würde bzw. ein Grenzwert erreicht werden würde, der zu einer Abregelung der PV-Anlage führen könnte.&lt;br /&gt;
Es kann auch zu einer Zwangsabregelung durch den Netzbetreiber führen, was vermieden werden soll.&lt;br /&gt;
 &lt;br /&gt;
Die interne Kalkulationslogik erstellt zu diesem Zweck ein Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039;.&lt;br /&gt;
Dieses Reading gibt dem User ein Signal, ob zu der aktuellen Stunde der Ladevorgang der Batterie freigegeben (1) oder nicht freigegeben werden sollte (0). Die Freigabe zur Ladung bedeutet dass:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; die Batterie mit ihrer vollen Ladeleistung angesteuert werden sollte um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=0&#039;&#039;&#039; die Batterie nur geladen werden sollte wenn der im Attribut plantControl-&amp;gt;feedinPowerLimit definierte Wert überschritten wird&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ist keine Freigabe zur Ladung vorhanden, kann bzw. sollte dennoch eine Ladung der Batterie vorgenommen werden, sofern eine über dem im &amp;lt;br&amp;gt;&lt;br /&gt;
Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limit liegende Einspeiseleistung vorhanden ist. In diesem Status sollte die Batterie nur mit der Differenzleistung von vorhandener Einspeiseleistung und dem gesetzen Einspeiselimit geladen werden und damit das gesetzte Einspeiselimit einhalten ohne die Anlage abzuregeln. Ist die Batterie in einer Balkengrafikebene dargestellt, wird im Mouse-Over Popup die Battrie mit &#039;&#039;&amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;&#039;&#039; gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Möglichkeiten der Batteriesteuerung sind stark von der individuellen Anlage abhängig und können hier nicht beschrieben werden. Ein Umsetzungsbeispiel mit einer Victron-Anlage mit Pylontech Batterie ist weiter unten dargestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Aktivierung und Arbeitsweise =====&lt;br /&gt;
&lt;br /&gt;
Die implementierte Logik zur optimierten Batterie Beladungssteuerung wird aktiviert, wenn folgende Kriterien erfüllt sind: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;capacity&#039;&#039;&#039; in den setupInverterDevXX Atributen ist gesetzt&lt;br /&gt;
* das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; für die jeweilige Batterie ist gesetzt&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;cap&#039;&#039;&#039; im Attribut setupBatteryDevXX der jeweiligen Batterie ist gesetzt&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Die Logik arbeitet wie folgt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Der resultierende Schwellenwert der Wirkleistungsbegrenzung: der Gesamtanlage wird durch die Auswertung der in den Inverter-Attributen setupInverterDevXX  gesetzen Schlüssel limit (optional) und capacity ermittelt. Inverter mit gesetztem Schlüssel feed = grid (deren Energie wird ausschließlich in das öffentlich Netz eingespeist) werden von der Betrachtung in diesem Kontext ausgeschlossen.&lt;br /&gt;
&lt;br /&gt;
;Die benötigte Beladung bis zu maxSoC (im Attribut setupBatteryDevXX) : wird ermittelt und mit der zu erwartenden PV Tagesprognose in Beziehung gesetzt. Sofern die PV-Erzeugung abzgl. Verbrauch noch nicht das Wirkleistungbegrenzungs-Limit erreicht UND noch genügend PV-Überschuß für eine Ladung auf &#039;&#039;maxSoC&#039;&#039; im Laufe der kommenden Stunden des Tages zu erwarten ist, bleibt das Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 0&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
;Wird das Wirkleistungbegrenzungs-Limit erreicht/überschritten und/oder die PV-Überschußprognose: zzgl. eines Sicherheitspuffers unterschritten, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 1&#039;&#039;&#039; gesetzt. Der User kann darauf reagieren und den Batterie Ladevorgang aktivieren. Die Möglichkeiten der Aktivierung sind natürlich von der installierten Anlage abhängig. Das SolarForecast Device greift nicht in die Batteriesteuerung direkt ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders ausgedrückt erfolgt immer dann eine Ladefreigabe, wenn einer der nachfolgenden Sachverhalte &#039;&#039;wahr&#039;&#039; ist:&lt;br /&gt;
&lt;br /&gt;
- die benötigte Ladeenergie (aller installierten Batterien) &amp;gt;= PV-Restüberschuß des Tages (Reading RestOfDayPVforecast) zzgl. Sicherheitsaufschlag&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- der Zeitpunkt des PV-Erzeugungszenit des laufenden Tages überschritten ist (Reading Today_MaxPVforecastTime)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn die aktuelle PV Leistung &amp;gt;= einer eventuellen Wechselrichter-Leistungsbegrenzung ist (Summe aller WR-Begrenzungen)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn das BatSoc-Management _nicht_ aktiviert ist (nicht alle oben genannten Aktivierungskriterien erfüllt sind)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind mehrere Batterien installiert und durch das Management einer Batterie die Einhaltung der genannten Kriterien bzw. Sachverhalte erwirkt wird, bleiben die weiteren Batterien im Modus Ladefreigabe (Battery_ChargeUnrestricted_XX=1).  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Umsetzungsbeispiel Batterie Ladesteuerung mit Victron GX Venus über den Grid Setpoint =====&lt;br /&gt;
&lt;br /&gt;
Ziel der Steuerung ist es abhängig vom Wert des Readings Battery_ChargeUnrestricted_XX (z.B. Battery_ChargeUnrestricted_01) die Ladung des angeschlossenen Batteriesystems zu aktivieren bzw. zu deaktivieren.&lt;br /&gt;
Das vorliegende Beispiel soll umzusetzen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 0 -&amp;gt; Batterie nicht aufladen bzw. nur laden wenn Einspeiselimit überschritten (Attribut plantControl-&amp;gt;feedinPowerLimit)&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 1 -&amp;gt; Batterie aufladen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Grid Setpoint ist ein Parameter in den Victron Systemeinstellungen. Das Victron System wird den eingestellten Grid Setpoint versuchen einzuhalten und bei einem positiven Wert Energie aus dem Netz beziehen bzw. bei einem negativen Grid Setpoint Energie in das Netz einspeisen.&lt;br /&gt;
&lt;br /&gt;
Normalerweise wird das Victron System die erzeugte PV Energie zunächst zur Deckung des Hausverbrauchs verwenden, ist dann noch ein PV Überschuß vorhanden, die Batterien aufladen und bei weiter vohandenen PV Überschuß diese Energie in das öffentliche Netz einspeisen sofern dem System eine Einspeisung erlaubt ist. Anderenfalls werden die Wechselrichter oder MPPT Smartloader heruntergeregelt bzw. limitiert. &lt;br /&gt;
&lt;br /&gt;
In der Standardeinstellung ist beim Victron System ein Grid Setpoint von ca. 20 bis 50 Watt, d.h. das System strebt danach diese Vorgabe zu erfüllen zieht ständig Energie in diesem Bereich aus dem öffentlich Netz von einem gelegentlichen Überschwingen der Regelung abgesehen. Damit ein eventueller PV Überschuß nicht zum Laden der Batterie verwendet, sondern statt dessen in das öffentliche Netz eingespeist wird, muß der Grid Setpoint um diesen Betrag abgesenkt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-24 114403.png|right|thumb|400px|Integration des Grid Setpoint-Managements in den Own_Spec-Bereich]]&lt;br /&gt;
&lt;br /&gt;
Damit man später per Attribut bzw. über den [[#Formatierung_der_Inhalte_im_Bereich_&amp;quot;Graphic_Header_Own_Specification&amp;quot;|Own_Spec-Bereich]] die automatische Ladesteuerung über den Grid Setpoint ein- bzw. ausschalten kann, legen wir ein userattr an:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 userattr &amp;lt;Name&amp;gt; userFn_GridSetpointManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin sind einige Vorbereitungen im Device MQTT2_cerboGX_c0619ab34e08_settings vorzunehmen. Dieses Device ist im vorliegenden Beispiel ein in FHEM vorhandenes MQTT2_DEVICE, über das die Victron CerboGX Einstellungen zugreifbar sowie einstellbar sind. Die Vorgehensweise zur Erstellung des MQTT2_DEVICE ist hier nicht beschrieben und wird vorausgesetzt.&lt;br /&gt;
&lt;br /&gt;
Damit ein entsprechender Set-Befehl zur Einstellung des Grid Setpoints vorhanden ist, werden folgende Attribute gesetzt:&lt;br /&gt;
&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings jsonMap Settings_CGwacs_AcPowerSetPoint_value:GridSetpoint&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings setList GridSetpoint W/c0619ab34e08/settings/0/Settings/CGwacs/AcPowerSetPoint {&amp;quot;value&amp;quot;:$EVTPART1}&lt;br /&gt;
&lt;br /&gt;
Nach dieser Attributierung kann mit einem &amp;quot;&#039;&#039;set MQTT2_cerboGX_c0619ab34e08_settings GridSetpoint &amp;lt;Wert&amp;gt;&#039;&#039;&amp;quot; der Grid Setpoint eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Das Attribut userFn_GridSetpointManagement kann nun im Perl Code ausgewertet werden um das Grid Setpoint-Management ein- bzw. auszuschalten.&lt;br /&gt;
Der nachfolgende Code wird in die Datei &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; eingefügt. Ist diese Datei nicht vorhanden, legen wir sie vorab als Kopie der ausgelieferten 99_myUtils.pm an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Steuerung Start/Stop der Batterieladung über den Victron Grid Setpoint&lt;br /&gt;
############################################################################&lt;br /&gt;
sub gridSetpointMgmt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vicsets   = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                               # Device Victron Einstellungen&lt;br /&gt;
  my $gspdef    = 20;                                                                  # Default Einstellung des Grid Setpoint&lt;br /&gt;
  my $targetgsp = $gspdef;                                                             # Voreinstellung Grid Setpoint&lt;br /&gt;
  my $neggspmax = FHEM::SolarForecast::CurrentVal ($name, &#039;feedinPowerLimit&#039;, 5000);   # max. gewünschte Einspeiseleistung in Watt&lt;br /&gt;
  $neggspmax    = $neggspmax * -1;&lt;br /&gt;
  my $gspm      = AttrVal ($name, &#039;userFn_GridSetpointManagement&#039;, &#039;aus&#039;);             # Freischaltung des Grid Setpoint-Managements&lt;br /&gt;
  my $curgsp    = ReadingsNum ($vicsets, &#039;GridSetpoint&#039;,         $gspdef);             # aktuelle Einstellung Grid Setpoint&lt;br /&gt;
  &lt;br /&gt;
  if ($gspm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name, &#039;Battery_ChargeUnrestricted_01&#039;, 0);         # Ladefreigabe (1 -&amp;gt; Bat Ladefreigabe)&lt;br /&gt;
    my $surp = ReadingsNum ($name, &#039;Current_Surplus&#039;,               0);         # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if (!$bcrq) {                                                               # Grid Setpoint absenken wenn keine .. &lt;br /&gt;
        $targetgsp = $gspdef - $surp;                                           # ..Batterie Ladefreigabe&lt;br /&gt;
        $targetgsp = $neggspmax if($targetgsp &amp;lt; $neggspmax);                    # Begrenzung der Einspeiseleistung&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($curgsp != $targetgsp) {&lt;br /&gt;
	  fhem (&amp;quot;set $vicsets GridSetpoint $targetgsp&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn gridSetpointMgmt -&amp;gt; GridSetpoint in $vicsets set to $targetgsp});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Victron_GridSetpoint_set&#039;, $targetgsp, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Vergleich des Setpoints mit der Vorgabe von &#039;&#039;$neggspmax&#039;&#039; dient dazu die maximale Einspeiseleistung in das öffentliche Netz zu begrenzen. Ist diese Grenze erreicht, wird der noch verbleibende Überschuß in die Batterie geladen. Dadurch wird eine Abregelung der Anlage vermieden wenn der Schwellenwert &#039;&#039;$neggspmax&#039;&#039;erreicht ist sofern die Batterie aufnahmefähig ist und nicht voll geladen ist. &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::gridSetpointMgmt  ($name);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zum Management des automatischen Grid Setpoint und der Anzeige des eingestellten Wertes wird das Attribut und die Readinganzeige in den Own_Spec-Bereich eingebunden, z.B.:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; graphicHeaderOwnspec  #Settings&lt;br /&gt;
                                   SetPoint&amp;amp;nbsp;Management:userFn_GridSetpointManagement&lt;br /&gt;
                                   Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Unterstützung eines netzdienlichen Verhaltens ====&lt;br /&gt;
&lt;br /&gt;
Der Steuerungsprozess der Batterieanlage leistet insgesamt einen kleinen Beitrag zur Netzstabilität, indem die Speicherladung in den Zeitraum der meisten prognostizierten Überschußeinspeisung gelegt wird. Im Sommer kann sich dieser Zeitraum in die Zeit nach dem Maxmimum des prognostizierten PV-Überschusses verlagern, wenn auch danach noch genügend Überschußenergie zu Volladung der Batterie prognostiziert wird. In dem Zusammenhang sollte im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; ein Einspeiselimit gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zur Verdeutlichung soll das Beispiel dienen:&lt;br /&gt;
&lt;br /&gt;
* die Batterie ist zu 60% geladen &lt;br /&gt;
* der User hat upSoC=40 eingestellt&lt;br /&gt;
* der User hat maxSoC=90 eingestellt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Am Vormittag ist genügend Sonne vohanden, das Maximumum der Energie über die Zeit wird aber noch erwartet. &lt;br /&gt;
Zu diesem Zeitpunkt wird das Reading  &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039; auf den Wert &amp;quot;0&amp;quot; gesetzt. Durch den Nutzer erfolgt daraufhin, zum Beipiel über ein Notify, ein anlagenspezifischer Befehl &amp;quot;Ladestop&amp;quot; an die Batterieanlage. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ab diesem Moment wird:&lt;br /&gt;
&lt;br /&gt;
# die Batterie nicht geladen&lt;br /&gt;
# die erzeugte PV-Energie dem Haushalt zur Verfügung gestellt bzw. der verbleibende Überschuß eingespeist, sofern der Überschuß unterhalb des im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limits liegt.&lt;br /&gt;
# ein eventuell über dem Limit &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; vorhandener Überschuß in die Batterie geladen und so die Netzlast verringert sowie die Batterie schonend geladen. (dieser Punkt trifft in den Monaten mit wenig PV-Erzeugung eher nicht zu)  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig liefert die Batterie Energie an das Hausnetz und wird von 60% bis maximal einem SoC-Wert entladen, der durch die [[#Die_dynamische_SOC_Steuerung_mit_Umsetzungsbeispiel|dynamische SOC Steuerung]] bestimmt wird. Dazu muß diese Steuerung natürlich implementiert sein. Sofern der berechnete SoC größer als upSoC ist, wird der maximale Entladungs-SoC auf upSoC gesetzt. &lt;br /&gt;
&lt;br /&gt;
Zusätzlich überprüft das Modul permanent bei jedem Zyklus die Differenz des aktuell vorhandenen SoC zum eingestellten maxSoC.&lt;br /&gt;
Sie soll nicht größer sein um mit dem (noch) zu erwartenden PV-überschuß des Tages der eingestellte maxSoC bzw. dessen Nähe wahrscheinlich erreicht werden kann. &lt;br /&gt;
Sollte der Differenz-Grenzwert erreicht sein, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; gesetzt und der Nutzer sollte dann über einen geeigneten Befehl seine Anlage in den Modus &amp;quot;Laden&amp;quot; umschalten.&lt;br /&gt;
Dieser Vorgang kann beliebig oft während des Tages alternieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Nutzung von batteryTrigger ===&lt;br /&gt;
Ergänzt werden die Möglichkeiten durch das set-Kommando: &lt;br /&gt;
&lt;br /&gt;
 batteryTrigger &amp;lt;1on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;1off&amp;gt;=&amp;lt;Wert&amp;gt; [&amp;lt;2on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;2off&amp;gt;=&amp;lt;Wert&amp;gt; ...] &lt;br /&gt;
&lt;br /&gt;
Das Kommando setzt Triggerpunkte bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %).&lt;br /&gt;
&lt;br /&gt;
Der verwendete SoC wird als resultierender SoC als Summe der aktuellen Ladung aller registrierten Batterie-Geräte im Verhältnis zur installierten Gesamtkapazität gebildet. Das bedeutet, dass alle einzelnen Batterie-Geräte als ein gemeinsamer Cluster betrachtet werden. &lt;br /&gt;
&lt;br /&gt;
Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise definiert werden.&lt;br /&gt;
Überschreiten die letzten drei SoC-Messungen eine definierte Xon-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = on&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
Unterschreiten die letzten drei SoC-Messungen eine definierte Xoff-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = off&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
&lt;br /&gt;
Der Inhalt der Readings kann durch ein User-Programm oder, bei Erzeugung von entsprechenden Events, mittels notify-Device ausgewertet werden um bei Eintreten eines definierten Ereignisses entsprechende Reaktionen auszulösen. Das kann zum Beispiel die Freigabe eines Heizstabes oberhalb eines bestimmten SOC sein oder ein Entladeverbot der Batterie unterhalb eines SOC-Wertes um Reserven für einen eventuellen Stromausfall zu behalten.&lt;br /&gt;
&lt;br /&gt;
Damit die Batterietrigger dynamisch geändert werden können, ist die Einstellung als Set-Kommando und nicht als Attribut ausgeführt.   &lt;br /&gt;
&lt;br /&gt;
Alle Triggerpunkte können mit dem set-Befehl:&lt;br /&gt;
&lt;br /&gt;
 reset batteryTriggerSet&lt;br /&gt;
&lt;br /&gt;
wieder gelöscht werden.&lt;br /&gt;
&lt;br /&gt;
== Verbrauchersteuerung - Registrieren und visualisieren 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;
Die Eigenschaften und das Schaltverhalten wird durch die Angabe der verfügbaren Schlüssel gesteuert. Die Möglichkeiten sind sehr umfangreich. Die nachfolgenden Abschnitte beschreiben die Verwendung am Beispiel oft vorkommender bzw. nachgefragter Sachverhalte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die Phasen der Verbrauchersteuerung ===&lt;br /&gt;
&lt;br /&gt;
Jeder Zyklus eines Verbrauchers durchläuft im Modul die folgenden Phasen:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Planung&#039;&#039;&#039; der Aktivzeiten des Verbrauchers, d.h. wann der Verbraucher geplant eingeschaltet sowie geplant ausgeschaltet wird und damit der Zyklus beendet wird.&lt;br /&gt;
# &#039;&#039;&#039;Start&#039;&#039;&#039; des Zyklus, d.h. Einschalten des Verbrauchers entsprechend der Planungsdaten sofern weitere, in den Consumer-Schlüsseln definierbare Rahmenbedingungen das Einschalten nicht verhindern (z.B. kein oder zu wenig PV-Energieerzeugung / PV-Überschuss)&lt;br /&gt;
# &#039;&#039;&#039;Permanente Überprüfung von&#039;&#039;&#039; eventuell vorhandenen &#039;&#039;&#039;Interruptbedingungen&#039;&#039;&#039; die den Verbraucher temporär ausschalten und, sofern die Interruptbedingung nicht mehr vorliegt, den Verbraucher wieder einschalten und so den gestarteten Zyklus fortsetzen.&lt;br /&gt;
#  &#039;&#039;&#039;Beendigung&#039;&#039;&#039; der Zyklus. Die Beendigung erfolgt entweder (normalerweise) wenn die geplante Endezeit der Zyklus erreicht ist oder eine optionale Endebedingung erfüllt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Steuerung der Phasen ====&lt;br /&gt;
Der Ablauf der Phasen kann durch verschiedene Schlüssel-Wert Paare beeinflusst und gesteuert werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; kann eine &#039;&#039;&#039;zusätzliche externe Bedingung&#039;&#039;&#039; definiert werden um den Einschaltvorgang des Consumers freizugeben. Ist die Bedingung (Regex) nicht erfüllt, erfolgt kein Einschalten des Verbrauchers auch wenn die sonstigen Voraussetzungen wie Zeitplanung, on-Schlüssel, auto-Mode und aktuelle PV-Leistung gegeben sind. Es erfolgt somit eine &#039;&#039;&#039;UND-Verknüpfung&#039;&#039;&#039; des Schlüssels swoncond mit den Planungsdaten und weiteren Einschaltbedingungen.&lt;br /&gt;
&lt;br /&gt;
Der optionale Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; definiert eine &#039;&#039;&#039;vorrangige Ausschaltbedingung&#039;&#039;&#039; (Regex). Sobald diese Bedingung erfüllt ist, wird der Consumer ausgeschaltet auch wenn die geplante Endezeit (consumerXX_planned_stop) noch nicht erreicht ist (&#039;&#039;&#039;ODER-Verknüpfung&#039;&#039;&#039;). Weitere Bedingungen wie off-Schlüssel und auto-Mode müssen zum automatischen Ausschalten erfüllt sein.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; kann während der geplanten Einschaltzeit eine automatische Unterbrechung sowie Wiedereinschaltung des Verbrauchers vorgenommen werden. Der Verbraucher wird temporär ausgeschaltet (interrupted) und wieder eingeschaltet (continued) wenn die Interrupt-Bedingung nicht mehr vorliegt. Die verbleibende Laufzeit wird durch einen Interrupt nicht beeinflusst! &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;power&#039;&#039;&#039; gibt die nominale Leistungsaufnahme des Verbrauchers gemäß seines Datenblattes an. Dieser Wert wird verwendet um die Schaltzeiten des Verbrauchers zu planen und das Schalten in Abhängigkeit des tatsächlichen PV-Überschusses zum Einplanungszeitpunkt zu steuern. Ist &#039;&#039;&#039;power=0&#039;&#039;&#039; gesetzt, wird der Verbraucher unabhängig von einem zum Zeitpunkt des Zyklus-Start eventuell nicht ausreichend vorhandenem PV-Überschuss wie geplant eingeschaltet und somit der Zyklus gestartet.&lt;br /&gt;
&lt;br /&gt;
Durch die Schlüssel &#039;&#039;&#039;notbefore&#039;&#039;&#039; und &#039;&#039;&#039;notafter&#039;&#039;&#039; kann der Startzeitpunkt des Verbrauchers so gesteuert werden, dass der Start des Zyklus nicht vor bzw. nach der angegebenen Zeit eingeplant wird. Diese Steuerung bezieht sich auf die &#039;&#039;Planung&#039;&#039;, d.h. der eigentliche Start des Verbrauchers kann sich unter Umständen durch vorhandene Rahmenbedingungen verzögern. &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; legt die geplanten Einschaltzeit, d.h. die Laufzeit des Zyklus fest. Der Name &#039;&#039;&#039;mintime&#039;&#039;&#039; ist nicht als MInimum-Zeit zu deuten, sondern beschreibt die angegebene Zeit in Minuten die der Zyklus dauern soll.&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist optional, da sich die Standard-Laufzeit des Verbrauchers von dessen Typ abgeleitet wird. Diese Standard Laufzeiten sind:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|dryer&lt;br /&gt;
|90 Minten&lt;br /&gt;
|-&lt;br /&gt;
|dishwasher&lt;br /&gt;
|180 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|washingmachine&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|heater&lt;br /&gt;
|240 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|charger&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|other&lt;br /&gt;
|60 Minuten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Der Verbraucher wurde nicht gestartet obwohl die Startzeit der Einplanung erreicht wurde ===&lt;br /&gt;
&lt;br /&gt;
Wenn die Startzeit des Consumers entsprechend der Einplanung erreicht oder überschritten ist, wird der Consumer eingeschaltet wenn die weiteren Voraussetzungen wahr sind:&lt;br /&gt;
&lt;br /&gt;
* es ist aktuell ein PV-Überschuss vorhanden und der PV-Überschuss deckt die kalkulierten Leistungsaufnahme des Verbrauchers ab. Mit den Schlüsseln &#039;&#039;&#039;power&#039;&#039;&#039; und &#039;&#039;&#039;spignorecond&#039;&#039;&#039; kann die Einschaltung trotz fehlendem PV-Überschuss ermöglicht werden. &lt;br /&gt;
&lt;br /&gt;
* die Angabe im Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; ist wahr (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* das Schalten ist über den Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; freigegeben (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* im Schlüssel &#039;&#039;&#039;on&#039;&#039;&#039; ist ein valides Einschaltkommando hinterlegt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind diese zusätzlichen Bedingungen nicht erfüllt, erfolgt kein Start des eingeplanten Zyklus. Der Verbraucher verbleibt in diesem Fall weiterhin im Status &#039;&#039;planned&#039;&#039; oder &#039;&#039;suspended&#039;&#039;. Die Startbedingungen werden regelmäßig reviewed und der Consumer gestartet sobald alle Startbedingungen wahr sind bzw. Start verhindernde Bedingungen entfallen sind. &lt;br /&gt;
&lt;br /&gt;
Dieser Vorgang erfolgt bis das geplante Ende des Verbaucherzyklus erreicht ist oder die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; zutrifft. Sobald die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; wahr ist, wird der gesamte Planungszyklus des Consumers beendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Kann manuell / automatisiert in den Planungszyklus eines Verbrauchers eingegriffen werden? ===&lt;br /&gt;
&lt;br /&gt;
Die Einplanung und die darauf aufbauenden Schaltprozesse laufen gemäß den hinterlegten Schlüsseloptionen im Modul automatatisch ab ohne dass ein Eingriff durch den Anwender erfolgen muß.&lt;br /&gt;
&lt;br /&gt;
Dennoch kann es gewünscht sein eine Neuplanung oder eine Sofortplanung eines Consumers vorzunehmen weil der Bedarf dazu besteht. Zu diesem Zweck stehen die Set-Kommandos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* consumerNewPlanning &lt;br /&gt;
&lt;br /&gt;
* consumerImmediatePlanning &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
zur Verfügung. &lt;br /&gt;
Beide Befehle initiieren die Consumer-Neuplanung, wobei mit dem Befehl &#039;&#039;consumerImmediatePlanning&#039;&#039; die eventuell im consumerXX Attribut gesetzten Schlüssel notbefore, notafter bzw. mode werden nicht beachtet werden. Dagenen beachtet der Befehl &#039;&#039;consumerNewPlanning&#039;&#039; alle definierten Schlüsseloptionen und dient gewöhnlich dazu einen abgeschlossenen Verbraucherzyklus wiederholt ausführen zu lassen weil die aktuelle Witterungslage dazu geeignet ist. &lt;br /&gt;
&lt;br /&gt;
Ein Anwendungsbeispiel dafür ist zum Beispiel die Ausführung von mehreren Waschmaschinen-Zyklen an einem langen, sonnigen Sommertag.&lt;br /&gt;
Diese beiden Set-Befehle können zum Beispiel über ein auf einen Schalter/Taster reagierendes Notify oder DOIF Device ausgeführt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung eines Verbrauchers mit getrennten Geräten für Messung und Schalten ===&lt;br /&gt;
&lt;br /&gt;
Es existieren in FHEM Geräte, die über verschiedene Kanäle für unterschiedliche Aufgaben verfügen. Diese Kanäle werden jeweils in einem gesonderten Device abgebildet. HomeMatic oder readingsProxy sind Beispiele für solche Varianten.&lt;br /&gt;
&lt;br /&gt;
Um solche Verbraucher einzubinden gibt es im consumerXX Attribut den Schlüssel &#039;&#039;&#039;switchdev&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Bei der Registrierung gibt man als Consumerdevice das Gerät für die Messung an und im Schüssel switchdev das entsprechende FHEM-Device, welches für die Schaltvorgänge benutzt wird. &lt;br /&gt;
Ist switchdev angegeben, beziehen sich die weiteren Schlüssel on, off, swstate, auto und asynchron auf dieses Gerät.&lt;br /&gt;
&lt;br /&gt;
In dem nachfolgenden Beispiel (Homematic) ist &#039;&#039;eg.az.fridge_Pwr&#039;&#039; FHEM Device für die Energiemessung. Die Schlüssel &#039;&#039;pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; geben Readings in diesem Device an damit SolarForecast den Verbrauch und die Energiemengen auslesen kann. Demgegenüber ist im Schlüssel &#039;&#039;switchdev&#039;&#039; das zugehörige Schalter-Device der Kombination angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eg.az.fridge_Pwr&lt;br /&gt;
type=noSchedule switchdev=eg.az.fridge_Sw power=0 icon=fridge pcurr=power:W:5 etotal=energyCalc:Wh &lt;br /&gt;
swstate=state:on:off auto=automatic&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung von Verbrauchern ohne Zeitplanung und aktivem Schalten ===&lt;br /&gt;
Manchmal besteht der Wunsch, Verbraucher in SolarForecast zu integrieren um lediglich folgende Sachverhalte abzubilden:&lt;br /&gt;
&lt;br /&gt;
* Visualisierung des Schaltstatus in der Consumer Legende und/oder der Energieflußgrafik&lt;br /&gt;
* Darstellung des aktuellen Energieverbrauchs in der Energieflußgrafik&lt;br /&gt;
* Erfassung der (externen) Schaltzeiten, d.h. der Zeiten der Gerätenutzung sowie der Verbrauchsdaten um deren Einfluß bei den Planungszeiten anderer Geräte durch SolarForecast berücksichtigen zu lassen&lt;br /&gt;
&lt;br /&gt;
In solchen Fällen werden bei der Registrierung die Schlüssel &#039;&#039;swstate, pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; zur Erfassung der Schaltzustände und der Energieverbrauchs angegeben, jedoch zur Verhinderung der Zeitplanung durch SolarForecast der Schlüssel &#039;&#039;&#039;type=noSchedule&#039;&#039;&#039; gesetzt sowie die Schlüssel &#039;&#039;on&#039;&#039; und &#039;&#039;off&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt eine mögliche Registrierung eines Zwischensteckers (Shelly) zur Erfassung der Daten eines Gefrierschrankes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Shelly.shellyplug4&lt;br /&gt;
type=noSchedule power=65 asynchron=1&lt;br /&gt;
icon=gefrierschrank &lt;br /&gt;
swstate=state:.*on.*:.*off.* &lt;br /&gt;
pcurr=relay_0_power:W:5 etotal=relay_0_energy_Wh:Wh&lt;br /&gt;
&amp;lt;/pre&amp;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;
&lt;br /&gt;
 Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off&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;
&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;
&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. Alternativ kann die Berücksichtigung des zwangsweisen PV Überschuss mit dem Schlüssel &amp;quot;spignorecond&amp;quot; im Consumer-Attribut ausgesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== zusätzliche Readings bzw. Erzeugung von statistischen Readings ==&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den zahlreichen im Modul per Standard erzeugten Readings kann der Anwender weitere Readings generieren lassen.&lt;br /&gt;
Diese zusätzlichen Readings geben entweder einen bestimmten Sachverhalt (Laufzeit, Status der API-Abfragen, etc.) oder einen statistischen Wert, z.B. die Batterieentladung des aktuellen Tages, wieder.&lt;br /&gt;
&lt;br /&gt;
Die zusätzlich erstellten Readings sind durch den Präfix &#039;&#039;&#039;special_&#039;&#039;&#039; im Device gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Diese zusätzlichen Informationen können durch das Setzen einer oder mehrerer Kennzeichen im Attribut &#039;&#039;&#039;ctrlSpecialReadings&#039;&#039;&#039; erzeugt werden. Die mögliche Auswahl wird je nach Bedarf ausgebaut und umfasst zum aktuellen Zeitpunkt (07.02.2025) diese Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;BatPowerIn_Sum: 	die Summe der momentanen Batterieladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;BatPowerOut_Sum: 	die Summe der momentanen Batterieentladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;allStringsFullfilled: 	Erfüllungsstatus der fehlerfreien Generierung aller Strings&lt;br /&gt;
;conForecastTillNextSunrise: 	Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
;currentAPIinterval: 	das aktuelle Abrufintervall der gewählten Strahlungsdaten-API in Sekunden&lt;br /&gt;
;currentRunMtsConsumer_XX: 	die Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; seit dem letzten Einschalten. (letzter Laufzyklus)&lt;br /&gt;
;dayAfterTomorrowPVforecast: 	liefert die Vorhersage der PV Erzeugung für Übermorgen (sofern verfügbar) ohne Autokorrektur (Rohdaten).&lt;br /&gt;
;daysUntilBatteryCare_XX: 	Tage bis zur nächsten Batterie XX Pflege (Erreichen der Ladung &#039;maxSoC&#039; aus Attribut ctrlBatSocManagementXX)&lt;br /&gt;
;lastretrieval_time: 	der letzte Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;lastretrieval_timestamp: 	der Timestamp der letzen Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;response_message: 	die letzte Statusmeldung der gewählten Strahlungsdaten-API&lt;br /&gt;
;runTimeAvgDayConsumer_XX: 	die durchschnittliche Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; an einem Tag&lt;br /&gt;
;runTimeCentralTask: 	die Laufzeit des letzten SolarForecast Intervalls (Gesamtprozess) in Sekunden&lt;br /&gt;
;runTimeTrainAI: 	die Laufzeit des letzten KI Trainingszyklus in Sekunden&lt;br /&gt;
;runTimeLastAPIAnswer: 	die letzte Antwortzeit des Strahlungsdaten-API Abrufs auf einen Request in Sekunden&lt;br /&gt;
;runTimeLastAPIProc: 	die letzte Prozesszeit zur Verarbeitung der empfangenen Strahlungsdaten-API Daten&lt;br /&gt;
;SunMinutes_Remain: 	die verbleibenden Minuten bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;SunHours_Remain: 	die verbleibenden Stunden bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;todayConsumptionForecast: 	Verbrauchsprognose pro Stunde des aktuellen Tages (01-24)&lt;br /&gt;
;todayConForecastTillSunset: 	Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
;todayDoneAPIcalls: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Calls&lt;br /&gt;
;todayDoneAPIrequests: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Requests&lt;br /&gt;
;todayConsumption: 	der gesamte Energieverbrauch (Wh) des Hauses am aktuellen Tag&lt;br /&gt;
;todayGridConsumption: 	die aus dem öffentlichen Netz bezogene Energie am aktuellen Tag&lt;br /&gt;
;todayGridFeedIn: 	die in das öffentliche Netz eingespeiste PV Energie am aktuellen Tag&lt;br /&gt;
;todayMaxAPIcalls: 	die maximal mögliche Anzahl Strahlungsdaten-API Calls. Ein Call kann mehrere API Requests enthalten.&lt;br /&gt;
;todayRemainingAPIcalls: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Calls&lt;br /&gt;
;todayRemainingAPIrequests: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Requests&lt;br /&gt;
;todayBatIn_XX: 	die am aktuellen Tag in die Batterie XX geladene Energie&lt;br /&gt;
;todayBatInSum: 	Summe der am aktuellen Tag in alle Batterien geladene Energie&lt;br /&gt;
;todayBatOut_XX: 	die am aktuellen Tag aus der Batterie XX entnommene Energie&lt;br /&gt;
;todayBatOutSum: 	Summe der am aktuellen Tag aus allen Batterien entnommene Energie&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Manche Angaben sind im Setup des Moduls optional, d.h. sie müssen nicht zwingend beim Setup angegeben werden. Allerdings sind diese Angaben für die Erstellung eines zusätzlichen Readings unter Umständen Voraussetzung. Es empfiehlt sich deshalb bei Setup so viele Informationen wie möglich zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
So ist zum Beispiel für die sinnvolle Erstellung der Informationen &#039;&#039;&#039;todayBatInSum&#039;&#039;&#039; und &#039;&#039;&#039;todayBatOutSum&#039;&#039;&#039; (Readings special_todayBatInSum und special_todayBatOutSum) das Vorhandensein der Schlüssel &#039;&#039;intotal&#039;&#039; und &#039;&#039;outtotal&#039;&#039; im Attribut setupBatteryDevXX notwendig (Beispiel):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupBatteryDev01 MQTT2_cerboGX_c0619ab34e08_battery &lt;br /&gt;
                              pin=BatIn:W pout=BatOut:W charge=SOC_value intotal=BatInTotal:Wh outtotal=BatOutTotal:Wh &lt;br /&gt;
                              cap=InstalledCapacity_Wh:Wh asynchron=1 show=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Fehlersuche ==&lt;br /&gt;
Das Modul SolarForecast ist sehr komplex und es die verschiedensten Datenquellen ausgewertet, zusammengeführt und daraus Ergebnisse berechnet und/oder visualisiert. Wird etwas nicht wie erwartet durch das Modul geliefert, können die Ursachen vielfältig sein. Natürlich kann ein Fehler im Modulcode vorliegen, oftmals gibt es aber andere Ursachen.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgenden Hinweise sollen Hilfe zur Selbsthilfe geben und sind eine Zusammenfassung von realen Fällen die mit dem beschriebenen Wegen und Verfahren gelöst wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die erwartete erzeugte PV-Energie ist im Modul zu gering und wird im Balkendiagramm nicht angezeigt === &lt;br /&gt;
&lt;br /&gt;
Die erzeugte PV-Energie wird nicht richtig angezeigt: Am Vormittag sind keine Werte vorhanden und, wenn dann etwas kommt, ist die Anzeige zu gering. Für 13 und 14 Uhr wurden ca. 5.000Wh erwartet (im Vergleich mit den Daten aus einer anderen Auswertungsquelle). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lösungsweg:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Aus dem List des Devices wurden die für den Fall wesentlichen Readings herausgezogen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVforecast 152 Wh&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVforecast 1400 Wh&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVforecast 2500 Wh&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVforecast 4392 Wh&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVforecast 4000 Wh&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVreal 300 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVforecast 6415 Wh&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVreal 3200 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVforecast 5629 Wh&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVreal 2700 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVforecast 3958 Wh&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVreal 900 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVforecast 945 Wh&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVreal 500 Wh&lt;br /&gt;
   &lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour18_PVforecast 59 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man sieht dass bis 12:00 keine erzeugte Energie vom WR gemeldet wird. Deswegen wird in der Balkengrafik nichts dargestellt. Auch danach bleibt die registrierte PV-Energie hinter den Erwartungen zurück. Zuständig für die Lieferung der PV-Energie an das Modul ist das Reading im Schlüssel:&lt;br /&gt;
&lt;br /&gt;
 setupInverterDev01 SH10rt pv=Total_DC_Power:W &amp;lt;mark&amp;gt;etotal=Total_Export_Energy_from_PV:kWh&amp;lt;/mark&amp;gt; capacity=10000 strings=Hauptdach,Flachdach&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Welche Änderungen es zwischen den Stunden gab, sieht man mit einem &amp;quot;get ... pvHistory XX&amp;quot; (&amp;quot;XX&amp;quot; steht für das Datum, d.h. den Tag, z.B. 02). &amp;lt;br&amp;gt;&lt;br /&gt;
Hier ein Beispiel für die Stunden 10 (9:00 - 9:59) und 11 (10:00 - 10:59). &amp;lt;br&amp;gt;&lt;br /&gt;
Wichtig ist hier der Key etotali01 für den ersten Inverter. Die Differenz zwischen den Werten beider Stunden ist die in der Stunde erzeugte Energie (hier 380 Wh). Diese 380 Wh findest du auch im Key pvrl01 als PVReal für diese Stunde. Das Modul rechnet intern immer mit Wh, kWh werden vorher in Wh umgerechnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
10 =&amp;gt; pvfc: 365, pvrl: 530, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63364714&amp;lt;/mark&amp;gt;, etotali02: 3044110, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;pvrl01: 380&amp;lt;/mark&amp;gt;, pvrl02: 150, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 574, con: 518, gcons: 22, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 1, feedprice: 0.1269&lt;br /&gt;
&lt;br /&gt;
            DoN: 1, sunaz: 137, sunalt: 12&lt;br /&gt;
&lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
      11 =&amp;gt; pvfc: 2966, pvrl: 1862, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63365094&amp;lt;/mark&amp;gt;, etotali02: 3044260, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            pvrl01: 1392, pvrl02: 470, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 774, con: 609, gcons: 25, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 4, feedprice: 0.1269&lt;br /&gt;
           &lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
D.h. wenn zwischen den beiden Stunden keine Differenzen zu finden sind, liegt es sehr wahrscheinlich am Input des Readings:&lt;br /&gt;
&lt;br /&gt;
 etotal=Total_Export_Energy_from_PV:kWh&lt;br /&gt;
&lt;br /&gt;
welches sich in den ersten Stunden nicht ändert und danach auch nur wenig.&lt;br /&gt;
&lt;br /&gt;
Man kann mit dem Attribut:&lt;br /&gt;
&lt;br /&gt;
 ctrlDebug=collectData&lt;br /&gt;
&lt;br /&gt;
die Datensammlung verfolgen (leider entstehen viele Daten im Log). Man sieht welche Werte von dem Inverter/Reading geliefert werden:&lt;br /&gt;
 &lt;br /&gt;
 ....&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; collect Inverter 01 data - device: STP_5000, delivery: default =&amp;gt;&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; pv: 0 W, &amp;lt;mark&amp;gt;etotal: 63378810 Wh&amp;lt;/mark&amp;gt;&lt;br /&gt;
 ....&lt;br /&gt;
&lt;br /&gt;
Dieser Wert muß bei PV Erzeugung kontinuierlich hochzählen. Wenn nicht, muss das angegebene Reading, d.h. die Quelle überprüft werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ergebnis der Prüfung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tatsächlich wurde ein Reading benutzt, das ungeeignet war: Statt &amp;quot;Total_PV_Generation&amp;quot; wurde &amp;quot;Total_export_energy_from_PV&amp;quot; genutzt. In diesem Reading wurde immer die in die Batterie gespeicherte Energie von der gesamten erzeugten Energie abgezogen. Daher war auch vormittags alles 0, da in dieser Periode alle PV-Energie in die Batterie geladen wurde bzw. in weiteren Stunden ein Anteil der dann bei dem PV-Erzeugungswert fehlte.&lt;br /&gt;
&lt;br /&gt;
Nachdem die Ursache beseitigt war, zeigt SolarForecast wieder die erwarteten PV-Erzeugungswerte an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Konfigurationsbeispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Visualisierung solare Vorhersage und reale Erzeugung ===&lt;br /&gt;
&lt;br /&gt;
Zu Beginn jedes neuen Tages gegen 00:00 Uhr werden durch das SolarForecast Device Events für die initiale PV Prognose des kommenden Tages erstellt.&lt;br /&gt;
Der Readingteil dieser Events heißt&lt;br /&gt;
&lt;br /&gt;
 AllPVforecastsToEvent&lt;br /&gt;
&lt;br /&gt;
Die Uhrzeiten der Events sind so aufbereitet und können direkt geloggt werden um sie in einen SVG Plot zu integrieren.&lt;br /&gt;
Im SolarForecast Device ist dieses Reading nicht sichtbar, nur die Events werden erstellt.&lt;br /&gt;
&lt;br /&gt;
Die meteorologischen Bedingungen verändern sich über den Tag permanent. Je nach gewählter Strahlungsdatenquelle (eine API oder DWD Device) erfolgt eine mehr oder weniger dynamische Anpassung der Prognose an die sich verändernde Umwelt.&lt;br /&gt;
&lt;br /&gt;
Aktuelle Prognosedaten sowie die reale PV Erzeugung der vergangenen Stunde können über die Readings&lt;br /&gt;
&lt;br /&gt;
 LastHourPVforecast&lt;br /&gt;
 LastHourPVreal&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-10-20 134050.png|right|thumb|400px|Übersicht solare Vorhersage]]&lt;br /&gt;
geloggt werden. &lt;br /&gt;
&lt;br /&gt;
Werden alle drei Werte in einem SVG kombiniert, kann die Entwicklung der Prognose über den Tag und die Beziehung von Prognose zu realer PV Erzeugnung pro Stunde visualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Für das rechts abgebildete Beispiel des Plots aus einer Datenbank &amp;quot;LogDBShort&amp;quot; sieht das gplot-File wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Created by FHEM/98_SVG.pm, 2024-03-08 15:05:31&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;TL&amp;gt;&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid&lt;br /&gt;
set ylabel &amp;quot;Wh&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Wh&amp;quot;&lt;br /&gt;
set yrange [0:7500]&lt;br /&gt;
set y2range [0:7500]&lt;br /&gt;
&lt;br /&gt;
#LogDBShort SolCast:LastHourPVforecast:::&lt;br /&gt;
#LogDBShort SolCast:LastHourPVreal:::&lt;br /&gt;
#LogDBShort SolCast:AllPVforecastsToEvent:::&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;aktuelle PV Vorhersage&#039; ls l6fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;reale PV Erzeugung&#039; ls l2fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;initiale PV Vorhersage&#039; ls l4 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; In manchen Fällen werden die Vorhersagewerte im SVG-Plot nicht angezeigt wenn FileLog verwendet wird. Ein Setzen des Attribute &amp;quot;fixedrange=3days +1&amp;quot; im SVG löst das Problem. Die Definition des SVG-Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_LogDBShort_SolCast SVG LogDBShort:SVG_LogDBShort_SolCast:HISTORY&lt;br /&gt;
attr SVG_LogDBShort_SolCast fixedrange 3days +1&lt;br /&gt;
attr SVG_LogDBShort_SolCast room Energie-&amp;gt;SolarPrognose&lt;br /&gt;
attr SVG_LogDBShort_SolCast sortby 2&lt;br /&gt;
attr SVG_LogDBShort_SolCast title &amp;quot;Übersicht solare Vorhersage&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Technisch bedingt werden an einem Tag X kurz nach 00:00 Uhr die am Vortag für den Tag X erzeugten Events aktualisiert. Diese Daten erzeugen in der Datenbank einen zweiten Satz an Daten mit dem gleichen Timestamp was für die Anzeige unvorteilhaft ist. &lt;br /&gt;
Um nur die aktualisierten Events von &#039;&#039;&#039;AllPVforecastsToEvent&#039;&#039;&#039; in der Datenbank zu erhalten, bietet sich ein DbRep-Device an. Die nachfolgende Vorschlagsdefinition kann per at-Device jeden Tag kurz vor Mitternacht (z.B. 23:57:10) ausgeführt werden. Es werden immer die in der Vergangenheit geschriebenen (veralteten) Daten aus der Datenbank gelöscht, doppelte Datesätze vermieden und immer die aktuellste initiale Prognose gespeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.Del.AllPVforecastsToEvent DbRep LogDBShort&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent alias Löschen Readings AllPVforecastsToEvent des Folgetages&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent comment ermöglicht dass die Readings AllPVforecastsToEvent am Folgetag wieder neu und aktuell geschrieben werden können&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent devStateIcon initialized:control_3dot_hor_s connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent disable 0&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent event-on-update-reading state&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent icon edit_delete&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent showproctime 1&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent device TYPE=SolarForecast&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_begin next_day_begin&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_end next_day_end&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das angegebene DbLog-Device &#039;&#039;&#039;LogDBShort&#039;&#039;&#039; ist natürlich anzupassen.&lt;br /&gt;
&lt;br /&gt;
Das at-Device zum Starten der Datenbankbereinigung sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define At.Del.AllPVforecastsToEvent at *23:58:10 set Rep.Del.AllPVforecastsToEvent delEntries&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent alias Start Löschen Readings AllPVforecastsToEventn LogDBShort&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent icon clock&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich sind auch hier die eigenen Devicenamen entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
Ab SolarForecast Version 1.51.7 kann die Eventerzeugung für bestimmte SVG Plot-Typen optimiert werden. &amp;lt;br&amp;gt; &lt;br /&gt;
Die Aktivierung dieser Optimierungen ist in der Online Hilfe zum Attribut &#039;&#039;&#039;plantControl-&amp;gt;genPVforecastsToEvent&#039;&#039;&#039; beschrieben. Bei Nutzung des Attributes plantControl-&amp;gt;genPVforecastsToEvent ist ebenfalls das Attribut &#039;&#039;&#039;event-on-update-reading=AllPVforecastsToEvent&#039;&#039;&#039; zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispielkonfiguration 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;
Bitte dabei diese DWD-Version aus dem [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter Contrib] von DS_Starter dazu nutzen&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|55_DWD_OpenData.pm&lt;br /&gt;
|136.2 KB ​&lt;br /&gt;
|29260  &lt;br /&gt;
|DS_Starter&lt;br /&gt;
|55_DWD_OpenData: contrib 1.17.7&lt;br /&gt;
|}&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 downloadTimeout 120&lt;br /&gt;
attr DWD comment Im DWD Wetterdevice verwendet Solarforecast : \&lt;br /&gt;
TTT,Neff,RR1c,ww,SunUp,SunRise,SunSet \&lt;br /&gt;
zusätzlich ist jedoch auch noch Rad1h notwendig \&lt;br /&gt;
wenn dieses DWD-Device als Strahlungsdevice genutzt wird.\&lt;br /&gt;
Die Station 10418 (Lüdenscheid) überträgt aktuell am 09.03.2025 (noch) Rad1h.\&lt;br /&gt;
attr DWD downloadTimeout 120&lt;br /&gt;
attr DWD forecastDays 7&lt;br /&gt;
attr DWD forecastProperties SunUp, SunRise, SunSet, Rad1h, R101, RR1c, TTT, Tx, Tn, Tg, DD, FX1, RR6c, R600, RRhc, Rh00, ww, wwd, Neff&lt;br /&gt;
attr DWD forecastRefresh 1&lt;br /&gt;
attr DWD forecastResolution 1&lt;br /&gt;
attr DWD forecastStation 10418&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 fc_description  -(state fc_time)&lt;br /&gt;
attr DWD verbose 2&lt;br /&gt;
&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;
defmod InverterDummy dummy&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;
defmod 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 feedinPrice 0.08&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 powerCost 0.25&lt;br /&gt;
attr SMA_Energymeter room 015_Zaehler,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;
defmod 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;
attr BatteryDummy userReadings total_pac, power_out, power_in, chargestatus, bat_rated_capacity, bat_loadtotal, bat_unloadtotal&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;
defmod N.PV.TotalConsumption.Dum.Energy notify SMA_Energymeter:Saldo_Wirkleistung:.* {\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung_2 Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&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;MB_USRW610_004&amp;quot;,&amp;quot;Power_Sum__W&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;
fhem &amp;quot;setreading InverterDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(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;
#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;
 # Batterie-total_pac  InverterDummy\&lt;br /&gt;
my $wert7 = sprintf(&amp;quot;%.3f&amp;quot;,((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy bat_rated_capacity &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert7));;\&lt;br /&gt;
 # möglicher Aufruf einer Batterie-Bebladung-Routine....SMABatteryChargewithTibber();;\&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;
defmod Forecast SolarForecast&lt;br /&gt;
attr Forecast DbLogExclude .*&lt;br /&gt;
attr Forecast DbLogInclude Current_BatCharge999&lt;br /&gt;
attr Forecast affectBatteryPreferredCharge 30&lt;br /&gt;
attr Forecast affectConsForecastLastDays 31&lt;br /&gt;
attr Forecast affect70percentRule 0&lt;br /&gt;
attr Forecast comment &amp;quot;wget -qO ./FHEM/76_SolarForecast.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/76_SolarForecast.pm&amp;quot;\&lt;br /&gt;
&amp;quot;wget -qO ./FHEM/55_DWD_OpenData.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/55_DWD_OpenData.pm&amp;quot;\&lt;br /&gt;
&amp;quot;13.01.2025 mit der Version 76_SolarForecast.pm:v1.43.2-s29518/2025-01-12&amp;quot;&lt;br /&gt;
attr Forecast graphicHeaderOwnspec PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal Verbrauch&amp;amp;nbsp;;bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast  Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest FCU-Erzeugung&amp;amp;nbsp;;:Current_PP01\&lt;br /&gt;
attr Forecast consumer01 FBDECT_fbahahttp_11657_0127183 icon=scene_washing_machine@orange type=washingmachine power=10 swstate:state notbefore=09 notafter=20 pcurr=power:W:3 etotal=energy:Wh interruptable=1 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer02 FBDECT_fbahahttp_E8_DF_70_07_3E_57 icon=light_floor_lamp@orange type=other power=15 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer03 FBDECT_fbahahttp_E8_DF_70_07_42_0B icon=raspberrypi@orange type=other power=8 swstate:state pcurr=power:W:1 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer04 FBDECT_fbahahttp_11657_0067275 icon=springbrunnen_icon@orange type=other power=50 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer05 FBDECT_fbahahttp_34_31_C4_D4_31_37 icon=sani_domestic_waterworks@orange type=other power=10 swstate:state pcurr=power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer06 tuya_local_bf5037060f450bdbd4rl0q icon=scene_clothes_dryer@orange type=dryer power=10 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer07 tuya_local_bfac44fb487476efd1vhdu icon=weather_sunset@orange type=noSchedule power=5 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumerControl adviceIcon=light_light_dim_100@gold&lt;br /&gt;
attr Forecast consumerControl showLegend=icon_top&lt;br /&gt;
attr Forecast consumerControl detailLink=1&lt;br /&gt;
attr Forecast ctrlAIdataStorageDuration 1825&lt;br /&gt;
attr Forecast ctrlAIshiftTrainStart 2&lt;br /&gt;
attr Forecast ctrlBatSocManagement01 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlBatSocManagement02 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlDebug none&lt;br /&gt;
attr Forecast plantControl genPVdeviation=continuously&lt;br /&gt;
attr Forecast plantControl cycleInterval=15&lt;br /&gt;
attr Forecast ctrlNextDayForecastReadings 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24&lt;br /&gt;
attr Forecast ctrlNextHoursSoCForecastReadings 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23&lt;br /&gt;
attr Forecast ctrlSpecialReadings BatPowerIn_Sum,BatPowerOut_Sum,SunHours_Remain,SunMinutes_Remain,allStringsFullfilled,conForecastTillNextSunrise,currentAPIinterval,currentRunMtsConsumer_01,currentRunMtsConsumer_02,currentRunMtsConsumer_03,currentRunMtsConsumer_04,currentRunMtsConsumer_05,currentRunMtsConsumer_06,currentRunMtsConsumer_07,dayAfterTomorrowPVforecast,daysUntilBatteryCare_01,daysUntilBatteryCare_02,lastretrieval_time,lastretrieval_timestamp,response_message,runTimeAvgDayConsumer_01,runTimeAvgDayConsumer_02,runTimeAvgDayConsumer_03,runTimeAvgDayConsumer_04,runTimeAvgDayConsumer_05,runTimeAvgDayConsumer_06,runTimeAvgDayConsumer_07,runTimeCentralTask,runTimeLastAPIAnswer,runTimeLastAPIProc,runTimeTrainAI,todayBatIn_01,todayBatIn_02,todayBatOut_01,todayBatOut_02,todayConForecastTillSunset,todayConsumptionForecast,todayDoneAPIcalls,todayDoneAPIrequests,todayGridConsumption,todayGridFeedIn,todayMaxAPIcalls,todayRemainingAPIcalls,todayRemainingAPIrequests&lt;br /&gt;
attr Forecast disable 0&lt;br /&gt;
attr Forecast event-min-interval .*:1800&lt;br /&gt;
attr Forecast event-on-change-reading .*&lt;br /&gt;
attr Forecast flowGraphicControl animate=1 consumerdist=80 h2consumerdist=50 shiftx=0  shifty=0 showconsumer=1 showconsumerdummy=1 showconsumerpower=1 showconsumerremaintime=0 size=400 strokewidth=12&lt;br /&gt;
attr Forecast graphicBeam1Color 3C14FF&lt;br /&gt;
attr Forecast graphicBeam1Content pvReal&lt;br /&gt;
attr Forecast graphicBeam2Color 19FF29&lt;br /&gt;
attr Forecast graphicBeam2Content pvForecast&lt;br /&gt;
attr Forecast graphicBeam3Color D60924&lt;br /&gt;
attr Forecast graphicBeam3Content batsocforecast_02&lt;br /&gt;
attr Forecast graphicBeam3FontColor FFFF0D&lt;br /&gt;
attr Forecast graphicBeam4Color FFFF1F&lt;br /&gt;
attr Forecast graphicBeam4Content batsocforecast_01&lt;br /&gt;
attr Forecast graphicBeam4FontColor 000000&lt;br /&gt;
attr Forecast graphicBeamHeightLevel1 200&lt;br /&gt;
attr Forecast graphicBeamHeightLevel2 200&lt;br /&gt;
attr Forecast graphicHeaderDetail all&lt;br /&gt;
attr Forecast graphicHeaderOwnspec #PV\&lt;br /&gt;
PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal\&lt;br /&gt;
PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast\&lt;br /&gt;
PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast\&lt;br /&gt;
:\&lt;br /&gt;
#\&lt;br /&gt;
AutarkyRate:Current_AutarkyRate\&lt;br /&gt;
Überschuss:Current_Surplus\&lt;br /&gt;
aktueller&amp;amp;nbsp;;Netzbezug:Current_GridConsumption\&lt;br /&gt;
:\&lt;br /&gt;
#Verbrauch\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenuntergang:special_todayConForecastTillSunset\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie01\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_01\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_01\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_01\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_01\&lt;br /&gt;
#Batterie01_tmp\&lt;br /&gt;
Current_PowerBatIn_01:Current_PowerBatIn_01\&lt;br /&gt;
Current_PowerBatOut_01:Current_PowerBatOut_01\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie02\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_02\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_02\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_02\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_02\&lt;br /&gt;
#Batterie02_tmp\&lt;br /&gt;
Current_PowerBatIn_02:Current_PowerBatIn_02\&lt;br /&gt;
Current_PowerBatOut_02:Current_PowerBatOut_02\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Settings\&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto \&lt;br /&gt;
Wetter:graphicShowWeather\&lt;br /&gt;
History:graphicHistoryHour\&lt;br /&gt;
ShowNight:graphicShowNight\&lt;br /&gt;
Debug:ctrlDebug\&lt;br /&gt;
FCU-Modus:FCU-Betriebsmodus@FCU&lt;br /&gt;
attr Forecast graphicHistoryHour 4&lt;br /&gt;
attr Forecast graphicHourCount 24&lt;br /&gt;
attr Forecast graphicLayoutType double&lt;br /&gt;
attr Forecast graphicShowDiff top&lt;br /&gt;
attr Forecast graphicShowNight 1&lt;br /&gt;
attr Forecast graphicShowWeather 1&lt;br /&gt;
attr Forecast group Energy Meter&lt;br /&gt;
attr Forecast room 020_PV,Energie&lt;br /&gt;
attr Forecast setupBatteryDev01 SBS25 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupBatteryDev02 SBS25_2 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupInverterDev01 SB25 pv=total_pac:kW etotal=etotal:kWh capacity=2500 strings=GarageSE limit=70&lt;br /&gt;
attr Forecast setupInverterDev02 SB30 pv=total_pac:kW etotal=etotal:kWh capacity=3000 strings=GarageNW,HausNW limit=70&lt;br /&gt;
attr Forecast setupInverterDev03 SB40 pv=total_pac:kW etotal=etotal:kWh capacity=4000 strings=HausSE1,HausSE2,HausSW limit=70&lt;br /&gt;
attr Forecast setupInverterStrings GarageSE,GarageNW,HausNW,HausSW,HausSE1,HausSE2&lt;br /&gt;
attr Forecast setupMeterDev SMA_Energymeter gcon=Bezug_Wirkleistung:W contotal=Bezug_Wirkleistung_Zaehler:kWh gfeedin=Einspeisung_Wirkleistung:W feedtotal=Einspeisung_Wirkleistung_Zaehler:kWh conprice=0.25:€ feedprice=0.08123:€&lt;br /&gt;
attr Forecast setupOtherProducer01 icon=Heizung_FCU_green@red MB_USRW610_004 pcurr=Power_L1__W:W etotal=Energy_L1_import__kWh:kWh&lt;br /&gt;
attr Forecast setupRadiationAPI DWD&lt;br /&gt;
attr Forecast setupStringPeak GarageSE=2.75 GarageNW=3.200 HausNW=2.230 HausSW=2.230 HausSE1=2.200 HausSE2=2.200&lt;br /&gt;
attr Forecast setupWeatherDev1 DWD&lt;br /&gt;
attr Forecast stateFormat Current_PV&lt;br /&gt;
attr Forecast userReadings Current_BatCharge999 {((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))) / ( (ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0) * 1000)  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0)*1000))*100}&lt;br /&gt;
attr Forecast verbose 2&lt;br /&gt;
&lt;br /&gt;
setstate Forecast 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .FCU_FCU-Betriebsmodus 2&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_ctrlDebug none&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicHistoryHour 4&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowNight 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowWeather 1&lt;br /&gt;
setstate Forecast 2025-01-13 08:24:25 .associatedWith SMA_Energymeter FBDECT_fbahahttp_11657_0127183 FBDECT_fbahahttp_E8_DF_70_07_3E_57 FBDECT_fbahahttp_E8_DF_70_07_42_0B FBDECT_fbahahttp_11657_0067275 FBDECT_fbahahttp_34_31_C4_D4_31_37 tuya_local_bf5037060f450bdbd4rl0q tuya_local_bfac44fb487476efd1vhdu SBS25 SBS25_2 SB25 SB30 SB40 DWD MB_USRW610_004&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .lastupdateForecastValues 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .pvCorrectionFactor_Auto_Soll on_complex_ai&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .signaldone_01 done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .signaldone_02 done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .signaldone_03 done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .signaldone_04 done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .signaldone_05 done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .signaldone_06 done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .signaldone_07 done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .signaldone_08 done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .signaldone_09 done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .signaldone_10 done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .signaldone_11 done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .signaldone_12 done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .signaldone_13 done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .signaldone_14 done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .signaldone_15 done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .signaldone_16 done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .signaldone_17 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .signaldone_18 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_01 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_02 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_01 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_02 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_AutarkyRate 83 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 Current_BatCharge999 10&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_01 12 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_02 8 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Consumption 626 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridConsumption 2 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridFeedIn 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PP_01 746.0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PV 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_01 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_02 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_01 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_02 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumption 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumptionRate 0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Surplus 120 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourGridconsumptionReal 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_ConsumptionForecast 2944 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayConsumptionForecast 3609 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_01 272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PPreal_01 748 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PPreal_01 787 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_01 271 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PPreal_01 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PPreal_01 745 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_01 267 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PPreal_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_01 255 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PPreal_01 752 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_01 226 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_01 50 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PPreal_01 681 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_02 233 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_01 845 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridConsumption 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_01 37 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_02 90 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_01 351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_02 188 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridConsumption 447 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVforecast 127 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridConsumption 1650 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVforecast 478 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVreal 26 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridConsumption 513 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVforecast 868 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVreal 97 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridConsumption 576 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVforecast 1157 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVreal 320 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_01 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_02 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridConsumption 1272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridFeedIn 7 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVforecast 1238 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVreal 945 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_01 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_02 53 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridConsumption 955 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridFeedIn 31 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PPreal_01 562 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVforecast 1168 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVreal 1410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_01 703 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_02 500 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_01 22 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_02 18 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridConsumption 32 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridFeedIn 71 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PPreal_01 777 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVreal 1416 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_01 296 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_02 70 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_01 74 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_02 258 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridConsumption 13 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridFeedIn 17 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PPreal_01 732 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVforecast 880 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVreal 1051 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_01 47 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_02 126 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_01 102 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_02 75 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridConsumption 15 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridFeedIn 23 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PPreal_01 771 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVforecast 117 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVreal 86 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_02 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_02 67 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridConsumption 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridFeedIn 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PPreal_01 723 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_01 349 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_02 124 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_01 73 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_02 450 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridConsumption 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridFeedIn 6 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PPreal_01 671 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecastTime 2025-01-13 14:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVdeviation 30.17 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVforecast 7663 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVreal 5351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunRise 08:28&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunSet 16:46&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_ConsumptionForecast 17043 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour05_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour06_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour07_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour08_PVforecast 10 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour09_PVforecast 161 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour10_PVforecast 275 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour11_PVforecast 532 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour12_PVforecast 730 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour13_PVforecast 1252 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour14_PVforecast 818 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour15_PVforecast 1465 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour16_PVforecast 303 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour17_PVforecast 20 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour18_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour19_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour20_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour21_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour22_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour23_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour24_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_PVforecast 5566 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunRise 08:27&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunSet 16:47&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01 name=&#039;_Waschmaschine&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_start 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_stop 14.01.2025 11:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02 name=&#039;_Esszimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_currentPower 15.3 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03 name=&#039;_FCU&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_currentPower 7.15 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04 name=&#039;_Brunnen&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05 name=&#039;_Zisterne&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06 name=&#039;SW Trockner&#039; state=&#039;unknown&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_stop 14.01.2025 08:30:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07 name=&#039;SW Urlaubslicht-Wohnzimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;noSchedule&#039; info=&#039;von extern umgeschaltet&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 nextCycletime 18:54:09&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 pvCorrectionFactor_10 0.53 (automatic - old factor: 1.00, Sun Alt range: 5, Cloud range: 75, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 pvCorrectionFactor_11 0.56 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 70, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 pvCorrectionFactor_12 0.64 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 pvCorrectionFactor_13 0.88 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 pvCorrectionFactor_14 1.10 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 50, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 pvCorrectionFactor_15 1.01 (automatic - old factor: 1.06, Sun Alt range: 15, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 pvCorrectionFactor_16 1.09 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 45, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 pvCorrectionFactor_17 0.28 (automatic - old factor: 0.52, Sun Alt range: 0, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 pvCorrectionFactor_Auto on_complex_ai&lt;br /&gt;
setstate Forecast 2024-10-30 19:42:19 setupStringAzimuth GarageSE=-55 GarageNW=125 HausNW=125 HausSW=35 HausSE1=-55 HausSE2=-55&lt;br /&gt;
setstate Forecast 2024-10-30 19:37:38 setupStringDeclination GarageSE=40 GarageNW=40 HausNW=50 HausSW=50 HausSE1=50 HausSE2=50&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerIn_Sum 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerOut_Sum 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunHours_Remain 0.00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunMinutes_Remain 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_allStringsFullfilled 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_conForecastTillNextSunrise 9467 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentAPIinterval 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_01 132 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_02 184 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_03 329512 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_04 200 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_05 27 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_06 193 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_07 106 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_dayAfterTomorrowPVforecast 7344 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_01 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_02 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_time 2025-01-13 18:53:54&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_timestamp 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_response_message success&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_01 545.94 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_02 382.10 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_03 1430.13 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_04 262.05 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_05 28.80 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_06 622.63 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_07 276.51 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeCentralTask 0.3744&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIAnswer -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIProc -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeTrainAI 1.2529&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_01 3683.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_02 1617.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_01 2287.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_02 1057.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConForecastTillSunset 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 special_todayConsumptionForecast_01 509 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 special_todayConsumptionForecast_02 499 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 special_todayConsumptionForecast_03 501 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 special_todayConsumptionForecast_04 511 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 special_todayConsumptionForecast_05 503 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 special_todayConsumptionForecast_06 495 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 special_todayConsumptionForecast_07 504 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 special_todayConsumptionForecast_08 561 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 special_todayConsumptionForecast_09 768 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 special_todayConsumptionForecast_10 783 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 special_todayConsumptionForecast_11 692 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 special_todayConsumptionForecast_12 791 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 special_todayConsumptionForecast_13 910 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 special_todayConsumptionForecast_14 1022 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 special_todayConsumptionForecast_15 965 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 special_todayConsumptionForecast_16 812 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 special_todayConsumptionForecast_17 884 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 special_todayConsumptionForecast_18 928 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_19 874 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_20 763 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_21 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_22 765 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_23 643 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_24 601 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIcalls 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIrequests 4532&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridConsumption 5500.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridFeedIn 178.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayMaxAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIrequests n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 state updated&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So sollte es dann als Ergebnis aussehen:&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13.png|zentriert|mini|Ergebnis nach kompletter Einrichtung]]&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13 Teil II.png|alternativtext=Unterer Teil der Anzeige|zentriert|mini]]&lt;br /&gt;
&lt;br /&gt;
== Praxisbeispiele und Lösungsansätze für Steuerungen ==&lt;br /&gt;
=== Fallstudie: Trockner darf pausiert werden, wenn nicht genug PV-Überschuss vorhanden ist, soll aber nach spätestens X Stunden fertig sein ===&lt;br /&gt;
Für diese Aufgabenstellung sind mehrere Schlüssel essentiell wichtig, &#039;&#039;&#039;power&#039;&#039;&#039;, &#039;&#039;&#039;mintime&#039;&#039;&#039;, &#039;&#039;&#039;mode&#039;&#039;&#039; und &#039;&#039;&#039;interruptable&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Die Bedingung, dass der Trockner nach spätestens X Stunden fertig sein soll, steht in einem Widerspruch zu der Möglichkeit den Trockner bei zu wenig PV-Überschuss unterbrechen zu können. Im Extremfall könnte nach dem Start die gesamte Planungszeit ungenügender Überschuss vorliegen und der Trockner nicht arbeiten. Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; (in Minuten) wird nun wie folgt angesetzt:&lt;br /&gt;
&lt;br /&gt;
 mintime = 2,5 x &amp;lt;gewöhnliche Betriebszeit für einen Trockengang (mneed, z.B. 120)&amp;gt; = 300 Minuten&lt;br /&gt;
&lt;br /&gt;
Das bedeutet, der Trockner wird nach 300 Minuten Laufzeit abgeschaltet werden bzw. vom Netz getrennt. Der Trockenvorgang wird natürlich bereits nach 120 Minuten beendet sein, sofern nach Start keine Unterbrechnung des Vorganges erfolgte. Wurde der Vorgang unterbrochen, soll der Trockner innerhalb &lt;br /&gt;
&lt;br /&gt;
 X+120 bis X+300 &lt;br /&gt;
&lt;br /&gt;
fertig sein. &lt;br /&gt;
&lt;br /&gt;
Demnach ist die ausgeführte Laufzeit des Trockners permanent zu überwachen, zu summieren (rtsum) und die notwendige Restzeit (mneed - rtsum) mit der noch verbleibenden Restzeit (mrest) bis zur geplanten Abschaltung des Consumers zu vergleichen. Ist der Consumer gestartet, wird die Laufzeit in der pvHistory für jede Stunde des Tages im Schlüssel &#039;&#039;minutescsmXX&#039;&#039; (XX = Consumernummer) aufgezeichnet und kann darüber ausgewertet werden. Somit ist:&lt;br /&gt;
&lt;br /&gt;
 msum = for (01 .. 24) {Summe von minutescsmXX} des aktuellen Tages&lt;br /&gt;
&lt;br /&gt;
Solange die Bedingung &lt;br /&gt;
&lt;br /&gt;
 mrest &amp;gt;= (mneed - msum)&lt;br /&gt;
&lt;br /&gt;
zutrifft, darf der Trockner unterbrochen werden, anderenfalls darf er nicht mehr unterbrochen werden da die Restzeit evtl. nicht ausreichen könnte um den Vorgang abzuschließen. Für die Planung des Trockners wird der Consumer wie gewöhnlich nach dem Bedarf im Modul registriert. Für die Steuerung der Unterbrechbarkeit wird noch ein Code erstellt, welcher im Trockner-Device &#039;&#039;Dryerdev&#039;&#039; das Reading &#039;&#039;SF_Int&#039;&#039; zur Unterbrechnungssteuerung verwaltet. Dieses Reading wird dem Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; übergeben. Für das Beispiel wird der Consumer &#039;07&#039; verwendet, es kann natürlich jede andere freie Nummer verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Dryerdev:Trockner&lt;br /&gt;
                        icon=scene_cloves_dryer type=dryer power=2000 mode=must mintime=300 &lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic asynchron=1&lt;br /&gt;
                        interruptable=Dryerdev:SF_Int:1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Kombination &#039;&#039;&#039;auto=automatic&#039;&#039;&#039; eröffnet die Möglickeit, in der Consumer-Legende den Trockner-Start zusätzlich manuell freizugeben oder zu verbieten. &lt;br /&gt;
&lt;br /&gt;
Im nachfolgenden Code werden modulinterne Subroutinen verwendet. Diese sind inklusive dem Paket &#039;&#039;FHEM::SolarForecast::&#039;&#039; anzugeben. Die erstellte Subroutine wird in die 99_mySolarForecastUtils.pm eingefügt. Die Datei 99_mySolarForecastUtils.pm wird vorher von 99_myUtils.pm kopiert und enthält für die Übersichtlichkeit nur Routinen für SolarForecast.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Trocknersteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub dryControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # gewöhlich benötigte Zeit für &lt;br /&gt;
                                                                                  # einen Trockengang, z.B. 120 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $dryer     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename des Trockners&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Trockner-Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit des Trockners&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      my $dhash = $defs{$dryer};&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 1, 0);                        # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 0, 0);                        # keine Interrupt-Freigabe&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die gewöhnliche Laufzeit des Trockners für einen Trockenvorgang (120 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::dryControl ($name, &#039;07&#039;, 120);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Fallstudie: Umwälzpumpe Pool soll X Stunden am Tag laufen. Ist kein PV-Überschuß vorhanden, müssen die X Stunden/Tag trotzdem erreicht werden ===&lt;br /&gt;
&lt;br /&gt;
Die Vorgehensweise ähnelt der Fallstudie zuvor. Verändernd kommt hinzu, dass der Planungszeitraum bewusst sehr lang angesetzt wird mit der Option, den Zyklus des Consumers vorfristig zu beenden sobald die Laufzeit von X Stunden am Tag erreicht ist. &lt;br /&gt;
Im folgenden Beispiel soll die Pumpe 5 Stunden am Tag (300 Minuten) laufen und dabei mögliche PV-Überschüsse ausnutzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Pump:Zirkulationspumpe&lt;br /&gt;
                        icon=sani_pump type=other power=50 mode=must mintime=780 notafter=09&lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic &lt;br /&gt;
                        interruptable=1 swoffcond=Pump:SF_Abort:1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit dieser Registrierung wird die Pumpe ca. 09 Uhr täglich starten. Wenn kein bzw. ungenügender PV-Überschuß vorhanden ist, erfolgt eine Unterbrechung nach dem Start. Ist genügender PV-Überschuß (wieder) vorhanden, erfolgt keine Unterbrechnung (mehr). Zusätzlich wird über den Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; eine vorfristige Beendigung veranlasst, sobald die gewünschte Tageslaufzeit erreicht ist.&lt;br /&gt;
&lt;br /&gt;
Zur Verwaltung des Schlüssels &#039;&#039;interruptable&#039;&#039; und des Readings &#039;&#039;SF_Abort&#039;&#039; verwenden wir eine leicht veränderte Subroutine aus dem vorhergehenden Fallbeispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Pumpensteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub pumpControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # Soll-Pumpenzeit, z.B. 300 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $pump      = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename der Pumpe&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;);&lt;br /&gt;
  my $intbl     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;interruptable&#039;, 1); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
  my $dhash     = $defs{$pump};&lt;br /&gt;
&lt;br /&gt;
  readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 0, 0);                                # default keine Zyklusbeendigung&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Pumpen Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit der Pumpe&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
     &lt;br /&gt;
      if ($msum &amp;gt;= $mneed) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 1, 0);                       # vorfristige Zyklusbeendigung&lt;br /&gt;
          return;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=1&amp;quot;) if(!$intbl);  # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=0&amp;quot;) if($intbl);   # keine Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Befehl &#039;&#039;attrKeyVal&#039;&#039; setzt den Schlüssel &#039;&#039;interruptable&#039;&#039; im Attribut &#039;&#039;consumer07&#039;&#039; dynamisch. Diese Strukturänderung wird automatisch im System gespeichert, sofern &#039;&#039;global-&amp;gt;autosave=1&#039;&#039; gesetzt ist. Diese Einstellung ist der FHEM default.  &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die Mindestlaufzeit der Umwälzpumpe (300 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::pumpControl ($name, &#039;07&#039;, 300);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamische Ladestromsteuerung eines Victron MultiPlus II Chargers mit Pylontech Batterie ===&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;
&lt;br /&gt;
 set &amp;lt;Device&amp;gt; MaxChargeCurrent &amp;lt;Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
eingestellt bzw. variiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Modul bietet dem Nutzer die Möglichkeit in dem Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltene Code wird am Ende jedes Zyklus (siehe Attribut &#039;&#039;plantControl-&amp;gt;cycleInterval&#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;
&lt;br /&gt;
&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 $mppt1   = &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common&#039;;              # SmartLoader Device&lt;br /&gt;
  my $maxcspc = 105;                        # max. Ladesollstrom (A) nominal&lt;br /&gt;
  my $spcorr  = 0.9;                        # Korrekturfaktor Überschuss 90%&lt;br /&gt;
  my $sch     = 0.25;                       # Verkürzungsfaktor Zeit bis Vollladung vor Sunset             &lt;br /&gt;
  &lt;br /&gt;
  my $cclvl0  = 15;                         # Ladestrom Level 0 max. 5  A (240 W) pro WR  (720  W)&lt;br /&gt;
  my $cclvl1  = 27;                         # Ladestrom Level 1 max. 9  A (432 W) pro WR  (1296 W)&lt;br /&gt;
  my $cclvl2  = 54;                         # Ladestrom Level 2 max. 18 A (864 W) pro WR  (2592 W)&lt;br /&gt;
  my $cclvl3  = 81;                         # Ladestrom Level 3 max. 27 A (1296 W) pro WR (3888 W)&lt;br /&gt;
  ###############&lt;br /&gt;
  &lt;br /&gt;
  my $cofc   = ReadingsNum ($name,  &#039;special_todayConForecastTillSunset&#039;, 0);&lt;br /&gt;
  my $pvfc   = ReadingsNum ($name,  &#039;RestOfDayPVforecast&#039;, 0);&lt;br /&gt;
  my $cpv    = ReadingsNum ($name,  &#039;Current_PV&#039;,          0);&lt;br /&gt;
  my $mppt1c = ReadingsNum ($mppt1, &#039;DC_0_Current_value&#039;,  0);             # Load I MPPT1 (max. 44 A)&lt;br /&gt;
  my $ssts   = CurrentVal  ($hash,  &#039;sunsetTodayTs&#039;,        0);&lt;br /&gt;
  my $srts   = CurrentVal  ($hash,  &#039;sunriseTodayTs&#039;,       0);&lt;br /&gt;
  my $sdiff  = ($ssts - $srts) / 3600;                                     # Sonnengang heute in h &lt;br /&gt;
  &lt;br /&gt;
  my $solh   = ReadingsNum ($name, &#039;special_SunHours_Remain&#039;, 0);          # h bis SunSet&lt;br /&gt;
  $solh      = $solh - ($sdiff * $sch);                                    # h bis SunSet - X&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;              # Ah Bat bis SOC&lt;br /&gt;
  $ahrem     = sprintf &amp;quot;%.0f&amp;quot;, $ahrem;&lt;br /&gt;
  &lt;br /&gt;
  my $fcdiff = ($pvfc - $cofc) * $spcorr;     # Korrektur d. noch prognostizierten Überschussenergie &lt;br /&gt;
  $fcdiff    = $fcdiff &amp;lt; 0 ? 0 : $fcdiff;     # Wh&lt;br /&gt;
  &lt;br /&gt;
  my $loadcur = $maxcspc;&lt;br /&gt;
  &lt;br /&gt;
  if ($cpv &amp;amp;&amp;amp; $solh &amp;amp;&amp;amp; $ahrem &amp;amp;&amp;amp; $fcdiff &amp;gt; $ahrem) {  # Ladeanforderung und Überschuss übersteigt &lt;br /&gt;
                                                      # Lademenge&lt;br /&gt;
      my $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($ahrem / $solh);    # A = Ah / h -&amp;gt; A Soll Schätzung&lt;br /&gt;
&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Battery charging process should be completed }.&lt;br /&gt;
                      qq{in &amp;gt;$solh&amp;lt; hours});&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; raw Target charging current: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($cspc - $mppt1c);      # SmartLoader IST berücksichtigen&lt;br /&gt;
	  &lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Charge Current minus MPPT load Current &amp;gt;$mppt1c&amp;lt;: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $loadcur = $cspc &amp;lt;= 0       ? 0       :     # nur MPPT Ladung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl0 ? $cclvl0 :     # Übergangsbereich&lt;br /&gt;
                 $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;
	  Log3 ($name, 3, qq{$name - userFn -&amp;gt; MaxChargeCurrent calculated: $loadcur});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent&#039;,       $loadcur.&#039; A&#039;,          1);&lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_HoursUntilChargeFinish&#039;, sprintf (&amp;quot;%.2f&amp;quot;,$solh), 1);&lt;br /&gt;
  CommandSet           (undef, &amp;quot;$vebus MaxChargeCurrent $loadcur&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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. 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;special_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;special_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;Verkürzungsfaktor Zeit bis Vollladung vor Sunset&#039;&#039;) reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche mindest Ladestromstärke ermittelt.&lt;br /&gt;
&lt;br /&gt;
&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 auch während der MQTT Intergration 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;
=== Poolheizung in Abhängigkeit von vorhandenem Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren) ===&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;consumer01&#039;&#039; wird beispielhaft wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr Forecast consumer01 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;&lt;br /&gt;
&lt;br /&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. &lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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, einen 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 Überschuss 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;. &lt;br /&gt;
&lt;br /&gt;
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;
=== PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) ===&lt;br /&gt;
[[Datei:Screenshot 2025-08-04 104835.png|mini|Darstellung der PV-Vorhersage in evcc auf Basis der SolarForecast-Daten]]&lt;br /&gt;
[https://evcc.io evcc] ist ein Energie-Management-System, mit dem u.a. Überschussladen von Elektroautos möglich ist. Hier ist beschreiben, wie die PV-Vorhersage von SolarForecast per API an evcc gesendet wird.&lt;br /&gt;
&lt;br /&gt;
Lege im SolarForecast-Device ein User-Reading mit dem Namen forecast_json an. Es wandelt die Forecast-Werte in JSON und ins UTC-Zeitformat um, so dass evcc die Daten verwenden kann:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
forecast_json {&lt;br /&gt;
&lt;br /&gt;
    use strict;&lt;br /&gt;
    use warnings;&lt;br /&gt;
    use JSON;&lt;br /&gt;
    use DateTime;&lt;br /&gt;
    use DateTime::Format::Strptime;&lt;br /&gt;
&lt;br /&gt;
    my $hour = 0;&lt;br /&gt;
    my @output;&lt;br /&gt;
&lt;br /&gt;
    # Parser für Datum mit CET/CEST&lt;br /&gt;
    my $parser = DateTime::Format::Strptime-&amp;gt;new(&lt;br /&gt;
        pattern   =&amp;gt; &#039;%Y-%m-%d %H:%M:%S&#039;,&lt;br /&gt;
        time_zone =&amp;gt; &#039;Europe/Berlin&#039;,&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    # Alle NextHour-Daten durchsuchen&lt;br /&gt;
    while ($hour &amp;lt; 100) {&lt;br /&gt;
        my $hour_str = sprintf(&#039;NextHour%02d&#039;, $hour);&lt;br /&gt;
        my $start_str = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;starttime&#039;, &#039;na&#039;); &lt;br /&gt;
        my $pvfc = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;pvfc&#039;, &#039;na&#039;);&lt;br /&gt;
&lt;br /&gt;
        # Schleife beenden, wenn keine Werte mehr vorhanden sind&lt;br /&gt;
        last if $start_str eq &#039;na&#039; or $pvfc eq &#039;na&#039;;&lt;br /&gt;
&lt;br /&gt;
        # parse und konvertiere Zeit&lt;br /&gt;
        my $start_dt = $parser-&amp;gt;parse_datetime($start_str);&lt;br /&gt;
        my $end_dt   = $start_dt-&amp;gt;clone-&amp;gt;add(hours =&amp;gt; 1);&lt;br /&gt;
&lt;br /&gt;
        # nach UTC konvertieren&lt;br /&gt;
        $start_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
        $end_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $start_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            end   =&amp;gt; $end_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            value =&amp;gt; 0 + $pvfc,&lt;br /&gt;
        };&lt;br /&gt;
        &lt;br /&gt;
        $hour++;&lt;br /&gt;
    }  &lt;br /&gt;
&lt;br /&gt;
    # Ausgabe als JSON&lt;br /&gt;
    my $json = JSON-&amp;gt;new-&amp;gt;utf8-&amp;gt;pretty-&amp;gt;encode(\@output);&lt;br /&gt;
    return $json;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Kommunikation von FHEM zu evcc läuft über den integrierten FHEM-Webserver, der die JSON-Daten aus dem Reading forecast_json veröffentlicht. Dazu wird in FHEM eine separate Webinstanz auf einem neuen Port erstellt, die ohne [[CsrfToken-HowTo|CSFR-Token]] (Achtung, Auswirkungen auf die Sicherheit beachten!) und nur von localhost aufrufbar ist (Voraussetzung: evcc läuft auf derselben Maschine wie FHEM):&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
defmod WEBapi FHEMWEB 8089&lt;br /&gt;
attr WEBapi csrfToken none&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;In der [https://docs.evcc.io/docs/tariffs#pv-vorhersage evcc-Konfig unter tariffs] steht die Quelle für die Solar-Vorhersage. Der FHEM-Befehl {ReadingsVal(&#039;solarforecast_dev&#039;,&#039;forecast_json&#039;,&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;)} wird dazu encoded und in die uri eingetragen. Trage statt solarforecast_dev den passenden Namen des SolarForecast-Device ein.&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
solar:&lt;br /&gt;
  type: custom&lt;br /&gt;
  interval: 20m    &lt;br /&gt;
  forecast:&lt;br /&gt;
    source: http&lt;br /&gt;
    uri: http://localhost:8089/fhem?cmd=%7BReadingsVal%28%27solarforecast_dev%27%2C%27forecast_json%27%2C%27%27%29%7D&amp;amp;XHR=1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Zur Verbesserung der Sicherheit kann das neue WEBapi Device auch ein [[CsrfToken-HowTo#csrfToken festlegen|festes CSFR-Token]] verwenden. Dieses Token muss dann in der evcc-Konfiguration an die uri mittels &amp;amp;fwcsrf=&amp;lt;festes token&amp;gt; angehängt werden.&lt;br /&gt;
&lt;br /&gt;
== weiterführende Links ==&lt;br /&gt;
* Forenthema &amp;quot;{{Link2Forum|Topic=137058|LinkText=76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support}}&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;
* Photovoltaik Ingenieurbüro Junge: https://www.ing-büro-junge.de/html/photovoltaik.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung&amp;diff=40301</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=40301"/>
		<updated>2025-08-04T09:45:36Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Hinweis|Die vorliegende Wiki-Seite befindet sich im Aufbau.}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Solarprognose und Verbrauchersteuerung&lt;br /&gt;
|ModType=d&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 Prognosewerte können die SolCast API, OpenMeteo API, Forecast.Solar API, Victron VRM Portal API oder alternativ DWD Stahlungswerte-Stationen verwendet werden&lt;br /&gt;
&lt;br /&gt;
::* optionale KI Unterstützung der PV-Prognose bei Verwendung von geeigneten Solar-API&#039;s&lt;br /&gt;
&lt;br /&gt;
::* es wird sowohl die Erzeugungsprognose als auch eine Verbrauchsprognose sowie SoC Prognose (bei Batterie-Integration) erstellt&lt;br /&gt;
&lt;br /&gt;
::* Wetterdaten werden über DWD Wetter-Stationen oder verschiedene API integriert. Es können verschiedene API zur Gewinnung von Solar- und Wetterdaten kombiniert werden. &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 FHEM-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 Integration von bis zu 4 Inverter und Smartloader (DC-DC Batterieladegeräte) ist möglich&lt;br /&gt;
&lt;br /&gt;
::* eine Integration von bis zu 3 nicht PV-Energieerzeugern wie BHKW, Windrädern oder Notstromaggregaten ist möglich&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;
::* Einbindung von bis zu drei Batteriespeichersystemen&lt;br /&gt;
&lt;br /&gt;
::* Bereitstellung von Leitwerten zur optimalen Einstellung/Steuerung von Batteriespeichersystemen&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 Benutzererlebnis 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;
Das Wiki gibt allgemeingültige und teilweise sehr spezifische bzw. tiefgehende Informationen und Handlungsempfehlungen zum SolarForecast Modul. Die dargestellten Informationen beziehen sich auf den zum Zeitpunkt der Wiki-Erstellung vorhandenen Entwicklungsstand des Moduls. Durch die stetige Weiterentwicklung können sich Abweichungen zum beschriebenen Inhalt ergeben oder zur Obsoleszenz dieser Inhalte führen. &lt;br /&gt;
&lt;br /&gt;
Vergleiche deshalb die Informationen immer mit der aktuellen Befehls-Referenz zum Modul!&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Ein SolarForecast Device wird mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 define &amp;lt;Name&amp;gt; SolarForecast &lt;br /&gt;
&lt;br /&gt;
angelegt. Nach der Definition wird der User durch einen Dialog geführt, der einige unerlässliche Einstellungen abfragt und in den entsprechenden Attributen und Readings persistiert. Alle Attribute und Readings die eine Einstellung der Anlage bewirken, sind mit dem Präfix &amp;quot;setup&amp;quot; versehen. &lt;br /&gt;
&lt;br /&gt;
Die Verwendung von setup-Readings gestattet es die Anlagenparameter dynamisch im Betrieb zu verändern. So kann mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringAzimuth   bzw.&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringDeclination &lt;br /&gt;
&lt;br /&gt;
die Ausrichtung und der Neigungswinkel der PV-Module ständig angepasst werden, was zum Beispiel bei einer dem Sonnenstand nachgeführten Anlage von Bedeutung ist.&lt;br /&gt;
&lt;br /&gt;
Die abgefragten Einstellungen während des Dialoges sind ausführlich in den entsprechenden Attributen bzw. Set-Kommandos erläutert. Die benötigten Informationen sind anhängig von der gewählten Prognose-API und können im Umfang variieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 213257.png|right|thumb|400px|Anlagenprüfung über Drucktaste in der Kopfgrafik]]&lt;br /&gt;
&lt;br /&gt;
Sobald alle verlangten Einstellungen vorgenommen sind, sollte eine Anlagenprüfung mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; plantConfiguration check&lt;br /&gt;
&lt;br /&gt;
oder über die angebotene Drucktaste in der Grafik durchgeführt werden. Es wird eine Plausibilitätsprüfung vorgenommen und das Ergebnis sowie eventuelle Hinweise bzw. Fehler ausgegeben.&lt;br /&gt;
Die Prüfung kann beliebig wiederholt werden und sollte sich bei jeder Einstellungsänderung der Anlage durchgeführt werden. Dadurch wird die Wahrscheinlichkeit von fehlerhaften Einstellungen minimiert.&lt;br /&gt;
&lt;br /&gt;
Neben den grundlegenden Einstellungen können im Device weitere sekundäre Anlagenkomponenten wie Batteriesystem(e) (Attribut setupBatteryDev1 - setupBatteryDev3), weitere Wetter-Devices (Attribut setupWeatherDev1 - setupWeatherDev3) oder sonstige Erzeuger (z.B. BHKW, Winderzeugung, Notstromaggregat) integriert werden (Attribut setupOtherProducer01 - setupOtherProducer03).&lt;br /&gt;
&lt;br /&gt;
Die verlangten Parameter der Anlage werden in der Online-Hilfe umfassend beschrieben und deren Funktion erschließt sich zum größten Teil selbst. Dennoch soll nachfolgend auf einige Punkte im Zusammenhang der Einrichtung eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Hinweise zur Struktur der Attribute ===&lt;br /&gt;
&lt;br /&gt;
Durch die umfangreichen Funktionen des Moduls würde bei Nutzung der im FHEM herkömmlich vorhandenen Attributstruktur die Anzahl der benötigten Attribute extrem stark steigen und nicht sinnvoll genutzt werden können. Deshalb gibt es neben den &#039;&#039;gewöhnlichen&#039;&#039; Attributen mit einfachen Werteauswahlmöglichkeiten oder Eingaben (z.B. ctrlDebug, ctrlSpecialReadings) sogenannte &#039;&#039;zusammengesetzte&#039;&#039; Attribute, deren Inhalt durch &#039;&#039;&#039;Schlüssel=Wert Paare&#039;&#039;&#039; gebildet wird und dadurch deutlich mehr Funktionen und Informationen transportieren als ein gewöhnliches Attribut.&lt;br /&gt;
&lt;br /&gt;
Für zusammengesetzte Attribute besteht die zusätzliche Möglichkeit, gewünschte Änderungen der Schlüssel=Wert Paare selektiv vornehmen zu können, ohne das gesamte Attribut aufrufen und ändern zu müssen. Die Vorgang, der vor allem für programmtechnische Manipulationen gedacht ist, kann durch eine Set-Funktion ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; attrKeyVal &amp;lt;Attribut&amp;gt; [&amp;lt;Gerät&amp;gt;] &amp;lt;Schlüssel=Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiele für zusammengesetzte Attribute sind:&lt;br /&gt;
&lt;br /&gt;
* aiControl&lt;br /&gt;
* plantControl&lt;br /&gt;
* setup* Attribute&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktionen der Attribute werden durch einen Präfix geclustert und so inhaltlich, aber vor allem auch in der Attribute Drop-Down Liste, strukturiert dargestellt.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der &#039;&#039;&#039;Präfixe&#039;&#039;&#039; sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ai&#039;&#039;&#039; - Steuerungsfunktionen für KI (z.B. aiControl)&lt;br /&gt;
* &#039;&#039;&#039;consumer&#039;&#039;&#039; - Registrierung und Einstellungen für Verbraucher (z.B. consumer02, consumerControl)&lt;br /&gt;
* &#039;&#039;&#039;ctrl&#039;&#039;&#039; - Steuerungsfunktion allgemeiner Art (z.B. ctrlDebug, ctrlSpecialReadings, ctrlUserExitFn)&lt;br /&gt;
* &#039;&#039;&#039;flowGraphic&#039;&#039;&#039; - Einstellungen für die Energieflußgrafik (z.B. flowGraphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphic&#039;&#039;&#039; - Einstellung für die Grafik allgemein (z.B. graphicSelect, graphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphicBeam&#039;&#039;&#039; -  Einstellungen bestimmte Balkeneigenschaften in der Balkengrafik (z.B. graphicBeamHeightLevel1)&lt;br /&gt;
* &#039;&#039;&#039;plant&#039;&#039;&#039; - übergreifende Einstellungen betreffend der gesamten PV-Anlage bzw. des SolarForecast-Devices (z.B. plantControl)&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039; - Registrierung von Geräten in der Gesamtanlage und Einstellung deren Eigenschaften (Inverter, Zähler, Batterien usw.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Einrichtung der Wechselrichter mit setupInverterDevXX ===&lt;br /&gt;
&lt;br /&gt;
Mit den Attributen setupInverterDev01 bis setupInverterDevXX werden die vorhandenen Wechselrichter der Anlage registriert.&lt;br /&gt;
Das Modul unterscheidet verschiedene Wechselrichter-Typen, die sich durch ihre Arbeitsweise innerhalb der Anlage unterscheiden. Die Schlüssel=Wert Paare in den Attributen können mehrzeilig organisiert werden. Das erleichtert die Übersicht wenn viele dieser Parameter eingegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;PV-Wechselrichter: Es ist der Standard Wechselrichter in einer PV-Anlage. An ihn sind die Solarzellen bzw. Strings angeschlossen. Die zugeordneten Strings können mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ohne diese Angabe werden diesem Gerät alle definierten Strings (siehe Attribut &#039;&#039;setupInverterStrings&#039;&#039;) zugeordnet. Der Wechselrichter liefert seine Energie in das Hausnetz. Alternativ kann mit der Angabe &#039;&#039;&#039;feed=grid&#039;&#039;&#039; die Funktion des Wechselrichters geändert werden. Diese Angabe sagt aus, dass dieser Wechselrichter ausschließlich in das öffentliche Netz einspeist.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel-Setup eines PV-Wechselrichters (SMA STP):&lt;br /&gt;
&lt;br /&gt;
 STP_5000 pvIn=string_1_pdc:kW pvOut=total_pac:kW etotal=etotal:kWh capacity=5000 strings=Süddach asynchron=1 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Solar-Ladegeräte: Solar-Ladegeräte sind DC-DC Wandler und liefern die Energie der angeschlossenen Solarzellen nicht in das Wechselstromnetz, sondern laden direkt eine Batterie bzw. versorgen einen Batteriewechselrichter auf der Gleichstromseite. Die Funktion als Solar-Ladegerät wird mit &#039;&#039;&#039;feed=bat&#039;&#039;&#039; aktiviert, die relevanten Strings können ebenfalls mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ein Beispiel eines Solar-Ladegerätes ist ein Victron SmartSolar MPPT. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel für das Setup eines Solar-Ladegeräts (SmartSolar Charger MPPT):&lt;br /&gt;
&lt;br /&gt;
 MQTT2_cerboGX_c0619ab34e08_solarcharger_Common pv=Yield_Power_value:W etotal=Yield_System_value:kWh capacity=2080 strings=Schleppdach feed=bat synchron=0 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Batterie-Wechselrichter: Dieses Gerät hat keine angeschlossenen Solarzellen und arbeitet als DC-AC bzw. AC-DC Wandler zwischen einer Batterie (=Gleichstromquelle) und dem Wechselstrom-Hausnetz. Die Funktion als Batterie-Wechselrichter wird mit der Angabe &#039;&#039;&#039;strings=none&#039;&#039;&#039; aktiviert. Die Schlüssel &#039;&#039;etotal&#039;&#039; und &#039;&#039;pv&#039;&#039; können bei einem Batterie-Wechselrichter ohne zugeordnete Solarzellen nicht gesetzt werden. Ein Beispiel eines Batterie-Wechselrichter ist der Victron MultiPlus II.&lt;br /&gt;
&lt;br /&gt;
Ein Setup-Beispiel für einen Batterie-Wechselrichter (Victron MultiPlus II):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dc2ac=DC_IN:W&lt;br /&gt;
ac2dc=DC_OUT:W&lt;br /&gt;
capacity=7200&lt;br /&gt;
strings=none&lt;br /&gt;
icon=inverter@darkorange:inverter@grey&lt;br /&gt;
asynchron=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Eigenschaften des Wechselrichters werden durch eine Reihe von &amp;lt;Schlüssel=Wert&amp;gt; Paaren festgelegt. Auf einige dieser Paramter soll hier eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Ausgewählte Schlüssel=Wert Paare ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;pvIn=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvIn&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell zugeführte PV-Leistung bereitstellt. Der Schlüssel ist optional und dient in erster Linie dazu den entsprechenden Input-Wert in der Flußgrafik anzuzeigen sofern man das Attribut flowGraphicControl-&amp;gt;showGenerators=1 setzt. Dadurch ist auch der Eigenverbrauch des Inverters bzw. dessen Wandlungsverlust visuell abschätzbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pvOut=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvOut&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell erzeugte Leistung als positiven Wert liefert. Für einen PV-Wechselrichter (DC-&amp;gt;AC) oder Solar-Ladegerät (DC-&amp;gt;DC) ist es die erzeugte PV-Leistung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ac2dc=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter vom Hausnetz in Richtung Batterie (AC-&amp;gt;DC) wandelt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;dc2ac=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter aus einer Gleichstromquelle, d.h. einer Batterie oder einem Solar-Ladegerät, in Richtung des Hausnetzes (AC) wandelt . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;capacity=&amp;lt;max. WR-Leistung&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In dem Schlüssel &#039;&#039;capacity&#039;&#039; wird die maximal mögliche Leistung in Watt (ohne Einheit) angegeben, die der Wechselrichter lt. seinem Datenblatt in der Lage ist zu leisten. &lt;br /&gt;
&lt;br /&gt;
Die Angabe &#039;&#039;capacity&#039;&#039; hat in erster Linie die Aufgabe, die max. mögliche PV-Leistung für die Prognose zu begrenzen. Oft sind die installierten Peak-Leistungen der PV-Module höher als die angeschlossene Wechselrichter-Leistung bzw. kommt es vor, dass die KI / (korrigierte) API-Prognose über der maximal möglichen Wechselrichter-Leistung liegt. In diesen Fällen wird die Prognose auf die angegebene &#039;&#039;capacity&#039;&#039; begrenzt.&lt;br /&gt;
&lt;br /&gt;
Der Wert in diesem Schlüssel kann, wie andere Schlüssel auch, dynamisch zur Laufzeit mit dem Set-Befehl &amp;quot;[[#Hinweise zur Struktur der Attribute|set &amp;lt;Name&amp;gt; attrKeyVal ...]]&amp;quot; geändert werden. Ein Beispiel zur Anwendung ergibt sich aus folgendem Szenario.&lt;br /&gt;
&lt;br /&gt;
Gegeben sei eine Anlage die aus Solarzellen (1300 W Peak) mit einem Solar-Ladegerät mit max. 1800 W Leistung, einer Batterie und einem Batterie-Wechselrichter besteht. Die Anlage versorgt nur das Hausnetz. Eine Netzeinspeisung ist nicht vorgesehen oder nicht erlaubt.  &lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, es ist ein Tag voller Sonnenschein prognostiziert und die Batterie ist zunächst entladen. Der Haushalt verbraucht 300 W. Dann würden die PV-Module Module ihre volle Leistung von 1300 W Peak leisten können, die sich auch in der Balken-Vorhersage niederschlägt. Die Leistung wird nicht begrenzt, weil:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* sie niedriger ist als die nominale und angegebene Wechselrichter Kapazität von &#039;&#039;capacity=1800&#039;&#039;&lt;br /&gt;
* die erzeugte Energie anteilig für die Verorgung des Hauses und die Aufladung der Batterie verwendet wird&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders verhält es sich wenn nach einer gewissen Zeit die Batterie voll ist und weiterhin volle PV Leistung zur Verfügung steht. In diesem Fall würde der Haushalt seine benötigte Leistung von 300 W abnehmen, aber das Solar-Ladegerät kann keine weitere Leistung mehr abgeben, da die Batterie bereits voll geladen ist, d.h. die Anlagensteuerung würde die PV-Anlage abregeln. In diesem Fall, wenn es einen längeren Zeitraum betrifft, muß auch die Prognose PV-Energie auf 300 Wh (bzw. den durchschnittlichen Energieverbrauch des Hauses pro Stunde) begrenzt werden, damit die PV-Prognose nach unten angepasst wird und so eine realitätsnahere Prognose ermöglicht wird. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;icon=&amp;lt;aktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;][:&amp;lt;inaktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Jeder Wechselrichter wird im Standard durch ein Icon getrennt nach Tag und Nacht, d.h. je nach Aktiv-Status und Inaktiv-Status, symbolisiert.&lt;br /&gt;
&lt;br /&gt;
;Tag bzw. Aktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Sonnensymbol im Standard verwendet. Batterie-Wechselrichter verwenden ein gefärbtes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
;Nacht bzw. Inaktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Symbol der aktuellen Mondphasen im Standard verwendet. Batterie-Wechselrichter verwenden ein ausgegrautes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie angegeben, kann man für Tag und Nacht jeweils ein Wunsch-Icon, wenn gewünscht mit einer alternativen Färbung, auswählen.&lt;br /&gt;
&lt;br /&gt;
 icon=inverter@darkorange:inverter@gray&lt;br /&gt;
&lt;br /&gt;
Soll nur das Icon für die Nacht bzw. Inaktivät geändert werden, kann dies in dieser Form angegeben werden:&lt;br /&gt;
&lt;br /&gt;
 icon=:inverter@gray  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(beachte den führenden &#039;:&#039;)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Der integrierte SolarForecast Grafikbereich ==&lt;br /&gt;
Das SolarForecast Modul beinhaltet eine Grafikdarstellung die sich in mehrere Bereiche gliedert. Diese Bereiche können über Attribute ein- bzw. ausgeblendet sowie die Inhalte festgelegt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 223545.png|right|thumb|400px|Bereiche der integrierten Grafik]]&lt;br /&gt;
&lt;br /&gt;
Der nebenstehende Screenshot gibt die Gliederung der Grafikbereiche wieder:&lt;br /&gt;
&lt;br /&gt;
 1 - der Kopfbereich (Graphic Header)&lt;br /&gt;
 2 - durch den Nutzer selbst definierbarer Inhalt (Graphic Header Own Specification) als Teil des Kopfbereiches&lt;br /&gt;
 3 - Bereich Verbraucherdarstellung (Consumer Legend)&lt;br /&gt;
 4 - Bereich Balkengrafik (Beam Graphic)&lt;br /&gt;
 5 - Energieflußgrafik (Flow Graphic)&lt;br /&gt;
&lt;br /&gt;
Jeder dieser Bereiche hat spezifische Steuerungsattribute zur Anpassung des Verhaltens und ggf. des Inhalts.&lt;br /&gt;
&lt;br /&gt;
=== 1 - Der Grafik Kopfbereich ===&lt;br /&gt;
Im Kopfbereich befinden sich fest verankerte Informationen zur verwendeten Vorhersage-API sowie deren Status, Informationen zum Sonnenaufgang und Sonnenuntergang, dem aktuellen Gesamtstatus des SolarForecast Devices, Abweichungskennzahlen der PV Vorhersage sowie weitere Kennzeichen zur Verfügung.&lt;br /&gt;
Über zwei Drucktasten kann eine Anlagenprüfung durchgeführt und in den Spportthread des Moduls im FHEM Forum abgesprungen werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;graphicHeaderShow&#039;&#039;&#039; kann der gesamte Kopfbereich 1 und 2 (nutzereigener Teilbereich) ausgeblendet werden. Wird der Kopbereich ausgeblendet, ist es hilfreich mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;showLink&#039;&#039;&#039; einen Link zur Detailgrafik einzufügen da der in der Kopfgrafik integrierte Link in diesem Fall nicht mehr zur Verfügung steht. &lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;graphicHeaderDetail&#039;&#039;&#039; definiert welche Bereiche des Grafikkopfes angezeigt werden sollen. Es kann die Anzeige des Energieverbrauches, der PV-Erzeugung und der vom Nutzer selbst definierte Inhalt miteinander frei kombiniert werden.&lt;br /&gt;
&lt;br /&gt;
=== 2 - Der Bereich mit selbst definierbarem Inhalt (Graphic Header Own Specification) ===&lt;br /&gt;
In diesem Bereich kann der User beliebige Readings, Set-Kommandos und Attribute des SolarForecast Devices oder anderer Devices, die sich im gleichen FHEM-System wie das SolarForecast Device befinden, anzeigen lassen.&lt;br /&gt;
&lt;br /&gt;
Dieser Bereich ist als Tabelle mit einer beliebigen Anzahl von Zeilen organisiert. Jede Zeile beinhaltet ein Kommentarfeld und vier Nutzfelder zur Darstellung ausgewähler Werte + Label. Der Bereich bzw. der Inhalt des Bereiches wird mit dem Attribut &#039;&#039;&#039;graphicHeaderOwnspec&#039;&#039;&#039; definiert.  &lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt ein real gesetztes graphicHeaderOwnspec Attribut. Die Leerzeilen sind nicht notwendig, erhöhen aber die Lesbarkeit der Struktur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
Autarkierate:Current_AutarkyRate&lt;br /&gt;
PV&amp;amp;nbsp;übermorgen:special_dayAfterTomorrowPVforecast&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;Sunset:special_todayConForecastTillSunset&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;nächsten&amp;amp;nbsp;Sunrise:special_conForecastTillNextSunrise&lt;br /&gt;
&lt;br /&gt;
#Batterie&lt;br /&gt;
BatteryLive&amp;amp;nbsp;Status:userFn_BatLive_State&lt;br /&gt;
SoC&amp;amp;nbsp;Limit:Settings_CGwacs_BatteryLife_MinimumSocLimit_value@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SoC&amp;amp;nbsp;Ist:SOC_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
SOC&amp;amp;nbsp;Optimum:Battery_OptimumTargetSoC&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
aktuelle&amp;amp;nbsp;Ladung:userFn_Bat_EnergyState&lt;br /&gt;
Verfügbar:userFn_BatLive_UsableEnergy&lt;br /&gt;
benötigte&amp;amp;nbsp;Ladeenergie:userFn_Bat_EnergyRemain&lt;br /&gt;
Ladefreigabe:Battery_ChargeRecommended&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
akt.&amp;amp;nbsp;DC&amp;amp;nbsp;Strom:DC_Current_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
Restladezeit&amp;amp;nbsp;Ziel:userFn_Bat_HoursUntilChargeFinish&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Soll:userFn_Bat_MaxChargeCurrent_set&lt;br /&gt;
:&lt;br /&gt;
&lt;br /&gt;
#Settings&lt;br /&gt;
Batterie&amp;amp;nbsp;Lademanagement:userFn_BatteryChargeManagement&lt;br /&gt;
SoC&amp;amp;nbsp;Management:userFn_BatterySoCManagement&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Ist:MaxChargeCurrent@MQTT2_cerboGX_c0619ab34e08_vebus&lt;br /&gt;
SmartSolar&amp;lt;br&amp;gt;Einspeisung:OvervoltageFeedIn@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
MPII&amp;amp;nbsp;Limit&amp;lt;br&amp;gt;Einspeisung&amp;amp;nbsp;(W):MaxFeedInPower@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SOC&amp;amp;nbsp;Limit&amp;amp;nbsp;Soll:MinimumSocLimit@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Verbr.&amp;amp;nbsp;Neuplanung:consumerNewPlanning&lt;br /&gt;
Wetteranzeige:graphicShowWeather &lt;br /&gt;
&lt;br /&gt;
Anzeige&amp;amp;nbsp;Nachtstunden:graphicShowNight&lt;br /&gt;
hist.&amp;amp;nbsp;Stunden:graphicHistoryHour&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto&lt;br /&gt;
Victron&amp;amp;nbsp;BatteryLife&amp;lt;br&amp;gt;(1=an,10=aus):BatteryLife@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Debug:ctrlDebu&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Kommentarfeld am Beginn einer Zeile wird durch ein &#039;&#039;&#039;#&#039;&#039;&#039; gekennzeichnet. Folgt dem # ein String, wird dieser String als Kommentarangabe gewertet und in der Grafik ausgegeben. Ein leeres Kommentarfeld wird lediglich durch ein # gefolgt von einem Leerzeichen oder NL beschrieben:&lt;br /&gt;
&lt;br /&gt;
 #:&amp;lt;Text&amp;gt;  (bzw nur # für einen &#039;leeren&#039; Titel)&lt;br /&gt;
&lt;br /&gt;
Ein Netzfeld bzw. ein Datensatz wird durch die Angabe von einem Label und dem darzustellenden Wert getrennt durch &#039;:&#039; definiert:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Label&amp;gt;:&amp;lt;Reading, Attribut oder Set-Kommando&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das System erkennt selbständig, ob es sich bei der Angabe um ein Reading, Attribut oder ein Set-Kommando handelt. Sollen Readings, Set-Kommandos und Attribute anderer Devices als dem SolarForecast-Device angezeigt werden, kann dies einfach durch Zusatz von&lt;br /&gt;
&lt;br /&gt;
 ....@&amp;lt;Device-Name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
an den Parameter erreicht werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-12-05 203916.png|right|thumb|400px|Darstellung eigener Grafikbereich]]&lt;br /&gt;
Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten &amp;quot;Wh&amp;quot; bzw. &amp;quot;kWh&amp;quot; werden entsprechend der Einstellung des Attributs &#039;&#039;&#039;graphicEnergyUnit&#039;&#039;&#039; umgerechnet. Im Label sind Leerzeichen durch &amp;quot;&amp;amp;amp;nbsp;&amp;quot; einzufügen, ein Zeilenumbruch durch &amp;quot;&amp;amp;lt;br&amp;amp;gt;&amp;quot;. Ein leeres Feld in einer Zeile wird durch &amp;quot;:&amp;quot; ohne eine weitere Angabe erzeugt.&lt;br /&gt;
&lt;br /&gt;
Die nebenstehende Abbildung zeigt die reale Darstellung der oben angegebenen Struktur im Attribut graphicHeaderOwnspec.&lt;br /&gt;
&lt;br /&gt;
==== Formatierung der Inhalte im Bereich &amp;quot;Graphic Header Own Specification&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
Die angezeigten Inhalte, wie z.B. Readingwerte, des User eigenen Bereiches (Attribut graphicHeaderOwnspec) können durch Spezifikationen im Attribut &#039;&#039;&#039;graphicHeaderOwnspecValForm&#039;&#039;&#039; manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
Die Online-Hilfe zum Attribut graphicHeaderOwnspecValForm erläutert die verfügbaren Möglichkeiten und Optionen.&lt;br /&gt;
Als Beispiel hier einige mögliche Notationen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &#039;userFn_Bat_HoursUntilChargeFinish&#039;                        =&amp;gt; &amp;quot;($VALUE).&#039; Stunden&#039;&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_battery.SOC_value&#039;             =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Settings_CGwacs_BatteryLife_MinimumSocLimit_value&#039;        =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Info_MaxChargeCurrent_value&#039;                              =&amp;gt; &amp;quot;($VALUE).&#039; A&#039;&amp;quot;,&lt;br /&gt;
  &#039;DC_Current_value&#039;                                         =&amp;gt; &amp;quot;%.0f A&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common.Regulated&#039; =&amp;gt; &amp;quot;($VALUE eq &#039;1&#039; ? &#039;Ja&#039; : &#039;Nein&#039;)&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine Besonderheit besteht bei darzustellenden Werten die die Einheiten &#039;Wh&#039; bzw. &#039;kWh&#039; besitzen. Diese Werte und Einheiten werden automatisch entsprechend des gesetzten Attributes graphicEnergyUnit umgerechnet und angezeigt.&lt;br /&gt;
&lt;br /&gt;
Soll in diesen Fällen eine automatische Formatierung umgangen werden, kann eine solche Notation verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &#039;Today_PVforecast&#039; =&amp;gt; &amp;quot;(sprintf &#039;%.1f &amp;amp;amp;nbsp;kWh&#039;, ($VALUE / 1000))&amp;quot;,&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Die Angabe von &amp;amp;amp;nbsp; vor &#039;kWh&#039; verhindert die Erkennung der Einheit und so auch die automatische Umsetzung durch das Modul. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 3 - Bereich Verbraucherdarstellung (Consumer Legend) ===&lt;br /&gt;
Dieser Grafikbereich zeigt die im Modul registrierten Verbraucher sowie deren Status und weitere Informationen an. Sind die Voraussetzungen gegeben, d.h. entsprechende Schlüssel in der ConsumerXX-Attributen gesetzt, können die Verbraucher über das Paneel manuell geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Zur Anpassung der Darstellung sind verschiedene Attribute verfügbar:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;consumerControl-&amp;gt;showLegend: Definiert die Lage bzw. Darstellungsweise der Verbraucherlegende sofern Verbraucher im SolarForecast Device registriert sind.&lt;br /&gt;
;consumerControl-&amp;gt;adviceIcon: Definiert die Art der Information über die geplanten Schaltzeiten eines Verbrauchers in der Verbraucherlegende. &lt;br /&gt;
;consumerControl-&amp;gt;detailLink: Wenn gesetzt, ist der jeweilige Verbraucher klickbar um direkt zur Detailansicht des jeweiligen Geräts auf einer neuen Browserseite zu gelangen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Standard wird das Verbraucherpaneel zwischen dem Kopfbereich und der ersten Balkengrafik Ebene dargestellt. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;showLegend&#039;&#039;&#039; und Argument &#039;&#039;&#039;icon_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_bottom&#039;&#039;&#039; kann das Verbraucherpaneel an das Ende des Grafikbereiches verschoben werden.&lt;br /&gt;
Die Verwendung von &#039;&#039;&#039;text_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_top&#039;&#039;&#039; blendet die Icon-Spalte im Verbraucherpaneel aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Screenshot 2025-02-08 093239.png|Darstellung mit consumerControl showLegend=icon_top (default)&lt;br /&gt;
File:Screenshot 2025-02-08 093646.png|Darstellung mit consumerControl showLegend=icon_bottom&lt;br /&gt;
File:Screenshot 2025-02-08 152018.png|Darstellung mit consumerControl showLegend=text_top bzw. text_bottom&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 213634.png|right|thumb|400px|]]&lt;br /&gt;
Ein Mouse-Over über das Uhrensymbol zeigt nähere Informationen zum Status, den Planungsdaten, Modus und weitere Daten des Verbrauchers. Der Schalter &amp;quot;Aus/Ein&amp;quot; visualisiert den Schaltzustand des Verbrauchers und können auch zum manuellen Schalten des Verbrauchers dienen. Voraussetzung ist, dass im consumer-Attribut die Schlüssel &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; mit den Set-Kommandos zum Schalten des Verbrauchers defininiert sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 222210.png|right|thumb|300px|]]&lt;br /&gt;
Der Auto-Schieberegler zeigt einerseits den Freigabestatus zum Schalten des Verbrauchers durch das SolarForecast Modul und kann andererseits manuell betätigt werden. Der Status des Reglers korrespondiert mit dem im zugehörigen Consumer Attribut vorhandenen Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; angegebenen Reading-Wert.&lt;br /&gt;
&lt;br /&gt;
Die Verbraucherbezeichnungen in dem Paneel können in der Standardkonfiguration angeklickt werden um direkt zur Detailansicht des Devices zu gelangen. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;detailLink&#039;&#039;&#039; kann der Link zur Detailansicht deaktiviert werden.&lt;br /&gt;
&lt;br /&gt;
Das Uhrensymbol kann mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;adviceIcon&#039;&#039;&#039; geändert und/oder dessen Farbe angepasst, sowie einen Informationstext statt eines Icons angezeigt werden. &lt;br /&gt;
&lt;br /&gt;
=== 4 - Bereich Balkengrafik (Beam Graphic) ===&lt;br /&gt;
&lt;br /&gt;
Die Balkengrafik des Moduls ist ein wesentliches Visualisierungshilfsmittel. Im Auslieferungszustand existiert eine Balkengrafikebene, die &#039;&#039;&#039;Ebene 1&#039;&#039;&#039;.&lt;br /&gt;
Jede Ebene kann zwei Balkendiagramme mit auswählbaren Inhalten, Farben und einstellbarem LayoutTyp darstellen. In Ebene 1 kann die Wettervorhersage eingebettet oder, bei Vorhandensein von Batteriegeräten, die zukünftigen Zeiten mit empfohlener Ladefreigabe und SoC-Prognose eingeblendet werden. &lt;br /&gt;
&lt;br /&gt;
Welche Daten in welchen Zeiträumen dargestellt werden sollen, die Bestimmung des Layouts, die Gestaltung der Balken und einiges mehr wird durch Attribute gesteuert. Ein Teil dieser Einstellungen wird über das zusammengesetzete Attribut &#039;&#039;&#039;graphicControl-&amp;gt;&#039;Schlüssel&#039;=&#039;Wert&#039;&#039;&#039;&#039; eingestellt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;grundsätzliche Layout Definitionen&#039;&#039;&#039;&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204342.png|right|thumb|400px|Standardanzeige mit Wetter-Icons, gesetzen Attributen graphicBeam1Color=D4C177, graphicHistoryHour=11]]&lt;br /&gt;
&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingTop:Legt den Platz in px im Balkendiagramm fest, der zwischen dem oberen Rand der jeweiligen Balkengrafik Ebene und der ersten Text- oder Iconreihe dieser Ebene eingefügt wird.&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingBottom:Legt den Platz in px im Balkendiagramm fest, der zwischen der letzten Text- oder Iconreihe der jeweiligen Balkengrafik Ebene und dem unteren Rand dieser Ebene eingefügt wird. &lt;br /&gt;
;graphicControl-&amp;gt;layoutType:Layout-Optionen zur grundlegenden Gestaltung der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourStyle:Format der Zeitangabe in der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourCount:Anzahl der darzustellenden Balken/Stunden in der Balkengrafk&lt;br /&gt;
[[Datei:Screenshot Screenshot 2025-05-21 153613.png|right|thumb|400px|Erweiterung des oberen und unteren Abstandes mit den Attributen graphicControl-&amp;gt;beamPaddingTop und graphicControl-&amp;gt;beamPaddingBottom]]&lt;br /&gt;
;graphicControl-&amp;gt;energyUnit:definiert die Einheit zur Anzeige der elektrischen Leistung in der Grafik&lt;br /&gt;
;graphicHistoryHour:Anzahl der vorangegangenen Stunden die in der Balkengrafik dargestellt werden&lt;br /&gt;
;graphicControl-&amp;gt;beamWidth:Vorgabe Breite der Balken der Balkengrafik in px (sonst automatische Bestimmung) &lt;br /&gt;
;graphicBeamHeightLevel1:Multiplikator zur Festlegung der maximalen Balkenhöhe der jeweiligen Ebene (hier Ebene 1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;Definition der Inhalte und Balkeneigenschaften&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204756.png|right|thumb|400px|Wie oben aber mit gesetzem Attribut graphicShowNight=1]]&lt;br /&gt;
;graphicBeam1Color:Farbauswahl des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2Color:Farbauswahl des sekundären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam1Content:Legt den darzustellenden Inhalt des primären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam2Content:Legt den darzustellenden Inhalt des sekundären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam1FontColor:Auswahl der Schriftfarbe des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2FontColor:Auswahl der Schriftfarbe des sekundären Balkens (Ebene 1)&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 205024.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=0 (ohne Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;zusätzliche Optionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;graphicShowNight:Anzeigen oder Verbergen der Nachtstunden in der Balkengrafik&lt;br /&gt;
;graphicShowWeather:Wettericons in der Balkengrafik anzeigen/verbergen (nur Ebene 1)&lt;br /&gt;
;graphicWeatherColor:Farbe der Wetter-Icons für die Tagesstunden&lt;br /&gt;
;graphicWeatherColorNight:Farbe der Wetter-Icons für die Nachtstunden&lt;br /&gt;
;graphicShowDiff:Zusätzliche Anzeige der Differenz &amp;quot;&amp;lt;primärer Balkeninhalt&amp;gt; - &amp;lt;sekundärer Balkeninhalt&amp;gt;&amp;quot; im Kopf- oder Fußbereich der Balkengrafik&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die genaue Beschreibung und deren Optionen sind der aktuellen Online-Hilfe zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Für alle Ebenen gilt:&#039;&#039;&#039; Ein Attribut mit einer ungeraden Balkennummer (z.B. graphicBeam1Content) bezieht sich immer auf den primären Balken, ein Attribut mit einer geraden Balkennummer (z.B. graphicBeam2Content) bezieht sich immer auf den sekundären Balken.&lt;br /&gt;
&lt;br /&gt;
Die Balken haben, wie die meisten Elemente in der Balkengrafik, eine Mouse-Over Eigenschaft welche relevante Informationen zu den dargestellten Werten anzeigt. &lt;br /&gt;
&lt;br /&gt;
Sind die Nachtunden mit &#039;&#039;&#039;graphicShowNight&#039;&#039;&#039; ausgeblendet, werden keine Balken angezeigt sofern es keine Werte anzuzeigen gibt. Sollten dennoch Werte ungleich 0 anzuzeigen sein, werden diese Werte auch trotz ausgeblendeter Nachstunden angezeigt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 2 ====&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 211741.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=01 (mit Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 2&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam3Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam4Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 4 für Balken 4) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wetter-Icons können nur in Ebene 1 integriert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 2 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 2 gibt, eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgende Ebene.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 3 ====&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 3&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam5Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam6Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 5 für Balken 5) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 3 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 3 gibt, ist eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgenden Ebenen, d.h. auch auf die Ebene 3.&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 5 - Die Energieflußgrafik (Flow Graphic) ===&lt;br /&gt;
[[Datei:Screenshot 2025-02-13 213424.png|right|thumb|400px|Energieflußgrafik mit Verbrauchern in der Nachtdarstellung (Mondphasen) nach Sonnenuntergang]]&lt;br /&gt;
&lt;br /&gt;
Die Energieflußgrafik stellt die registrierten Erzeuger, Batterien, Netzzugänge und Verbraucher strukturiert in mehreren Ebenen dar:&lt;br /&gt;
&lt;br /&gt;
;Ebene 1: In der oberen Ebene befinden sich die PV-Generatoren, Smart-Loader sowie sonstigen Erzeuger &lt;br /&gt;
;Ebene 2: Die mittlere Ebene organisiert den Zugang zum öffentlichen Netz, dem Hausknoten, dem Batterieknoten sowie einem Dummy-Verbraucher (Lampensymbol) für den Energieverbrauch des Hauses der keinem der registrierten Verbraucher zugeordnet werden kann.&lt;br /&gt;
;Ebene 3: In der unteren Ebene werden die registrierten Verbraucher dargestellt. Unterhalb der Verbrauchersymbole werden der aktuelle Verbrauch (bzw. der On/Off-Zustand) sowie darunter die Restlaufzeit (Minuten) des Verbrauchers, sofern er durch das Modul geplant und gestartet wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Position und Gestaltung der Grafikelemente ist umfangreich über das Attribut &#039;&#039;&#039;flowGraphicControl&#039;&#039;&#039; und den darin verfügbaren Schlüsseln einstellbar.&lt;br /&gt;
Die Bedeutung der Schlüssel ist in der Online-Hilfe zum Attribut mit einem Beispiel beschrieben. &lt;br /&gt;
&lt;br /&gt;
Darüber hinaus enthalten die Setup-Attribute &#039;&#039;&#039;setupInverterDevXX&#039;&#039;&#039;, &#039;&#039;&#039;setupOtherProducerXX&#039;&#039;&#039; und &#039;&#039;&#039;consumerXX&#039;&#039;&#039; weitere Einstellungsmöglichkeiten um deren Icons und Färbungen in der Flußgrafik individuell einstellen zu können. So sind zum Beispiel die Icons der PV-Inverter und deren Färbung mit dem Schlüssel &#039;&#039;&#039;icon&#039;&#039;&#039; der setupInverterDevXX-Attribute in Abhängigkeit von Tag und Nacht separat definierbar.&lt;br /&gt;
&lt;br /&gt;
In den Verbraucher-Attributen ist mit dem Schlüssel &#039;&#039;&#039;noshow&#039;&#039;&#039; die Sichtbarkeit in der Flußgrafik definierbar.&lt;br /&gt;
&lt;br /&gt;
Generell steuert das Attribut &#039;&#039;&#039;graphicSelect&#039;&#039;&#039; die Ein- bzw. Ausblendung der gesamten Flußgrafik.&lt;br /&gt;
&lt;br /&gt;
== Die Verbrauchsprognose ==&lt;br /&gt;
Im Gegensatz zu der PV Prognose gibt es keine API oder andere externen Datenquellen die für die Verbrauchsprognose herangezogen werden könnten.&lt;br /&gt;
&lt;br /&gt;
Zum Zweck der Verbrauchsermittlung verwendet das Modul die Meterdaten aus dem Attribut &#039;&#039;setupMeterDev&#039;&#039; sowie den weiteren setup-Attributen &#039;&#039;setupInverterDevXX&#039;&#039;. &lt;br /&gt;
Sind auch andere Erzeuger (BHKW, Windanlagen, etc.) bzw. eine Batterie vorhanden, sind ebenfalls die Attribute &#039;&#039;setupOtherProducerXX&#039;&#039; bzw. &#039;&#039;setupBatteryDev&#039;&#039; für die Berechnung des Hausverbrauchs relevant. In diesen Attributen gibt es die Schlüssel &#039;&#039;*total&#039;&#039; die teilweise optional sind. Für die Verbrauchsprognose bilden sie jedoch die Berechnungsgrundlage und sind deswegen für diese Funktionalität wichtig anzugeben.&lt;br /&gt;
&lt;br /&gt;
Die Verbrauchswerte werden stundengenau erfasst und im Datenspeicher &#039;&#039;pvHistory&#039;&#039; für 31 Tage, sowie im Datenspeicher &#039;&#039;pvCircular&#039;&#039; 210 Tage gespeichert. Die beiden Datenspeicher übernehmen unterschiedliche Aufgaben im Rahmen der Prognoseerstellung. Auf Grundlage der gespeicherten und somit historischen Verbrauchswerte erstellt das Modul eine Prognose für die kommende Zeit.&lt;br /&gt;
&lt;br /&gt;
Mit dem Kommando &lt;br /&gt;
&lt;br /&gt;
   &amp;quot;get ... pvHistory [Tag]&amp;quot; &lt;br /&gt;
&lt;br /&gt;
wird der Inhalt aufgelistet. Die Schlüssel &#039;&#039;confc&#039;&#039;, &#039;&#039;con&#039;&#039; und &#039;&#039;gcon&#039;&#039; zeigen die Verbrauchsprognose, den Verbrauch und den Netzbezug der jeweiligen Stunde des gewählten Tages.&lt;br /&gt;
Die Stunde &amp;quot;99&amp;quot; zeigt die Summen dieser Schlüsssel für den Tag:&lt;br /&gt;
&lt;br /&gt;
      99 =&amp;gt; etotal: , pvfc: 782, pvrl: 0, rad1h: -&lt;br /&gt;
            confc: 14540, con: 13873, gcon: 13873, gfeedin: 0&lt;br /&gt;
            batintotal: , batin: 0, batouttotal: , batout: 0&lt;br /&gt;
            batmaxsoc: -, batsetsoc: -&lt;br /&gt;
            wid: , wcc: , wrp: , pvcorrf: , dayname: So&lt;br /&gt;
            cyclescsm01: 0&lt;br /&gt;
            cyclescsm02: 0&lt;br /&gt;
            cyclescsm03: 0&lt;br /&gt;
            cyclescsm04: 1, hourscsme04: 0.00&lt;br /&gt;
            cyclescsm05: 0&lt;br /&gt;
            cyclescsm06: 0&lt;br /&gt;
            cyclescsm07: 1, hourscsme07: 0.00&lt;br /&gt;
            cyclescsm08: 1, hourscsme08: 0.00&lt;br /&gt;
            cyclescsm09: 1, hourscsme09: 0.03 &lt;br /&gt;
&lt;br /&gt;
In dem Beispiel wurden für den Tag 14540 Wh Verbrauch prognostiziert, 13873 Wh tatsächlich verbraucht und davon 13873 Wh aus dem Netz bezogen. Leider war an diesem Tag keinerlei PV Ertrag vorhanden, was man auch an dem Schlüssel &#039;&#039;pvrl&#039;&#039; erkennen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Inhalt des pvCircular-Speichers kann mit dem Befehl  &lt;br /&gt;
&lt;br /&gt;
     &amp;quot;get ... pvCircular [Tag]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Das nachfolgende Beispiel zeigt die Ausgabe für die Tagesstunde 23:&lt;br /&gt;
&lt;br /&gt;
 23 =&amp;gt; pvapifc: 0, pvaifc: -, pvfc: 0, aihit: 0, pvrl: 0&lt;br /&gt;
       batin01: 0, batin02: -, batin03: -&lt;br /&gt;
       batout01: 619, batout02: -, batout03: -&lt;br /&gt;
       confc: 650, gcon: 23, gfeedin: 0, wcc: 40, rr1c: 0.00&lt;br /&gt;
       temp: -6.00, wid: 100, wtxt: Bewölkungsentwicklung nicht beobachtet&lt;br /&gt;
       pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
       ... &lt;br /&gt;
       con_all =&amp;gt; Sa  @ 617 762&lt;br /&gt;
                  Di  @ 693 645&lt;br /&gt;
                  Mo  @ 620 679&lt;br /&gt;
                  So  @ 669 666 636&lt;br /&gt;
                  Mi  @ 701 626&lt;br /&gt;
                  Do  @ 612 642&lt;br /&gt;
                  Fr  @ 615 606&lt;br /&gt;
&lt;br /&gt;
Der Schüssel &#039;&#039;con_all&#039;&#039; enthält einen Hash aus Arrays die für jeden Wochentag (Mo..So) bis zu 30 Verbrauchswerte (in Wh) für die angezeigte Stunde speichern. Wie hier erkennbar ist, wurden an den drei vergangenen Sonntagen jweils 669 Wh, 666 Wh bzw. 636 Wh in der Stunde 23 (22:00-22:59) verbraucht.&lt;br /&gt;
Der Median aus diesen Werten geht in die Verbrauchsprognose ein. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wochentagsnamen Mo..So sind von den installierten Locales auf Betriebsystemebene abhängig. Ist keine deutsche locale installiert, werden die englischen Wochentagsnamen Mon..Sun verwendet. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Wie wird der Verbrauch des Hauses ermittelt und gespeichert? ===&lt;br /&gt;
Die Verbrauchsdaten des Hauses werden auf Stundenbasis ermittelt und gespeichert. Das &amp;quot;Haus&amp;quot; steht als Synonym aller im Kontext des Solarforecast Devices zusammengeführten Inverter (setupInverterDevXX), sonstigen Erzeuger (setupOtherProducerXX), Netzanschlüsse (setupMeterDev), Verbraucher (consumerXX) und Batterien (setupBatteryDev).&lt;br /&gt;
&lt;br /&gt;
Alle diese Daten werden durch das Modul mit jedem ausgeführten Zyklus (Attribut plantControl-&amp;gt;cycleInterval) und, wenn ein Event eines als &#039;asynchron&#039; definierten Devices auftritt, gesammelt und daraus permanent ein aktualisierter Verbrauch berechnet. Die Berechnung beschreibt folgende Formel:&lt;br /&gt;
&lt;br /&gt;
 PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung - Verbrauch = 0&lt;br /&gt;
&lt;br /&gt;
bzw.&lt;br /&gt;
 &lt;br /&gt;
 Verbrauch (Wh) = PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung&lt;br /&gt;
            con = PV           + PP                 - GridIn          + GridCon   - BatIn          + BatOut&lt;br /&gt;
&lt;br /&gt;
Die PV-Erzeugung beinhaltet die Summe aller durch die angegebnen Inverter (setupInverterDev01 .. setupInverterDevXX) erzeugten Energien. Die &amp;quot;sonstige Erzeugung&amp;quot; summiert sich aus den Werten aller angegebenen Producer (setupOtherProducer01 .. setupOtherProducerXX). Der Verbrauch wird durch die registrierten Geräte consumerXX teilweise direkt erfasst, ist aber grundsätzlich unvollständig da nicht alle Verbrauchswerte im &amp;quot;Haus&amp;quot; gemessen und durch das Modul erfasst werden können.&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel zeigt das Ergebnis bei 300 Wh PV-Erzeugung und gleichzeitige 500 Wh Netzbezug:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 300 + 0 - 0 + 500 - 0 + 0 = 800 Wh&lt;br /&gt;
&lt;br /&gt;
Bei 1300Wh PV-Erzeugung, 100 Wh Netzeinspeisung sowie 200 Wh Batterieladung ergibt sich der Verbrauch zu:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 1300 + 0 - 100 + 0 - 200 + 0 = 1000 Wh&lt;br /&gt;
&lt;br /&gt;
Ohne Erzeugung, aber mit der Energielieferung von 500 Wh aus der Batterie, 800 Wh Netzbezug (mit einem Anteil Batterienachladung aus dem Netz von 200 Wh) sieht die Verbrauchsrechnung wie folgt aus: &lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 0 + 0 - 0 + 800 - 200 + 500 = 1100 Wh&lt;br /&gt;
&lt;br /&gt;
Der so ermittelte Verbrauchsert wird mit jedem Zyklus in der pvHistory im Schlüssel &amp;quot;con&amp;quot; gespeichert. Man kann sich die gespeicherten Werte mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;name&amp;gt; pvHistory [&amp;lt;Tag&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Nachfolgendes Beispiel zeigt einen Datensatz für die Stunde 8 eines Tages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      08 =&amp;gt; pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotali01: 62940734, etotali02: 2928860, etotali03: -&lt;br /&gt;
            pvrl01: 0, pvrl02: 0, pvrl03: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 630, con: 962, gcons: 962, conprice: 0.2958&lt;br /&gt;
            gfeedin: 0, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 120, sunalt: -3&lt;br /&gt;
            batintotal: 3713815.07742543, batouttotal: 3604468.26993988, batin: 0, batout: 0&lt;br /&gt;
            wid: 161, wcc: 89, rr1c: 0.00, pvcorrf: 0.27/0.00 temp: 7.40, &lt;br /&gt;
            csmt01: 110996.12, csme01: 32.1399999999994, minutescsm01: 30&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 2513.67, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1581293.6, csme04: 136.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 1662.17, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 90.53, csme06: 0, minutescsm06: 0&lt;br /&gt;
            csmt07: 39.75, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 38050, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 131627, csme09: 33.2000000000116, minutescsm09: 39&lt;br /&gt;
            minutescsm10: 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Schlüssel &amp;quot;con&amp;quot; ist der gespeicherte Verbrauch von 962 Wh ersichtlich.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit bekommt man mit dem Attribut &#039;&#039;ctrlDebug=collectData&#039;&#039; einen Einblick in die Verbrauchsermittlung bei jedem Zyklus und kann so die Eingangswerte und das daraus resultierende Ergebnis im FHEM Log nachverfolgen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
2024.11.28 11:38:20.080 1: SolCast DEBUG&amp;gt; EnergyConsumption input -&amp;gt; PV: 96, PP: 0, GridIn: 0, GridCon: 582, BatIn: 5, BatOut: 0&lt;br /&gt;
2024.11.28 11:38:20.081 1: SolCast DEBUG&amp;gt; EnergyConsumption result -&amp;gt; 673 Wh&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie wird die Verbrauchsprognose erstellt? ===&lt;br /&gt;
&lt;br /&gt;
Aus den gespeicherten con-Werten (Verbrauchsdaten) der pvCircular (Schlüssel con_all) sowie Einträgen der pvHistory wird der Median der historischen Tage ermittelt und für den kommenden Tag bzw. die kommen Stunden zur Prognose angewendet. Dabei geht per default jeder verfügbare historische Tag gleichberechtigt in die Prognose ein. Mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039; kann festgelegt werden, dass nur gleiche Wochentage (Mo..So) für die Prognose verwendet werden. Hierbei spielt die Vermutung, dass das Verbrauchsverhalten eine gewisse Korrelation zum Wochentag hat, eine Rolle. &lt;br /&gt;
&lt;br /&gt;
Verwendet man die Einstellung consForecastIdentWeekdays=1, hat es sich als vorteilhaft erwiesen, das Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays&#039;&#039;&#039; auf einen niedrigeren Wert als den Default zu setzen. Eine Einstellung auf &#039;8&#039; zum Beispiel verwendet den Median der gleichen Wochentage der vergangenenen 8 Wochen. Dadurch wird nicht zu weit in die Vergangenheit verzweigt und so eine langsame Veränderung des Verbrauchsmedian, zum Beispiel hervorgerufen durch den Übergang vom Winter in das Frühjahr hinein, abgebildet.&lt;br /&gt;
&lt;br /&gt;
Weiteren Einfluß auf die Verbrauchsprognose kann mit dem Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; im Consumerattribut genommen werden. Insbesondere bei der unregelmäßigen Nutzung von Verbrauchern mit hoher Leistung kann die Projektion der aufgezeichneten historischen Werte in die Prognose zu unverhältnismäßig hohen Verbrauchswerwartunden führen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Möglicherweise führt in Fällen die Verwendung eine der nachfolgenden Optionen zu einem besseren Ergebnis:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;1 -&#039;&#039;&#039; die allgemeine Verbrauchsprognose wird um die gespeicherten Energieverbrauchsanteile reduziert.&lt;br /&gt;
* &#039;&#039;&#039;2 -&#039;&#039;&#039; wie bei &#039;1&#039;, jedoch gehen die Planungsdaten des Verbrauchers bei der Prognose der kommenden Stunden wieder mit ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;&#039;exconfc&#039;&#039;&#039; in einem der Consumer verwendet, sollte&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays=4&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
eingestellt werden. Hintergrund ist, dass die Verbrauchsanteile der jeweiligen Verbraucher nur maximal 31 Tage in der pvHistory verfügbar sind. Für längere Zeiträume stehen nur Gesamtsummen des Verbrauchs in der pvCircular zu Verfügung.  &lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=1&#039;&#039;&#039; werden die in der Historie aufgezeichneten Verbrauchsbestandteile aus einer Prognose herausgerechnet. Konkret werden die in der pvHistory aufgezeichneten Verbrauchsbestandteile für die relevante Stunde ermittelt und daraus ein Durchschnitt gebildet der vom Prognosewert subtrahiert wird. Mit dem Attributwert plantControl-&amp;gt;consForecastIdentWeekdays=1 werden wiederum nur identische Wochentage (Mo .. So) zusammengefasst.&lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=2&#039;&#039;&#039; erfolgt ebenso die Eliminierung des Verbrauchsanteils, es wird jedoch auf die Planungsdaten für diesen Verbraucher zugegriffen und die geplanten Energieanteile wiederum der Verbrauchsprognose für die kommenden Stunden hinzugerechnet.&lt;br /&gt;
&lt;br /&gt;
In beiden Anwendungsfällen ist es notwendig, dass dem Modul durch die Angabe entsprechender Readings der Energieverbrauch im Setup des Consumers bekannt gemacht wird damit diese Energieanteile registriert werden können. Allgemein funktioniert die Verbrauchsprognose gut wenn Verbrauchsprozesse regelmäßig in einem wiederkehrenden Zeitraster ablaufen, der Verbrauch durch persönliche Rituale bestimmt ist. So zum Beispiel könnte am Dienstag und Samstag gewöhnlich die Waschmaschine laufen, das E-Auto täglich aufgeladen werden und gebügelt wird oft am Sonntag Nachmittag.&lt;br /&gt;
&lt;br /&gt;
Unregelmäßige Nutzung, vor allem vom Großverbrauchern, lässt sich nur sehr schwer und ungenügend auf zukünftige Verbrauchsprognosen projizieren.&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis der Prognose wird im Kopf der Grafik in der Zeile &#039;&#039;Verbrauch&#039;&#039; sowie in diversen Readings wie &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RestOfDayConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den Rest des Tages)&lt;br /&gt;
* &#039;&#039;&#039;NextHours_Sum04_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für die nächsten 4 Stunden)&lt;br /&gt;
* &#039;&#039;&#039;Tomorrow_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den kommenden Tag)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
angezeigt.&lt;br /&gt;
&lt;br /&gt;
Weitere Aggregationen kann man sich über das Attribut &#039;&#039;&#039;ctrlStatisticReadings&#039;&#039;&#039; bei Bedarf zuschalten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;conForecastTillNextSunrise&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
* &#039;&#039;&#039;todayConForecastTillSunset&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
* &#039;&#039;&#039;todayConsumptionForecast&#039;&#039;&#039; - Verbrauchsprognose aufgesplittet pro Stunde des aktuellen Tages (01-24) &lt;br /&gt;
 &lt;br /&gt;
==== Debugging der Verbrauchsprognose ====&lt;br /&gt;
Um sich einen Einblick über die Erstellung der Verbrauchsprognose zu verschaffen, bietet sich die Einschaltung von:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
an. Mit diesem gesetzten Attribut wird die Erstellung der Prognose im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; ################### Start Consumption forecast ###################&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; Basics - installed locale: de_DE.UTF-8, used scheme: DE&lt;br /&gt;
2025.02.27 19:52:00.064 1: SolCast DEBUG&amp;gt; process Today dayname: Do, Tomorrow dayname: Fr&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 01 - 74.43 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 10 - 290.77 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 24 - 660.70 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 20, hod: 07 - 459.93 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;07&#039; register for exclude day 20, hod: 02 - 0.33 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 30, hod: 08 - 264.78 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next Hours (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; excl. hist 74 Wh for Hour 01, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; estimated cons of Hour 01: 436 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; excl. hist 0 Wh for Hour 02, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 02: 428 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 03: 458 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 04: 503 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 05: 489 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 06: 482 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; excl. hist 460 Wh for Hour 07, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 07: 274 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 265 Wh for Hour 08, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 08: 441 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 09: 558 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 291 Wh for Hour 10, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 10: 443 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 11: 881 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 12: 794 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 13: 840 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 14: 660 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 15: 812 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 16: 752 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 17: 597 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 18: 652 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 19: 634 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 20: 628 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 21: 713 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 22: 596 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 23: 629 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; excl. hist 661 Wh for Hour 24, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons of Hour 24: 660 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons Tomorrow: 16848 Wh, Individual hourly values considered: 72, exclude: 0 Wh (avg of 0 entities)&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Store Consumption forecast values (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour00&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;20&#039; confc: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour01&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;21&#039; confc: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour02&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;22&#039; confc: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour03&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;23&#039; confc: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store &#039;NextHour04&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;24&#039; confc: 660&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour05&#039; hod &#039;01&#039; confc: 436, confcEx: 436&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour06&#039; hod &#039;02&#039; confc: 428, confcEx: 428&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour07&#039; hod &#039;03&#039; confc: 458, confcEx: 458&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour08&#039; hod &#039;04&#039; confc: 503, confcEx: 503&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour09&#039; hod &#039;05&#039; confc: 489, confcEx: 489&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour10&#039; hod &#039;06&#039; confc: 482, confcEx: 482&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour11&#039; hod &#039;07&#039; confc: 274, confcEx: 274&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour12&#039; hod &#039;08&#039; confc: 441, confcEx: 441&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour13&#039; hod &#039;09&#039; confc: 558, confcEx: 558&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour14&#039; hod &#039;10&#039; confc: 443, confcEx: 443&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour15&#039; hod &#039;11&#039; confc: 881, confcEx: 881&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour16&#039; hod &#039;12&#039; confc: 794, confcEx: 794&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour17&#039; hod &#039;13&#039; confc: 840, confcEx: 840&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour18&#039; hod &#039;14&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour19&#039; hod &#039;15&#039; confc: 812, confcEx: 812&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour20&#039; hod &#039;16&#039; confc: 752, confcEx: 752&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour21&#039; hod &#039;17&#039; confc: 597, confcEx: 597&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour22&#039; hod &#039;18&#039; confc: 652, confcEx: 652&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour23&#039; hod &#039;19&#039; confc: 634, confcEx: 634&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour24&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour25&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour26&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour27&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour28&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; consumption calculated - day: 27, hod: 20, con: 574 Wh&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; write pvCircular consumption - hod: 99, todayConsumption: 11210 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe startet mit &#039;&#039;&amp;quot;Start Consumption forecast&#039;&#039;&amp;quot;, es werden die zu exkludierenden historischen Daten für jeden Consumer bzgl. jedem Tag (day) und Stunde des Tages (hod) getrennt registriert. Diese Werte werden durch die gespeicherte Einträge in der pvHistory (max. 31 historische Tage) geliefert. &lt;br /&gt;
&lt;br /&gt;
Im nächsten Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next Hours (new median)&amp;quot;&#039;&#039; werden die Prognosen für die nächsten Stunden kalkuliert und die zuvor registrierten Excludes angewendet. Die Prognose für den kommenden Tag ist im Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next day (new median)&amp;quot;&#039;&#039; protokolliert. Die Prognose für den kommenden Tag ist nicht einfach die Summe der Prognose der nächsten Stunden, denn in den kommenden Stunden werden auch die verfügbaren Planungen der Consumer einbezogen. Für den kommenden Tag können diese Werte unter Umständen nicht einbezogen werden da sie zum Zeitpunkt X noch nicht verfügbar sind.&lt;br /&gt;
&lt;br /&gt;
Im Abschnitt &#039;&#039;&amp;quot;Store Consumption forecast values (new median)&amp;quot;&#039;&#039; erscheinen die effektiv gespeicherten Werte. Diese sind die Grandlage für die grafische Darstellung sowie weiteren Kalkulationen.&lt;br /&gt;
&lt;br /&gt;
=== Wie kann eine fehlerhafte Verbrauchsprognose korrigiert werden? ===&lt;br /&gt;
Wie im vorherigen Abschnitt beschrieben, wird die Prognose aus den gespeicherten &amp;quot;con&amp;quot;-Werten der vergangenen Tage (bzw. Stunden) abgeleitet. &lt;br /&gt;
Grundsätzlich muß zunächst sichergestellt werden, dass die auszulesenden Readings der angegebenen Energiezähler sowie deren Einheiten! korrekt eingestellt sind. Das gilt ebenfalls für die registrierten Verbraucher im Modul.&lt;br /&gt;
&lt;br /&gt;
Für einen ersten Überblick bietet sich das Debug Attribut an zu setzen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
Beispielausgabe des Debug:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2024.09.21 13:28:27.041 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day ###################&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;01&amp;lt; considering possible exclusions: 14082&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;08&amp;lt; considering possible exclusions: 16446&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;15&amp;lt; considering possible exclusions: 14568&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;25&amp;lt; considering possible exclusions: 15522&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; estimated Consumption for tomorrow: 15154, days for avg: 4&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next hours ###################&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 14 -&amp;gt; 850 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 14 -&amp;gt; 643 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 14 -&amp;gt; 590 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 14 -&amp;gt; 522 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 13:00:00, confc: 651, days for avg: 4, hist. consumption registered consumers: 560.97&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 15 -&amp;gt; 720 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 15 -&amp;gt; 743 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 15 -&amp;gt; 897 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 15 -&amp;gt; 557 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 14:00:00, confc: 729, days for avg: 4, hist. consumption registered consumers: 620.97&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 16 -&amp;gt; 676 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 16 -&amp;gt; 790 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 16 -&amp;gt; 785 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 16 -&amp;gt; 581 Wh&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 15:00:00, confc: 708, days for avg: 4, hist. consumption registered consumers: 647.29&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 17 -&amp;gt; 622 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 17 -&amp;gt; 639 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 17 -&amp;gt; 646 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 17 -&amp;gt; 572 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 16:00:00, confc: 619, days for avg: 4, hist. consumption registered consumers: 618.30&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 18 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 18 -&amp;gt; 614 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 18 -&amp;gt; 580 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 18 -&amp;gt; 480 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 17:00:00, confc: 567, days for avg: 4, hist. consumption registered consumers: 583.41&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 19 -&amp;gt; 615 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 19 -&amp;gt; 1659 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 19 -&amp;gt; 597 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 19 -&amp;gt; 618 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 18:00:00, confc: 872, days for avg: 4, hist. consumption registered consumers: 636.97&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 20 -&amp;gt; 611 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 20 -&amp;gt; 1124 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 20 -&amp;gt; 546 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 20 -&amp;gt; 479 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 19:00:00, confc: 690, days for avg: 4, hist. consumption registered consumers: 578.87&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 21 -&amp;gt; 1474 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 21 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 21 -&amp;gt; 619 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 21 -&amp;gt; 433 Wh&lt;br /&gt;
2024.09.21 13:28:27.058 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Im ersten Teil wird die erwartete Consumption für den nächsten Tag unter Berücksichtigung möglicher Ausschlüsse von Verbrauchern ausgegeben. Ausschlüsse von Verbrauchern ergeben sich wenn in dem Verbraucherattribut der Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; gesetzt ist. Er besagt, dass die Verbrauchswerte des Verbrauchers in eine zukünftige Prognose nicht eingehen sollen. Zum Beispiel wenn ein Verbraucher mit sehr hohen Verbrauchswerten nur sporadisch eingesetzt wird und dadurch die Prognose stark verfälschen würde. Es ist auch zu sehen, dass bedingt durch das Attribut &#039;&#039;&#039;affectConsForecastIdentWeekdays = 1&#039;&#039;&#039; nur die historischen Tage 01, 08, 15 und 25 berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Teil wird die berechnete Erwartung für die nächsten Stunden ausgegeben. &lt;br /&gt;
Zur Beschreibung der Fehlersuche gehen wir davon aus, dass die Prognose von 780 Wh am 2024-09-21 20:00:00 zu hoch erscheint weil am Tag &amp;quot;07&amp;quot; ein Wert von 1474 Wh gespeichert ist:&lt;br /&gt;
&lt;br /&gt;
 SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt geben wir die historischen Werte für den Tag 07 aus:&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;Name&amp;gt; pvHistory 07&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz interessiert die Stunde 21. Sie resultiert aus der obigen Angabe &amp;quot;starttime: xxxx-xx-xx 20:00:00&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      21 =&amp;gt; etotal: 64354660, pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 496, con: 1474, gcons: 23, conprice: 0.2958&lt;br /&gt;
            gfeedin: 5, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 289, sunalt: -8&lt;br /&gt;
            batintotal: 3064096.92456668, batouttotal: 2958021.37946804, batin: 0, batout: 1460&lt;br /&gt;
            wid: 101, wcc: 20, rr1c: 0.00, pvcorrf: 1.00/-temp: 26.00, &lt;br /&gt;
            csmt01: 64262.43, csme01: 28.8099999999977, minutescsm01: 25&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 0, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1389417.4, csme04: 94.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 0, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 290.15, csme06: 6.66999999999996, minutescsm06: 54&lt;br /&gt;
            csmt07: 0, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 32800, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 103987.8, csme09: 38, minutescsm09: 43&lt;br /&gt;
            csmt10: 9151.24999999783, csme10: 3.99999999997999, minutescsm10: 60&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz sind die Energieverbrauchsanteile der im Device registrierten Verbraucher mit dem Schlüssel &amp;quot;csmeXX&amp;quot; gespeichert. Dabei ist &amp;quot;XX&amp;quot; die Verbrauchernummer. In dem Beispiel existieren die Anteile csme01 und csme03 - csme10. Keiner dieser Verbraucher hat einen auffälligen Verbrauchswert gespeichert, d.h. die Messung der Verbraucher scheidet als Problemquelle aus. Wäre ein unverhältmismäßig hoher Verbrauch bei einem der Verbraucher feststellbar, müssten die Schlüssel &#039;&#039;&#039;pcurr&#039;&#039;&#039; und &#039;&#039;&#039;etotal&#039;&#039;&#039; im consumerXX-Attribut geprüft, sowie die Datenlieferung des Consumerdevices selbst geprüft werden.  &lt;br /&gt;
&lt;br /&gt;
Es wurde offensichtlich ein hoher Verbrauch von einem nicht registrierten Verbraucher verursacht oder durch die Übertragung eines Meßfehlers des Devices, angegeben im Attribut &#039;&#039;&#039;setupMeterDev&#039;&#039;&#039;, in das SolarForecast Device übertragen. Eine weitere Analyse ist an dieser Stelle nicht möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Behebung des falschen Wertes kann ein Reset der gespeicherten Consumption der relevanten Stunde durchgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; reset consumptionHistory 07 21&lt;br /&gt;
&lt;br /&gt;
== Modulinterne Datenstrukturen ==&lt;br /&gt;
Das Modul speichert die verschiedenen historischen und aktuellen Daten wie PV-Prognose, Witterungsdaten (Regen, Bewölkung), Strahlungsdaten, Einspeisung, Bezug, reale Erzeugungsdaten und vieles mehr zur Laufzeit im Arbeitsspeicher. Dadurch ist die Verarbeitung dieser Daten im Vergleich zu Lesevorgängen aus dem Filesystem bzw. einer Datenbank sehr performant. Allerdings würden diese Daten bei einem FHEM Absturz bzw. bei einem regulären Shutdown verlorengehen.&lt;br /&gt;
&lt;br /&gt;
Deswegen werden die relevanten Daten regelmäßig in Dateien gesichert und bei Bedarf wiederhergestellt. Diese Dateien befinden sich im Verzeichnis &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; und heißen &#039;&#039;&#039;.*_SolarForecast_.*&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Die Daten werden in jedem Zyklus der Zentralschleife (CentralTask) gesammelt bzw. berechnet. Der Zyklus wird mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;cycleInterval&#039;&#039;&#039; eingestellt.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit können diese Daten über get-Kommandos abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvHistory [Tag]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der pvHistory Datenspeicher enthält die vergangenen Kennwerte der letzten 31 Tage mit einer Genauigkeit von einer Stunde. Es werden die Prognosewerte für Erzeugung und Verbrauch, die realen Werte für Erzeugung und Verbrauch sowie ebenso die Laufzeiten jedes einzelnen Verbrauchers (Consumer) festgehalten. Für jeden Tag gibt es die Stunde &amp;quot;99&amp;quot; die eine Summierung der Stundenwerte des Tages bzw. Sonderschlüssel enthält.&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf lässt sich mit dem Befehl &amp;quot;set ... reset pvHistory&amp;quot; der gesamte Inhalt des Speichers löschen (nicht empfohlen). Selektiver funktioniert die Datenlöschung mit &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt;&amp;quot; (Daten eines bestimmten Tages löschen) bzw. &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt; &amp;lt;Stunde&amp;gt;&amp;quot; (Daten der Stunde  eines bestimmten Tages löschen). Die letzten beiden Kommandos müssen über die Kommandozeile im Browser ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvCircular &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Ringspeicher enthält Daten der letzten 24 Stunden sowie fortwährend berechnete Werte wie Korrekturfaktoren der PV-Erzeugung und Prognosequalität.&lt;br /&gt;
Neue Stundenwerte des Tages überschreiben die gespeicherten Schüssel des vorangegangenen Tages sofern es sich nicht um fortwährend berechnete Werte handelt. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... nextHours&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Speicher enthält sämtliche Prognosewerte der kommenden Stunden beginnend mit der aktuellen Stunde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... radiationApiData&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Abhängig von der ausgewählten Strahlungsdaten API enthält dieser Speicher die von der API gelieferten Rohdaten sowie evtl. weitere für die Funktion benötigte Daten wie API-Keys, Response Messages, Anzahl der API Abruf und weitere.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valCurrent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Struktur wird nicht regelmäßig im Filesystem gespeichert und enthält immer aktuell gesammelte oder berechnete/gelieferte Daten wie z.B. die Autarkierate, letze Laufzeit der Zentralschleife (CentralTask), Zeit des Sonnenauf- und untergangs sowie weitere Betriebsdaten. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valConsumerMaster [XX]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zeigt die Daten der aktuell im SolarForecast Device registrierten Verbraucher. Mit der Nummer &#039;&#039;&#039;XX&#039;&#039;&#039; kann ein bestimmter Verbraucher angesprungen werden. Die Nummer korrespondiert mit dem entsprechenden &#039;&#039;&#039;consumerXX&#039;&#039;&#039; Attribut.&lt;br /&gt;
Neben anderen Betriebs- und Energiedaten werden insbesondere folgende Daten ermittelt, die für die zukünftige Planung der Verbraucherschaltzeiten relevant sind:&lt;br /&gt;
&lt;br /&gt;
* epieces - prognostizierte Energiescheiben pro Betriebsstunde &lt;br /&gt;
&lt;br /&gt;
Ausgehend von gespeicherten historischen Verbrauchsdaten des Verbrauchers wird der Energieverbrauch des Verbrauchers in seiner ersten Betriebsstunde prognostiziert, was insbesondere für die Planung der optimalen Startzeit des Verbrauchers in Bezug zu der prognostizierten PV Energie und den Verbrauchswerten weiterer vorhandener bzw. zu planender Verbraucher Berücksichtigung findet. Weitere Informationen zur Verbrauchersteuerung in diesem  [[#Verbrauchersteuerung_-_Registrieren_und_visualisieren_von_Verbrauchern|Abschnitt]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Schnittstelle für Modulautoren bzw. eigenen Code ===&lt;br /&gt;
&lt;br /&gt;
Die im vorherigen Artikel beschriebenen internen Datenstrukturen können durch externen Code abgefragt und ausgewertet werden.&lt;br /&gt;
Dazu stehen die folgenden Funktionen zur Verfügung. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]BatteryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Bn&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valBattery&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CurrentVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valCurrent&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]InverterVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valInverter&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ProducerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valProducer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]HistoryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Day&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvHistory&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CircularVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvCircular&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]NexthoursVal (&#039;&amp;lt;Name&amp;gt;&#039;, &amp;lt;nhr&amp;gt;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... nextHours&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ConsumerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valConsumerMaster&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]RadiationAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;DateTime&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... radiationApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]WeatherAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;TimeCode&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... weatherApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StatusAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;QTag&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... statusApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StringVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valStrings&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Angabe des Packages (FHEM::SolarForecast::) ist nur notwendig wenn die Funktionen von außerhalb des SolarForecast-Devices aufgerufen werden. Innerhalb des Devices (Code-Ausführung im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039;) kann darauf verzichtet werden.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der Platzhalter sind:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     &amp;lt;Name&amp;gt;     - Name des SolarForecast Devices&lt;br /&gt;
     &amp;lt;Day&amp;gt;      - abzufragender Tag (01 - 31)&lt;br /&gt;
     &amp;lt;Bn&amp;gt;       - Batterie Nummer (01, 02, ...)&lt;br /&gt;
     &amp;lt;DateTime&amp;gt; - Startzeit der Form YYYY-MM-DD hh:00:00&lt;br /&gt;
     &amp;lt;TimeCode&amp;gt; - Zeitwert der Form fcX_XX (z.B. fc1_19)&lt;br /&gt;
     &amp;lt;APIname&amp;gt;  - Hauptname der API gemäß setupWeatherDev1 (z.B. OpenMeteo)&lt;br /&gt;
     &amp;lt;String&amp;gt;   - Name des PV-Modulstrings wie im Attribut &#039;setupInverterStrings&#039;&lt;br /&gt;
     &amp;lt;QTag&amp;gt;     - Question Tag, z.B. &#039;?All&#039;&lt;br /&gt;
     &amp;lt;Nr&amp;gt;       - laufende Nummer des Verbrauchers / Gerätes (01, 02, 03, 04,...)&lt;br /&gt;
     &amp;lt;HoD&amp;gt;      - abzufragende Stunde (01 - 24, 99)&lt;br /&gt;
     &amp;lt;nhr&amp;gt;      - nächste Stunde (NextHour00, NextHour01,...)&lt;br /&gt;
     &amp;lt;Key&amp;gt;      - der abzufragende Schlüssel &lt;br /&gt;
     &amp;lt;default&amp;gt;  - def default-Rückgabewert&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Auswerten von internen Arrays ===&lt;br /&gt;
&lt;br /&gt;
Die meisten der internen Datenstrukturen liefern bei der Abfrage einen einfachen String oder numerischen Wert der ausgewertet werden kann. Es gibt allerdings auch intern gespeicherte Wertelisten. Werden die Listenstrukturen mit den oben beschriebenen Befehlen abgefragt, wird eine Referenz auf die Liste geliefert sofern sie vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
Um auf die Werte einer solchen Liste zuzugreifen, ist am Beispiel des Arrays &#039;&#039;surplusslidereg&#039;&#039; aus dem Current-Speicher (get ... valCurrent) dargestellt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
my $splref = CurrentVal ($name, &#039;surplusslidereg&#039;, &#039;.&#039;);&lt;br /&gt;
my $spser  = ref $splref eq &#039;ARRAY&#039; ? join &#039; &#039;, @{$splref} : undef;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Variable $spser enthält bei Vorhandensein der Liste einen String, der die Listenelemente von &#039;surplusslidereg&#039; durch Leerzeichen getrennt enthält.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backup und Wiederherstellung der Moduldaten ==&lt;br /&gt;
Neben der Datenhaltung in den Attributen und Readings des SolarForecast Devices, erzeugt jedes SolarForecast Device Dateien im Verzeichnis  &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; mit folgenden Inhalten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PVH_SolarForecast_&amp;lt;name&amp;gt;        - PV History&lt;br /&gt;
PVC_SolarForecast_&amp;lt;name&amp;gt;        - PV Circular&lt;br /&gt;
PVCfg_SolarForecast_&amp;lt;name&amp;gt;      - PV Anlagenkonfiguration&lt;br /&gt;
PVCsm_SolarForecast_&amp;lt;name&amp;gt;      - Consumer Status&lt;br /&gt;
ScApi_SolarForecast_&amp;lt;name&amp;gt;      - Strahlungswerte aus verwendeter API&lt;br /&gt;
StatApi_SolarForecast_&amp;lt;name&amp;gt;    - Statusdaten der verwendeten API&#039;s&lt;br /&gt;
WeatherApi_SolarForecast_&amp;lt;name&amp;gt; - Wetterdaten der gewählten Wetter-API (außer DWD-Device)&lt;br /&gt;
AItra_SolarForecast_&amp;lt;name&amp;gt;      - KI Entscheidungsquelle (trainierte Daten)&lt;br /&gt;
AIraw_SolarForecast_&amp;lt;name&amp;gt;      - KI Input Daten = Raw Trainigsdaten&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nach Ausprägung und eingesetzten Features des SolarForecast Devices sind alle oder nur ein Teil dieser Dateien vorhanden. Dabei ist &#039;&#039;&#039;&amp;lt;name&amp;gt;&#039;&#039;&#039; der Name des SolarForecast Devices.&lt;br /&gt;
&lt;br /&gt;
Bei einem Filebackup des FHEM-Servers ist darauf zu achten, dass diese Dateien in dem Backup enthalten sind. Der Inhalt der Dateien ist nicht statisch, sondern kann sich dynamisch aktualisieren. Um im Bedarfsfall einen aktuellen Datenstand zu haben, ist mindestens ein tägliches Backup dieser Dateien empfehlenswert. Eventuell auch öfter mit Hilfe einer Versionierung welche z.B. immer die letzten 3 Versionen aufbewahrt.&lt;br /&gt;
&lt;br /&gt;
Beim Start von FHEM werden bestimmte Dateien automatisch gelesen und in das SolarForecast Device importiert. &lt;br /&gt;
Der Vorgang ist mit verbose=3 im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2023.10.02 09:57:07.967 3: SolCast6 - cached data &amp;quot;pvHistory&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.969 3: SolCast6 - cached data &amp;quot;pvCircular&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;consumerMaster&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;radiationApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;statusApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;weatherApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.974 3: SolCast6 - cached data &amp;quot;aiTrainedData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.976 3: SolCast6 - cached data &amp;quot;aiRawData&amp;quot; restored&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bestimmte Betriebsdaten, wie z.B. die witterungsabhängigen Korrekturfaktoren (circular) oder die KI-Daten (aitrained/airaw), bauen sich über die Zeit immer granularer auf und stellen einen wertvollen Datenbestand dar.&lt;br /&gt;
&lt;br /&gt;
Wird das SolarForecast Device gelöscht und anschließend wieder neu mit dem gleichen Namen definiert, können die bisher verfügbaren Daten sehr einfach wiederhergestellt werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. starten von FHEM (bestimmte Daten werden automatisch importiert)&lt;br /&gt;
* 5. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Soll das neue SolarForecast Device mit einem anderen Namen oder weitere SolarForecast Devices erstellt werden, welche die Betriebsdaten des primären Devices verwenden sollen, ist wie folgt vorzugehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. umbenenen der Dateien, wobei &amp;lt;name&amp;gt; durch den Namen des neuen SolarForecast Devices ersetzt wird&lt;br /&gt;
* 5. starten von FHEM (die Daten werden automatisch importiert)&lt;br /&gt;
* 6. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn sich die SolarForecast Devices hinsichtlich ihres Models oder der integrierten Consumer unterscheiden, sind die Dateien &amp;quot;PVCsm_SolarForecast_&amp;lt;name&amp;gt; &amp;quot; , &amp;quot;ScApi_SolarForecast_&amp;lt;name&amp;gt;&amp;quot; von dem Verfahren auszuschließen.&lt;br /&gt;
&lt;br /&gt;
== Batterieintegration und -steuerung ==&lt;br /&gt;
&lt;br /&gt;
=== Wie eine Batterie eingebunden wird ===&lt;br /&gt;
Wie immer muß die Batterieanlage zunächst mit einem für die Batterie spezifischen FHEM-Device in FHEM definiert sein.&lt;br /&gt;
In diesem Device werden Readings erwartet die folgende Werte bereitstellen:&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieentladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die installierte Batteriekapazität liefert (&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; dieser Schlüssel ist für die Aktivierung des Batterie SOC-Managements und die grafische Anzeige des SOC wesentlich!)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Lade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Entlade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* Reading welches den aktuellen Ladezustand (SOC in Prozent) liefert (optional)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Batterie, bzw. das Batteriedevice wird mit dem Attribut &#039;&#039;&#039;setupBatteryDev&#039;&#039;&#039; im SolarForecast Device registriert. Die Syntax des Attributes ist in  der Online-Hilfe zum Attribut umfassend erläutert. &lt;br /&gt;
Auch wenn manche Readings optional sind, wird empfohlen alle Werte bereitzustellen um alle Batterie-Funktionen im Modul nutzen zu können. Durch die Weiterentwicklung des Moduls können optionale Readings später auch obligatorisch werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Visualisierung der Batterie in der Balkengrafik ====&lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;setupBatteryDevXX&#039;&#039;&#039; verfügt über den Schlüssel &#039;&#039;&#039;show&#039;&#039;&#039;, mit dem die Einblendung des bzw. der Batteriesymbole in den Ebenen der Balkengrafik gesteuert werden kann:&lt;br /&gt;
[[Datei:Screenshot 2025-02-23 192002.png|right|thumb|400px|Einblendung der Batterieleiste und Darstellung des Batterie-SoC als Balkencontent in der zweiten Ebene]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 0 - keine Anzeige des Gerätes (default)&lt;br /&gt;
* 1 - Anzeige des Gerätes in der Balkengrafik Ebene 1&lt;br /&gt;
* 2 - Anzeige des Gerätes in der Balkengrafik Ebene 2 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Symbole und die Farbgebung der Batterie(n) können mittels des Schlüssels &#039;&#039;&#039;icon&#039;&#039;&#039; verändert werden. Die Online-Hilfe gibt weitere Informationen zur Ausgestaltung. &lt;br /&gt;
&lt;br /&gt;
In der Batteriedarstellung wird das Symbol der aktuellen Stunde hervorgehoben. Ein Mouse-Over zeigt wesentliche Betriebszustände der Batterie. Die Batteriesymbole vergangener Stunden zeigen mit einem Mouse-Over die erreichten SoC (State of Charge) Stände. Die kommenden Stunden visualisieren die folgenden Prognosen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der prognostizierte SoC unter Berücksichtigung der PV-Prognose und der [[#Aktivierung_des_Batterie_SOC-Managements|Batteriesteuerung]] sofern sie im Modul aktiviert ist.&lt;br /&gt;
* eine Freigabe bzw. Empfehlung der Batterieladung zur [[#Unterstützung_eines_netzdienlichen_Verhaltens|Unterstützung eines netzdienlichen Verhaltens]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Neben der Einblendung der Batterieleiste über der Balkengrafik selbst können bestimmte Batteriekennwerte als Balkeninhalt dargestellt werden. Die Auswahl erfolgt über das Attribut &#039;&#039;&#039;graphicBeamXContent&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Aktivierung des Batterie SOC- und Lade-Managements ===&lt;br /&gt;
Das integrierte SOC- und Lade-Management verfolgt insbesondere zwei Ziele: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* den Ladezustand der Batterie(n) zu optmimieren, was besonders in den Monaten mit geringerer PV-Erzeugung einen wertvollen Beitrag zur Erhöhung der Autarkierate und Batteriepflege leisten kann&lt;br /&gt;
 &lt;br /&gt;
* eine PV-Prognose und Verbrauch optimierte Beladungssteuerung, die in den Monaten mit hoher PV-Erzeugung hilft eine evtl. Abregelung der Anlage zu verhindern, die Batterie ausgewogen über den Tag zu laden und ein netzdienliches Verhalten zu unterstützen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese beiden Aspekte der Batteriesteuerung werden in den folgenden Abschnitten beschrieben. Sind mehrere Batterien installiert, kann die Steuerung getrennt für jede einzelne Batterie aktiviert und eingestellt werden. Dabei ist zu beachten, dass vom Modul nur Signale und Readings bereitgestellt werden, die durch eine entsprechende Routine ausgewertet werden können um spezifische Befehle zur Umsetzung der Steuerung an das Batteriesystem zu senden. &lt;br /&gt;
 &lt;br /&gt;
Für eine Aktivierung des Managements muß zunächst das Batterie-Device wie im vorigen Abschnitt im SolarForecast Device registriert werden.&lt;br /&gt;
Das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; aktiviert die im Modul integrierte SOC- und Lade-Management Routine: &lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; ctrlBatSocManagement01 lowSoc=&amp;lt;Wert&amp;gt; upSoC=&amp;lt;Wert&amp;gt; [maxSoC=&amp;lt;Wert&amp;gt;] [careCycle=&amp;lt;Wert&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
Die einzelnen Schlüssel werden der Kalkulationsroutine als Steuerungsparameter übergeben und bedeuten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;lowSoc:unterer Mindest-SoC, die Batterie wird nicht tiefer als dieser Wert entladen (muß &amp;gt; 0 sein). Dieser Wert kann zum Beispiel dazu dienen, stets eine Mindestenergiemenge für den Fall eines Stromausfalls im öffentlichen Netz in den Batterien vorzuhalten.&lt;br /&gt;
&lt;br /&gt;
;upSoC:oberer Mindest-SoC, Der übliche Wert des optimalen SoC bewegt sich in Perioden mit hohen PV-Überschuß tendenziell zwischen &#039;lowSoC&#039; und &#039;upSoC&#039;, in Perioden mit geringer PV-Ausbeute bzw. geringem PV Energieüberschuß bewegt sich der optimale SoC tendenziell zwischen &#039;upSoC&#039; und &#039;maxSoC&#039;. Die Einstellung von upSoC=50 für ein ausgewogenes Verhalten kann als guter Startwert dienen.&lt;br /&gt;
&lt;br /&gt;
;maxSoC:maximaler Mindest-SoC, d.h. der SoC Wert der mindestens im Abstand von &#039;careCycle&#039; Tagen erreicht werden muß um den Ladungsausgleich im Speicherverbund auszuführen. Die Angabe ist optional (muß &amp;lt;= 100 sein, default: 95)&lt;br /&gt;
&lt;br /&gt;
;careCycle:maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens &#039;maxSoC&#039; auftreten darf. Die Angabe ist optional. (default: 20)&lt;br /&gt;
&lt;br /&gt;
;loadAbort: definiert eine vom Anwender gewünnschte Bedingung für einen generellen Ladeabbruch und Wiederfreigabe der Lademöglichkeit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle Werte sind ganze Zahlen in %. Dabei gilt: &lt;br /&gt;
&lt;br /&gt;
 lowSoc &amp;lt; upSoC &amp;lt; maxSoC&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====  Erläuterung der Batterie-Steuerungsreadings ==== &lt;br /&gt;
&lt;br /&gt;
Für die Steuerung des Batteriesystems gibt es im SolarForecast einen Satz an Readings, die unterschiedliche Zustände signalisieren und für entsprechende Steuerungsaufgaben bezüglich der Batteriesysteme eingesetzt werden können. In den nachfolgenden Abschnitten werden diese Zusammenhänge noch dataillierter beschrieben.&lt;br /&gt;
&lt;br /&gt;
;Hinweis: SolarForecast stellt lediglich Steuerungsinformationen zur Verfügung. Die Umsetzung des Eingriffs in das Batteriesystem erfolgt durch den Anwender selbst über entsprechende Skripte. In den thematischen Abschnitten werden Beispiele für solche Steuerungsskripte vorgestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle erstellten Readings gelten für ein Batteriesystem, es können mehrere Batteriesysteme in SolarForecast integriert sein. Die Endung &#039;&#039;XX&#039;&#039; der Readings beschreibt die Nummer des Batteriesystems und korrespondiert mit der Endung des entsprechenden Attributes &#039;&#039;ctrlBatSocManagementXX&#039;&#039; bzw. &#039;&#039;setupBatteryDevXX&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Battery_OptimumTargetSoC_XX: Mit den im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; hinterlegten Parametern unter Berücksichtigung von PV- und Verbrauchsprognosen wird ein optimaler SOC-Wert errechnet. Dieser Wert dient zur Einstellung des unteren SOC des Batteriesystems.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeRequest_XX: Dieses Reading signalisiert mit 1 eine Anforderung zur Zwangsladung der Batterie um die Batterie vor Schäden zu schützen (wenn der SOC unter ctrlBatSocManagementXX-&amp;gt;lowSoc gefallen ist) oder wenn der aktuelle SOC unter den berechneten Mindest-SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeUnrestricted_XX: Dieses Reading kann den Wert &#039;&#039;&#039;0&#039;&#039;&#039; oder &#039;&#039;&#039;1&#039;&#039;&#039; einnehmen. Ist der Inhalt 0, sollte die Batterie nur geladen werden, wenn der im Attribut &#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039; definierte Wert überschritten wird. Ist der Inhalt 1, sollte die Batterie mit der vollen zur Verfügung stehenden Ladeleistung angesteuert werden, um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeAbort_XX: Im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; kann mit dem Schlüssel &#039;&#039;loadAbort&#039;&#039; eine Bedingung definiert werden, bei deren Eintritt die Ladung der Batterie abgebrochen werden soll. In diesem Fall wird &#039;&#039;Battery_ChargeAbort_XX=1&#039;&#039; gesetzt. Mit einem entsprechenden Befehl kann der Anwender das Batteriesystem anweisen den Ladevorgang abzubrechen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Nutzung des Batterie SOC-Management ====&lt;br /&gt;
&lt;br /&gt;
Oftmals wird durch die Anlagenhersteller ein hoher statischer SOC eingestellt bzw. empfohlen, der eine längere Verharrungszeit auf einem tiefen SOC-Wert verhindern soll. Allerdings wechseln sich in auch in den Herbst-, Frühlings- und Wintermonaten Zeiten mit wenig PV-Erzeugung mit Phasen stärkerer Solarstrahlung bei klarem Himmel und Sonnenschein ab.&lt;br /&gt;
&lt;br /&gt;
Ein statischer SOC würde dazu führen, dass in den erwähnten Phasen zuviel Energie in das öffentliche Netz eingespeist wird. Dies soll verhindert werden da die wertvolle Energie besser im eigenen Netz gespeichert und in Dunkelphasen verwendet werden kann. Andererseits soll die Batterie nicht zu lange auf einem tiefen SOC verbleiben und außerdem in gewissen Abständen auf einen so hohen SOC geladen werden der den internen Zellausgleich ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Die SOC Kalkulationsroutine des Moduls errechnet unter Berücksichtigung des prognostizierten PV-Ertrages der kommenden Tage, des aktuellen SOC und der im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; (nachfolgend beschrieben) angegebenen Steuerparameter den Vorschlag für eine optimale SOC-Einstellung. Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert.&lt;br /&gt;
&lt;br /&gt;
Durch das Modul selbst findet keine Steuerung der Batterie statt. Es stellt entsprechende Readings zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen SoC.&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SoC unter den optimalen SoC gefallen ist. In diesem Fall sollte die Batterie, unter Umständen mit Netzstrom, zwangsgeladen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Readings können zur Steuerung des SoC (State of Charge) sowie zur Steuerung des verwendeten Ladestroms der Batterie verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ermittlung des optimalen SOC erfolgt nach folgender Logik:&lt;br /&gt;
&lt;br /&gt;
# 	Ausgehend von &#039;lowSoc&#039; wird der Mindest-SoC kurz vor Sonnenuntergang um 5% inkrementiert sofern am laufenden Tag &#039;maxSoC&#039; nicht erreicht wurde und die PV-Prognose keinen hinreichenden Ertrag des kommenden Tages vorhersagt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Wird &#039;maxSoC&#039; (wieder) erreicht, wird Mindest-SoC um 5%, aber nicht tiefer als &#039;lowSoc&#039;, verringert. Ist der berechnete Mindest-SoC größer als &#039;upSoc&#039;, wird der Mindest-SoC auf &#039;upSoc&#039; gesetzt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#   Mindest-SoC wird soweit verringert, dass die prognostizierte PV Energie des aktuellen bzw. des folgenden Tages von der Batterie aufgenommen werden kann. Mindest-SoC wird typisch auf &#039;upSoc&#039; und nicht tiefer als &#039;lowSoc&#039; verringert.  &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Das Modul erfasst den letzten Zeitpunkt am &#039;maxSoC&#039;-Level, um eine Ladung auf &#039;maxSoC&#039; mindestens alle &#039;careCycle&#039; Tage zu realisieren. Zu diesem Zweck wird der optimierte SoC in Abhängigkeit der Resttage bis zum nächsten &#039;careCycle&#039; Zeitpunkt derart verändert, dass durch eine tägliche 5% SoC-Steigerung &#039;maxSoC&#039; am &#039;careCycle&#039; Zeitpunkt rechnerisch erreicht wird. Wird zwischenzeitlich &#039;maxSoC&#039; erreicht, beginnt der &#039;careCycle&#039; Zeitraum erneut. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im fünften Schritt werden die Grenzen &#039;lowSoc&#039; und &#039;upSoc&#039; berücksichtigt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im letzten Schritt erfolgt Generierung des Readings &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; zur Signalisierung einer eventuell empfohlenen Zwangsladung auf den berechneten Min-SoC. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei sehr wenig Erzeugungungsprognose, d.h. wenn sich der berechnete Min-SoC oberhalb von &#039;upSoC&#039; bewegt, wird &#039;upSoC&#039; eingestellt. Liegt der berechnete Min-SoC unterhalb von &#039;upSoC&#039;, ist jedoch größer als &#039;lowSoC&#039;, wird der berechnete SOC im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; eingestellt. Somit eignet sich die Angabe im Schlüssel &#039;upSoC&#039; um in Zeiten geringer Solarenergieerzeugung die Batterie für eine Notstromerzeugung auf mindestens diesem Wert zu halten. Sollte die PV-Prognose kurzfristig einen größeren Ertrag vorhersagen als die Batterie durch die Einhaltung von &#039;upSoC&#039; aufnehmen kann, wird der Min-SoC unter &#039;upSoC&#039; abgesenkt um möglichst allen PV-Überschuß in der Batterie zu speichern und somit dem Eigenverbrauch zuzuführen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der berechnete Mindest-SoC ist immer nur ein unterer Grenzwert. Die Batterie kann durch Ladevorgänge natürlich jederzeit einen höheren als den im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; dargestellten optimalen SoC haben. Der optimale SoC sollte nicht unterschritten werden um die oben genannten Zusammenhänge abbilden zu können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Die dynamische SOC Steuerung mit Umsetzungsbeispiel =====&lt;br /&gt;
Das Modul bietet eine Unterstützung zur automatisierten Einstellung eines optimalen SoC Wertes.&lt;br /&gt;
&lt;br /&gt;
Ziel ist es, den Minimum SoC in Abhängigkeit der zu erwartenden Solarerträge des aktuellen und des folgenden Tages so einzustellen, dass der prognostizierte Solarertrag von der Batterie aufgenommen werden kann. Die Einspeisung in das öffentliche Netz soll minimiert werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin soll ein unterer SoC nicht unterschritten, sowie ein oberer Minimum SoC im Normalfall nicht überschritten werden. Der obere Grenzwert stellt sicher, dass die Batterie mindestens bis zu diesem Wert wieder entladen werden kann. Dadurch bleibt innerhalb der Batterie immer genügend Kapazität verfügbar um unvorhergesehene PV Energie aufnehmen zu können.&lt;br /&gt;
&lt;br /&gt;
Aktiviert wird die Unterstützung der Batteriesteuerung durch das Setzen des Attributes &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; z.B. mit diesen Angaben:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagementXX lowSoc=x upSoC=x maxSoC=x careCycle=x &lt;br /&gt;
&lt;br /&gt;
so zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=98 careCycle=20&lt;br /&gt;
&lt;br /&gt;
Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert. &lt;br /&gt;
Ist dieses Attribut gesetzt, werden Steuerungs-Readings erstellt, die der Nutzer auswerten und seine Batterieanlage z.B. via notify oder DOIF steuern kann. &amp;lt;bR&amp;gt;&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen Mindest-SoC.&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SOC unter den optimalen SOC bzw. minimalen SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
Die Schlüssel &#039;&#039;&#039;lowSoc&#039;&#039;&#039; und &#039;&#039;&#039;upSoC&#039;&#039;&#039; sind die unteren und oberen Grenzen, zwischen denen sich der Minimum SoC im normalen Betrieb bewegen soll.&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;maxSoC&#039;&#039;&#039; stellt eine Ladungsgrenze dar, die mindestens alle X (careCycle) Tage erreicht werden soll. Zu diesem Zweck errechnet das Modul die Anzahl der nötigen Erhöhungen der Minimum Batterieladung von 5% pro Tag um ausgehend vom aktuellen SoC-Level. Der resultierende Minimum SoC Wert wird entsprechend angepasst. Wurde der einstellte maxSoC Level erreicht, startet der Wartungszyklus (careCycle) erneut. &amp;lt;br&amp;gt;&lt;br /&gt;
Der maxSoC in Verbindung mit dem durch &#039;&#039;&#039;careCycle&#039;&#039;&#039; definierten Zyklus soll sicherstellen, dass der Batterieverbund in regelmäßigen Abständen einen Ladungsausgleich vollziehen kann. &lt;br /&gt;
&lt;br /&gt;
Durch die Modullogik erfolgt eine 5 protentige Anhebung des Minimum SoC wenn am Vortag maxSoC nicht erreicht wurde. Die Anhebung erfolgt aber nicht über upSoC. upSoC ist die obere Grenze des Minimum SoC. Wird am Vortag mindestens die maxSoC Ladung erreicht, verringert sich der Minimum SoC wieder schrittweise um 5%, aber nicht tiefer als lowSoc.&lt;br /&gt;
&lt;br /&gt;
Ergänzt wird die Logik noch um die PV Vorhersage. Dabei wird die obige Minimum SoC Berechnung um die Erwartung der PV Erwartung am aktuellen und folgenden Tag korrigiert. Das bedeutet, dass der Minimum SoC z.B. von heute 50% auf 10% abgesenkt und dadurch die gespeicherte Energie dem Haushalt zugeführt wird, wenn am heutigen oder kommenden Tag eine entsprechende PV Energie zu erwarten ist um die Batterie wieder vollständig zu zuladen.&lt;br /&gt;
Dadurch ist immer genügend &amp;quot;Freiplatz&amp;quot; in der Batterie und andererseits hat die Batterie in langen Dunkelphasen eine Reserve für einen eventuellen Stromausfall (falls der abgesichert werden soll) und wird vor einem dauerhaften tiefen SoC geschützt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Umsetzungsbeispiel =====&lt;br /&gt;
&lt;br /&gt;
Wie das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; genutzt werden kann, wird am Beispiel einer Victron Batterieanlage gezeigt. Die Anlage wird durch Cerbo GX Gerät gesteuert. Der Cerbo GX ist per MQTT2 in FHEM eingebunden. Umgesetzt ist die Steuerung der Batterie &#039;01&#039;, d.h. die Angabe &#039;XX&#039; ist durch &#039;01&#039; ersetzt.&lt;br /&gt;
&lt;br /&gt;
Die folgende kleine Logik ist in einem &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; File eingebaut und wird regelmäßig mit&lt;br /&gt;
&lt;br /&gt;
 batSocChargeMgmnt (&#039;&amp;lt;Name SolarForecast Device&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
aufgerufen. Der Aufruf erfolgt durch Angabe der Routine im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; des SolarForecast Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
  # Hinweis: die Zeichen &#039;::&#039; vor der Routine sind durch das SolarForecast Package bedingt&lt;br /&gt;
  ::batSocChargeMgmnt ($name);&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Routine wird dadurch automatisch am Ende jedes Zyklus (siehe Attribut plantControl-&amp;gt;cycleInterval) ausgeführt.&lt;br /&gt;
Um die SOC Managementfunktion nach Bedarf ein- bzw. ausschalten zu können wird zunächst im SolarForecast Device ein userattr zur Steuerung der SOC-Logik angelegt:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; userattr userFn_BatterySoCManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
Die Perl Routine &#039;&#039;&#039;batSocChargeMgmnt&#039;&#039;&#039; ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#  Batterie SOC und Max. Ladestrom Management&lt;br /&gt;
############################################################################&lt;br /&gt;
sub batSocChargeMgmnt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vebus   = &#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;;                            # Victron Vebus Device&lt;br /&gt;
  my $vicsets = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                         # Victron Einstellungen&lt;br /&gt;
&lt;br /&gt;
  my $maxcspc = 105;                                                           # max. Ladestrom (A) Victron MPII Verbund&lt;br /&gt;
  my $actmcc  = ReadingsNum ($vebus, &#039;MaxChargeCurrent&#039;, undef);               # akt. Ladestromeinstellung&lt;br /&gt;
  my $load    = $actmcc // $maxcspc;                                           # Soll-Ladestrom (A)&lt;br /&gt;
&lt;br /&gt;
  ## Battery SoC Management&lt;br /&gt;
  ###########################&lt;br /&gt;
  my $ubsm = AttrVal ($name, &#039;userFn_BatterySoCManagement&#039;, &#039;aus&#039;); &lt;br /&gt;
  &lt;br /&gt;
  if ($ubsm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name,    &#039;Battery_ChargeRequest_01&#039;,     0);&lt;br /&gt;
    my $csoc = ReadingsNum ($vicsets, &#039;MinimumSocLimit&#039;,             10);      # akt. SoC&lt;br /&gt;
    my $osoc = ReadingsNum ($name,    &#039;Battery_OptimumTargetSoC_01&#039;, 10);      # Soll-SoC&lt;br /&gt;
    my $surp = ReadingsNum ($name,    &#039;Current_Surplus&#039;,              0);      # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if ($csoc != $osoc) {&lt;br /&gt;
      CommandSet (undef, &amp;quot;$vicsets MinimumSocLimit $osoc&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn SoCMgmnt -&amp;gt; MinimumSocLimit in $vicsets set to $osoc %});&lt;br /&gt;
    }&lt;br /&gt;
	                                           &lt;br /&gt;
    if ($bcrq &amp;amp;&amp;amp; $surp &amp;lt; 1000) {                                              # max. Strom b. Battery_ChargeRequest &lt;br /&gt;
      $load = 21;&lt;br /&gt;
    }&lt;br /&gt;
	else {&lt;br /&gt;
	  $load = $maxcspc;&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Batterie Einstellung MaxChargeCurrent&lt;br /&gt;
  ##########################################&lt;br /&gt;
  if ($load != $actmcc) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$vebus MaxChargeCurrent $load&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
    Log3 ($name, 3, qq{$name - userFn ChargeMgmnt -&amp;gt; MaxChargeCurrent in $vebus set }.&lt;br /&gt;
                    qq{from old $actmcc A to $load A});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent_set&#039;, $load, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist im SolarForecast Device das Reading  &#039;&#039;&#039;Battery_ChargeRequest_01&#039;&#039;&#039; gesetzt, ist der aktuelle SOC kleiner als der optimale SOC und die Batterie wird (eventuell aus dem öffentlichen Netz) geladen. Das kann automatisch durch den Cerbo GX bzw. in anderen Anlagen durch einen entsprechenden Befehl erfolgen.&lt;br /&gt;
Damit die Netzbeladung nicht mit der vollen Ladestromstärke geschieht, wird der Ladestrom auf den gewünschten Wert (hier 21 A -&amp;gt; ca. 1000 W bei einem 48V System) reduziert sofern kein oder zu wenig PV-Überschuß vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== weitere mögliche Aspekte der SOC- und Batterieladesteuerung ====&lt;br /&gt;
&lt;br /&gt;
SolarForecast liefert durch seine internen Logiken bereits sehr hilfreiche Signale zur Steuerung von Batteriesystemen in Form von Readings an. Abhängig von den individuellen Möglichkeiten der vorhandenen Anlage käme zum Beispiel zusätzlich zu einer Steurung des optimalen SOC oder der Zeitfenster für die Batterieaufladung auch eine Steuerung des Ladestroms bzw. der verwendeten Ladeleistung in Betracht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hintergründe:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Das Laden eines Akkus mit möglichst gleichbleibender und geringer Leistung wirkt sich positiv auf dessen Langlebigkeit aus, was u.a. auch daran liegt, dass der Temperaturstreß im Akku bei langsamer Energiezuführung nur gering ist.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom führt zu einem geringen Absacken der Akkuspannung beim (ggf, temporären) Abschalten des Ladestroms, was sich positiv auf die SOC-Schätzung auswirkt.&lt;br /&gt;
    &lt;br /&gt;
* Ein geringer Ladestrom führt, insb. bei Nutzung passiver Balancer (sind in den Akku-Systemen üblicherweise verbaut), zu einer geringen Differenz zwischen den einzelnen Zellspannungen und damit zu einer besseren Kapazitätsausnutzung eins Akkus.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom kann zu einem zeitlich punktgenauen Zielfüllstand (im Winter 100%, ansonsten natürlich weniger) am Ende des Tages führen.&lt;br /&gt;
    &lt;br /&gt;
* Eine geringer Ladestrom führt auch zu geringen Leitungsverlusten, da der Strom quadratisch zu den Leitungsverlusten beiträgt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann auch die Verweildauer oder die Begrenzung des SOC, auf den die Batterie maximal geladen werden soll, Gegenstand von Optimierungen sein.&lt;br /&gt;
&lt;br /&gt;
Die häufig zu findende Empfehlung, Akkus nicht zu lange bei einem SOC von 100% verweilen zu lassen, liegt weniger an dem SOC als solchem, sondern daran, dass &#039;&#039;SOC=100%&#039;&#039; üblicherweise dadurch ermittelt wird, dass eine Zelle im Akku einen Spannungsschwellenwert überschreitet, der – würde dieser Schwellenwert zeitlich länger überschritten sein – zu einer Schädigung des Akkus führen könnte. Schädlich sind insbesondere häufige Nachladevorgänge bei Werten um die 100% SOC, da Zellen dann ja häufiger und damit - integral gesehen - auch länger den o.g. Schwellenwert überschreiten.&lt;br /&gt;
&lt;br /&gt;
Einige Akku-Hersteller, z.B. BYD, haben auf o.g, Grund in der (neueren) Firmware Ihrer Systeme einen SOC-Threshold (bei BYD liegt dieser bei 95%) eingebaut. Dieser Wert muss nach einem erreichten SOC von 100% unterschritten  werden, bevor überhaupt eine weitere Ladung erfolgt. Insbesondere in der dunklen Jahreszeit kann es daher sinnvoll sein, den Akku unter Verwendung von PV-Leistung so zu füllen, dass dieser möglichst nur einmal vor Einbruch der Dunkelheit auf &#039;&#039;SOC=100%&#039;&#039; geladen wird. Hierbei sollte darauf geachtet werden, dass der Ladeschlussstrom des jeweiligen Systems nicht unterschritten wird. &lt;br /&gt;
&lt;br /&gt;
SolarForecast unterstützt die oben betrachtete Batteriesteuerung durch die optionale Angabe von &#039;&#039;&#039;loadAbort&#039;&#039;&#039; im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039;. Das in diesem Kontext erstellte Reading &#039;&#039;&#039;Battery_ChargeAbort_XX&#039;&#039;&#039; stellt die auswertbaren Steuerungsinformationen zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== PV-Prognose und Verbrauch optimierte Beladungssteuerung unter Berücksichtigung einer Wirkleistungsbegrenzung ====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-04-25 143910.png|right|thumb|400px|Batterie Popup &amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Batterie geladen. sobald PV-Überschuß vorhanden ist ohne eine Prognose zu berücksichtigen. Dadurch sind die Batterien im Sommer unter Umständen schon um 10-12 Uhr voll geladen und die Anlage liefert ihre mehr oder weniger volle Energie (je nach Ausrichtung) in das öffentliche Netz. Dann könnte es zu einer Begrenzung der PV-Leistung durch einen Schwellenwert (z.B. 70%-Regelung) oder eventuell Zwangsabregelung durch den Netzbetreiber kommen.&lt;br /&gt;
&lt;br /&gt;
Hintergrund dieser Erweiterung ist das Bestreben, eine optimale Unterstützung bei der Maximierung des Eigenverbrauchs zu geben und einen Beitrag zur Netzstabilität zu leisten.&lt;br /&gt;
Das Ziel der Beladungssteuerung der Batterie ist es, die Ladung der Batterie über den Tag verteilt so zu steuern, dass die Batterie erst dann geladen wird, wenn durch den PV-Überschuß eine Netzeinspeisung erfolgen würde bzw. ein Grenzwert erreicht werden würde, der zu einer Abregelung der PV-Anlage führen könnte.&lt;br /&gt;
Es kann auch zu einer Zwangsabregelung durch den Netzbetreiber führen, was vermieden werden soll.&lt;br /&gt;
 &lt;br /&gt;
Die interne Kalkulationslogik erstellt zu diesem Zweck ein Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039;.&lt;br /&gt;
Dieses Reading gibt dem User ein Signal, ob zu der aktuellen Stunde der Ladevorgang der Batterie freigegeben (1) oder nicht freigegeben werden sollte (0). Die Freigabe zur Ladung bedeutet dass:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; die Batterie mit ihrer vollen Ladeleistung angesteuert werden sollte um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=0&#039;&#039;&#039; die Batterie nur geladen werden sollte wenn der im Attribut plantControl-&amp;gt;feedinPowerLimit definierte Wert überschritten wird&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ist keine Freigabe zur Ladung vorhanden, kann bzw. sollte dennoch eine Ladung der Batterie vorgenommen werden, sofern eine über dem im &amp;lt;br&amp;gt;&lt;br /&gt;
Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limit liegende Einspeiseleistung vorhanden ist. In diesem Status sollte die Batterie nur mit der Differenzleistung von vorhandener Einspeiseleistung und dem gesetzen Einspeiselimit geladen werden und damit das gesetzte Einspeiselimit einhalten ohne die Anlage abzuregeln. Ist die Batterie in einer Balkengrafikebene dargestellt, wird im Mouse-Over Popup die Battrie mit &#039;&#039;&amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;&#039;&#039; gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Möglichkeiten der Batteriesteuerung sind stark von der individuellen Anlage abhängig und können hier nicht beschrieben werden. Ein Umsetzungsbeispiel mit einer Victron-Anlage mit Pylontech Batterie ist weiter unten dargestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Aktivierung und Arbeitsweise =====&lt;br /&gt;
&lt;br /&gt;
Die implementierte Logik zur optimierten Batterie Beladungssteuerung wird aktiviert, wenn folgende Kriterien erfüllt sind: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;capacity&#039;&#039;&#039; in den setupInverterDevXX Atributen ist gesetzt&lt;br /&gt;
* das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; für die jeweilige Batterie ist gesetzt&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;cap&#039;&#039;&#039; im Attribut setupBatteryDevXX der jeweiligen Batterie ist gesetzt&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Die Logik arbeitet wie folgt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Der resultierende Schwellenwert der Wirkleistungsbegrenzung: der Gesamtanlage wird durch die Auswertung der in den Inverter-Attributen setupInverterDevXX  gesetzen Schlüssel limit (optional) und capacity ermittelt. Inverter mit gesetztem Schlüssel feed = grid (deren Energie wird ausschließlich in das öffentlich Netz eingespeist) werden von der Betrachtung in diesem Kontext ausgeschlossen.&lt;br /&gt;
&lt;br /&gt;
;Die benötigte Beladung bis zu maxSoC (im Attribut setupBatteryDevXX) : wird ermittelt und mit der zu erwartenden PV Tagesprognose in Beziehung gesetzt. Sofern die PV-Erzeugung abzgl. Verbrauch noch nicht das Wirkleistungbegrenzungs-Limit erreicht UND noch genügend PV-Überschuß für eine Ladung auf &#039;&#039;maxSoC&#039;&#039; im Laufe der kommenden Stunden des Tages zu erwarten ist, bleibt das Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 0&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
;Wird das Wirkleistungbegrenzungs-Limit erreicht/überschritten und/oder die PV-Überschußprognose: zzgl. eines Sicherheitspuffers unterschritten, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 1&#039;&#039;&#039; gesetzt. Der User kann darauf reagieren und den Batterie Ladevorgang aktivieren. Die Möglichkeiten der Aktivierung sind natürlich von der installierten Anlage abhängig. Das SolarForecast Device greift nicht in die Batteriesteuerung direkt ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders ausgedrückt erfolgt immer dann eine Ladefreigabe, wenn einer der nachfolgenden Sachverhalte &#039;&#039;wahr&#039;&#039; ist:&lt;br /&gt;
&lt;br /&gt;
- die benötigte Ladeenergie (aller installierten Batterien) &amp;gt;= PV-Restüberschuß des Tages (Reading RestOfDayPVforecast) zzgl. Sicherheitsaufschlag&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- der Zeitpunkt des PV-Erzeugungszenit des laufenden Tages überschritten ist (Reading Today_MaxPVforecastTime)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn die aktuelle PV Leistung &amp;gt;= einer eventuellen Wechselrichter-Leistungsbegrenzung ist (Summe aller WR-Begrenzungen)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn das BatSoc-Management _nicht_ aktiviert ist (nicht alle oben genannten Aktivierungskriterien erfüllt sind)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind mehrere Batterien installiert und durch das Management einer Batterie die Einhaltung der genannten Kriterien bzw. Sachverhalte erwirkt wird, bleiben die weiteren Batterien im Modus Ladefreigabe (Battery_ChargeUnrestricted_XX=1).  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Umsetzungsbeispiel Batterie Ladesteuerung mit Victron GX Venus über den Grid Setpoint =====&lt;br /&gt;
&lt;br /&gt;
Ziel der Steuerung ist es abhängig vom Wert des Readings Battery_ChargeUnrestricted_XX (z.B. Battery_ChargeUnrestricted_01) die Ladung des angeschlossenen Batteriesystems zu aktivieren bzw. zu deaktivieren.&lt;br /&gt;
Das vorliegende Beispiel soll umzusetzen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 0 -&amp;gt; Batterie nicht aufladen bzw. nur laden wenn Einspeiselimit überschritten (Attribut plantControl-&amp;gt;feedinPowerLimit)&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 1 -&amp;gt; Batterie aufladen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Grid Setpoint ist ein Parameter in den Victron Systemeinstellungen. Das Victron System wird den eingestellten Grid Setpoint versuchen einzuhalten und bei einem positiven Wert Energie aus dem Netz beziehen bzw. bei einem negativen Grid Setpoint Energie in das Netz einspeisen.&lt;br /&gt;
&lt;br /&gt;
Normalerweise wird das Victron System die erzeugte PV Energie zunächst zur Deckung des Hausverbrauchs verwenden, ist dann noch ein PV Überschuß vorhanden, die Batterien aufladen und bei weiter vohandenen PV Überschuß diese Energie in das öffentliche Netz einspeisen sofern dem System eine Einspeisung erlaubt ist. Anderenfalls werden die Wechselrichter oder MPPT Smartloader heruntergeregelt bzw. limitiert. &lt;br /&gt;
&lt;br /&gt;
In der Standardeinstellung ist beim Victron System ein Grid Setpoint von ca. 20 bis 50 Watt, d.h. das System strebt danach diese Vorgabe zu erfüllen zieht ständig Energie in diesem Bereich aus dem öffentlich Netz von einem gelegentlichen Überschwingen der Regelung abgesehen. Damit ein eventueller PV Überschuß nicht zum Laden der Batterie verwendet, sondern statt dessen in das öffentliche Netz eingespeist wird, muß der Grid Setpoint um diesen Betrag abgesenkt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-24 114403.png|right|thumb|400px|Integration des Grid Setpoint-Managements in den Own_Spec-Bereich]]&lt;br /&gt;
&lt;br /&gt;
Damit man später per Attribut bzw. über den [[#Formatierung_der_Inhalte_im_Bereich_&amp;quot;Graphic_Header_Own_Specification&amp;quot;|Own_Spec-Bereich]] die automatische Ladesteuerung über den Grid Setpoint ein- bzw. ausschalten kann, legen wir ein userattr an:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 userattr &amp;lt;Name&amp;gt; userFn_GridSetpointManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin sind einige Vorbereitungen im Device MQTT2_cerboGX_c0619ab34e08_settings vorzunehmen. Dieses Device ist im vorliegenden Beispiel ein in FHEM vorhandenes MQTT2_DEVICE, über das die Victron CerboGX Einstellungen zugreifbar sowie einstellbar sind. Die Vorgehensweise zur Erstellung des MQTT2_DEVICE ist hier nicht beschrieben und wird vorausgesetzt.&lt;br /&gt;
&lt;br /&gt;
Damit ein entsprechender Set-Befehl zur Einstellung des Grid Setpoints vorhanden ist, werden folgende Attribute gesetzt:&lt;br /&gt;
&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings jsonMap Settings_CGwacs_AcPowerSetPoint_value:GridSetpoint&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings setList GridSetpoint W/c0619ab34e08/settings/0/Settings/CGwacs/AcPowerSetPoint {&amp;quot;value&amp;quot;:$EVTPART1}&lt;br /&gt;
&lt;br /&gt;
Nach dieser Attributierung kann mit einem &amp;quot;&#039;&#039;set MQTT2_cerboGX_c0619ab34e08_settings GridSetpoint &amp;lt;Wert&amp;gt;&#039;&#039;&amp;quot; der Grid Setpoint eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Das Attribut userFn_GridSetpointManagement kann nun im Perl Code ausgewertet werden um das Grid Setpoint-Management ein- bzw. auszuschalten.&lt;br /&gt;
Der nachfolgende Code wird in die Datei &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; eingefügt. Ist diese Datei nicht vorhanden, legen wir sie vorab als Kopie der ausgelieferten 99_myUtils.pm an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Steuerung Start/Stop der Batterieladung über den Victron Grid Setpoint&lt;br /&gt;
############################################################################&lt;br /&gt;
sub gridSetpointMgmt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vicsets   = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                               # Device Victron Einstellungen&lt;br /&gt;
  my $gspdef    = 20;                                                                  # Default Einstellung des Grid Setpoint&lt;br /&gt;
  my $targetgsp = $gspdef;                                                             # Voreinstellung Grid Setpoint&lt;br /&gt;
  my $neggspmax = FHEM::SolarForecast::CurrentVal ($name, &#039;feedinPowerLimit&#039;, 5000);   # max. gewünschte Einspeiseleistung in Watt&lt;br /&gt;
  $neggspmax    = $neggspmax * -1;&lt;br /&gt;
  my $gspm      = AttrVal ($name, &#039;userFn_GridSetpointManagement&#039;, &#039;aus&#039;);             # Freischaltung des Grid Setpoint-Managements&lt;br /&gt;
  my $curgsp    = ReadingsNum ($vicsets, &#039;GridSetpoint&#039;,         $gspdef);             # aktuelle Einstellung Grid Setpoint&lt;br /&gt;
  &lt;br /&gt;
  if ($gspm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name, &#039;Battery_ChargeUnrestricted_01&#039;, 0);         # Ladefreigabe (1 -&amp;gt; Bat Ladefreigabe)&lt;br /&gt;
    my $surp = ReadingsNum ($name, &#039;Current_Surplus&#039;,               0);         # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if (!$bcrq) {                                                               # Grid Setpoint absenken wenn keine .. &lt;br /&gt;
        $targetgsp = $gspdef - $surp;                                           # ..Batterie Ladefreigabe&lt;br /&gt;
        $targetgsp = $neggspmax if($targetgsp &amp;lt; $neggspmax);                    # Begrenzung der Einspeiseleistung&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($curgsp != $targetgsp) {&lt;br /&gt;
	  fhem (&amp;quot;set $vicsets GridSetpoint $targetgsp&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn gridSetpointMgmt -&amp;gt; GridSetpoint in $vicsets set to $targetgsp});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Victron_GridSetpoint_set&#039;, $targetgsp, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Vergleich des Setpoints mit der Vorgabe von &#039;&#039;$neggspmax&#039;&#039; dient dazu die maximale Einspeiseleistung in das öffentliche Netz zu begrenzen. Ist diese Grenze erreicht, wird der noch verbleibende Überschuß in die Batterie geladen. Dadurch wird eine Abregelung der Anlage vermieden wenn der Schwellenwert &#039;&#039;$neggspmax&#039;&#039;erreicht ist sofern die Batterie aufnahmefähig ist und nicht voll geladen ist. &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::gridSetpointMgmt  ($name);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zum Management des automatischen Grid Setpoint und der Anzeige des eingestellten Wertes wird das Attribut und die Readinganzeige in den Own_Spec-Bereich eingebunden, z.B.:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; graphicHeaderOwnspec  #Settings&lt;br /&gt;
                                   SetPoint&amp;amp;nbsp;Management:userFn_GridSetpointManagement&lt;br /&gt;
                                   Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Unterstützung eines netzdienlichen Verhaltens ====&lt;br /&gt;
&lt;br /&gt;
Der Steuerungsprozess der Batterieanlage leistet insgesamt einen kleinen Beitrag zur Netzstabilität, indem die Speicherladung in den Zeitraum der meisten prognostizierten Überschußeinspeisung gelegt wird. Im Sommer kann sich dieser Zeitraum in die Zeit nach dem Maxmimum des prognostizierten PV-Überschusses verlagern, wenn auch danach noch genügend Überschußenergie zu Volladung der Batterie prognostiziert wird. In dem Zusammenhang sollte im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; ein Einspeiselimit gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zur Verdeutlichung soll das Beispiel dienen:&lt;br /&gt;
&lt;br /&gt;
* die Batterie ist zu 60% geladen &lt;br /&gt;
* der User hat upSoC=40 eingestellt&lt;br /&gt;
* der User hat maxSoC=90 eingestellt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Am Vormittag ist genügend Sonne vohanden, das Maximumum der Energie über die Zeit wird aber noch erwartet. &lt;br /&gt;
Zu diesem Zeitpunkt wird das Reading  &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039; auf den Wert &amp;quot;0&amp;quot; gesetzt. Durch den Nutzer erfolgt daraufhin, zum Beipiel über ein Notify, ein anlagenspezifischer Befehl &amp;quot;Ladestop&amp;quot; an die Batterieanlage. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ab diesem Moment wird:&lt;br /&gt;
&lt;br /&gt;
# die Batterie nicht geladen&lt;br /&gt;
# die erzeugte PV-Energie dem Haushalt zur Verfügung gestellt bzw. der verbleibende Überschuß eingespeist, sofern der Überschuß unterhalb des im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limits liegt.&lt;br /&gt;
# ein eventuell über dem Limit &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; vorhandener Überschuß in die Batterie geladen und so die Netzlast verringert sowie die Batterie schonend geladen. (dieser Punkt trifft in den Monaten mit wenig PV-Erzeugung eher nicht zu)  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig liefert die Batterie Energie an das Hausnetz und wird von 60% bis maximal einem SoC-Wert entladen, der durch die [[#Die_dynamische_SOC_Steuerung_mit_Umsetzungsbeispiel|dynamische SOC Steuerung]] bestimmt wird. Dazu muß diese Steuerung natürlich implementiert sein. Sofern der berechnete SoC größer als upSoC ist, wird der maximale Entladungs-SoC auf upSoC gesetzt. &lt;br /&gt;
&lt;br /&gt;
Zusätzlich überprüft das Modul permanent bei jedem Zyklus die Differenz des aktuell vorhandenen SoC zum eingestellten maxSoC.&lt;br /&gt;
Sie soll nicht größer sein um mit dem (noch) zu erwartenden PV-überschuß des Tages der eingestellte maxSoC bzw. dessen Nähe wahrscheinlich erreicht werden kann. &lt;br /&gt;
Sollte der Differenz-Grenzwert erreicht sein, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; gesetzt und der Nutzer sollte dann über einen geeigneten Befehl seine Anlage in den Modus &amp;quot;Laden&amp;quot; umschalten.&lt;br /&gt;
Dieser Vorgang kann beliebig oft während des Tages alternieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Nutzung von batteryTrigger ===&lt;br /&gt;
Ergänzt werden die Möglichkeiten durch das set-Kommando: &lt;br /&gt;
&lt;br /&gt;
 batteryTrigger &amp;lt;1on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;1off&amp;gt;=&amp;lt;Wert&amp;gt; [&amp;lt;2on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;2off&amp;gt;=&amp;lt;Wert&amp;gt; ...] &lt;br /&gt;
&lt;br /&gt;
Das Kommando setzt Triggerpunkte bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %).&lt;br /&gt;
&lt;br /&gt;
Der verwendete SoC wird als resultierender SoC als Summe der aktuellen Ladung aller registrierten Batterie-Geräte im Verhältnis zur installierten Gesamtkapazität gebildet. Das bedeutet, dass alle einzelnen Batterie-Geräte als ein gemeinsamer Cluster betrachtet werden. &lt;br /&gt;
&lt;br /&gt;
Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise definiert werden.&lt;br /&gt;
Überschreiten die letzten drei SoC-Messungen eine definierte Xon-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = on&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
Unterschreiten die letzten drei SoC-Messungen eine definierte Xoff-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = off&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
&lt;br /&gt;
Der Inhalt der Readings kann durch ein User-Programm oder, bei Erzeugung von entsprechenden Events, mittels notify-Device ausgewertet werden um bei Eintreten eines definierten Ereignisses entsprechende Reaktionen auszulösen. Das kann zum Beispiel die Freigabe eines Heizstabes oberhalb eines bestimmten SOC sein oder ein Entladeverbot der Batterie unterhalb eines SOC-Wertes um Reserven für einen eventuellen Stromausfall zu behalten.&lt;br /&gt;
&lt;br /&gt;
Damit die Batterietrigger dynamisch geändert werden können, ist die Einstellung als Set-Kommando und nicht als Attribut ausgeführt.   &lt;br /&gt;
&lt;br /&gt;
Alle Triggerpunkte können mit dem set-Befehl:&lt;br /&gt;
&lt;br /&gt;
 reset batteryTriggerSet&lt;br /&gt;
&lt;br /&gt;
wieder gelöscht werden.&lt;br /&gt;
&lt;br /&gt;
== Verbrauchersteuerung - Registrieren und visualisieren 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;
Die Eigenschaften und das Schaltverhalten wird durch die Angabe der verfügbaren Schlüssel gesteuert. Die Möglichkeiten sind sehr umfangreich. Die nachfolgenden Abschnitte beschreiben die Verwendung am Beispiel oft vorkommender bzw. nachgefragter Sachverhalte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die Phasen der Verbrauchersteuerung ===&lt;br /&gt;
&lt;br /&gt;
Jeder Zyklus eines Verbrauchers durchläuft im Modul die folgenden Phasen:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Planung&#039;&#039;&#039; der Aktivzeiten des Verbrauchers, d.h. wann der Verbraucher geplant eingeschaltet sowie geplant ausgeschaltet wird und damit der Zyklus beendet wird.&lt;br /&gt;
# &#039;&#039;&#039;Start&#039;&#039;&#039; des Zyklus, d.h. Einschalten des Verbrauchers entsprechend der Planungsdaten sofern weitere, in den Consumer-Schlüsseln definierbare Rahmenbedingungen das Einschalten nicht verhindern (z.B. kein oder zu wenig PV-Energieerzeugung / PV-Überschuss)&lt;br /&gt;
# &#039;&#039;&#039;Permanente Überprüfung von&#039;&#039;&#039; eventuell vorhandenen &#039;&#039;&#039;Interruptbedingungen&#039;&#039;&#039; die den Verbraucher temporär ausschalten und, sofern die Interruptbedingung nicht mehr vorliegt, den Verbraucher wieder einschalten und so den gestarteten Zyklus fortsetzen.&lt;br /&gt;
#  &#039;&#039;&#039;Beendigung&#039;&#039;&#039; der Zyklus. Die Beendigung erfolgt entweder (normalerweise) wenn die geplante Endezeit der Zyklus erreicht ist oder eine optionale Endebedingung erfüllt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Steuerung der Phasen ====&lt;br /&gt;
Der Ablauf der Phasen kann durch verschiedene Schlüssel-Wert Paare beeinflusst und gesteuert werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; kann eine &#039;&#039;&#039;zusätzliche externe Bedingung&#039;&#039;&#039; definiert werden um den Einschaltvorgang des Consumers freizugeben. Ist die Bedingung (Regex) nicht erfüllt, erfolgt kein Einschalten des Verbrauchers auch wenn die sonstigen Voraussetzungen wie Zeitplanung, on-Schlüssel, auto-Mode und aktuelle PV-Leistung gegeben sind. Es erfolgt somit eine &#039;&#039;&#039;UND-Verknüpfung&#039;&#039;&#039; des Schlüssels swoncond mit den Planungsdaten und weiteren Einschaltbedingungen.&lt;br /&gt;
&lt;br /&gt;
Der optionale Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; definiert eine &#039;&#039;&#039;vorrangige Ausschaltbedingung&#039;&#039;&#039; (Regex). Sobald diese Bedingung erfüllt ist, wird der Consumer ausgeschaltet auch wenn die geplante Endezeit (consumerXX_planned_stop) noch nicht erreicht ist (&#039;&#039;&#039;ODER-Verknüpfung&#039;&#039;&#039;). Weitere Bedingungen wie off-Schlüssel und auto-Mode müssen zum automatischen Ausschalten erfüllt sein.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; kann während der geplanten Einschaltzeit eine automatische Unterbrechung sowie Wiedereinschaltung des Verbrauchers vorgenommen werden. Der Verbraucher wird temporär ausgeschaltet (interrupted) und wieder eingeschaltet (continued) wenn die Interrupt-Bedingung nicht mehr vorliegt. Die verbleibende Laufzeit wird durch einen Interrupt nicht beeinflusst! &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;power&#039;&#039;&#039; gibt die nominale Leistungsaufnahme des Verbrauchers gemäß seines Datenblattes an. Dieser Wert wird verwendet um die Schaltzeiten des Verbrauchers zu planen und das Schalten in Abhängigkeit des tatsächlichen PV-Überschusses zum Einplanungszeitpunkt zu steuern. Ist &#039;&#039;&#039;power=0&#039;&#039;&#039; gesetzt, wird der Verbraucher unabhängig von einem zum Zeitpunkt des Zyklus-Start eventuell nicht ausreichend vorhandenem PV-Überschuss wie geplant eingeschaltet und somit der Zyklus gestartet.&lt;br /&gt;
&lt;br /&gt;
Durch die Schlüssel &#039;&#039;&#039;notbefore&#039;&#039;&#039; und &#039;&#039;&#039;notafter&#039;&#039;&#039; kann der Startzeitpunkt des Verbrauchers so gesteuert werden, dass der Start des Zyklus nicht vor bzw. nach der angegebenen Zeit eingeplant wird. Diese Steuerung bezieht sich auf die &#039;&#039;Planung&#039;&#039;, d.h. der eigentliche Start des Verbrauchers kann sich unter Umständen durch vorhandene Rahmenbedingungen verzögern. &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; legt die geplanten Einschaltzeit, d.h. die Laufzeit des Zyklus fest. Der Name &#039;&#039;&#039;mintime&#039;&#039;&#039; ist nicht als MInimum-Zeit zu deuten, sondern beschreibt die angegebene Zeit in Minuten die der Zyklus dauern soll.&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist optional, da sich die Standard-Laufzeit des Verbrauchers von dessen Typ abgeleitet wird. Diese Standard Laufzeiten sind:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|dryer&lt;br /&gt;
|90 Minten&lt;br /&gt;
|-&lt;br /&gt;
|dishwasher&lt;br /&gt;
|180 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|washingmachine&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|heater&lt;br /&gt;
|240 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|charger&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|other&lt;br /&gt;
|60 Minuten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Der Verbraucher wurde nicht gestartet obwohl die Startzeit der Einplanung erreicht wurde ===&lt;br /&gt;
&lt;br /&gt;
Wenn die Startzeit des Consumers entsprechend der Einplanung erreicht oder überschritten ist, wird der Consumer eingeschaltet wenn die weiteren Voraussetzungen wahr sind:&lt;br /&gt;
&lt;br /&gt;
* es ist aktuell ein PV-Überschuss vorhanden und der PV-Überschuss deckt die kalkulierten Leistungsaufnahme des Verbrauchers ab. Mit den Schlüsseln &#039;&#039;&#039;power&#039;&#039;&#039; und &#039;&#039;&#039;spignorecond&#039;&#039;&#039; kann die Einschaltung trotz fehlendem PV-Überschuss ermöglicht werden. &lt;br /&gt;
&lt;br /&gt;
* die Angabe im Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; ist wahr (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* das Schalten ist über den Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; freigegeben (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* im Schlüssel &#039;&#039;&#039;on&#039;&#039;&#039; ist ein valides Einschaltkommando hinterlegt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind diese zusätzlichen Bedingungen nicht erfüllt, erfolgt kein Start des eingeplanten Zyklus. Der Verbraucher verbleibt in diesem Fall weiterhin im Status &#039;&#039;planned&#039;&#039; oder &#039;&#039;suspended&#039;&#039;. Die Startbedingungen werden regelmäßig reviewed und der Consumer gestartet sobald alle Startbedingungen wahr sind bzw. Start verhindernde Bedingungen entfallen sind. &lt;br /&gt;
&lt;br /&gt;
Dieser Vorgang erfolgt bis das geplante Ende des Verbaucherzyklus erreicht ist oder die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; zutrifft. Sobald die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; wahr ist, wird der gesamte Planungszyklus des Consumers beendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Kann manuell / automatisiert in den Planungszyklus eines Verbrauchers eingegriffen werden? ===&lt;br /&gt;
&lt;br /&gt;
Die Einplanung und die darauf aufbauenden Schaltprozesse laufen gemäß den hinterlegten Schlüsseloptionen im Modul automatatisch ab ohne dass ein Eingriff durch den Anwender erfolgen muß.&lt;br /&gt;
&lt;br /&gt;
Dennoch kann es gewünscht sein eine Neuplanung oder eine Sofortplanung eines Consumers vorzunehmen weil der Bedarf dazu besteht. Zu diesem Zweck stehen die Set-Kommandos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* consumerNewPlanning &lt;br /&gt;
&lt;br /&gt;
* consumerImmediatePlanning &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
zur Verfügung. &lt;br /&gt;
Beide Befehle initiieren die Consumer-Neuplanung, wobei mit dem Befehl &#039;&#039;consumerImmediatePlanning&#039;&#039; die eventuell im consumerXX Attribut gesetzten Schlüssel notbefore, notafter bzw. mode werden nicht beachtet werden. Dagenen beachtet der Befehl &#039;&#039;consumerNewPlanning&#039;&#039; alle definierten Schlüsseloptionen und dient gewöhnlich dazu einen abgeschlossenen Verbraucherzyklus wiederholt ausführen zu lassen weil die aktuelle Witterungslage dazu geeignet ist. &lt;br /&gt;
&lt;br /&gt;
Ein Anwendungsbeispiel dafür ist zum Beispiel die Ausführung von mehreren Waschmaschinen-Zyklen an einem langen, sonnigen Sommertag.&lt;br /&gt;
Diese beiden Set-Befehle können zum Beispiel über ein auf einen Schalter/Taster reagierendes Notify oder DOIF Device ausgeführt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung eines Verbrauchers mit getrennten Geräten für Messung und Schalten ===&lt;br /&gt;
&lt;br /&gt;
Es existieren in FHEM Geräte, die über verschiedene Kanäle für unterschiedliche Aufgaben verfügen. Diese Kanäle werden jeweils in einem gesonderten Device abgebildet. HomeMatic oder readingsProxy sind Beispiele für solche Varianten.&lt;br /&gt;
&lt;br /&gt;
Um solche Verbraucher einzubinden gibt es im consumerXX Attribut den Schlüssel &#039;&#039;&#039;switchdev&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Bei der Registrierung gibt man als Consumerdevice das Gerät für die Messung an und im Schüssel switchdev das entsprechende FHEM-Device, welches für die Schaltvorgänge benutzt wird. &lt;br /&gt;
Ist switchdev angegeben, beziehen sich die weiteren Schlüssel on, off, swstate, auto und asynchron auf dieses Gerät.&lt;br /&gt;
&lt;br /&gt;
In dem nachfolgenden Beispiel (Homematic) ist &#039;&#039;eg.az.fridge_Pwr&#039;&#039; FHEM Device für die Energiemessung. Die Schlüssel &#039;&#039;pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; geben Readings in diesem Device an damit SolarForecast den Verbrauch und die Energiemengen auslesen kann. Demgegenüber ist im Schlüssel &#039;&#039;switchdev&#039;&#039; das zugehörige Schalter-Device der Kombination angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eg.az.fridge_Pwr&lt;br /&gt;
type=noSchedule switchdev=eg.az.fridge_Sw power=0 icon=fridge pcurr=power:W:5 etotal=energyCalc:Wh &lt;br /&gt;
swstate=state:on:off auto=automatic&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung von Verbrauchern ohne Zeitplanung und aktivem Schalten ===&lt;br /&gt;
Manchmal besteht der Wunsch, Verbraucher in SolarForecast zu integrieren um lediglich folgende Sachverhalte abzubilden:&lt;br /&gt;
&lt;br /&gt;
* Visualisierung des Schaltstatus in der Consumer Legende und/oder der Energieflußgrafik&lt;br /&gt;
* Darstellung des aktuellen Energieverbrauchs in der Energieflußgrafik&lt;br /&gt;
* Erfassung der (externen) Schaltzeiten, d.h. der Zeiten der Gerätenutzung sowie der Verbrauchsdaten um deren Einfluß bei den Planungszeiten anderer Geräte durch SolarForecast berücksichtigen zu lassen&lt;br /&gt;
&lt;br /&gt;
In solchen Fällen werden bei der Registrierung die Schlüssel &#039;&#039;swstate, pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; zur Erfassung der Schaltzustände und der Energieverbrauchs angegeben, jedoch zur Verhinderung der Zeitplanung durch SolarForecast der Schlüssel &#039;&#039;&#039;type=noSchedule&#039;&#039;&#039; gesetzt sowie die Schlüssel &#039;&#039;on&#039;&#039; und &#039;&#039;off&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt eine mögliche Registrierung eines Zwischensteckers (Shelly) zur Erfassung der Daten eines Gefrierschrankes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Shelly.shellyplug4&lt;br /&gt;
type=noSchedule power=65 asynchron=1&lt;br /&gt;
icon=gefrierschrank &lt;br /&gt;
swstate=state:.*on.*:.*off.* &lt;br /&gt;
pcurr=relay_0_power:W:5 etotal=relay_0_energy_Wh:Wh&lt;br /&gt;
&amp;lt;/pre&amp;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;
&lt;br /&gt;
 Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off&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;
&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;
&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. Alternativ kann die Berücksichtigung des zwangsweisen PV Überschuss mit dem Schlüssel &amp;quot;spignorecond&amp;quot; im Consumer-Attribut ausgesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== zusätzliche Readings bzw. Erzeugung von statistischen Readings ==&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den zahlreichen im Modul per Standard erzeugten Readings kann der Anwender weitere Readings generieren lassen.&lt;br /&gt;
Diese zusätzlichen Readings geben entweder einen bestimmten Sachverhalt (Laufzeit, Status der API-Abfragen, etc.) oder einen statistischen Wert, z.B. die Batterieentladung des aktuellen Tages, wieder.&lt;br /&gt;
&lt;br /&gt;
Die zusätzlich erstellten Readings sind durch den Präfix &#039;&#039;&#039;special_&#039;&#039;&#039; im Device gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Diese zusätzlichen Informationen können durch das Setzen einer oder mehrerer Kennzeichen im Attribut &#039;&#039;&#039;ctrlSpecialReadings&#039;&#039;&#039; erzeugt werden. Die mögliche Auswahl wird je nach Bedarf ausgebaut und umfasst zum aktuellen Zeitpunkt (07.02.2025) diese Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;BatPowerIn_Sum: 	die Summe der momentanen Batterieladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;BatPowerOut_Sum: 	die Summe der momentanen Batterieentladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;allStringsFullfilled: 	Erfüllungsstatus der fehlerfreien Generierung aller Strings&lt;br /&gt;
;conForecastTillNextSunrise: 	Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
;currentAPIinterval: 	das aktuelle Abrufintervall der gewählten Strahlungsdaten-API in Sekunden&lt;br /&gt;
;currentRunMtsConsumer_XX: 	die Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; seit dem letzten Einschalten. (letzter Laufzyklus)&lt;br /&gt;
;dayAfterTomorrowPVforecast: 	liefert die Vorhersage der PV Erzeugung für Übermorgen (sofern verfügbar) ohne Autokorrektur (Rohdaten).&lt;br /&gt;
;daysUntilBatteryCare_XX: 	Tage bis zur nächsten Batterie XX Pflege (Erreichen der Ladung &#039;maxSoC&#039; aus Attribut ctrlBatSocManagementXX)&lt;br /&gt;
;lastretrieval_time: 	der letzte Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;lastretrieval_timestamp: 	der Timestamp der letzen Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;response_message: 	die letzte Statusmeldung der gewählten Strahlungsdaten-API&lt;br /&gt;
;runTimeAvgDayConsumer_XX: 	die durchschnittliche Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; an einem Tag&lt;br /&gt;
;runTimeCentralTask: 	die Laufzeit des letzten SolarForecast Intervalls (Gesamtprozess) in Sekunden&lt;br /&gt;
;runTimeTrainAI: 	die Laufzeit des letzten KI Trainingszyklus in Sekunden&lt;br /&gt;
;runTimeLastAPIAnswer: 	die letzte Antwortzeit des Strahlungsdaten-API Abrufs auf einen Request in Sekunden&lt;br /&gt;
;runTimeLastAPIProc: 	die letzte Prozesszeit zur Verarbeitung der empfangenen Strahlungsdaten-API Daten&lt;br /&gt;
;SunMinutes_Remain: 	die verbleibenden Minuten bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;SunHours_Remain: 	die verbleibenden Stunden bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;todayConsumptionForecast: 	Verbrauchsprognose pro Stunde des aktuellen Tages (01-24)&lt;br /&gt;
;todayConForecastTillSunset: 	Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
;todayDoneAPIcalls: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Calls&lt;br /&gt;
;todayDoneAPIrequests: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Requests&lt;br /&gt;
;todayConsumption: 	der gesamte Energieverbrauch (Wh) des Hauses am aktuellen Tag&lt;br /&gt;
;todayGridConsumption: 	die aus dem öffentlichen Netz bezogene Energie am aktuellen Tag&lt;br /&gt;
;todayGridFeedIn: 	die in das öffentliche Netz eingespeiste PV Energie am aktuellen Tag&lt;br /&gt;
;todayMaxAPIcalls: 	die maximal mögliche Anzahl Strahlungsdaten-API Calls. Ein Call kann mehrere API Requests enthalten.&lt;br /&gt;
;todayRemainingAPIcalls: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Calls&lt;br /&gt;
;todayRemainingAPIrequests: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Requests&lt;br /&gt;
;todayBatIn_XX: 	die am aktuellen Tag in die Batterie XX geladene Energie&lt;br /&gt;
;todayBatInSum: 	Summe der am aktuellen Tag in alle Batterien geladene Energie&lt;br /&gt;
;todayBatOut_XX: 	die am aktuellen Tag aus der Batterie XX entnommene Energie&lt;br /&gt;
;todayBatOutSum: 	Summe der am aktuellen Tag aus allen Batterien entnommene Energie&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Manche Angaben sind im Setup des Moduls optional, d.h. sie müssen nicht zwingend beim Setup angegeben werden. Allerdings sind diese Angaben für die Erstellung eines zusätzlichen Readings unter Umständen Voraussetzung. Es empfiehlt sich deshalb bei Setup so viele Informationen wie möglich zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
So ist zum Beispiel für die sinnvolle Erstellung der Informationen &#039;&#039;&#039;todayBatInSum&#039;&#039;&#039; und &#039;&#039;&#039;todayBatOutSum&#039;&#039;&#039; (Readings special_todayBatInSum und special_todayBatOutSum) das Vorhandensein der Schlüssel &#039;&#039;intotal&#039;&#039; und &#039;&#039;outtotal&#039;&#039; im Attribut setupBatteryDevXX notwendig (Beispiel):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupBatteryDev01 MQTT2_cerboGX_c0619ab34e08_battery &lt;br /&gt;
                              pin=BatIn:W pout=BatOut:W charge=SOC_value intotal=BatInTotal:Wh outtotal=BatOutTotal:Wh &lt;br /&gt;
                              cap=InstalledCapacity_Wh:Wh asynchron=1 show=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Fehlersuche ==&lt;br /&gt;
Das Modul SolarForecast ist sehr komplex und es die verschiedensten Datenquellen ausgewertet, zusammengeführt und daraus Ergebnisse berechnet und/oder visualisiert. Wird etwas nicht wie erwartet durch das Modul geliefert, können die Ursachen vielfältig sein. Natürlich kann ein Fehler im Modulcode vorliegen, oftmals gibt es aber andere Ursachen.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgenden Hinweise sollen Hilfe zur Selbsthilfe geben und sind eine Zusammenfassung von realen Fällen die mit dem beschriebenen Wegen und Verfahren gelöst wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die erwartete erzeugte PV-Energie ist im Modul zu gering und wird im Balkendiagramm nicht angezeigt === &lt;br /&gt;
&lt;br /&gt;
Die erzeugte PV-Energie wird nicht richtig angezeigt: Am Vormittag sind keine Werte vorhanden und, wenn dann etwas kommt, ist die Anzeige zu gering. Für 13 und 14 Uhr wurden ca. 5.000Wh erwartet (im Vergleich mit den Daten aus einer anderen Auswertungsquelle). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lösungsweg:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Aus dem List des Devices wurden die für den Fall wesentlichen Readings herausgezogen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVforecast 152 Wh&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVforecast 1400 Wh&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVforecast 2500 Wh&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVforecast 4392 Wh&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVforecast 4000 Wh&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVreal 300 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVforecast 6415 Wh&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVreal 3200 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVforecast 5629 Wh&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVreal 2700 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVforecast 3958 Wh&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVreal 900 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVforecast 945 Wh&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVreal 500 Wh&lt;br /&gt;
   &lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour18_PVforecast 59 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man sieht dass bis 12:00 keine erzeugte Energie vom WR gemeldet wird. Deswegen wird in der Balkengrafik nichts dargestellt. Auch danach bleibt die registrierte PV-Energie hinter den Erwartungen zurück. Zuständig für die Lieferung der PV-Energie an das Modul ist das Reading im Schlüssel:&lt;br /&gt;
&lt;br /&gt;
 setupInverterDev01 SH10rt pv=Total_DC_Power:W &amp;lt;mark&amp;gt;etotal=Total_Export_Energy_from_PV:kWh&amp;lt;/mark&amp;gt; capacity=10000 strings=Hauptdach,Flachdach&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Welche Änderungen es zwischen den Stunden gab, sieht man mit einem &amp;quot;get ... pvHistory XX&amp;quot; (&amp;quot;XX&amp;quot; steht für das Datum, d.h. den Tag, z.B. 02). &amp;lt;br&amp;gt;&lt;br /&gt;
Hier ein Beispiel für die Stunden 10 (9:00 - 9:59) und 11 (10:00 - 10:59). &amp;lt;br&amp;gt;&lt;br /&gt;
Wichtig ist hier der Key etotali01 für den ersten Inverter. Die Differenz zwischen den Werten beider Stunden ist die in der Stunde erzeugte Energie (hier 380 Wh). Diese 380 Wh findest du auch im Key pvrl01 als PVReal für diese Stunde. Das Modul rechnet intern immer mit Wh, kWh werden vorher in Wh umgerechnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
10 =&amp;gt; pvfc: 365, pvrl: 530, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63364714&amp;lt;/mark&amp;gt;, etotali02: 3044110, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;pvrl01: 380&amp;lt;/mark&amp;gt;, pvrl02: 150, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 574, con: 518, gcons: 22, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 1, feedprice: 0.1269&lt;br /&gt;
&lt;br /&gt;
            DoN: 1, sunaz: 137, sunalt: 12&lt;br /&gt;
&lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
      11 =&amp;gt; pvfc: 2966, pvrl: 1862, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63365094&amp;lt;/mark&amp;gt;, etotali02: 3044260, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            pvrl01: 1392, pvrl02: 470, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 774, con: 609, gcons: 25, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 4, feedprice: 0.1269&lt;br /&gt;
           &lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
D.h. wenn zwischen den beiden Stunden keine Differenzen zu finden sind, liegt es sehr wahrscheinlich am Input des Readings:&lt;br /&gt;
&lt;br /&gt;
 etotal=Total_Export_Energy_from_PV:kWh&lt;br /&gt;
&lt;br /&gt;
welches sich in den ersten Stunden nicht ändert und danach auch nur wenig.&lt;br /&gt;
&lt;br /&gt;
Man kann mit dem Attribut:&lt;br /&gt;
&lt;br /&gt;
 ctrlDebug=collectData&lt;br /&gt;
&lt;br /&gt;
die Datensammlung verfolgen (leider entstehen viele Daten im Log). Man sieht welche Werte von dem Inverter/Reading geliefert werden:&lt;br /&gt;
 &lt;br /&gt;
 ....&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; collect Inverter 01 data - device: STP_5000, delivery: default =&amp;gt;&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; pv: 0 W, &amp;lt;mark&amp;gt;etotal: 63378810 Wh&amp;lt;/mark&amp;gt;&lt;br /&gt;
 ....&lt;br /&gt;
&lt;br /&gt;
Dieser Wert muß bei PV Erzeugung kontinuierlich hochzählen. Wenn nicht, muss das angegebene Reading, d.h. die Quelle überprüft werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ergebnis der Prüfung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tatsächlich wurde ein Reading benutzt, das ungeeignet war: Statt &amp;quot;Total_PV_Generation&amp;quot; wurde &amp;quot;Total_export_energy_from_PV&amp;quot; genutzt. In diesem Reading wurde immer die in die Batterie gespeicherte Energie von der gesamten erzeugten Energie abgezogen. Daher war auch vormittags alles 0, da in dieser Periode alle PV-Energie in die Batterie geladen wurde bzw. in weiteren Stunden ein Anteil der dann bei dem PV-Erzeugungswert fehlte.&lt;br /&gt;
&lt;br /&gt;
Nachdem die Ursache beseitigt war, zeigt SolarForecast wieder die erwarteten PV-Erzeugungswerte an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Konfigurationsbeispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Visualisierung solare Vorhersage und reale Erzeugung ===&lt;br /&gt;
&lt;br /&gt;
Zu Beginn jedes neuen Tages gegen 00:00 Uhr werden durch das SolarForecast Device Events für die initiale PV Prognose des kommenden Tages erstellt.&lt;br /&gt;
Der Readingteil dieser Events heißt&lt;br /&gt;
&lt;br /&gt;
 AllPVforecastsToEvent&lt;br /&gt;
&lt;br /&gt;
Die Uhrzeiten der Events sind so aufbereitet und können direkt geloggt werden um sie in einen SVG Plot zu integrieren.&lt;br /&gt;
Im SolarForecast Device ist dieses Reading nicht sichtbar, nur die Events werden erstellt.&lt;br /&gt;
&lt;br /&gt;
Die meteorologischen Bedingungen verändern sich über den Tag permanent. Je nach gewählter Strahlungsdatenquelle (eine API oder DWD Device) erfolgt eine mehr oder weniger dynamische Anpassung der Prognose an die sich verändernde Umwelt.&lt;br /&gt;
&lt;br /&gt;
Aktuelle Prognosedaten sowie die reale PV Erzeugung der vergangenen Stunde können über die Readings&lt;br /&gt;
&lt;br /&gt;
 LastHourPVforecast&lt;br /&gt;
 LastHourPVreal&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-10-20 134050.png|right|thumb|400px|Übersicht solare Vorhersage]]&lt;br /&gt;
geloggt werden. &lt;br /&gt;
&lt;br /&gt;
Werden alle drei Werte in einem SVG kombiniert, kann die Entwicklung der Prognose über den Tag und die Beziehung von Prognose zu realer PV Erzeugnung pro Stunde visualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Für das rechts abgebildete Beispiel des Plots aus einer Datenbank &amp;quot;LogDBShort&amp;quot; sieht das gplot-File wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Created by FHEM/98_SVG.pm, 2024-03-08 15:05:31&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;TL&amp;gt;&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid&lt;br /&gt;
set ylabel &amp;quot;Wh&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Wh&amp;quot;&lt;br /&gt;
set yrange [0:7500]&lt;br /&gt;
set y2range [0:7500]&lt;br /&gt;
&lt;br /&gt;
#LogDBShort SolCast:LastHourPVforecast:::&lt;br /&gt;
#LogDBShort SolCast:LastHourPVreal:::&lt;br /&gt;
#LogDBShort SolCast:AllPVforecastsToEvent:::&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;aktuelle PV Vorhersage&#039; ls l6fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;reale PV Erzeugung&#039; ls l2fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;initiale PV Vorhersage&#039; ls l4 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; In manchen Fällen werden die Vorhersagewerte im SVG-Plot nicht angezeigt wenn FileLog verwendet wird. Ein Setzen des Attribute &amp;quot;fixedrange=3days +1&amp;quot; im SVG löst das Problem. Die Definition des SVG-Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_LogDBShort_SolCast SVG LogDBShort:SVG_LogDBShort_SolCast:HISTORY&lt;br /&gt;
attr SVG_LogDBShort_SolCast fixedrange 3days +1&lt;br /&gt;
attr SVG_LogDBShort_SolCast room Energie-&amp;gt;SolarPrognose&lt;br /&gt;
attr SVG_LogDBShort_SolCast sortby 2&lt;br /&gt;
attr SVG_LogDBShort_SolCast title &amp;quot;Übersicht solare Vorhersage&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Technisch bedingt werden an einem Tag X kurz nach 00:00 Uhr die am Vortag für den Tag X erzeugten Events aktualisiert. Diese Daten erzeugen in der Datenbank einen zweiten Satz an Daten mit dem gleichen Timestamp was für die Anzeige unvorteilhaft ist. &lt;br /&gt;
Um nur die aktualisierten Events von &#039;&#039;&#039;AllPVforecastsToEvent&#039;&#039;&#039; in der Datenbank zu erhalten, bietet sich ein DbRep-Device an. Die nachfolgende Vorschlagsdefinition kann per at-Device jeden Tag kurz vor Mitternacht (z.B. 23:57:10) ausgeführt werden. Es werden immer die in der Vergangenheit geschriebenen (veralteten) Daten aus der Datenbank gelöscht, doppelte Datesätze vermieden und immer die aktuellste initiale Prognose gespeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.Del.AllPVforecastsToEvent DbRep LogDBShort&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent alias Löschen Readings AllPVforecastsToEvent des Folgetages&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent comment ermöglicht dass die Readings AllPVforecastsToEvent am Folgetag wieder neu und aktuell geschrieben werden können&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent devStateIcon initialized:control_3dot_hor_s connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent disable 0&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent event-on-update-reading state&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent icon edit_delete&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent showproctime 1&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent device TYPE=SolarForecast&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_begin next_day_begin&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_end next_day_end&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das angegebene DbLog-Device &#039;&#039;&#039;LogDBShort&#039;&#039;&#039; ist natürlich anzupassen.&lt;br /&gt;
&lt;br /&gt;
Das at-Device zum Starten der Datenbankbereinigung sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define At.Del.AllPVforecastsToEvent at *23:58:10 set Rep.Del.AllPVforecastsToEvent delEntries&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent alias Start Löschen Readings AllPVforecastsToEventn LogDBShort&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent icon clock&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich sind auch hier die eigenen Devicenamen entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
Ab SolarForecast Version 1.51.7 kann die Eventerzeugung für bestimmte SVG Plot-Typen optimiert werden. &amp;lt;br&amp;gt; &lt;br /&gt;
Die Aktivierung dieser Optimierungen ist in der Online Hilfe zum Attribut &#039;&#039;&#039;plantControl-&amp;gt;genPVforecastsToEvent&#039;&#039;&#039; beschrieben. Bei Nutzung des Attributes plantControl-&amp;gt;genPVforecastsToEvent ist ebenfalls das Attribut &#039;&#039;&#039;event-on-update-reading=AllPVforecastsToEvent&#039;&#039;&#039; zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispielkonfiguration 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;
Bitte dabei diese DWD-Version aus dem [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter Contrib] von DS_Starter dazu nutzen&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|55_DWD_OpenData.pm&lt;br /&gt;
|136.2 KB ​&lt;br /&gt;
|29260  &lt;br /&gt;
|DS_Starter&lt;br /&gt;
|55_DWD_OpenData: contrib 1.17.7&lt;br /&gt;
|}&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 downloadTimeout 120&lt;br /&gt;
attr DWD comment Im DWD Wetterdevice verwendet Solarforecast : \&lt;br /&gt;
TTT,Neff,RR1c,ww,SunUp,SunRise,SunSet \&lt;br /&gt;
zusätzlich ist jedoch auch noch Rad1h notwendig \&lt;br /&gt;
wenn dieses DWD-Device als Strahlungsdevice genutzt wird.\&lt;br /&gt;
Die Station 10418 (Lüdenscheid) überträgt aktuell am 09.03.2025 (noch) Rad1h.\&lt;br /&gt;
attr DWD downloadTimeout 120&lt;br /&gt;
attr DWD forecastDays 7&lt;br /&gt;
attr DWD forecastProperties SunUp, SunRise, SunSet, Rad1h, R101, RR1c, TTT, Tx, Tn, Tg, DD, FX1, RR6c, R600, RRhc, Rh00, ww, wwd, Neff&lt;br /&gt;
attr DWD forecastRefresh 1&lt;br /&gt;
attr DWD forecastResolution 1&lt;br /&gt;
attr DWD forecastStation 10418&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 fc_description  -(state fc_time)&lt;br /&gt;
attr DWD verbose 2&lt;br /&gt;
&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;
defmod InverterDummy dummy&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;
defmod 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 feedinPrice 0.08&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 powerCost 0.25&lt;br /&gt;
attr SMA_Energymeter room 015_Zaehler,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;
defmod 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;
attr BatteryDummy userReadings total_pac, power_out, power_in, chargestatus, bat_rated_capacity, bat_loadtotal, bat_unloadtotal&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;
defmod N.PV.TotalConsumption.Dum.Energy notify SMA_Energymeter:Saldo_Wirkleistung:.* {\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung_2 Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&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;MB_USRW610_004&amp;quot;,&amp;quot;Power_Sum__W&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;
fhem &amp;quot;setreading InverterDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(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;
#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;
 # Batterie-total_pac  InverterDummy\&lt;br /&gt;
my $wert7 = sprintf(&amp;quot;%.3f&amp;quot;,((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy bat_rated_capacity &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert7));;\&lt;br /&gt;
 # möglicher Aufruf einer Batterie-Bebladung-Routine....SMABatteryChargewithTibber();;\&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;
defmod Forecast SolarForecast&lt;br /&gt;
attr Forecast DbLogExclude .*&lt;br /&gt;
attr Forecast DbLogInclude Current_BatCharge999&lt;br /&gt;
attr Forecast affectBatteryPreferredCharge 30&lt;br /&gt;
attr Forecast affectConsForecastLastDays 31&lt;br /&gt;
attr Forecast affect70percentRule 0&lt;br /&gt;
attr Forecast comment &amp;quot;wget -qO ./FHEM/76_SolarForecast.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/76_SolarForecast.pm&amp;quot;\&lt;br /&gt;
&amp;quot;wget -qO ./FHEM/55_DWD_OpenData.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/55_DWD_OpenData.pm&amp;quot;\&lt;br /&gt;
&amp;quot;13.01.2025 mit der Version 76_SolarForecast.pm:v1.43.2-s29518/2025-01-12&amp;quot;&lt;br /&gt;
attr Forecast graphicHeaderOwnspec PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal Verbrauch&amp;amp;nbsp;;bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast  Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest FCU-Erzeugung&amp;amp;nbsp;;:Current_PP01\&lt;br /&gt;
attr Forecast consumer01 FBDECT_fbahahttp_11657_0127183 icon=scene_washing_machine@orange type=washingmachine power=10 swstate:state notbefore=09 notafter=20 pcurr=power:W:3 etotal=energy:Wh interruptable=1 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer02 FBDECT_fbahahttp_E8_DF_70_07_3E_57 icon=light_floor_lamp@orange type=other power=15 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer03 FBDECT_fbahahttp_E8_DF_70_07_42_0B icon=raspberrypi@orange type=other power=8 swstate:state pcurr=power:W:1 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer04 FBDECT_fbahahttp_11657_0067275 icon=springbrunnen_icon@orange type=other power=50 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer05 FBDECT_fbahahttp_34_31_C4_D4_31_37 icon=sani_domestic_waterworks@orange type=other power=10 swstate:state pcurr=power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer06 tuya_local_bf5037060f450bdbd4rl0q icon=scene_clothes_dryer@orange type=dryer power=10 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer07 tuya_local_bfac44fb487476efd1vhdu icon=weather_sunset@orange type=noSchedule power=5 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumerControl adviceIcon=light_light_dim_100@gold&lt;br /&gt;
attr Forecast consumerControl showLegend=icon_top&lt;br /&gt;
attr Forecast consumerControl detailLink=1&lt;br /&gt;
attr Forecast ctrlAIdataStorageDuration 1825&lt;br /&gt;
attr Forecast ctrlAIshiftTrainStart 2&lt;br /&gt;
attr Forecast ctrlBatSocManagement01 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlBatSocManagement02 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlDebug none&lt;br /&gt;
attr Forecast plantControl genPVdeviation=continuously&lt;br /&gt;
attr Forecast plantControl cycleInterval=15&lt;br /&gt;
attr Forecast ctrlNextDayForecastReadings 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24&lt;br /&gt;
attr Forecast ctrlNextHoursSoCForecastReadings 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23&lt;br /&gt;
attr Forecast ctrlSpecialReadings BatPowerIn_Sum,BatPowerOut_Sum,SunHours_Remain,SunMinutes_Remain,allStringsFullfilled,conForecastTillNextSunrise,currentAPIinterval,currentRunMtsConsumer_01,currentRunMtsConsumer_02,currentRunMtsConsumer_03,currentRunMtsConsumer_04,currentRunMtsConsumer_05,currentRunMtsConsumer_06,currentRunMtsConsumer_07,dayAfterTomorrowPVforecast,daysUntilBatteryCare_01,daysUntilBatteryCare_02,lastretrieval_time,lastretrieval_timestamp,response_message,runTimeAvgDayConsumer_01,runTimeAvgDayConsumer_02,runTimeAvgDayConsumer_03,runTimeAvgDayConsumer_04,runTimeAvgDayConsumer_05,runTimeAvgDayConsumer_06,runTimeAvgDayConsumer_07,runTimeCentralTask,runTimeLastAPIAnswer,runTimeLastAPIProc,runTimeTrainAI,todayBatIn_01,todayBatIn_02,todayBatOut_01,todayBatOut_02,todayConForecastTillSunset,todayConsumptionForecast,todayDoneAPIcalls,todayDoneAPIrequests,todayGridConsumption,todayGridFeedIn,todayMaxAPIcalls,todayRemainingAPIcalls,todayRemainingAPIrequests&lt;br /&gt;
attr Forecast disable 0&lt;br /&gt;
attr Forecast event-min-interval .*:1800&lt;br /&gt;
attr Forecast event-on-change-reading .*&lt;br /&gt;
attr Forecast flowGraphicControl animate=1 consumerdist=80 h2consumerdist=50 shiftx=0  shifty=0 showconsumer=1 showconsumerdummy=1 showconsumerpower=1 showconsumerremaintime=0 size=400 strokewidth=12&lt;br /&gt;
attr Forecast graphicBeam1Color 3C14FF&lt;br /&gt;
attr Forecast graphicBeam1Content pvReal&lt;br /&gt;
attr Forecast graphicBeam2Color 19FF29&lt;br /&gt;
attr Forecast graphicBeam2Content pvForecast&lt;br /&gt;
attr Forecast graphicBeam3Color D60924&lt;br /&gt;
attr Forecast graphicBeam3Content batsocforecast_02&lt;br /&gt;
attr Forecast graphicBeam3FontColor FFFF0D&lt;br /&gt;
attr Forecast graphicBeam4Color FFFF1F&lt;br /&gt;
attr Forecast graphicBeam4Content batsocforecast_01&lt;br /&gt;
attr Forecast graphicBeam4FontColor 000000&lt;br /&gt;
attr Forecast graphicBeamHeightLevel1 200&lt;br /&gt;
attr Forecast graphicBeamHeightLevel2 200&lt;br /&gt;
attr Forecast graphicHeaderDetail all&lt;br /&gt;
attr Forecast graphicHeaderOwnspec #PV\&lt;br /&gt;
PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal\&lt;br /&gt;
PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast\&lt;br /&gt;
PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast\&lt;br /&gt;
:\&lt;br /&gt;
#\&lt;br /&gt;
AutarkyRate:Current_AutarkyRate\&lt;br /&gt;
Überschuss:Current_Surplus\&lt;br /&gt;
aktueller&amp;amp;nbsp;;Netzbezug:Current_GridConsumption\&lt;br /&gt;
:\&lt;br /&gt;
#Verbrauch\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenuntergang:special_todayConForecastTillSunset\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie01\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_01\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_01\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_01\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_01\&lt;br /&gt;
#Batterie01_tmp\&lt;br /&gt;
Current_PowerBatIn_01:Current_PowerBatIn_01\&lt;br /&gt;
Current_PowerBatOut_01:Current_PowerBatOut_01\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie02\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_02\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_02\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_02\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_02\&lt;br /&gt;
#Batterie02_tmp\&lt;br /&gt;
Current_PowerBatIn_02:Current_PowerBatIn_02\&lt;br /&gt;
Current_PowerBatOut_02:Current_PowerBatOut_02\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Settings\&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto \&lt;br /&gt;
Wetter:graphicShowWeather\&lt;br /&gt;
History:graphicHistoryHour\&lt;br /&gt;
ShowNight:graphicShowNight\&lt;br /&gt;
Debug:ctrlDebug\&lt;br /&gt;
FCU-Modus:FCU-Betriebsmodus@FCU&lt;br /&gt;
attr Forecast graphicHistoryHour 4&lt;br /&gt;
attr Forecast graphicHourCount 24&lt;br /&gt;
attr Forecast graphicLayoutType double&lt;br /&gt;
attr Forecast graphicShowDiff top&lt;br /&gt;
attr Forecast graphicShowNight 1&lt;br /&gt;
attr Forecast graphicShowWeather 1&lt;br /&gt;
attr Forecast group Energy Meter&lt;br /&gt;
attr Forecast room 020_PV,Energie&lt;br /&gt;
attr Forecast setupBatteryDev01 SBS25 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupBatteryDev02 SBS25_2 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupInverterDev01 SB25 pv=total_pac:kW etotal=etotal:kWh capacity=2500 strings=GarageSE limit=70&lt;br /&gt;
attr Forecast setupInverterDev02 SB30 pv=total_pac:kW etotal=etotal:kWh capacity=3000 strings=GarageNW,HausNW limit=70&lt;br /&gt;
attr Forecast setupInverterDev03 SB40 pv=total_pac:kW etotal=etotal:kWh capacity=4000 strings=HausSE1,HausSE2,HausSW limit=70&lt;br /&gt;
attr Forecast setupInverterStrings GarageSE,GarageNW,HausNW,HausSW,HausSE1,HausSE2&lt;br /&gt;
attr Forecast setupMeterDev SMA_Energymeter gcon=Bezug_Wirkleistung:W contotal=Bezug_Wirkleistung_Zaehler:kWh gfeedin=Einspeisung_Wirkleistung:W feedtotal=Einspeisung_Wirkleistung_Zaehler:kWh conprice=0.25:€ feedprice=0.08123:€&lt;br /&gt;
attr Forecast setupOtherProducer01 icon=Heizung_FCU_green@red MB_USRW610_004 pcurr=Power_L1__W:W etotal=Energy_L1_import__kWh:kWh&lt;br /&gt;
attr Forecast setupRadiationAPI DWD&lt;br /&gt;
attr Forecast setupStringPeak GarageSE=2.75 GarageNW=3.200 HausNW=2.230 HausSW=2.230 HausSE1=2.200 HausSE2=2.200&lt;br /&gt;
attr Forecast setupWeatherDev1 DWD&lt;br /&gt;
attr Forecast stateFormat Current_PV&lt;br /&gt;
attr Forecast userReadings Current_BatCharge999 {((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))) / ( (ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0) * 1000)  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0)*1000))*100}&lt;br /&gt;
attr Forecast verbose 2&lt;br /&gt;
&lt;br /&gt;
setstate Forecast 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .FCU_FCU-Betriebsmodus 2&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_ctrlDebug none&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicHistoryHour 4&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowNight 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowWeather 1&lt;br /&gt;
setstate Forecast 2025-01-13 08:24:25 .associatedWith SMA_Energymeter FBDECT_fbahahttp_11657_0127183 FBDECT_fbahahttp_E8_DF_70_07_3E_57 FBDECT_fbahahttp_E8_DF_70_07_42_0B FBDECT_fbahahttp_11657_0067275 FBDECT_fbahahttp_34_31_C4_D4_31_37 tuya_local_bf5037060f450bdbd4rl0q tuya_local_bfac44fb487476efd1vhdu SBS25 SBS25_2 SB25 SB30 SB40 DWD MB_USRW610_004&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .lastupdateForecastValues 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .pvCorrectionFactor_Auto_Soll on_complex_ai&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .signaldone_01 done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .signaldone_02 done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .signaldone_03 done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .signaldone_04 done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .signaldone_05 done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .signaldone_06 done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .signaldone_07 done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .signaldone_08 done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .signaldone_09 done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .signaldone_10 done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .signaldone_11 done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .signaldone_12 done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .signaldone_13 done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .signaldone_14 done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .signaldone_15 done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .signaldone_16 done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .signaldone_17 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .signaldone_18 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_01 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_02 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_01 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_02 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_AutarkyRate 83 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 Current_BatCharge999 10&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_01 12 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_02 8 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Consumption 626 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridConsumption 2 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridFeedIn 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PP_01 746.0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PV 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_01 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_02 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_01 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_02 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumption 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumptionRate 0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Surplus 120 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourGridconsumptionReal 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_ConsumptionForecast 2944 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayConsumptionForecast 3609 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_01 272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PPreal_01 748 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PPreal_01 787 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_01 271 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PPreal_01 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PPreal_01 745 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_01 267 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PPreal_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_01 255 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PPreal_01 752 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_01 226 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_01 50 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PPreal_01 681 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_02 233 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_01 845 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridConsumption 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_01 37 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_02 90 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_01 351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_02 188 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridConsumption 447 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVforecast 127 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridConsumption 1650 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVforecast 478 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVreal 26 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridConsumption 513 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVforecast 868 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVreal 97 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridConsumption 576 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVforecast 1157 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVreal 320 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_01 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_02 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridConsumption 1272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridFeedIn 7 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVforecast 1238 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVreal 945 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_01 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_02 53 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridConsumption 955 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridFeedIn 31 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PPreal_01 562 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVforecast 1168 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVreal 1410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_01 703 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_02 500 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_01 22 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_02 18 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridConsumption 32 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridFeedIn 71 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PPreal_01 777 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVreal 1416 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_01 296 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_02 70 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_01 74 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_02 258 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridConsumption 13 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridFeedIn 17 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PPreal_01 732 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVforecast 880 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVreal 1051 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_01 47 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_02 126 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_01 102 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_02 75 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridConsumption 15 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridFeedIn 23 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PPreal_01 771 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVforecast 117 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVreal 86 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_02 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_02 67 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridConsumption 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridFeedIn 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PPreal_01 723 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_01 349 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_02 124 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_01 73 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_02 450 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridConsumption 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridFeedIn 6 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PPreal_01 671 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecastTime 2025-01-13 14:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVdeviation 30.17 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVforecast 7663 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVreal 5351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunRise 08:28&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunSet 16:46&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_ConsumptionForecast 17043 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour05_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour06_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour07_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour08_PVforecast 10 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour09_PVforecast 161 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour10_PVforecast 275 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour11_PVforecast 532 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour12_PVforecast 730 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour13_PVforecast 1252 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour14_PVforecast 818 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour15_PVforecast 1465 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour16_PVforecast 303 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour17_PVforecast 20 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour18_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour19_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour20_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour21_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour22_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour23_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour24_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_PVforecast 5566 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunRise 08:27&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunSet 16:47&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01 name=&#039;_Waschmaschine&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_start 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_stop 14.01.2025 11:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02 name=&#039;_Esszimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_currentPower 15.3 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03 name=&#039;_FCU&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_currentPower 7.15 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04 name=&#039;_Brunnen&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05 name=&#039;_Zisterne&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06 name=&#039;SW Trockner&#039; state=&#039;unknown&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_stop 14.01.2025 08:30:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07 name=&#039;SW Urlaubslicht-Wohnzimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;noSchedule&#039; info=&#039;von extern umgeschaltet&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 nextCycletime 18:54:09&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 pvCorrectionFactor_10 0.53 (automatic - old factor: 1.00, Sun Alt range: 5, Cloud range: 75, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 pvCorrectionFactor_11 0.56 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 70, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 pvCorrectionFactor_12 0.64 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 pvCorrectionFactor_13 0.88 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 pvCorrectionFactor_14 1.10 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 50, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 pvCorrectionFactor_15 1.01 (automatic - old factor: 1.06, Sun Alt range: 15, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 pvCorrectionFactor_16 1.09 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 45, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 pvCorrectionFactor_17 0.28 (automatic - old factor: 0.52, Sun Alt range: 0, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 pvCorrectionFactor_Auto on_complex_ai&lt;br /&gt;
setstate Forecast 2024-10-30 19:42:19 setupStringAzimuth GarageSE=-55 GarageNW=125 HausNW=125 HausSW=35 HausSE1=-55 HausSE2=-55&lt;br /&gt;
setstate Forecast 2024-10-30 19:37:38 setupStringDeclination GarageSE=40 GarageNW=40 HausNW=50 HausSW=50 HausSE1=50 HausSE2=50&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerIn_Sum 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerOut_Sum 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunHours_Remain 0.00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunMinutes_Remain 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_allStringsFullfilled 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_conForecastTillNextSunrise 9467 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentAPIinterval 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_01 132 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_02 184 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_03 329512 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_04 200 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_05 27 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_06 193 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_07 106 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_dayAfterTomorrowPVforecast 7344 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_01 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_02 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_time 2025-01-13 18:53:54&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_timestamp 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_response_message success&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_01 545.94 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_02 382.10 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_03 1430.13 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_04 262.05 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_05 28.80 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_06 622.63 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_07 276.51 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeCentralTask 0.3744&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIAnswer -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIProc -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeTrainAI 1.2529&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_01 3683.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_02 1617.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_01 2287.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_02 1057.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConForecastTillSunset 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 special_todayConsumptionForecast_01 509 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 special_todayConsumptionForecast_02 499 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 special_todayConsumptionForecast_03 501 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 special_todayConsumptionForecast_04 511 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 special_todayConsumptionForecast_05 503 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 special_todayConsumptionForecast_06 495 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 special_todayConsumptionForecast_07 504 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 special_todayConsumptionForecast_08 561 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 special_todayConsumptionForecast_09 768 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 special_todayConsumptionForecast_10 783 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 special_todayConsumptionForecast_11 692 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 special_todayConsumptionForecast_12 791 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 special_todayConsumptionForecast_13 910 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 special_todayConsumptionForecast_14 1022 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 special_todayConsumptionForecast_15 965 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 special_todayConsumptionForecast_16 812 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 special_todayConsumptionForecast_17 884 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 special_todayConsumptionForecast_18 928 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_19 874 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_20 763 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_21 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_22 765 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_23 643 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_24 601 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIcalls 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIrequests 4532&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridConsumption 5500.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridFeedIn 178.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayMaxAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIrequests n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 state updated&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So sollte es dann als Ergebnis aussehen:&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13.png|zentriert|mini|Ergebnis nach kompletter Einrichtung]]&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13 Teil II.png|alternativtext=Unterer Teil der Anzeige|zentriert|mini]]&lt;br /&gt;
&lt;br /&gt;
== Praxisbeispiele und Lösungsansätze für Steuerungen ==&lt;br /&gt;
=== Fallstudie: Trockner darf pausiert werden, wenn nicht genug PV-Überschuss vorhanden ist, soll aber nach spätestens X Stunden fertig sein ===&lt;br /&gt;
Für diese Aufgabenstellung sind mehrere Schlüssel essentiell wichtig, &#039;&#039;&#039;power&#039;&#039;&#039;, &#039;&#039;&#039;mintime&#039;&#039;&#039;, &#039;&#039;&#039;mode&#039;&#039;&#039; und &#039;&#039;&#039;interruptable&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Die Bedingung, dass der Trockner nach spätestens X Stunden fertig sein soll, steht in einem Widerspruch zu der Möglichkeit den Trockner bei zu wenig PV-Überschuss unterbrechen zu können. Im Extremfall könnte nach dem Start die gesamte Planungszeit ungenügender Überschuss vorliegen und der Trockner nicht arbeiten. Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; (in Minuten) wird nun wie folgt angesetzt:&lt;br /&gt;
&lt;br /&gt;
 mintime = 2,5 x &amp;lt;gewöhnliche Betriebszeit für einen Trockengang (mneed, z.B. 120)&amp;gt; = 300 Minuten&lt;br /&gt;
&lt;br /&gt;
Das bedeutet, der Trockner wird nach 300 Minuten Laufzeit abgeschaltet werden bzw. vom Netz getrennt. Der Trockenvorgang wird natürlich bereits nach 120 Minuten beendet sein, sofern nach Start keine Unterbrechnung des Vorganges erfolgte. Wurde der Vorgang unterbrochen, soll der Trockner innerhalb &lt;br /&gt;
&lt;br /&gt;
 X+120 bis X+300 &lt;br /&gt;
&lt;br /&gt;
fertig sein. &lt;br /&gt;
&lt;br /&gt;
Demnach ist die ausgeführte Laufzeit des Trockners permanent zu überwachen, zu summieren (rtsum) und die notwendige Restzeit (mneed - rtsum) mit der noch verbleibenden Restzeit (mrest) bis zur geplanten Abschaltung des Consumers zu vergleichen. Ist der Consumer gestartet, wird die Laufzeit in der pvHistory für jede Stunde des Tages im Schlüssel &#039;&#039;minutescsmXX&#039;&#039; (XX = Consumernummer) aufgezeichnet und kann darüber ausgewertet werden. Somit ist:&lt;br /&gt;
&lt;br /&gt;
 msum = for (01 .. 24) {Summe von minutescsmXX} des aktuellen Tages&lt;br /&gt;
&lt;br /&gt;
Solange die Bedingung &lt;br /&gt;
&lt;br /&gt;
 mrest &amp;gt;= (mneed - msum)&lt;br /&gt;
&lt;br /&gt;
zutrifft, darf der Trockner unterbrochen werden, anderenfalls darf er nicht mehr unterbrochen werden da die Restzeit evtl. nicht ausreichen könnte um den Vorgang abzuschließen. Für die Planung des Trockners wird der Consumer wie gewöhnlich nach dem Bedarf im Modul registriert. Für die Steuerung der Unterbrechbarkeit wird noch ein Code erstellt, welcher im Trockner-Device &#039;&#039;Dryerdev&#039;&#039; das Reading &#039;&#039;SF_Int&#039;&#039; zur Unterbrechnungssteuerung verwaltet. Dieses Reading wird dem Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; übergeben. Für das Beispiel wird der Consumer &#039;07&#039; verwendet, es kann natürlich jede andere freie Nummer verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Dryerdev:Trockner&lt;br /&gt;
                        icon=scene_cloves_dryer type=dryer power=2000 mode=must mintime=300 &lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic asynchron=1&lt;br /&gt;
                        interruptable=Dryerdev:SF_Int:1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Kombination &#039;&#039;&#039;auto=automatic&#039;&#039;&#039; eröffnet die Möglickeit, in der Consumer-Legende den Trockner-Start zusätzlich manuell freizugeben oder zu verbieten. &lt;br /&gt;
&lt;br /&gt;
Im nachfolgenden Code werden modulinterne Subroutinen verwendet. Diese sind inklusive dem Paket &#039;&#039;FHEM::SolarForecast::&#039;&#039; anzugeben. Die erstellte Subroutine wird in die 99_mySolarForecastUtils.pm eingefügt. Die Datei 99_mySolarForecastUtils.pm wird vorher von 99_myUtils.pm kopiert und enthält für die Übersichtlichkeit nur Routinen für SolarForecast.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Trocknersteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub dryControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # gewöhlich benötigte Zeit für &lt;br /&gt;
                                                                                  # einen Trockengang, z.B. 120 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $dryer     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename des Trockners&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Trockner-Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit des Trockners&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      my $dhash = $defs{$dryer};&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 1, 0);                        # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 0, 0);                        # keine Interrupt-Freigabe&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die gewöhnliche Laufzeit des Trockners für einen Trockenvorgang (120 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::dryControl ($name, &#039;07&#039;, 120);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Fallstudie: Umwälzpumpe Pool soll X Stunden am Tag laufen. Ist kein PV-Überschuß vorhanden, müssen die X Stunden/Tag trotzdem erreicht werden ===&lt;br /&gt;
&lt;br /&gt;
Die Vorgehensweise ähnelt der Fallstudie zuvor. Verändernd kommt hinzu, dass der Planungszeitraum bewusst sehr lang angesetzt wird mit der Option, den Zyklus des Consumers vorfristig zu beenden sobald die Laufzeit von X Stunden am Tag erreicht ist. &lt;br /&gt;
Im folgenden Beispiel soll die Pumpe 5 Stunden am Tag (300 Minuten) laufen und dabei mögliche PV-Überschüsse ausnutzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Pump:Zirkulationspumpe&lt;br /&gt;
                        icon=sani_pump type=other power=50 mode=must mintime=780 notafter=09&lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic &lt;br /&gt;
                        interruptable=1 swoffcond=Pump:SF_Abort:1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit dieser Registrierung wird die Pumpe ca. 09 Uhr täglich starten. Wenn kein bzw. ungenügender PV-Überschuß vorhanden ist, erfolgt eine Unterbrechung nach dem Start. Ist genügender PV-Überschuß (wieder) vorhanden, erfolgt keine Unterbrechnung (mehr). Zusätzlich wird über den Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; eine vorfristige Beendigung veranlasst, sobald die gewünschte Tageslaufzeit erreicht ist.&lt;br /&gt;
&lt;br /&gt;
Zur Verwaltung des Schlüssels &#039;&#039;interruptable&#039;&#039; und des Readings &#039;&#039;SF_Abort&#039;&#039; verwenden wir eine leicht veränderte Subroutine aus dem vorhergehenden Fallbeispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Pumpensteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub pumpControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # Soll-Pumpenzeit, z.B. 300 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $pump      = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename der Pumpe&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;);&lt;br /&gt;
  my $intbl     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;interruptable&#039;, 1); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
  my $dhash     = $defs{$pump};&lt;br /&gt;
&lt;br /&gt;
  readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 0, 0);                                # default keine Zyklusbeendigung&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Pumpen Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit der Pumpe&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
     &lt;br /&gt;
      if ($msum &amp;gt;= $mneed) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 1, 0);                       # vorfristige Zyklusbeendigung&lt;br /&gt;
          return;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=1&amp;quot;) if(!$intbl);  # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=0&amp;quot;) if($intbl);   # keine Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Befehl &#039;&#039;attrKeyVal&#039;&#039; setzt den Schlüssel &#039;&#039;interruptable&#039;&#039; im Attribut &#039;&#039;consumer07&#039;&#039; dynamisch. Diese Strukturänderung wird automatisch im System gespeichert, sofern &#039;&#039;global-&amp;gt;autosave=1&#039;&#039; gesetzt ist. Diese Einstellung ist der FHEM default.  &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die Mindestlaufzeit der Umwälzpumpe (300 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::pumpControl ($name, &#039;07&#039;, 300);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamische Ladestromsteuerung eines Victron MultiPlus II Chargers mit Pylontech Batterie ===&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;
&lt;br /&gt;
 set &amp;lt;Device&amp;gt; MaxChargeCurrent &amp;lt;Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
eingestellt bzw. variiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Modul bietet dem Nutzer die Möglichkeit in dem Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltene Code wird am Ende jedes Zyklus (siehe Attribut &#039;&#039;plantControl-&amp;gt;cycleInterval&#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;
&lt;br /&gt;
&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 $mppt1   = &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common&#039;;              # SmartLoader Device&lt;br /&gt;
  my $maxcspc = 105;                        # max. Ladesollstrom (A) nominal&lt;br /&gt;
  my $spcorr  = 0.9;                        # Korrekturfaktor Überschuss 90%&lt;br /&gt;
  my $sch     = 0.25;                       # Verkürzungsfaktor Zeit bis Vollladung vor Sunset             &lt;br /&gt;
  &lt;br /&gt;
  my $cclvl0  = 15;                         # Ladestrom Level 0 max. 5  A (240 W) pro WR  (720  W)&lt;br /&gt;
  my $cclvl1  = 27;                         # Ladestrom Level 1 max. 9  A (432 W) pro WR  (1296 W)&lt;br /&gt;
  my $cclvl2  = 54;                         # Ladestrom Level 2 max. 18 A (864 W) pro WR  (2592 W)&lt;br /&gt;
  my $cclvl3  = 81;                         # Ladestrom Level 3 max. 27 A (1296 W) pro WR (3888 W)&lt;br /&gt;
  ###############&lt;br /&gt;
  &lt;br /&gt;
  my $cofc   = ReadingsNum ($name,  &#039;special_todayConForecastTillSunset&#039;, 0);&lt;br /&gt;
  my $pvfc   = ReadingsNum ($name,  &#039;RestOfDayPVforecast&#039;, 0);&lt;br /&gt;
  my $cpv    = ReadingsNum ($name,  &#039;Current_PV&#039;,          0);&lt;br /&gt;
  my $mppt1c = ReadingsNum ($mppt1, &#039;DC_0_Current_value&#039;,  0);             # Load I MPPT1 (max. 44 A)&lt;br /&gt;
  my $ssts   = CurrentVal  ($hash,  &#039;sunsetTodayTs&#039;,        0);&lt;br /&gt;
  my $srts   = CurrentVal  ($hash,  &#039;sunriseTodayTs&#039;,       0);&lt;br /&gt;
  my $sdiff  = ($ssts - $srts) / 3600;                                     # Sonnengang heute in h &lt;br /&gt;
  &lt;br /&gt;
  my $solh   = ReadingsNum ($name, &#039;special_SunHours_Remain&#039;, 0);          # h bis SunSet&lt;br /&gt;
  $solh      = $solh - ($sdiff * $sch);                                    # h bis SunSet - X&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;              # Ah Bat bis SOC&lt;br /&gt;
  $ahrem     = sprintf &amp;quot;%.0f&amp;quot;, $ahrem;&lt;br /&gt;
  &lt;br /&gt;
  my $fcdiff = ($pvfc - $cofc) * $spcorr;     # Korrektur d. noch prognostizierten Überschussenergie &lt;br /&gt;
  $fcdiff    = $fcdiff &amp;lt; 0 ? 0 : $fcdiff;     # Wh&lt;br /&gt;
  &lt;br /&gt;
  my $loadcur = $maxcspc;&lt;br /&gt;
  &lt;br /&gt;
  if ($cpv &amp;amp;&amp;amp; $solh &amp;amp;&amp;amp; $ahrem &amp;amp;&amp;amp; $fcdiff &amp;gt; $ahrem) {  # Ladeanforderung und Überschuss übersteigt &lt;br /&gt;
                                                      # Lademenge&lt;br /&gt;
      my $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($ahrem / $solh);    # A = Ah / h -&amp;gt; A Soll Schätzung&lt;br /&gt;
&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Battery charging process should be completed }.&lt;br /&gt;
                      qq{in &amp;gt;$solh&amp;lt; hours});&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; raw Target charging current: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($cspc - $mppt1c);      # SmartLoader IST berücksichtigen&lt;br /&gt;
	  &lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Charge Current minus MPPT load Current &amp;gt;$mppt1c&amp;lt;: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $loadcur = $cspc &amp;lt;= 0       ? 0       :     # nur MPPT Ladung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl0 ? $cclvl0 :     # Übergangsbereich&lt;br /&gt;
                 $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;
	  Log3 ($name, 3, qq{$name - userFn -&amp;gt; MaxChargeCurrent calculated: $loadcur});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent&#039;,       $loadcur.&#039; A&#039;,          1);&lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_HoursUntilChargeFinish&#039;, sprintf (&amp;quot;%.2f&amp;quot;,$solh), 1);&lt;br /&gt;
  CommandSet           (undef, &amp;quot;$vebus MaxChargeCurrent $loadcur&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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. 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;special_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;special_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;Verkürzungsfaktor Zeit bis Vollladung vor Sunset&#039;&#039;) reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche mindest Ladestromstärke ermittelt.&lt;br /&gt;
&lt;br /&gt;
&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 auch während der MQTT Intergration 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;
=== Poolheizung in Abhängigkeit von vorhandenem Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren) ===&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;consumer01&#039;&#039; wird beispielhaft wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr Forecast consumer01 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;&lt;br /&gt;
&lt;br /&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. &lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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, einen 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 Überschuss 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;. &lt;br /&gt;
&lt;br /&gt;
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;
=== PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) ===&lt;br /&gt;
[[Datei:Screenshot 2025-08-04 104835.png|mini|Darstellung der PV-Vorhersage in evcc auf Basis der SolarForecast-Daten]]&lt;br /&gt;
[https://evcc.io evcc] ist ein Energie-Management-System, mit dem u.a. Überschussladen von Elektroautos möglich ist. Hier ist beschreiben, wie die PV-Vorhersage von SolarForecast per API an evcc gesendet wird.&lt;br /&gt;
&lt;br /&gt;
Lege im SolarForecast-Device ein User-Reading mit dem Namen forecast_json an. Es wandelt die Forecast-Werte in JSON und ins UTC-Zeitformat um, so dass evcc die Daten verwenden kann:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
forecast_json {&lt;br /&gt;
&lt;br /&gt;
    use strict;&lt;br /&gt;
    use warnings;&lt;br /&gt;
    use JSON;&lt;br /&gt;
    use DateTime;&lt;br /&gt;
    use DateTime::Format::Strptime;&lt;br /&gt;
&lt;br /&gt;
    my $hour = 0;&lt;br /&gt;
    my @output;&lt;br /&gt;
&lt;br /&gt;
    # Parser für Datum mit CET/CEST&lt;br /&gt;
    my $parser = DateTime::Format::Strptime-&amp;gt;new(&lt;br /&gt;
        pattern   =&amp;gt; &#039;%Y-%m-%d %H:%M:%S&#039;,&lt;br /&gt;
        time_zone =&amp;gt; &#039;Europe/Berlin&#039;,&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    # Alle NextHour-Daten durchsuchen&lt;br /&gt;
    while ($hour &amp;lt; 100) {&lt;br /&gt;
        my $hour_str = sprintf(&#039;NextHour%02d&#039;, $hour);&lt;br /&gt;
        my $start_str = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;starttime&#039;, &#039;na&#039;); &lt;br /&gt;
        my $pvfc = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;pvfc&#039;, &#039;na&#039;);&lt;br /&gt;
&lt;br /&gt;
        # Schleife beenden, wenn keine Werte mehr vorhanden sind&lt;br /&gt;
        last if $start_str eq &#039;na&#039; or $pvfc eq &#039;na&#039;;&lt;br /&gt;
&lt;br /&gt;
        # parse und konvertiere Zeit&lt;br /&gt;
        my $start_dt = $parser-&amp;gt;parse_datetime($start_str);&lt;br /&gt;
        my $end_dt   = $start_dt-&amp;gt;clone-&amp;gt;add(hours =&amp;gt; 1);&lt;br /&gt;
&lt;br /&gt;
        # nach UTC konvertieren&lt;br /&gt;
        $start_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
        $end_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $start_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            end   =&amp;gt; $end_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            value =&amp;gt; 0 + $pvfc,&lt;br /&gt;
        };&lt;br /&gt;
        &lt;br /&gt;
        $hour++;&lt;br /&gt;
    }  &lt;br /&gt;
&lt;br /&gt;
    # Ausgabe als JSON&lt;br /&gt;
    my $json = JSON-&amp;gt;new-&amp;gt;utf8-&amp;gt;pretty-&amp;gt;encode(\@output);&lt;br /&gt;
    return $json;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Kommunikation von FHEM zu evcc läuft über den integrierten FHEM-Webserver, der die JSON-Daten aus dem Reading forecast_json veröffentlicht. Dazu wird in FHEM eine separate Webinstanz auf einem neuen Port erstellt, die ohne [[CsrfToken-HowTo|CSFR-Token]] (Achtung, Auswirkungen auf die Sicherheit beachten!) und nur von localhost aufrufbar ist (Voraussetzung: evcc läuft auf derselben Maschine wie FHEM):&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
defmod WEBapi FHEMWEB 8089&lt;br /&gt;
attr WEBapi csrfToken none&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;In der [https://docs.evcc.io/docs/tariffs#pv-vorhersage evcc-Konfig unter tariffs] steht die Quelle für die Solar-Vorhersage. Der FHEM-Befehl {ReadingsVal(&#039;solarforecast_dev&#039;,&#039;forecast_json&#039;,&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;)} wird dazu encoded und in die uri eingetragen. Trage statt solarforecast_dev den passenden Namen des SolarForecast-Device ein.&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
solar:&lt;br /&gt;
  type: custom&lt;br /&gt;
  interval: 2m    &lt;br /&gt;
  forecast:&lt;br /&gt;
    source: http&lt;br /&gt;
    uri: http://localhost:8089/fhem?cmd=%7BReadingsVal%28%27solarforecast_dev%27%2C%27forecast_json%27%2C%27%27%29%7D&amp;amp;XHR=1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Zur Verbesserung der Sicherheit kann das neue WEBapi Device auch ein [[CsrfToken-HowTo#csrfToken festlegen|festes CSFR-Token]] verwenden. Dieses Token muss dann in der evcc-Konfiguration an die uri mittels &amp;amp;fwcsrf=&amp;lt;festes token&amp;gt; angehängt werden.&lt;br /&gt;
&lt;br /&gt;
== weiterführende Links ==&lt;br /&gt;
* Forenthema &amp;quot;{{Link2Forum|Topic=137058|LinkText=76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support}}&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;
* Photovoltaik Ingenieurbüro Junge: https://www.ing-büro-junge.de/html/photovoltaik.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Datei:Screenshot_2025-08-04_104835.png&amp;diff=40300</id>
		<title>Datei:Screenshot 2025-08-04 104835.png</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Datei:Screenshot_2025-08-04_104835.png&amp;diff=40300"/>
		<updated>2025-08-04T09:44:17Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Darstellung der PV-Vorhersage in evcc mit SolarForecast-Daten&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung&amp;diff=40299</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=40299"/>
		<updated>2025-08-04T09:41:59Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Anbindung an evcc&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Hinweis|Die vorliegende Wiki-Seite befindet sich im Aufbau.}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Solarprognose und Verbrauchersteuerung&lt;br /&gt;
|ModType=d&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 Prognosewerte können die SolCast API, OpenMeteo API, Forecast.Solar API, Victron VRM Portal API oder alternativ DWD Stahlungswerte-Stationen verwendet werden&lt;br /&gt;
&lt;br /&gt;
::* optionale KI Unterstützung der PV-Prognose bei Verwendung von geeigneten Solar-API&#039;s&lt;br /&gt;
&lt;br /&gt;
::* es wird sowohl die Erzeugungsprognose als auch eine Verbrauchsprognose sowie SoC Prognose (bei Batterie-Integration) erstellt&lt;br /&gt;
&lt;br /&gt;
::* Wetterdaten werden über DWD Wetter-Stationen oder verschiedene API integriert. Es können verschiedene API zur Gewinnung von Solar- und Wetterdaten kombiniert werden. &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 FHEM-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 Integration von bis zu 4 Inverter und Smartloader (DC-DC Batterieladegeräte) ist möglich&lt;br /&gt;
&lt;br /&gt;
::* eine Integration von bis zu 3 nicht PV-Energieerzeugern wie BHKW, Windrädern oder Notstromaggregaten ist möglich&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;
::* Einbindung von bis zu drei Batteriespeichersystemen&lt;br /&gt;
&lt;br /&gt;
::* Bereitstellung von Leitwerten zur optimalen Einstellung/Steuerung von Batteriespeichersystemen&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 Benutzererlebnis 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;
Das Wiki gibt allgemeingültige und teilweise sehr spezifische bzw. tiefgehende Informationen und Handlungsempfehlungen zum SolarForecast Modul. Die dargestellten Informationen beziehen sich auf den zum Zeitpunkt der Wiki-Erstellung vorhandenen Entwicklungsstand des Moduls. Durch die stetige Weiterentwicklung können sich Abweichungen zum beschriebenen Inhalt ergeben oder zur Obsoleszenz dieser Inhalte führen. &lt;br /&gt;
&lt;br /&gt;
Vergleiche deshalb die Informationen immer mit der aktuellen Befehls-Referenz zum Modul!&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Ein SolarForecast Device wird mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 define &amp;lt;Name&amp;gt; SolarForecast &lt;br /&gt;
&lt;br /&gt;
angelegt. Nach der Definition wird der User durch einen Dialog geführt, der einige unerlässliche Einstellungen abfragt und in den entsprechenden Attributen und Readings persistiert. Alle Attribute und Readings die eine Einstellung der Anlage bewirken, sind mit dem Präfix &amp;quot;setup&amp;quot; versehen. &lt;br /&gt;
&lt;br /&gt;
Die Verwendung von setup-Readings gestattet es die Anlagenparameter dynamisch im Betrieb zu verändern. So kann mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringAzimuth   bzw.&lt;br /&gt;
 set &amp;lt;Name&amp;gt; setupStringDeclination &lt;br /&gt;
&lt;br /&gt;
die Ausrichtung und der Neigungswinkel der PV-Module ständig angepasst werden, was zum Beispiel bei einer dem Sonnenstand nachgeführten Anlage von Bedeutung ist.&lt;br /&gt;
&lt;br /&gt;
Die abgefragten Einstellungen während des Dialoges sind ausführlich in den entsprechenden Attributen bzw. Set-Kommandos erläutert. Die benötigten Informationen sind anhängig von der gewählten Prognose-API und können im Umfang variieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 213257.png|right|thumb|400px|Anlagenprüfung über Drucktaste in der Kopfgrafik]]&lt;br /&gt;
&lt;br /&gt;
Sobald alle verlangten Einstellungen vorgenommen sind, sollte eine Anlagenprüfung mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; plantConfiguration check&lt;br /&gt;
&lt;br /&gt;
oder über die angebotene Drucktaste in der Grafik durchgeführt werden. Es wird eine Plausibilitätsprüfung vorgenommen und das Ergebnis sowie eventuelle Hinweise bzw. Fehler ausgegeben.&lt;br /&gt;
Die Prüfung kann beliebig wiederholt werden und sollte sich bei jeder Einstellungsänderung der Anlage durchgeführt werden. Dadurch wird die Wahrscheinlichkeit von fehlerhaften Einstellungen minimiert.&lt;br /&gt;
&lt;br /&gt;
Neben den grundlegenden Einstellungen können im Device weitere sekundäre Anlagenkomponenten wie Batteriesystem(e) (Attribut setupBatteryDev1 - setupBatteryDev3), weitere Wetter-Devices (Attribut setupWeatherDev1 - setupWeatherDev3) oder sonstige Erzeuger (z.B. BHKW, Winderzeugung, Notstromaggregat) integriert werden (Attribut setupOtherProducer01 - setupOtherProducer03).&lt;br /&gt;
&lt;br /&gt;
Die verlangten Parameter der Anlage werden in der Online-Hilfe umfassend beschrieben und deren Funktion erschließt sich zum größten Teil selbst. Dennoch soll nachfolgend auf einige Punkte im Zusammenhang der Einrichtung eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Hinweise zur Struktur der Attribute ===&lt;br /&gt;
&lt;br /&gt;
Durch die umfangreichen Funktionen des Moduls würde bei Nutzung der im FHEM herkömmlich vorhandenen Attributstruktur die Anzahl der benötigten Attribute extrem stark steigen und nicht sinnvoll genutzt werden können. Deshalb gibt es neben den &#039;&#039;gewöhnlichen&#039;&#039; Attributen mit einfachen Werteauswahlmöglichkeiten oder Eingaben (z.B. ctrlDebug, ctrlSpecialReadings) sogenannte &#039;&#039;zusammengesetzte&#039;&#039; Attribute, deren Inhalt durch &#039;&#039;&#039;Schlüssel=Wert Paare&#039;&#039;&#039; gebildet wird und dadurch deutlich mehr Funktionen und Informationen transportieren als ein gewöhnliches Attribut.&lt;br /&gt;
&lt;br /&gt;
Für zusammengesetzte Attribute besteht die zusätzliche Möglichkeit, gewünschte Änderungen der Schlüssel=Wert Paare selektiv vornehmen zu können, ohne das gesamte Attribut aufrufen und ändern zu müssen. Die Vorgang, der vor allem für programmtechnische Manipulationen gedacht ist, kann durch eine Set-Funktion ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; attrKeyVal &amp;lt;Attribut&amp;gt; [&amp;lt;Gerät&amp;gt;] &amp;lt;Schlüssel=Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiele für zusammengesetzte Attribute sind:&lt;br /&gt;
&lt;br /&gt;
* aiControl&lt;br /&gt;
* plantControl&lt;br /&gt;
* setup* Attribute&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Funktionen der Attribute werden durch einen Präfix geclustert und so inhaltlich, aber vor allem auch in der Attribute Drop-Down Liste, strukturiert dargestellt.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der &#039;&#039;&#039;Präfixe&#039;&#039;&#039; sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ai&#039;&#039;&#039; - Steuerungsfunktionen für KI (z.B. aiControl)&lt;br /&gt;
* &#039;&#039;&#039;consumer&#039;&#039;&#039; - Registrierung und Einstellungen für Verbraucher (z.B. consumer02, consumerControl)&lt;br /&gt;
* &#039;&#039;&#039;ctrl&#039;&#039;&#039; - Steuerungsfunktion allgemeiner Art (z.B. ctrlDebug, ctrlSpecialReadings, ctrlUserExitFn)&lt;br /&gt;
* &#039;&#039;&#039;flowGraphic&#039;&#039;&#039; - Einstellungen für die Energieflußgrafik (z.B. flowGraphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphic&#039;&#039;&#039; - Einstellung für die Grafik allgemein (z.B. graphicSelect, graphicControl)&lt;br /&gt;
* &#039;&#039;&#039;graphicBeam&#039;&#039;&#039; -  Einstellungen bestimmte Balkeneigenschaften in der Balkengrafik (z.B. graphicBeamHeightLevel1)&lt;br /&gt;
* &#039;&#039;&#039;plant&#039;&#039;&#039; - übergreifende Einstellungen betreffend der gesamten PV-Anlage bzw. des SolarForecast-Devices (z.B. plantControl)&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039; - Registrierung von Geräten in der Gesamtanlage und Einstellung deren Eigenschaften (Inverter, Zähler, Batterien usw.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Einrichtung der Wechselrichter mit setupInverterDevXX ===&lt;br /&gt;
&lt;br /&gt;
Mit den Attributen setupInverterDev01 bis setupInverterDevXX werden die vorhandenen Wechselrichter der Anlage registriert.&lt;br /&gt;
Das Modul unterscheidet verschiedene Wechselrichter-Typen, die sich durch ihre Arbeitsweise innerhalb der Anlage unterscheiden. Die Schlüssel=Wert Paare in den Attributen können mehrzeilig organisiert werden. Das erleichtert die Übersicht wenn viele dieser Parameter eingegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;PV-Wechselrichter: Es ist der Standard Wechselrichter in einer PV-Anlage. An ihn sind die Solarzellen bzw. Strings angeschlossen. Die zugeordneten Strings können mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ohne diese Angabe werden diesem Gerät alle definierten Strings (siehe Attribut &#039;&#039;setupInverterStrings&#039;&#039;) zugeordnet. Der Wechselrichter liefert seine Energie in das Hausnetz. Alternativ kann mit der Angabe &#039;&#039;&#039;feed=grid&#039;&#039;&#039; die Funktion des Wechselrichters geändert werden. Diese Angabe sagt aus, dass dieser Wechselrichter ausschließlich in das öffentliche Netz einspeist.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel-Setup eines PV-Wechselrichters (SMA STP):&lt;br /&gt;
&lt;br /&gt;
 STP_5000 pvIn=string_1_pdc:kW pvOut=total_pac:kW etotal=etotal:kWh capacity=5000 strings=Süddach asynchron=1 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Solar-Ladegeräte: Solar-Ladegeräte sind DC-DC Wandler und liefern die Energie der angeschlossenen Solarzellen nicht in das Wechselstromnetz, sondern laden direkt eine Batterie bzw. versorgen einen Batteriewechselrichter auf der Gleichstromseite. Die Funktion als Solar-Ladegerät wird mit &#039;&#039;&#039;feed=bat&#039;&#039;&#039; aktiviert, die relevanten Strings können ebenfalls mit dem Schlüssel &#039;&#039;&#039;strings&#039;&#039;&#039; zugeordnet werden. Ein Beispiel eines Solar-Ladegerätes ist ein Victron SmartSolar MPPT. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel für das Setup eines Solar-Ladegeräts (SmartSolar Charger MPPT):&lt;br /&gt;
&lt;br /&gt;
 MQTT2_cerboGX_c0619ab34e08_solarcharger_Common pv=Yield_Power_value:W etotal=Yield_System_value:kWh capacity=2080 strings=Schleppdach feed=bat synchron=0 limit=100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Batterie-Wechselrichter: Dieses Gerät hat keine angeschlossenen Solarzellen und arbeitet als DC-AC bzw. AC-DC Wandler zwischen einer Batterie (=Gleichstromquelle) und dem Wechselstrom-Hausnetz. Die Funktion als Batterie-Wechselrichter wird mit der Angabe &#039;&#039;&#039;strings=none&#039;&#039;&#039; aktiviert. Die Schlüssel &#039;&#039;etotal&#039;&#039; und &#039;&#039;pv&#039;&#039; können bei einem Batterie-Wechselrichter ohne zugeordnete Solarzellen nicht gesetzt werden. Ein Beispiel eines Batterie-Wechselrichter ist der Victron MultiPlus II.&lt;br /&gt;
&lt;br /&gt;
Ein Setup-Beispiel für einen Batterie-Wechselrichter (Victron MultiPlus II):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dc2ac=DC_IN:W&lt;br /&gt;
ac2dc=DC_OUT:W&lt;br /&gt;
capacity=7200&lt;br /&gt;
strings=none&lt;br /&gt;
icon=inverter@darkorange:inverter@grey&lt;br /&gt;
asynchron=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Eigenschaften des Wechselrichters werden durch eine Reihe von &amp;lt;Schlüssel=Wert&amp;gt; Paaren festgelegt. Auf einige dieser Paramter soll hier eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==== Ausgewählte Schlüssel=Wert Paare ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;pvIn=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvIn&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell zugeführte PV-Leistung bereitstellt. Der Schlüssel ist optional und dient in erster Linie dazu den entsprechenden Input-Wert in der Flußgrafik anzuzeigen sofern man das Attribut flowGraphicControl-&amp;gt;showGenerators=1 setzt. Dadurch ist auch der Eigenverbrauch des Inverters bzw. dessen Wandlungsverlust visuell abschätzbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pvOut=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
Dem Schlüssel &#039;&#039;pvOut&#039;&#039; wird ein Reading und dessen Einheit (W,kW) des Wechselrichter-Device zugeordnet, welches die aktuell erzeugte Leistung als positiven Wert liefert. Für einen PV-Wechselrichter (DC-&amp;gt;AC) oder Solar-Ladegerät (DC-&amp;gt;DC) ist es die erzeugte PV-Leistung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ac2dc=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter vom Hausnetz in Richtung Batterie (AC-&amp;gt;DC) wandelt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;dc2ac=&amp;lt;Readingname&amp;gt;:&amp;lt;Einheit&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist nur für einen Batterie-Wechselrichter setzbar. Das Reading liefert die aktuelle Leistung, die der Wechselrichter aus einer Gleichstromquelle, d.h. einer Batterie oder einem Solar-Ladegerät, in Richtung des Hausnetzes (AC) wandelt . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;capacity=&amp;lt;max. WR-Leistung&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In dem Schlüssel &#039;&#039;capacity&#039;&#039; wird die maximal mögliche Leistung in Watt (ohne Einheit) angegeben, die der Wechselrichter lt. seinem Datenblatt in der Lage ist zu leisten. &lt;br /&gt;
&lt;br /&gt;
Die Angabe &#039;&#039;capacity&#039;&#039; hat in erster Linie die Aufgabe, die max. mögliche PV-Leistung für die Prognose zu begrenzen. Oft sind die installierten Peak-Leistungen der PV-Module höher als die angeschlossene Wechselrichter-Leistung bzw. kommt es vor, dass die KI / (korrigierte) API-Prognose über der maximal möglichen Wechselrichter-Leistung liegt. In diesen Fällen wird die Prognose auf die angegebene &#039;&#039;capacity&#039;&#039; begrenzt.&lt;br /&gt;
&lt;br /&gt;
Der Wert in diesem Schlüssel kann, wie andere Schlüssel auch, dynamisch zur Laufzeit mit dem Set-Befehl &amp;quot;[[#Hinweise zur Struktur der Attribute|set &amp;lt;Name&amp;gt; attrKeyVal ...]]&amp;quot; geändert werden. Ein Beispiel zur Anwendung ergibt sich aus folgendem Szenario.&lt;br /&gt;
&lt;br /&gt;
Gegeben sei eine Anlage die aus Solarzellen (1300 W Peak) mit einem Solar-Ladegerät mit max. 1800 W Leistung, einer Batterie und einem Batterie-Wechselrichter besteht. Die Anlage versorgt nur das Hausnetz. Eine Netzeinspeisung ist nicht vorgesehen oder nicht erlaubt.  &lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, es ist ein Tag voller Sonnenschein prognostiziert und die Batterie ist zunächst entladen. Der Haushalt verbraucht 300 W. Dann würden die PV-Module Module ihre volle Leistung von 1300 W Peak leisten können, die sich auch in der Balken-Vorhersage niederschlägt. Die Leistung wird nicht begrenzt, weil:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* sie niedriger ist als die nominale und angegebene Wechselrichter Kapazität von &#039;&#039;capacity=1800&#039;&#039;&lt;br /&gt;
* die erzeugte Energie anteilig für die Verorgung des Hauses und die Aufladung der Batterie verwendet wird&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders verhält es sich wenn nach einer gewissen Zeit die Batterie voll ist und weiterhin volle PV Leistung zur Verfügung steht. In diesem Fall würde der Haushalt seine benötigte Leistung von 300 W abnehmen, aber das Solar-Ladegerät kann keine weitere Leistung mehr abgeben, da die Batterie bereits voll geladen ist, d.h. die Anlagensteuerung würde die PV-Anlage abregeln. In diesem Fall, wenn es einen längeren Zeitraum betrifft, muß auch die Prognose PV-Energie auf 300 Wh (bzw. den durchschnittlichen Energieverbrauch des Hauses pro Stunde) begrenzt werden, damit die PV-Prognose nach unten angepasst wird und so eine realitätsnahere Prognose ermöglicht wird. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;icon=&amp;lt;aktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;][:&amp;lt;inaktiv&amp;gt;[@&amp;lt;Farbe&amp;gt;]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Jeder Wechselrichter wird im Standard durch ein Icon getrennt nach Tag und Nacht, d.h. je nach Aktiv-Status und Inaktiv-Status, symbolisiert.&lt;br /&gt;
&lt;br /&gt;
;Tag bzw. Aktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Sonnensymbol im Standard verwendet. Batterie-Wechselrichter verwenden ein gefärbtes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
;Nacht bzw. Inaktivität: Für Wechselrichter mit angeschlossenen PV-Modulen wird ein entsprechend gefärbtes Symbol der aktuellen Mondphasen im Standard verwendet. Batterie-Wechselrichter verwenden ein ausgegrautes Invertersymbol.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie angegeben, kann man für Tag und Nacht jeweils ein Wunsch-Icon, wenn gewünscht mit einer alternativen Färbung, auswählen.&lt;br /&gt;
&lt;br /&gt;
 icon=inverter@darkorange:inverter@gray&lt;br /&gt;
&lt;br /&gt;
Soll nur das Icon für die Nacht bzw. Inaktivät geändert werden, kann dies in dieser Form angegeben werden:&lt;br /&gt;
&lt;br /&gt;
 icon=:inverter@gray  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(beachte den führenden &#039;:&#039;)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Der integrierte SolarForecast Grafikbereich ==&lt;br /&gt;
Das SolarForecast Modul beinhaltet eine Grafikdarstellung die sich in mehrere Bereiche gliedert. Diese Bereiche können über Attribute ein- bzw. ausgeblendet sowie die Inhalte festgelegt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-09-21 223545.png|right|thumb|400px|Bereiche der integrierten Grafik]]&lt;br /&gt;
&lt;br /&gt;
Der nebenstehende Screenshot gibt die Gliederung der Grafikbereiche wieder:&lt;br /&gt;
&lt;br /&gt;
 1 - der Kopfbereich (Graphic Header)&lt;br /&gt;
 2 - durch den Nutzer selbst definierbarer Inhalt (Graphic Header Own Specification) als Teil des Kopfbereiches&lt;br /&gt;
 3 - Bereich Verbraucherdarstellung (Consumer Legend)&lt;br /&gt;
 4 - Bereich Balkengrafik (Beam Graphic)&lt;br /&gt;
 5 - Energieflußgrafik (Flow Graphic)&lt;br /&gt;
&lt;br /&gt;
Jeder dieser Bereiche hat spezifische Steuerungsattribute zur Anpassung des Verhaltens und ggf. des Inhalts.&lt;br /&gt;
&lt;br /&gt;
=== 1 - Der Grafik Kopfbereich ===&lt;br /&gt;
Im Kopfbereich befinden sich fest verankerte Informationen zur verwendeten Vorhersage-API sowie deren Status, Informationen zum Sonnenaufgang und Sonnenuntergang, dem aktuellen Gesamtstatus des SolarForecast Devices, Abweichungskennzahlen der PV Vorhersage sowie weitere Kennzeichen zur Verfügung.&lt;br /&gt;
Über zwei Drucktasten kann eine Anlagenprüfung durchgeführt und in den Spportthread des Moduls im FHEM Forum abgesprungen werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;graphicHeaderShow&#039;&#039;&#039; kann der gesamte Kopfbereich 1 und 2 (nutzereigener Teilbereich) ausgeblendet werden. Wird der Kopbereich ausgeblendet, ist es hilfreich mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;showLink&#039;&#039;&#039; einen Link zur Detailgrafik einzufügen da der in der Kopfgrafik integrierte Link in diesem Fall nicht mehr zur Verfügung steht. &lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;graphicHeaderDetail&#039;&#039;&#039; definiert welche Bereiche des Grafikkopfes angezeigt werden sollen. Es kann die Anzeige des Energieverbrauches, der PV-Erzeugung und der vom Nutzer selbst definierte Inhalt miteinander frei kombiniert werden.&lt;br /&gt;
&lt;br /&gt;
=== 2 - Der Bereich mit selbst definierbarem Inhalt (Graphic Header Own Specification) ===&lt;br /&gt;
In diesem Bereich kann der User beliebige Readings, Set-Kommandos und Attribute des SolarForecast Devices oder anderer Devices, die sich im gleichen FHEM-System wie das SolarForecast Device befinden, anzeigen lassen.&lt;br /&gt;
&lt;br /&gt;
Dieser Bereich ist als Tabelle mit einer beliebigen Anzahl von Zeilen organisiert. Jede Zeile beinhaltet ein Kommentarfeld und vier Nutzfelder zur Darstellung ausgewähler Werte + Label. Der Bereich bzw. der Inhalt des Bereiches wird mit dem Attribut &#039;&#039;&#039;graphicHeaderOwnspec&#039;&#039;&#039; definiert.  &lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt ein real gesetztes graphicHeaderOwnspec Attribut. Die Leerzeilen sind nicht notwendig, erhöhen aber die Lesbarkeit der Struktur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
Autarkierate:Current_AutarkyRate&lt;br /&gt;
PV&amp;amp;nbsp;übermorgen:special_dayAfterTomorrowPVforecast&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;Sunset:special_todayConForecastTillSunset&lt;br /&gt;
Verbrauch&amp;amp;nbsp;bis&amp;lt;br&amp;gt;nächsten&amp;amp;nbsp;Sunrise:special_conForecastTillNextSunrise&lt;br /&gt;
&lt;br /&gt;
#Batterie&lt;br /&gt;
BatteryLive&amp;amp;nbsp;Status:userFn_BatLive_State&lt;br /&gt;
SoC&amp;amp;nbsp;Limit:Settings_CGwacs_BatteryLife_MinimumSocLimit_value@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SoC&amp;amp;nbsp;Ist:SOC_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
SOC&amp;amp;nbsp;Optimum:Battery_OptimumTargetSoC&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
aktuelle&amp;amp;nbsp;Ladung:userFn_Bat_EnergyState&lt;br /&gt;
Verfügbar:userFn_BatLive_UsableEnergy&lt;br /&gt;
benötigte&amp;amp;nbsp;Ladeenergie:userFn_Bat_EnergyRemain&lt;br /&gt;
Ladefreigabe:Battery_ChargeRecommended&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
akt.&amp;amp;nbsp;DC&amp;amp;nbsp;Strom:DC_Current_value@MQTT2_cerboGX_c0619ab34e08_battery&lt;br /&gt;
Restladezeit&amp;amp;nbsp;Ziel:userFn_Bat_HoursUntilChargeFinish&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Soll:userFn_Bat_MaxChargeCurrent_set&lt;br /&gt;
:&lt;br /&gt;
&lt;br /&gt;
#Settings&lt;br /&gt;
Batterie&amp;amp;nbsp;Lademanagement:userFn_BatteryChargeManagement&lt;br /&gt;
SoC&amp;amp;nbsp;Management:userFn_BatterySoCManagement&lt;br /&gt;
MPII&amp;amp;nbsp;Ladestrom&amp;lt;br&amp;gt;Limit&amp;amp;nbsp;Ist:MaxChargeCurrent@MQTT2_cerboGX_c0619ab34e08_vebus&lt;br /&gt;
SmartSolar&amp;lt;br&amp;gt;Einspeisung:OvervoltageFeedIn@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
MPII&amp;amp;nbsp;Limit&amp;lt;br&amp;gt;Einspeisung&amp;amp;nbsp;(W):MaxFeedInPower@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
SOC&amp;amp;nbsp;Limit&amp;amp;nbsp;Soll:MinimumSocLimit@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Verbr.&amp;amp;nbsp;Neuplanung:consumerNewPlanning&lt;br /&gt;
Wetteranzeige:graphicShowWeather &lt;br /&gt;
&lt;br /&gt;
Anzeige&amp;amp;nbsp;Nachtstunden:graphicShowNight&lt;br /&gt;
hist.&amp;amp;nbsp;Stunden:graphicHistoryHour&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto&lt;br /&gt;
Victron&amp;amp;nbsp;BatteryLife&amp;lt;br&amp;gt;(1=an,10=aus):BatteryLife@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&lt;br /&gt;
Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
Debug:ctrlDebu&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Kommentarfeld am Beginn einer Zeile wird durch ein &#039;&#039;&#039;#&#039;&#039;&#039; gekennzeichnet. Folgt dem # ein String, wird dieser String als Kommentarangabe gewertet und in der Grafik ausgegeben. Ein leeres Kommentarfeld wird lediglich durch ein # gefolgt von einem Leerzeichen oder NL beschrieben:&lt;br /&gt;
&lt;br /&gt;
 #:&amp;lt;Text&amp;gt;  (bzw nur # für einen &#039;leeren&#039; Titel)&lt;br /&gt;
&lt;br /&gt;
Ein Netzfeld bzw. ein Datensatz wird durch die Angabe von einem Label und dem darzustellenden Wert getrennt durch &#039;:&#039; definiert:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Label&amp;gt;:&amp;lt;Reading, Attribut oder Set-Kommando&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das System erkennt selbständig, ob es sich bei der Angabe um ein Reading, Attribut oder ein Set-Kommando handelt. Sollen Readings, Set-Kommandos und Attribute anderer Devices als dem SolarForecast-Device angezeigt werden, kann dies einfach durch Zusatz von&lt;br /&gt;
&lt;br /&gt;
 ....@&amp;lt;Device-Name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
an den Parameter erreicht werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-12-05 203916.png|right|thumb|400px|Darstellung eigener Grafikbereich]]&lt;br /&gt;
Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten &amp;quot;Wh&amp;quot; bzw. &amp;quot;kWh&amp;quot; werden entsprechend der Einstellung des Attributs &#039;&#039;&#039;graphicEnergyUnit&#039;&#039;&#039; umgerechnet. Im Label sind Leerzeichen durch &amp;quot;&amp;amp;amp;nbsp;&amp;quot; einzufügen, ein Zeilenumbruch durch &amp;quot;&amp;amp;lt;br&amp;amp;gt;&amp;quot;. Ein leeres Feld in einer Zeile wird durch &amp;quot;:&amp;quot; ohne eine weitere Angabe erzeugt.&lt;br /&gt;
&lt;br /&gt;
Die nebenstehende Abbildung zeigt die reale Darstellung der oben angegebenen Struktur im Attribut graphicHeaderOwnspec.&lt;br /&gt;
&lt;br /&gt;
==== Formatierung der Inhalte im Bereich &amp;quot;Graphic Header Own Specification&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
Die angezeigten Inhalte, wie z.B. Readingwerte, des User eigenen Bereiches (Attribut graphicHeaderOwnspec) können durch Spezifikationen im Attribut &#039;&#039;&#039;graphicHeaderOwnspecValForm&#039;&#039;&#039; manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
Die Online-Hilfe zum Attribut graphicHeaderOwnspecValForm erläutert die verfügbaren Möglichkeiten und Optionen.&lt;br /&gt;
Als Beispiel hier einige mögliche Notationen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &#039;userFn_Bat_HoursUntilChargeFinish&#039;                        =&amp;gt; &amp;quot;($VALUE).&#039; Stunden&#039;&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_battery.SOC_value&#039;             =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Settings_CGwacs_BatteryLife_MinimumSocLimit_value&#039;        =&amp;gt; &amp;quot;%.1f %%&amp;quot;,&lt;br /&gt;
  &#039;Info_MaxChargeCurrent_value&#039;                              =&amp;gt; &amp;quot;($VALUE).&#039; A&#039;&amp;quot;,&lt;br /&gt;
  &#039;DC_Current_value&#039;                                         =&amp;gt; &amp;quot;%.0f A&amp;quot;,&lt;br /&gt;
  &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common.Regulated&#039; =&amp;gt; &amp;quot;($VALUE eq &#039;1&#039; ? &#039;Ja&#039; : &#039;Nein&#039;)&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine Besonderheit besteht bei darzustellenden Werten die die Einheiten &#039;Wh&#039; bzw. &#039;kWh&#039; besitzen. Diese Werte und Einheiten werden automatisch entsprechend des gesetzten Attributes graphicEnergyUnit umgerechnet und angezeigt.&lt;br /&gt;
&lt;br /&gt;
Soll in diesen Fällen eine automatische Formatierung umgangen werden, kann eine solche Notation verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &#039;Today_PVforecast&#039; =&amp;gt; &amp;quot;(sprintf &#039;%.1f &amp;amp;amp;nbsp;kWh&#039;, ($VALUE / 1000))&amp;quot;,&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Die Angabe von &amp;amp;amp;nbsp; vor &#039;kWh&#039; verhindert die Erkennung der Einheit und so auch die automatische Umsetzung durch das Modul. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 3 - Bereich Verbraucherdarstellung (Consumer Legend) ===&lt;br /&gt;
Dieser Grafikbereich zeigt die im Modul registrierten Verbraucher sowie deren Status und weitere Informationen an. Sind die Voraussetzungen gegeben, d.h. entsprechende Schlüssel in der ConsumerXX-Attributen gesetzt, können die Verbraucher über das Paneel manuell geschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Zur Anpassung der Darstellung sind verschiedene Attribute verfügbar:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;consumerControl-&amp;gt;showLegend: Definiert die Lage bzw. Darstellungsweise der Verbraucherlegende sofern Verbraucher im SolarForecast Device registriert sind.&lt;br /&gt;
;consumerControl-&amp;gt;adviceIcon: Definiert die Art der Information über die geplanten Schaltzeiten eines Verbrauchers in der Verbraucherlegende. &lt;br /&gt;
;consumerControl-&amp;gt;detailLink: Wenn gesetzt, ist der jeweilige Verbraucher klickbar um direkt zur Detailansicht des jeweiligen Geräts auf einer neuen Browserseite zu gelangen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Standard wird das Verbraucherpaneel zwischen dem Kopfbereich und der ersten Balkengrafik Ebene dargestellt. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;showLegend&#039;&#039;&#039; und Argument &#039;&#039;&#039;icon_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_bottom&#039;&#039;&#039; kann das Verbraucherpaneel an das Ende des Grafikbereiches verschoben werden.&lt;br /&gt;
Die Verwendung von &#039;&#039;&#039;text_bottom&#039;&#039;&#039; oder &#039;&#039;&#039;text_top&#039;&#039;&#039; blendet die Icon-Spalte im Verbraucherpaneel aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Screenshot 2025-02-08 093239.png|Darstellung mit consumerControl showLegend=icon_top (default)&lt;br /&gt;
File:Screenshot 2025-02-08 093646.png|Darstellung mit consumerControl showLegend=icon_bottom&lt;br /&gt;
File:Screenshot 2025-02-08 152018.png|Darstellung mit consumerControl showLegend=text_top bzw. text_bottom&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 213634.png|right|thumb|400px|]]&lt;br /&gt;
Ein Mouse-Over über das Uhrensymbol zeigt nähere Informationen zum Status, den Planungsdaten, Modus und weitere Daten des Verbrauchers. Der Schalter &amp;quot;Aus/Ein&amp;quot; visualisiert den Schaltzustand des Verbrauchers und können auch zum manuellen Schalten des Verbrauchers dienen. Voraussetzung ist, dass im consumer-Attribut die Schlüssel &amp;quot;on&amp;quot; und &amp;quot;off&amp;quot; mit den Set-Kommandos zum Schalten des Verbrauchers defininiert sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-08 222210.png|right|thumb|300px|]]&lt;br /&gt;
Der Auto-Schieberegler zeigt einerseits den Freigabestatus zum Schalten des Verbrauchers durch das SolarForecast Modul und kann andererseits manuell betätigt werden. Der Status des Reglers korrespondiert mit dem im zugehörigen Consumer Attribut vorhandenen Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; angegebenen Reading-Wert.&lt;br /&gt;
&lt;br /&gt;
Die Verbraucherbezeichnungen in dem Paneel können in der Standardkonfiguration angeklickt werden um direkt zur Detailansicht des Devices zu gelangen. Mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;detailLink&#039;&#039;&#039; kann der Link zur Detailansicht deaktiviert werden.&lt;br /&gt;
&lt;br /&gt;
Das Uhrensymbol kann mit dem Attribut &#039;&#039;&#039;consumerControl-&amp;gt;adviceIcon&#039;&#039;&#039; geändert und/oder dessen Farbe angepasst, sowie einen Informationstext statt eines Icons angezeigt werden. &lt;br /&gt;
&lt;br /&gt;
=== 4 - Bereich Balkengrafik (Beam Graphic) ===&lt;br /&gt;
&lt;br /&gt;
Die Balkengrafik des Moduls ist ein wesentliches Visualisierungshilfsmittel. Im Auslieferungszustand existiert eine Balkengrafikebene, die &#039;&#039;&#039;Ebene 1&#039;&#039;&#039;.&lt;br /&gt;
Jede Ebene kann zwei Balkendiagramme mit auswählbaren Inhalten, Farben und einstellbarem LayoutTyp darstellen. In Ebene 1 kann die Wettervorhersage eingebettet oder, bei Vorhandensein von Batteriegeräten, die zukünftigen Zeiten mit empfohlener Ladefreigabe und SoC-Prognose eingeblendet werden. &lt;br /&gt;
&lt;br /&gt;
Welche Daten in welchen Zeiträumen dargestellt werden sollen, die Bestimmung des Layouts, die Gestaltung der Balken und einiges mehr wird durch Attribute gesteuert. Ein Teil dieser Einstellungen wird über das zusammengesetzete Attribut &#039;&#039;&#039;graphicControl-&amp;gt;&#039;Schlüssel&#039;=&#039;Wert&#039;&#039;&#039;&#039; eingestellt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;grundsätzliche Layout Definitionen&#039;&#039;&#039;&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204342.png|right|thumb|400px|Standardanzeige mit Wetter-Icons, gesetzen Attributen graphicBeam1Color=D4C177, graphicHistoryHour=11]]&lt;br /&gt;
&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingTop:Legt den Platz in px im Balkendiagramm fest, der zwischen dem oberen Rand der jeweiligen Balkengrafik Ebene und der ersten Text- oder Iconreihe dieser Ebene eingefügt wird.&lt;br /&gt;
;graphicControl-&amp;gt;beamPaddingBottom:Legt den Platz in px im Balkendiagramm fest, der zwischen der letzten Text- oder Iconreihe der jeweiligen Balkengrafik Ebene und dem unteren Rand dieser Ebene eingefügt wird. &lt;br /&gt;
;graphicControl-&amp;gt;layoutType:Layout-Optionen zur grundlegenden Gestaltung der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourStyle:Format der Zeitangabe in der Balkengrafik&lt;br /&gt;
;graphicControl-&amp;gt;hourCount:Anzahl der darzustellenden Balken/Stunden in der Balkengrafk&lt;br /&gt;
[[Datei:Screenshot Screenshot 2025-05-21 153613.png|right|thumb|400px|Erweiterung des oberen und unteren Abstandes mit den Attributen graphicControl-&amp;gt;beamPaddingTop und graphicControl-&amp;gt;beamPaddingBottom]]&lt;br /&gt;
;graphicControl-&amp;gt;energyUnit:definiert die Einheit zur Anzeige der elektrischen Leistung in der Grafik&lt;br /&gt;
;graphicHistoryHour:Anzahl der vorangegangenen Stunden die in der Balkengrafik dargestellt werden&lt;br /&gt;
;graphicControl-&amp;gt;beamWidth:Vorgabe Breite der Balken der Balkengrafik in px (sonst automatische Bestimmung) &lt;br /&gt;
;graphicBeamHeightLevel1:Multiplikator zur Festlegung der maximalen Balkenhöhe der jeweiligen Ebene (hier Ebene 1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;Definition der Inhalte und Balkeneigenschaften&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 204756.png|right|thumb|400px|Wie oben aber mit gesetzem Attribut graphicShowNight=1]]&lt;br /&gt;
;graphicBeam1Color:Farbauswahl des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2Color:Farbauswahl des sekundären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam1Content:Legt den darzustellenden Inhalt des primären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam2Content:Legt den darzustellenden Inhalt des sekundären Balken fest (Ebene 1)&lt;br /&gt;
;graphicBeam1FontColor:Auswahl der Schriftfarbe des primären Balkens (Ebene 1)&lt;br /&gt;
;graphicBeam2FontColor:Auswahl der Schriftfarbe des sekundären Balkens (Ebene 1)&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 205024.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=0 (ohne Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::*&#039;&#039;&#039;zusätzliche Optionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;graphicShowNight:Anzeigen oder Verbergen der Nachtstunden in der Balkengrafik&lt;br /&gt;
;graphicShowWeather:Wettericons in der Balkengrafik anzeigen/verbergen (nur Ebene 1)&lt;br /&gt;
;graphicWeatherColor:Farbe der Wetter-Icons für die Tagesstunden&lt;br /&gt;
;graphicWeatherColorNight:Farbe der Wetter-Icons für die Nachtstunden&lt;br /&gt;
;graphicShowDiff:Zusätzliche Anzeige der Differenz &amp;quot;&amp;lt;primärer Balkeninhalt&amp;gt; - &amp;lt;sekundärer Balkeninhalt&amp;gt;&amp;quot; im Kopf- oder Fußbereich der Balkengrafik&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die genaue Beschreibung und deren Optionen sind der aktuellen Online-Hilfe zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Für alle Ebenen gilt:&#039;&#039;&#039; Ein Attribut mit einer ungeraden Balkennummer (z.B. graphicBeam1Content) bezieht sich immer auf den primären Balken, ein Attribut mit einer geraden Balkennummer (z.B. graphicBeam2Content) bezieht sich immer auf den sekundären Balken.&lt;br /&gt;
&lt;br /&gt;
Die Balken haben, wie die meisten Elemente in der Balkengrafik, eine Mouse-Over Eigenschaft welche relevante Informationen zu den dargestellten Werten anzeigt. &lt;br /&gt;
&lt;br /&gt;
Sind die Nachtunden mit &#039;&#039;&#039;graphicShowNight&#039;&#039;&#039; ausgeblendet, werden keine Balken angezeigt sofern es keine Werte anzuzeigen gibt. Sollten dennoch Werte ungleich 0 anzuzeigen sein, werden diese Werte auch trotz ausgeblendeter Nachstunden angezeigt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 2 ====&lt;br /&gt;
[[Datei:Screenshot 2025-01-12 211741.png|right|thumb|400px|Balkengrafik mit aktivierter Ebene 2, gesetzem Attribut graphicShowNight=01 (mit Zeitsynchronisation zwischen Ebene 1 und Ebene 2)]]&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 2&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam3Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam4Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 4 für Balken 4) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wetter-Icons können nur in Ebene 1 integriert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 2 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 2 gibt, eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgende Ebene.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== Aktivierung der Balkengrafik Ebene 3 ====&lt;br /&gt;
&lt;br /&gt;
Um die &#039;&#039;&#039;Ebene 3&#039;&#039;&#039; der Balkengrafik zu aktivieren, setzt man das Attribut &#039;&#039;&#039;graphicBeam5Content&#039;&#039;&#039; und/oder &#039;&#039;&#039;graphicBeam6Content&#039;&#039;&#039; mit den gewünschten darzustellenden Inhalten. Die weiteren Darstellungsoptionen, wie graphicBeamCColor, können ebenfalls für den jeweiligen Balken selektiv definiert werden wenn ein Attribut mit der entsprechenden Nummer (z.B. 5 für Balken 5) vorhanden ist. &lt;br /&gt;
&lt;br /&gt;
Werden in der Balkengrafik die Nachtstunden ausgeblendet (&#039;&#039;&#039;graphicShowNight=0&#039;&#039;&#039; bzw. default), findet zwischen der Ebene 1 und der Ebene 3 keine Synchronisation der Zeitebene statt. Falls es einen inhaltlichen Zusammenhang zwischen den Werten der Ebene 1 und Ebene 3 gibt, ist eine Zeitsynchronisation zwischen den Ebenen wünschenswert und sinnvoll. Durch Setzen des Attrbut &#039;&#039;&#039;graphicShowNight=01&#039;&#039;&#039; kann diese Synchronisation eingeschaltet werden. &lt;br /&gt;
&lt;br /&gt;
Dabei ist die Ebene 1 die führende Ebene, d.h. diese Ebene vererbt die exkludierten bzw. eventuell inkludierten Nachtstunden (wenn Werte in den Balken der Ebene 1 angezeigt werden sollen) an die nachfolgenden Ebenen, d.h. auch auf die Ebene 3.&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 5 - Die Energieflußgrafik (Flow Graphic) ===&lt;br /&gt;
[[Datei:Screenshot 2025-02-13 213424.png|right|thumb|400px|Energieflußgrafik mit Verbrauchern in der Nachtdarstellung (Mondphasen) nach Sonnenuntergang]]&lt;br /&gt;
&lt;br /&gt;
Die Energieflußgrafik stellt die registrierten Erzeuger, Batterien, Netzzugänge und Verbraucher strukturiert in mehreren Ebenen dar:&lt;br /&gt;
&lt;br /&gt;
;Ebene 1: In der oberen Ebene befinden sich die PV-Generatoren, Smart-Loader sowie sonstigen Erzeuger &lt;br /&gt;
;Ebene 2: Die mittlere Ebene organisiert den Zugang zum öffentlichen Netz, dem Hausknoten, dem Batterieknoten sowie einem Dummy-Verbraucher (Lampensymbol) für den Energieverbrauch des Hauses der keinem der registrierten Verbraucher zugeordnet werden kann.&lt;br /&gt;
;Ebene 3: In der unteren Ebene werden die registrierten Verbraucher dargestellt. Unterhalb der Verbrauchersymbole werden der aktuelle Verbrauch (bzw. der On/Off-Zustand) sowie darunter die Restlaufzeit (Minuten) des Verbrauchers, sofern er durch das Modul geplant und gestartet wurde. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Position und Gestaltung der Grafikelemente ist umfangreich über das Attribut &#039;&#039;&#039;flowGraphicControl&#039;&#039;&#039; und den darin verfügbaren Schlüsseln einstellbar.&lt;br /&gt;
Die Bedeutung der Schlüssel ist in der Online-Hilfe zum Attribut mit einem Beispiel beschrieben. &lt;br /&gt;
&lt;br /&gt;
Darüber hinaus enthalten die Setup-Attribute &#039;&#039;&#039;setupInverterDevXX&#039;&#039;&#039;, &#039;&#039;&#039;setupOtherProducerXX&#039;&#039;&#039; und &#039;&#039;&#039;consumerXX&#039;&#039;&#039; weitere Einstellungsmöglichkeiten um deren Icons und Färbungen in der Flußgrafik individuell einstellen zu können. So sind zum Beispiel die Icons der PV-Inverter und deren Färbung mit dem Schlüssel &#039;&#039;&#039;icon&#039;&#039;&#039; der setupInverterDevXX-Attribute in Abhängigkeit von Tag und Nacht separat definierbar.&lt;br /&gt;
&lt;br /&gt;
In den Verbraucher-Attributen ist mit dem Schlüssel &#039;&#039;&#039;noshow&#039;&#039;&#039; die Sichtbarkeit in der Flußgrafik definierbar.&lt;br /&gt;
&lt;br /&gt;
Generell steuert das Attribut &#039;&#039;&#039;graphicSelect&#039;&#039;&#039; die Ein- bzw. Ausblendung der gesamten Flußgrafik.&lt;br /&gt;
&lt;br /&gt;
== Die Verbrauchsprognose ==&lt;br /&gt;
Im Gegensatz zu der PV Prognose gibt es keine API oder andere externen Datenquellen die für die Verbrauchsprognose herangezogen werden könnten.&lt;br /&gt;
&lt;br /&gt;
Zum Zweck der Verbrauchsermittlung verwendet das Modul die Meterdaten aus dem Attribut &#039;&#039;setupMeterDev&#039;&#039; sowie den weiteren setup-Attributen &#039;&#039;setupInverterDevXX&#039;&#039;. &lt;br /&gt;
Sind auch andere Erzeuger (BHKW, Windanlagen, etc.) bzw. eine Batterie vorhanden, sind ebenfalls die Attribute &#039;&#039;setupOtherProducerXX&#039;&#039; bzw. &#039;&#039;setupBatteryDev&#039;&#039; für die Berechnung des Hausverbrauchs relevant. In diesen Attributen gibt es die Schlüssel &#039;&#039;*total&#039;&#039; die teilweise optional sind. Für die Verbrauchsprognose bilden sie jedoch die Berechnungsgrundlage und sind deswegen für diese Funktionalität wichtig anzugeben.&lt;br /&gt;
&lt;br /&gt;
Die Verbrauchswerte werden stundengenau erfasst und im Datenspeicher &#039;&#039;pvHistory&#039;&#039; für 31 Tage, sowie im Datenspeicher &#039;&#039;pvCircular&#039;&#039; 210 Tage gespeichert. Die beiden Datenspeicher übernehmen unterschiedliche Aufgaben im Rahmen der Prognoseerstellung. Auf Grundlage der gespeicherten und somit historischen Verbrauchswerte erstellt das Modul eine Prognose für die kommende Zeit.&lt;br /&gt;
&lt;br /&gt;
Mit dem Kommando &lt;br /&gt;
&lt;br /&gt;
   &amp;quot;get ... pvHistory [Tag]&amp;quot; &lt;br /&gt;
&lt;br /&gt;
wird der Inhalt aufgelistet. Die Schlüssel &#039;&#039;confc&#039;&#039;, &#039;&#039;con&#039;&#039; und &#039;&#039;gcon&#039;&#039; zeigen die Verbrauchsprognose, den Verbrauch und den Netzbezug der jeweiligen Stunde des gewählten Tages.&lt;br /&gt;
Die Stunde &amp;quot;99&amp;quot; zeigt die Summen dieser Schlüsssel für den Tag:&lt;br /&gt;
&lt;br /&gt;
      99 =&amp;gt; etotal: , pvfc: 782, pvrl: 0, rad1h: -&lt;br /&gt;
            confc: 14540, con: 13873, gcon: 13873, gfeedin: 0&lt;br /&gt;
            batintotal: , batin: 0, batouttotal: , batout: 0&lt;br /&gt;
            batmaxsoc: -, batsetsoc: -&lt;br /&gt;
            wid: , wcc: , wrp: , pvcorrf: , dayname: So&lt;br /&gt;
            cyclescsm01: 0&lt;br /&gt;
            cyclescsm02: 0&lt;br /&gt;
            cyclescsm03: 0&lt;br /&gt;
            cyclescsm04: 1, hourscsme04: 0.00&lt;br /&gt;
            cyclescsm05: 0&lt;br /&gt;
            cyclescsm06: 0&lt;br /&gt;
            cyclescsm07: 1, hourscsme07: 0.00&lt;br /&gt;
            cyclescsm08: 1, hourscsme08: 0.00&lt;br /&gt;
            cyclescsm09: 1, hourscsme09: 0.03 &lt;br /&gt;
&lt;br /&gt;
In dem Beispiel wurden für den Tag 14540 Wh Verbrauch prognostiziert, 13873 Wh tatsächlich verbraucht und davon 13873 Wh aus dem Netz bezogen. Leider war an diesem Tag keinerlei PV Ertrag vorhanden, was man auch an dem Schlüssel &#039;&#039;pvrl&#039;&#039; erkennen kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Inhalt des pvCircular-Speichers kann mit dem Befehl  &lt;br /&gt;
&lt;br /&gt;
     &amp;quot;get ... pvCircular [Tag]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Das nachfolgende Beispiel zeigt die Ausgabe für die Tagesstunde 23:&lt;br /&gt;
&lt;br /&gt;
 23 =&amp;gt; pvapifc: 0, pvaifc: -, pvfc: 0, aihit: 0, pvrl: 0&lt;br /&gt;
       batin01: 0, batin02: -, batin03: -&lt;br /&gt;
       batout01: 619, batout02: -, batout03: -&lt;br /&gt;
       confc: 650, gcon: 23, gfeedin: 0, wcc: 40, rr1c: 0.00&lt;br /&gt;
       temp: -6.00, wid: 100, wtxt: Bewölkungsentwicklung nicht beobachtet&lt;br /&gt;
       pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
       ... &lt;br /&gt;
       con_all =&amp;gt; Sa  @ 617 762&lt;br /&gt;
                  Di  @ 693 645&lt;br /&gt;
                  Mo  @ 620 679&lt;br /&gt;
                  So  @ 669 666 636&lt;br /&gt;
                  Mi  @ 701 626&lt;br /&gt;
                  Do  @ 612 642&lt;br /&gt;
                  Fr  @ 615 606&lt;br /&gt;
&lt;br /&gt;
Der Schüssel &#039;&#039;con_all&#039;&#039; enthält einen Hash aus Arrays die für jeden Wochentag (Mo..So) bis zu 30 Verbrauchswerte (in Wh) für die angezeigte Stunde speichern. Wie hier erkennbar ist, wurden an den drei vergangenen Sonntagen jweils 669 Wh, 666 Wh bzw. 636 Wh in der Stunde 23 (22:00-22:59) verbraucht.&lt;br /&gt;
Der Median aus diesen Werten geht in die Verbrauchsprognose ein. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Die Wochentagsnamen Mo..So sind von den installierten Locales auf Betriebsystemebene abhängig. Ist keine deutsche locale installiert, werden die englischen Wochentagsnamen Mon..Sun verwendet. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Wie wird der Verbrauch des Hauses ermittelt und gespeichert? ===&lt;br /&gt;
Die Verbrauchsdaten des Hauses werden auf Stundenbasis ermittelt und gespeichert. Das &amp;quot;Haus&amp;quot; steht als Synonym aller im Kontext des Solarforecast Devices zusammengeführten Inverter (setupInverterDevXX), sonstigen Erzeuger (setupOtherProducerXX), Netzanschlüsse (setupMeterDev), Verbraucher (consumerXX) und Batterien (setupBatteryDev).&lt;br /&gt;
&lt;br /&gt;
Alle diese Daten werden durch das Modul mit jedem ausgeführten Zyklus (Attribut plantControl-&amp;gt;cycleInterval) und, wenn ein Event eines als &#039;asynchron&#039; definierten Devices auftritt, gesammelt und daraus permanent ein aktualisierter Verbrauch berechnet. Die Berechnung beschreibt folgende Formel:&lt;br /&gt;
&lt;br /&gt;
 PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung - Verbrauch = 0&lt;br /&gt;
&lt;br /&gt;
bzw.&lt;br /&gt;
 &lt;br /&gt;
 Verbrauch (Wh) = PV-Erzeugung + sonstige Erzeugung - Netzeinspeisung + Netzbezug - Batterieladung + Batterieentladung&lt;br /&gt;
            con = PV           + PP                 - GridIn          + GridCon   - BatIn          + BatOut&lt;br /&gt;
&lt;br /&gt;
Die PV-Erzeugung beinhaltet die Summe aller durch die angegebnen Inverter (setupInverterDev01 .. setupInverterDevXX) erzeugten Energien. Die &amp;quot;sonstige Erzeugung&amp;quot; summiert sich aus den Werten aller angegebenen Producer (setupOtherProducer01 .. setupOtherProducerXX). Der Verbrauch wird durch die registrierten Geräte consumerXX teilweise direkt erfasst, ist aber grundsätzlich unvollständig da nicht alle Verbrauchswerte im &amp;quot;Haus&amp;quot; gemessen und durch das Modul erfasst werden können.&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel zeigt das Ergebnis bei 300 Wh PV-Erzeugung und gleichzeitige 500 Wh Netzbezug:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 300 + 0 - 0 + 500 - 0 + 0 = 800 Wh&lt;br /&gt;
&lt;br /&gt;
Bei 1300Wh PV-Erzeugung, 100 Wh Netzeinspeisung sowie 200 Wh Batterieladung ergibt sich der Verbrauch zu:&lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 1300 + 0 - 100 + 0 - 200 + 0 = 1000 Wh&lt;br /&gt;
&lt;br /&gt;
Ohne Erzeugung, aber mit der Energielieferung von 500 Wh aus der Batterie, 800 Wh Netzbezug (mit einem Anteil Batterienachladung aus dem Netz von 200 Wh) sieht die Verbrauchsrechnung wie folgt aus: &lt;br /&gt;
&lt;br /&gt;
 Verbrauch = 0 + 0 - 0 + 800 - 200 + 500 = 1100 Wh&lt;br /&gt;
&lt;br /&gt;
Der so ermittelte Verbrauchsert wird mit jedem Zyklus in der pvHistory im Schlüssel &amp;quot;con&amp;quot; gespeichert. Man kann sich die gespeicherten Werte mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;name&amp;gt; pvHistory [&amp;lt;Tag&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
angezeigt werden. Nachfolgendes Beispiel zeigt einen Datensatz für die Stunde 8 eines Tages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      08 =&amp;gt; pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotali01: 62940734, etotali02: 2928860, etotali03: -&lt;br /&gt;
            pvrl01: 0, pvrl02: 0, pvrl03: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 630, con: 962, gcons: 962, conprice: 0.2958&lt;br /&gt;
            gfeedin: 0, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 120, sunalt: -3&lt;br /&gt;
            batintotal: 3713815.07742543, batouttotal: 3604468.26993988, batin: 0, batout: 0&lt;br /&gt;
            wid: 161, wcc: 89, rr1c: 0.00, pvcorrf: 0.27/0.00 temp: 7.40, &lt;br /&gt;
            csmt01: 110996.12, csme01: 32.1399999999994, minutescsm01: 30&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 2513.67, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1581293.6, csme04: 136.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 1662.17, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 90.53, csme06: 0, minutescsm06: 0&lt;br /&gt;
            csmt07: 39.75, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 38050, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 131627, csme09: 33.2000000000116, minutescsm09: 39&lt;br /&gt;
            minutescsm10: 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Schlüssel &amp;quot;con&amp;quot; ist der gespeicherte Verbrauch von 962 Wh ersichtlich.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit bekommt man mit dem Attribut &#039;&#039;ctrlDebug=collectData&#039;&#039; einen Einblick in die Verbrauchsermittlung bei jedem Zyklus und kann so die Eingangswerte und das daraus resultierende Ergebnis im FHEM Log nachverfolgen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
2024.11.28 11:38:20.080 1: SolCast DEBUG&amp;gt; EnergyConsumption input -&amp;gt; PV: 96, PP: 0, GridIn: 0, GridCon: 582, BatIn: 5, BatOut: 0&lt;br /&gt;
2024.11.28 11:38:20.081 1: SolCast DEBUG&amp;gt; EnergyConsumption result -&amp;gt; 673 Wh&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie wird die Verbrauchsprognose erstellt? ===&lt;br /&gt;
&lt;br /&gt;
Aus den gespeicherten con-Werten (Verbrauchsdaten) der pvCircular (Schlüssel con_all) sowie Einträgen der pvHistory wird der Median der historischen Tage ermittelt und für den kommenden Tag bzw. die kommen Stunden zur Prognose angewendet. Dabei geht per default jeder verfügbare historische Tag gleichberechtigt in die Prognose ein. Mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039; kann festgelegt werden, dass nur gleiche Wochentage (Mo..So) für die Prognose verwendet werden. Hierbei spielt die Vermutung, dass das Verbrauchsverhalten eine gewisse Korrelation zum Wochentag hat, eine Rolle. &lt;br /&gt;
&lt;br /&gt;
Verwendet man die Einstellung consForecastIdentWeekdays=1, hat es sich als vorteilhaft erwiesen, das Attribut &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays&#039;&#039;&#039; auf einen niedrigeren Wert als den Default zu setzen. Eine Einstellung auf &#039;8&#039; zum Beispiel verwendet den Median der gleichen Wochentage der vergangenenen 8 Wochen. Dadurch wird nicht zu weit in die Vergangenheit verzweigt und so eine langsame Veränderung des Verbrauchsmedian, zum Beispiel hervorgerufen durch den Übergang vom Winter in das Frühjahr hinein, abgebildet.&lt;br /&gt;
&lt;br /&gt;
Weiteren Einfluß auf die Verbrauchsprognose kann mit dem Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; im Consumerattribut genommen werden. Insbesondere bei der unregelmäßigen Nutzung von Verbrauchern mit hoher Leistung kann die Projektion der aufgezeichneten historischen Werte in die Prognose zu unverhältnismäßig hohen Verbrauchswerwartunden führen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Möglicherweise führt in Fällen die Verwendung eine der nachfolgenden Optionen zu einem besseren Ergebnis:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;1 -&#039;&#039;&#039; die allgemeine Verbrauchsprognose wird um die gespeicherten Energieverbrauchsanteile reduziert.&lt;br /&gt;
* &#039;&#039;&#039;2 -&#039;&#039;&#039; wie bei &#039;1&#039;, jedoch gehen die Planungsdaten des Verbrauchers bei der Prognose der kommenden Stunden wieder mit ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;&#039;exconfc&#039;&#039;&#039; in einem der Consumer verwendet, sollte&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastIdentWeekdays=1&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;plantControl-&amp;gt;consForecastLastDays=4&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
eingestellt werden. Hintergrund ist, dass die Verbrauchsanteile der jeweiligen Verbraucher nur maximal 31 Tage in der pvHistory verfügbar sind. Für längere Zeiträume stehen nur Gesamtsummen des Verbrauchs in der pvCircular zu Verfügung.  &lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=1&#039;&#039;&#039; werden die in der Historie aufgezeichneten Verbrauchsbestandteile aus einer Prognose herausgerechnet. Konkret werden die in der pvHistory aufgezeichneten Verbrauchsbestandteile für die relevante Stunde ermittelt und daraus ein Durchschnitt gebildet der vom Prognosewert subtrahiert wird. Mit dem Attributwert plantControl-&amp;gt;consForecastIdentWeekdays=1 werden wiederum nur identische Wochentage (Mo .. So) zusammengefasst.&lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;&#039;exconfc=2&#039;&#039;&#039; erfolgt ebenso die Eliminierung des Verbrauchsanteils, es wird jedoch auf die Planungsdaten für diesen Verbraucher zugegriffen und die geplanten Energieanteile wiederum der Verbrauchsprognose für die kommenden Stunden hinzugerechnet.&lt;br /&gt;
&lt;br /&gt;
In beiden Anwendungsfällen ist es notwendig, dass dem Modul durch die Angabe entsprechender Readings der Energieverbrauch im Setup des Consumers bekannt gemacht wird damit diese Energieanteile registriert werden können. Allgemein funktioniert die Verbrauchsprognose gut wenn Verbrauchsprozesse regelmäßig in einem wiederkehrenden Zeitraster ablaufen, der Verbrauch durch persönliche Rituale bestimmt ist. So zum Beispiel könnte am Dienstag und Samstag gewöhnlich die Waschmaschine laufen, das E-Auto täglich aufgeladen werden und gebügelt wird oft am Sonntag Nachmittag.&lt;br /&gt;
&lt;br /&gt;
Unregelmäßige Nutzung, vor allem vom Großverbrauchern, lässt sich nur sehr schwer und ungenügend auf zukünftige Verbrauchsprognosen projizieren.&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis der Prognose wird im Kopf der Grafik in der Zeile &#039;&#039;Verbrauch&#039;&#039; sowie in diversen Readings wie &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RestOfDayConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den Rest des Tages)&lt;br /&gt;
* &#039;&#039;&#039;NextHours_Sum04_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für die nächsten 4 Stunden)&lt;br /&gt;
* &#039;&#039;&#039;Tomorrow_ConsumptionForecast&#039;&#039;&#039; (Verbrauchsprognose für den kommenden Tag)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
angezeigt.&lt;br /&gt;
&lt;br /&gt;
Weitere Aggregationen kann man sich über das Attribut &#039;&#039;&#039;ctrlStatisticReadings&#039;&#039;&#039; bei Bedarf zuschalten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;conForecastTillNextSunrise&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
* &#039;&#039;&#039;todayConForecastTillSunset&#039;&#039;&#039; - Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
* &#039;&#039;&#039;todayConsumptionForecast&#039;&#039;&#039; - Verbrauchsprognose aufgesplittet pro Stunde des aktuellen Tages (01-24) &lt;br /&gt;
 &lt;br /&gt;
==== Debugging der Verbrauchsprognose ====&lt;br /&gt;
Um sich einen Einblick über die Erstellung der Verbrauchsprognose zu verschaffen, bietet sich die Einschaltung von:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
an. Mit diesem gesetzten Attribut wird die Erstellung der Prognose im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; ################### Start Consumption forecast ###################&lt;br /&gt;
2025.02.27 19:52:00.063 1: SolCast DEBUG&amp;gt; Basics - installed locale: de_DE.UTF-8, used scheme: DE&lt;br /&gt;
2025.02.27 19:52:00.064 1: SolCast DEBUG&amp;gt; process Today dayname: Do, Tomorrow dayname: Fr&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 01 - 74.43 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 10 - 290.77 Wh&lt;br /&gt;
2025.02.27 19:52:00.065 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 13, hod: 24 - 660.70 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 20, hod: 07 - 459.93 Wh&lt;br /&gt;
2025.02.27 19:52:00.066 1: SolCast DEBUG&amp;gt; consumer &#039;07&#039; register for exclude day 20, hod: 02 - 0.33 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; consumer &#039;03&#039; register for exclude day 30, hod: 08 - 264.78 Wh&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next Hours (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; excl. hist 74 Wh for Hour 01, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.067 1: SolCast DEBUG&amp;gt; estimated cons of Hour 01: 436 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; excl. hist 0 Wh for Hour 02, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 02: 428 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 03: 458 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.068 1: SolCast DEBUG&amp;gt; estimated cons of Hour 04: 503 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 05: 489 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 06: 482 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; excl. hist 460 Wh for Hour 07, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.069 1: SolCast DEBUG&amp;gt; estimated cons of Hour 07: 274 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 265 Wh for Hour 08, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 08: 441 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; estimated cons of Hour 09: 558 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.070 1: SolCast DEBUG&amp;gt; excl. hist 291 Wh for Hour 10, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 10: 443 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 11: 881 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.071 1: SolCast DEBUG&amp;gt; estimated cons of Hour 12: 794 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 13: 840 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 14: 660 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 15: 812 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.072 1: SolCast DEBUG&amp;gt; estimated cons of Hour 16: 752 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 17: 597 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 18: 652 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 19: 634 Wh, Considered value numbers: 4&lt;br /&gt;
2025.02.27 19:52:00.073 1: SolCast DEBUG&amp;gt; estimated cons of Hour 20: 628 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 21: 713 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 22: 596 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; estimated cons of Hour 23: 629 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.074 1: SolCast DEBUG&amp;gt; excl. hist 661 Wh for Hour 24, Considered value numbers: 1&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons of Hour 24: 660 Wh, Considered value numbers: 3&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; estimated cons Tomorrow: 16848 Wh, Individual hourly values considered: 72, exclude: 0 Wh (avg of 0 entities)&lt;br /&gt;
2025.02.27 19:52:00.075 1: SolCast DEBUG&amp;gt; ################### Store Consumption forecast values (new median) ###################&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour00&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;20&#039; confc: 628&lt;br /&gt;
2025.02.27 19:52:00.076 1: SolCast DEBUG&amp;gt; store &#039;NextHour01&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;21&#039; confc: 713&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour02&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;22&#039; confc: 596&lt;br /&gt;
2025.02.27 19:52:00.077 1: SolCast DEBUG&amp;gt; store &#039;NextHour03&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;23&#039; confc: 629&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store &#039;NextHour04&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.078 1: SolCast DEBUG&amp;gt; store circular/history hod &#039;24&#039; confc: 660&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour05&#039; hod &#039;01&#039; confc: 436, confcEx: 436&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour06&#039; hod &#039;02&#039; confc: 428, confcEx: 428&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour07&#039; hod &#039;03&#039; confc: 458, confcEx: 458&lt;br /&gt;
2025.02.27 19:52:00.079 1: SolCast DEBUG&amp;gt; store &#039;NextHour08&#039; hod &#039;04&#039; confc: 503, confcEx: 503&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour09&#039; hod &#039;05&#039; confc: 489, confcEx: 489&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour10&#039; hod &#039;06&#039; confc: 482, confcEx: 482&lt;br /&gt;
2025.02.27 19:52:00.080 1: SolCast DEBUG&amp;gt; store &#039;NextHour11&#039; hod &#039;07&#039; confc: 274, confcEx: 274&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour12&#039; hod &#039;08&#039; confc: 441, confcEx: 441&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour13&#039; hod &#039;09&#039; confc: 558, confcEx: 558&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour14&#039; hod &#039;10&#039; confc: 443, confcEx: 443&lt;br /&gt;
2025.02.27 19:52:00.081 1: SolCast DEBUG&amp;gt; store &#039;NextHour15&#039; hod &#039;11&#039; confc: 881, confcEx: 881&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour16&#039; hod &#039;12&#039; confc: 794, confcEx: 794&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour17&#039; hod &#039;13&#039; confc: 840, confcEx: 840&lt;br /&gt;
2025.02.27 19:52:00.082 1: SolCast DEBUG&amp;gt; store &#039;NextHour18&#039; hod &#039;14&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour19&#039; hod &#039;15&#039; confc: 812, confcEx: 812&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour20&#039; hod &#039;16&#039; confc: 752, confcEx: 752&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour21&#039; hod &#039;17&#039; confc: 597, confcEx: 597&lt;br /&gt;
2025.02.27 19:52:00.083 1: SolCast DEBUG&amp;gt; store &#039;NextHour22&#039; hod &#039;18&#039; confc: 652, confcEx: 652&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour23&#039; hod &#039;19&#039; confc: 634, confcEx: 634&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour24&#039; hod &#039;20&#039; confc: 628, confcEx: 628&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour25&#039; hod &#039;21&#039; confc: 713, confcEx: 713&lt;br /&gt;
2025.02.27 19:52:00.084 1: SolCast DEBUG&amp;gt; store &#039;NextHour26&#039; hod &#039;22&#039; confc: 596, confcEx: 596&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour27&#039; hod &#039;23&#039; confc: 629, confcEx: 629&lt;br /&gt;
2025.02.27 19:52:00.085 1: SolCast DEBUG&amp;gt; store &#039;NextHour28&#039; hod &#039;24&#039; confc: 660, confcEx: 660&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; consumption calculated - day: 27, hod: 20, con: 574 Wh&lt;br /&gt;
2025.02.27 19:52:00.086 1: SolCast DEBUG&amp;gt; write pvCircular consumption - hod: 99, todayConsumption: 11210 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe startet mit &#039;&#039;&amp;quot;Start Consumption forecast&#039;&#039;&amp;quot;, es werden die zu exkludierenden historischen Daten für jeden Consumer bzgl. jedem Tag (day) und Stunde des Tages (hod) getrennt registriert. Diese Werte werden durch die gespeicherte Einträge in der pvHistory (max. 31 historische Tage) geliefert. &lt;br /&gt;
&lt;br /&gt;
Im nächsten Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next Hours (new median)&amp;quot;&#039;&#039; werden die Prognosen für die nächsten Stunden kalkuliert und die zuvor registrierten Excludes angewendet. Die Prognose für den kommenden Tag ist im Abschnitt &#039;&#039;&amp;quot;Consumption forecast for the next day (new median)&amp;quot;&#039;&#039; protokolliert. Die Prognose für den kommenden Tag ist nicht einfach die Summe der Prognose der nächsten Stunden, denn in den kommenden Stunden werden auch die verfügbaren Planungen der Consumer einbezogen. Für den kommenden Tag können diese Werte unter Umständen nicht einbezogen werden da sie zum Zeitpunkt X noch nicht verfügbar sind.&lt;br /&gt;
&lt;br /&gt;
Im Abschnitt &#039;&#039;&amp;quot;Store Consumption forecast values (new median)&amp;quot;&#039;&#039; erscheinen die effektiv gespeicherten Werte. Diese sind die Grandlage für die grafische Darstellung sowie weiteren Kalkulationen.&lt;br /&gt;
&lt;br /&gt;
=== Wie kann eine fehlerhafte Verbrauchsprognose korrigiert werden? ===&lt;br /&gt;
Wie im vorherigen Abschnitt beschrieben, wird die Prognose aus den gespeicherten &amp;quot;con&amp;quot;-Werten der vergangenen Tage (bzw. Stunden) abgeleitet. &lt;br /&gt;
Grundsätzlich muß zunächst sichergestellt werden, dass die auszulesenden Readings der angegebenen Energiezähler sowie deren Einheiten! korrekt eingestellt sind. Das gilt ebenfalls für die registrierten Verbraucher im Modul.&lt;br /&gt;
&lt;br /&gt;
Für einen ersten Überblick bietet sich das Debug Attribut an zu setzen:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; ctrlDebug consumption_long&lt;br /&gt;
&lt;br /&gt;
Beispielausgabe des Debug:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2024.09.21 13:28:27.041 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next day ###################&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;01&amp;lt; considering possible exclusions: 14082&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;08&amp;lt; considering possible exclusions: 16446&lt;br /&gt;
2024.09.21 13:28:27.042 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;15&amp;lt; considering possible exclusions: 14568&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; History Consumption day &amp;gt;25&amp;lt; considering possible exclusions: 15522&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; estimated Consumption for tomorrow: 15154, days for avg: 4&lt;br /&gt;
2024.09.21 13:28:27.043 1: SolCast DEBUG&amp;gt; ################### Consumption forecast for the next hours ###################&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 14 -&amp;gt; 850 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 14 -&amp;gt; 643 Wh&lt;br /&gt;
2024.09.21 13:28:27.044 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 14 -&amp;gt; 590 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 14 -&amp;gt; 522 Wh&lt;br /&gt;
2024.09.21 13:28:27.045 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 13:00:00, confc: 651, days for avg: 4, hist. consumption registered consumers: 560.97&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 15 -&amp;gt; 720 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 15 -&amp;gt; 743 Wh&lt;br /&gt;
2024.09.21 13:28:27.046 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 15 -&amp;gt; 897 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 15 -&amp;gt; 557 Wh&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 14:00:00, confc: 729, days for avg: 4, hist. consumption registered consumers: 620.97&lt;br /&gt;
2024.09.21 13:28:27.047 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 16 -&amp;gt; 676 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 16 -&amp;gt; 790 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 16 -&amp;gt; 785 Wh&lt;br /&gt;
2024.09.21 13:28:27.048 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 16 -&amp;gt; 581 Wh&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 15:00:00, confc: 708, days for avg: 4, hist. consumption registered consumers: 647.29&lt;br /&gt;
2024.09.21 13:28:27.049 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 17 -&amp;gt; 622 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 17 -&amp;gt; 639 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 17 -&amp;gt; 646 Wh&lt;br /&gt;
2024.09.21 13:28:27.050 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 17 -&amp;gt; 572 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 16:00:00, confc: 619, days for avg: 4, hist. consumption registered consumers: 618.30&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 18 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.051 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 18 -&amp;gt; 614 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 18 -&amp;gt; 580 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 18 -&amp;gt; 480 Wh&lt;br /&gt;
2024.09.21 13:28:27.052 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 17:00:00, confc: 567, days for avg: 4, hist. consumption registered consumers: 583.41&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 19 -&amp;gt; 615 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 19 -&amp;gt; 1659 Wh&lt;br /&gt;
2024.09.21 13:28:27.053 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 19 -&amp;gt; 597 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 19 -&amp;gt; 618 Wh&lt;br /&gt;
2024.09.21 13:28:27.054 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 18:00:00, confc: 872, days for avg: 4, hist. consumption registered consumers: 636.97&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 20 -&amp;gt; 611 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 20 -&amp;gt; 1124 Wh&lt;br /&gt;
2024.09.21 13:28:27.055 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 20 -&amp;gt; 546 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 20 -&amp;gt; 479 Wh&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 19:00:00, confc: 690, days for avg: 4, hist. consumption registered consumers: 578.87&lt;br /&gt;
2024.09.21 13:28:27.056 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 07, hod: 21 -&amp;gt; 1474 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 14, hod: 21 -&amp;gt; 596 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 24, hod: 21 -&amp;gt; 619 Wh&lt;br /&gt;
2024.09.21 13:28:27.057 1: SolCast DEBUG&amp;gt;     historical Consumption added for Sa -&amp;gt; date: 31, hod: 21 -&amp;gt; 433 Wh&lt;br /&gt;
2024.09.21 13:28:27.058 1: SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Im ersten Teil wird die erwartete Consumption für den nächsten Tag unter Berücksichtigung möglicher Ausschlüsse von Verbrauchern ausgegeben. Ausschlüsse von Verbrauchern ergeben sich wenn in dem Verbraucherattribut der Schlüssel &#039;&#039;&#039;exconfc&#039;&#039;&#039; gesetzt ist. Er besagt, dass die Verbrauchswerte des Verbrauchers in eine zukünftige Prognose nicht eingehen sollen. Zum Beispiel wenn ein Verbraucher mit sehr hohen Verbrauchswerten nur sporadisch eingesetzt wird und dadurch die Prognose stark verfälschen würde. Es ist auch zu sehen, dass bedingt durch das Attribut &#039;&#039;&#039;affectConsForecastIdentWeekdays = 1&#039;&#039;&#039; nur die historischen Tage 01, 08, 15 und 25 berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Teil wird die berechnete Erwartung für die nächsten Stunden ausgegeben. &lt;br /&gt;
Zur Beschreibung der Fehlersuche gehen wir davon aus, dass die Prognose von 780 Wh am 2024-09-21 20:00:00 zu hoch erscheint weil am Tag &amp;quot;07&amp;quot; ein Wert von 1474 Wh gespeichert ist:&lt;br /&gt;
&lt;br /&gt;
 SolCast DEBUG&amp;gt; estimated Consumption for Sa -&amp;gt; starttime: 2024-09-21 20:00:00, confc: 780, days for avg: 4, hist. consumption registered consumers: 584.96&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt geben wir die historischen Werte für den Tag 07 aus:&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;Name&amp;gt; pvHistory 07&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz interessiert die Stunde 21. Sie resultiert aus der obigen Angabe &amp;quot;starttime: xxxx-xx-xx 20:00:00&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      21 =&amp;gt; etotal: 64354660, pvfc: 0, pvrl: 0, pvrlvd: 1, rad1h: -&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
            confc: 496, con: 1474, gcons: 23, conprice: 0.2958&lt;br /&gt;
            gfeedin: 5, feedprice: 0.1269&lt;br /&gt;
            DoN: 0, sunaz: 289, sunalt: -8&lt;br /&gt;
            batintotal: 3064096.92456668, batouttotal: 2958021.37946804, batin: 0, batout: 1460&lt;br /&gt;
            wid: 101, wcc: 20, rr1c: 0.00, pvcorrf: 1.00/-temp: 26.00, &lt;br /&gt;
            csmt01: 64262.43, csme01: 28.8099999999977, minutescsm01: 25&lt;br /&gt;
            minutescsm02: 0&lt;br /&gt;
            csmt03: 0, csme03: 0, minutescsm03: 0&lt;br /&gt;
            csmt04: 1389417.4, csme04: 94.5, minutescsm04: 60&lt;br /&gt;
            csmt05: 0, csme05: 0, minutescsm05: 0&lt;br /&gt;
            csmt06: 290.15, csme06: 6.66999999999996, minutescsm06: 54&lt;br /&gt;
            csmt07: 0, csme07: 0, minutescsm07: 0&lt;br /&gt;
            csmt08: 32800, csme08: 0, minutescsm08: 0&lt;br /&gt;
            csmt09: 103987.8, csme09: 38, minutescsm09: 43&lt;br /&gt;
            csmt10: 9151.24999999783, csme10: 3.99999999997999, minutescsm10: 60&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In dem Datensatz sind die Energieverbrauchsanteile der im Device registrierten Verbraucher mit dem Schlüssel &amp;quot;csmeXX&amp;quot; gespeichert. Dabei ist &amp;quot;XX&amp;quot; die Verbrauchernummer. In dem Beispiel existieren die Anteile csme01 und csme03 - csme10. Keiner dieser Verbraucher hat einen auffälligen Verbrauchswert gespeichert, d.h. die Messung der Verbraucher scheidet als Problemquelle aus. Wäre ein unverhältmismäßig hoher Verbrauch bei einem der Verbraucher feststellbar, müssten die Schlüssel &#039;&#039;&#039;pcurr&#039;&#039;&#039; und &#039;&#039;&#039;etotal&#039;&#039;&#039; im consumerXX-Attribut geprüft, sowie die Datenlieferung des Consumerdevices selbst geprüft werden.  &lt;br /&gt;
&lt;br /&gt;
Es wurde offensichtlich ein hoher Verbrauch von einem nicht registrierten Verbraucher verursacht oder durch die Übertragung eines Meßfehlers des Devices, angegeben im Attribut &#039;&#039;&#039;setupMeterDev&#039;&#039;&#039;, in das SolarForecast Device übertragen. Eine weitere Analyse ist an dieser Stelle nicht möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Behebung des falschen Wertes kann ein Reset der gespeicherten Consumption der relevanten Stunde durchgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;Name&amp;gt; reset consumptionHistory 07 21&lt;br /&gt;
&lt;br /&gt;
== Modulinterne Datenstrukturen ==&lt;br /&gt;
Das Modul speichert die verschiedenen historischen und aktuellen Daten wie PV-Prognose, Witterungsdaten (Regen, Bewölkung), Strahlungsdaten, Einspeisung, Bezug, reale Erzeugungsdaten und vieles mehr zur Laufzeit im Arbeitsspeicher. Dadurch ist die Verarbeitung dieser Daten im Vergleich zu Lesevorgängen aus dem Filesystem bzw. einer Datenbank sehr performant. Allerdings würden diese Daten bei einem FHEM Absturz bzw. bei einem regulären Shutdown verlorengehen.&lt;br /&gt;
&lt;br /&gt;
Deswegen werden die relevanten Daten regelmäßig in Dateien gesichert und bei Bedarf wiederhergestellt. Diese Dateien befinden sich im Verzeichnis &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; und heißen &#039;&#039;&#039;.*_SolarForecast_.*&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Die Daten werden in jedem Zyklus der Zentralschleife (CentralTask) gesammelt bzw. berechnet. Der Zyklus wird mit dem Attribut &#039;&#039;&#039;plantControl-&amp;gt;cycleInterval&#039;&#039;&#039; eingestellt.&lt;br /&gt;
&lt;br /&gt;
Zur Laufzeit können diese Daten über get-Kommandos abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvHistory [Tag]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der pvHistory Datenspeicher enthält die vergangenen Kennwerte der letzten 31 Tage mit einer Genauigkeit von einer Stunde. Es werden die Prognosewerte für Erzeugung und Verbrauch, die realen Werte für Erzeugung und Verbrauch sowie ebenso die Laufzeiten jedes einzelnen Verbrauchers (Consumer) festgehalten. Für jeden Tag gibt es die Stunde &amp;quot;99&amp;quot; die eine Summierung der Stundenwerte des Tages bzw. Sonderschlüssel enthält.&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf lässt sich mit dem Befehl &amp;quot;set ... reset pvHistory&amp;quot; der gesamte Inhalt des Speichers löschen (nicht empfohlen). Selektiver funktioniert die Datenlöschung mit &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt;&amp;quot; (Daten eines bestimmten Tages löschen) bzw. &amp;quot;set ... reset pvHistory &amp;lt;Tag&amp;gt; &amp;lt;Stunde&amp;gt;&amp;quot; (Daten der Stunde  eines bestimmten Tages löschen). Die letzten beiden Kommandos müssen über die Kommandozeile im Browser ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... pvCircular &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Ringspeicher enthält Daten der letzten 24 Stunden sowie fortwährend berechnete Werte wie Korrekturfaktoren der PV-Erzeugung und Prognosequalität.&lt;br /&gt;
Neue Stundenwerte des Tages überschreiben die gespeicherten Schüssel des vorangegangenen Tages sofern es sich nicht um fortwährend berechnete Werte handelt. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... nextHours&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Speicher enthält sämtliche Prognosewerte der kommenden Stunden beginnend mit der aktuellen Stunde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... radiationApiData&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Abhängig von der ausgewählten Strahlungsdaten API enthält dieser Speicher die von der API gelieferten Rohdaten sowie evtl. weitere für die Funktion benötigte Daten wie API-Keys, Response Messages, Anzahl der API Abruf und weitere.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valCurrent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Struktur wird nicht regelmäßig im Filesystem gespeichert und enthält immer aktuell gesammelte oder berechnete/gelieferte Daten wie z.B. die Autarkierate, letze Laufzeit der Zentralschleife (CentralTask), Zeit des Sonnenauf- und untergangs sowie weitere Betriebsdaten. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
get ... valConsumerMaster [XX]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zeigt die Daten der aktuell im SolarForecast Device registrierten Verbraucher. Mit der Nummer &#039;&#039;&#039;XX&#039;&#039;&#039; kann ein bestimmter Verbraucher angesprungen werden. Die Nummer korrespondiert mit dem entsprechenden &#039;&#039;&#039;consumerXX&#039;&#039;&#039; Attribut.&lt;br /&gt;
Neben anderen Betriebs- und Energiedaten werden insbesondere folgende Daten ermittelt, die für die zukünftige Planung der Verbraucherschaltzeiten relevant sind:&lt;br /&gt;
&lt;br /&gt;
* epieces - prognostizierte Energiescheiben pro Betriebsstunde &lt;br /&gt;
&lt;br /&gt;
Ausgehend von gespeicherten historischen Verbrauchsdaten des Verbrauchers wird der Energieverbrauch des Verbrauchers in seiner ersten Betriebsstunde prognostiziert, was insbesondere für die Planung der optimalen Startzeit des Verbrauchers in Bezug zu der prognostizierten PV Energie und den Verbrauchswerten weiterer vorhandener bzw. zu planender Verbraucher Berücksichtigung findet. Weitere Informationen zur Verbrauchersteuerung in diesem  [[#Verbrauchersteuerung_-_Registrieren_und_visualisieren_von_Verbrauchern|Abschnitt]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Schnittstelle für Modulautoren bzw. eigenen Code ===&lt;br /&gt;
&lt;br /&gt;
Die im vorherigen Artikel beschriebenen internen Datenstrukturen können durch externen Code abgefragt und ausgewertet werden.&lt;br /&gt;
Dazu stehen die folgenden Funktionen zur Verfügung. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]BatteryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Bn&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valBattery&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CurrentVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valCurrent&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]InverterVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valInverter&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ProducerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valProducer&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]HistoryVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Day&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvHistory&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]CircularVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;HoD&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... pvCircular&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]NexthoursVal (&#039;&amp;lt;Name&amp;gt;&#039;, &amp;lt;nhr&amp;gt;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... nextHours&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]ConsumerVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;Nr&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valConsumerMaster&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]RadiationAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;DateTime&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... radiationApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]WeatherAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;TimeCode&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... weatherApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StatusAPIVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;APIname&amp;gt;&#039;, &#039;&amp;lt;QTag&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... statusApiData&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
::* [FHEM::SolarForecast::]StringVal (&#039;&amp;lt;Name&amp;gt;&#039;, &#039;&amp;lt;String&amp;gt;&#039;, &#039;&amp;lt;Key&amp;gt;&#039;, &amp;lt;default&amp;gt;) &amp;lt;br&amp;gt; entspricht der Abfrage mit &amp;quot;get ... valStrings&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Angabe des Packages (FHEM::SolarForecast::) ist nur notwendig wenn die Funktionen von außerhalb des SolarForecast-Devices aufgerufen werden. Innerhalb des Devices (Code-Ausführung im Attribut &#039;&#039;ctrlUserExitFn&#039;&#039;) kann darauf verzichtet werden.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der Platzhalter sind:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     &amp;lt;Name&amp;gt;     - Name des SolarForecast Devices&lt;br /&gt;
     &amp;lt;Day&amp;gt;      - abzufragender Tag (01 - 31)&lt;br /&gt;
     &amp;lt;Bn&amp;gt;       - Batterie Nummer (01, 02, ...)&lt;br /&gt;
     &amp;lt;DateTime&amp;gt; - Startzeit der Form YYYY-MM-DD hh:00:00&lt;br /&gt;
     &amp;lt;TimeCode&amp;gt; - Zeitwert der Form fcX_XX (z.B. fc1_19)&lt;br /&gt;
     &amp;lt;APIname&amp;gt;  - Hauptname der API gemäß setupWeatherDev1 (z.B. OpenMeteo)&lt;br /&gt;
     &amp;lt;String&amp;gt;   - Name des PV-Modulstrings wie im Attribut &#039;setupInverterStrings&#039;&lt;br /&gt;
     &amp;lt;QTag&amp;gt;     - Question Tag, z.B. &#039;?All&#039;&lt;br /&gt;
     &amp;lt;Nr&amp;gt;       - laufende Nummer des Verbrauchers / Gerätes (01, 02, 03, 04,...)&lt;br /&gt;
     &amp;lt;HoD&amp;gt;      - abzufragende Stunde (01 - 24, 99)&lt;br /&gt;
     &amp;lt;nhr&amp;gt;      - nächste Stunde (NextHour00, NextHour01,...)&lt;br /&gt;
     &amp;lt;Key&amp;gt;      - der abzufragende Schlüssel &lt;br /&gt;
     &amp;lt;default&amp;gt;  - def default-Rückgabewert&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Auswerten von internen Arrays ===&lt;br /&gt;
&lt;br /&gt;
Die meisten der internen Datenstrukturen liefern bei der Abfrage einen einfachen String oder numerischen Wert der ausgewertet werden kann. Es gibt allerdings auch intern gespeicherte Wertelisten. Werden die Listenstrukturen mit den oben beschriebenen Befehlen abgefragt, wird eine Referenz auf die Liste geliefert sofern sie vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
Um auf die Werte einer solchen Liste zuzugreifen, ist am Beispiel des Arrays &#039;&#039;surplusslidereg&#039;&#039; aus dem Current-Speicher (get ... valCurrent) dargestellt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
my $splref = CurrentVal ($name, &#039;surplusslidereg&#039;, &#039;.&#039;);&lt;br /&gt;
my $spser  = ref $splref eq &#039;ARRAY&#039; ? join &#039; &#039;, @{$splref} : undef;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Variable $spser enthält bei Vorhandensein der Liste einen String, der die Listenelemente von &#039;surplusslidereg&#039; durch Leerzeichen getrennt enthält.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backup und Wiederherstellung der Moduldaten ==&lt;br /&gt;
Neben der Datenhaltung in den Attributen und Readings des SolarForecast Devices, erzeugt jedes SolarForecast Device Dateien im Verzeichnis  &#039;&#039;&#039;../fhem/FHEM/FhemUtils&#039;&#039;&#039; mit folgenden Inhalten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PVH_SolarForecast_&amp;lt;name&amp;gt;        - PV History&lt;br /&gt;
PVC_SolarForecast_&amp;lt;name&amp;gt;        - PV Circular&lt;br /&gt;
PVCfg_SolarForecast_&amp;lt;name&amp;gt;      - PV Anlagenkonfiguration&lt;br /&gt;
PVCsm_SolarForecast_&amp;lt;name&amp;gt;      - Consumer Status&lt;br /&gt;
ScApi_SolarForecast_&amp;lt;name&amp;gt;      - Strahlungswerte aus verwendeter API&lt;br /&gt;
StatApi_SolarForecast_&amp;lt;name&amp;gt;    - Statusdaten der verwendeten API&#039;s&lt;br /&gt;
WeatherApi_SolarForecast_&amp;lt;name&amp;gt; - Wetterdaten der gewählten Wetter-API (außer DWD-Device)&lt;br /&gt;
AItra_SolarForecast_&amp;lt;name&amp;gt;      - KI Entscheidungsquelle (trainierte Daten)&lt;br /&gt;
AIraw_SolarForecast_&amp;lt;name&amp;gt;      - KI Input Daten = Raw Trainigsdaten&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nach Ausprägung und eingesetzten Features des SolarForecast Devices sind alle oder nur ein Teil dieser Dateien vorhanden. Dabei ist &#039;&#039;&#039;&amp;lt;name&amp;gt;&#039;&#039;&#039; der Name des SolarForecast Devices.&lt;br /&gt;
&lt;br /&gt;
Bei einem Filebackup des FHEM-Servers ist darauf zu achten, dass diese Dateien in dem Backup enthalten sind. Der Inhalt der Dateien ist nicht statisch, sondern kann sich dynamisch aktualisieren. Um im Bedarfsfall einen aktuellen Datenstand zu haben, ist mindestens ein tägliches Backup dieser Dateien empfehlenswert. Eventuell auch öfter mit Hilfe einer Versionierung welche z.B. immer die letzten 3 Versionen aufbewahrt.&lt;br /&gt;
&lt;br /&gt;
Beim Start von FHEM werden bestimmte Dateien automatisch gelesen und in das SolarForecast Device importiert. &lt;br /&gt;
Der Vorgang ist mit verbose=3 im Log protokolliert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2023.10.02 09:57:07.967 3: SolCast6 - cached data &amp;quot;pvHistory&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.969 3: SolCast6 - cached data &amp;quot;pvCircular&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;consumerMaster&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;radiationApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;statusApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.970 3: SolCast6 - cached data &amp;quot;weatherApiData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.974 3: SolCast6 - cached data &amp;quot;aiTrainedData&amp;quot; restored&lt;br /&gt;
2023.10.02 09:57:07.976 3: SolCast6 - cached data &amp;quot;aiRawData&amp;quot; restored&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Bestimmte Betriebsdaten, wie z.B. die witterungsabhängigen Korrekturfaktoren (circular) oder die KI-Daten (aitrained/airaw), bauen sich über die Zeit immer granularer auf und stellen einen wertvollen Datenbestand dar.&lt;br /&gt;
&lt;br /&gt;
Wird das SolarForecast Device gelöscht und anschließend wieder neu mit dem gleichen Namen definiert, können die bisher verfügbaren Daten sehr einfach wiederhergestellt werden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. starten von FHEM (bestimmte Daten werden automatisch importiert)&lt;br /&gt;
* 5. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Soll das neue SolarForecast Device mit einem anderen Namen oder weitere SolarForecast Devices erstellt werden, welche die Betriebsdaten des primären Devices verwenden sollen, ist wie folgt vorzugehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)&lt;br /&gt;
* 2. FHEM stoppen&lt;br /&gt;
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)&lt;br /&gt;
* 4. umbenenen der Dateien, wobei &amp;lt;name&amp;gt; durch den Namen des neuen SolarForecast Devices ersetzt wird&lt;br /&gt;
* 5. starten von FHEM (die Daten werden automatisch importiert)&lt;br /&gt;
* 6. mit dem Befehl &amp;quot;set &amp;lt;name&amp;gt; plantConfiguration restore&amp;quot; die Anlagenkonfiguration wiederherstellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn sich die SolarForecast Devices hinsichtlich ihres Models oder der integrierten Consumer unterscheiden, sind die Dateien &amp;quot;PVCsm_SolarForecast_&amp;lt;name&amp;gt; &amp;quot; , &amp;quot;ScApi_SolarForecast_&amp;lt;name&amp;gt;&amp;quot; von dem Verfahren auszuschließen.&lt;br /&gt;
&lt;br /&gt;
== Batterieintegration und -steuerung ==&lt;br /&gt;
&lt;br /&gt;
=== Wie eine Batterie eingebunden wird ===&lt;br /&gt;
Wie immer muß die Batterieanlage zunächst mit einem für die Batterie spezifischen FHEM-Device in FHEM definiert sein.&lt;br /&gt;
In diesem Device werden Readings erwartet die folgende Werte bereitstellen:&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die aktuelle Batterieentladeleistung liefert&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die installierte Batteriekapazität liefert (&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; dieser Schlüssel ist für die Aktivierung des Batterie SOC-Managements und die grafische Anzeige des SOC wesentlich!)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Lade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* ein Reading welches die bis dato vorliegende Entlade-Energiemenge als fortlaufenden Zähler liefert (optional)&lt;br /&gt;
&lt;br /&gt;
::* Reading welches den aktuellen Ladezustand (SOC in Prozent) liefert (optional)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Batterie, bzw. das Batteriedevice wird mit dem Attribut &#039;&#039;&#039;setupBatteryDev&#039;&#039;&#039; im SolarForecast Device registriert. Die Syntax des Attributes ist in  der Online-Hilfe zum Attribut umfassend erläutert. &lt;br /&gt;
Auch wenn manche Readings optional sind, wird empfohlen alle Werte bereitzustellen um alle Batterie-Funktionen im Modul nutzen zu können. Durch die Weiterentwicklung des Moduls können optionale Readings später auch obligatorisch werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Visualisierung der Batterie in der Balkengrafik ====&lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;setupBatteryDevXX&#039;&#039;&#039; verfügt über den Schlüssel &#039;&#039;&#039;show&#039;&#039;&#039;, mit dem die Einblendung des bzw. der Batteriesymbole in den Ebenen der Balkengrafik gesteuert werden kann:&lt;br /&gt;
[[Datei:Screenshot 2025-02-23 192002.png|right|thumb|400px|Einblendung der Batterieleiste und Darstellung des Batterie-SoC als Balkencontent in der zweiten Ebene]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* 0 - keine Anzeige des Gerätes (default)&lt;br /&gt;
* 1 - Anzeige des Gerätes in der Balkengrafik Ebene 1&lt;br /&gt;
* 2 - Anzeige des Gerätes in der Balkengrafik Ebene 2 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Symbole und die Farbgebung der Batterie(n) können mittels des Schlüssels &#039;&#039;&#039;icon&#039;&#039;&#039; verändert werden. Die Online-Hilfe gibt weitere Informationen zur Ausgestaltung. &lt;br /&gt;
&lt;br /&gt;
In der Batteriedarstellung wird das Symbol der aktuellen Stunde hervorgehoben. Ein Mouse-Over zeigt wesentliche Betriebszustände der Batterie. Die Batteriesymbole vergangener Stunden zeigen mit einem Mouse-Over die erreichten SoC (State of Charge) Stände. Die kommenden Stunden visualisieren die folgenden Prognosen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der prognostizierte SoC unter Berücksichtigung der PV-Prognose und der [[#Aktivierung_des_Batterie_SOC-Managements|Batteriesteuerung]] sofern sie im Modul aktiviert ist.&lt;br /&gt;
* eine Freigabe bzw. Empfehlung der Batterieladung zur [[#Unterstützung_eines_netzdienlichen_Verhaltens|Unterstützung eines netzdienlichen Verhaltens]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Neben der Einblendung der Batterieleiste über der Balkengrafik selbst können bestimmte Batteriekennwerte als Balkeninhalt dargestellt werden. Die Auswahl erfolgt über das Attribut &#039;&#039;&#039;graphicBeamXContent&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Aktivierung des Batterie SOC- und Lade-Managements ===&lt;br /&gt;
Das integrierte SOC- und Lade-Management verfolgt insbesondere zwei Ziele: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* den Ladezustand der Batterie(n) zu optmimieren, was besonders in den Monaten mit geringerer PV-Erzeugung einen wertvollen Beitrag zur Erhöhung der Autarkierate und Batteriepflege leisten kann&lt;br /&gt;
 &lt;br /&gt;
* eine PV-Prognose und Verbrauch optimierte Beladungssteuerung, die in den Monaten mit hoher PV-Erzeugung hilft eine evtl. Abregelung der Anlage zu verhindern, die Batterie ausgewogen über den Tag zu laden und ein netzdienliches Verhalten zu unterstützen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese beiden Aspekte der Batteriesteuerung werden in den folgenden Abschnitten beschrieben. Sind mehrere Batterien installiert, kann die Steuerung getrennt für jede einzelne Batterie aktiviert und eingestellt werden. Dabei ist zu beachten, dass vom Modul nur Signale und Readings bereitgestellt werden, die durch eine entsprechende Routine ausgewertet werden können um spezifische Befehle zur Umsetzung der Steuerung an das Batteriesystem zu senden. &lt;br /&gt;
 &lt;br /&gt;
Für eine Aktivierung des Managements muß zunächst das Batterie-Device wie im vorigen Abschnitt im SolarForecast Device registriert werden.&lt;br /&gt;
Das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; aktiviert die im Modul integrierte SOC- und Lade-Management Routine: &lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; ctrlBatSocManagement01 lowSoc=&amp;lt;Wert&amp;gt; upSoC=&amp;lt;Wert&amp;gt; [maxSoC=&amp;lt;Wert&amp;gt;] [careCycle=&amp;lt;Wert&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
Die einzelnen Schlüssel werden der Kalkulationsroutine als Steuerungsparameter übergeben und bedeuten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;lowSoc:unterer Mindest-SoC, die Batterie wird nicht tiefer als dieser Wert entladen (muß &amp;gt; 0 sein). Dieser Wert kann zum Beispiel dazu dienen, stets eine Mindestenergiemenge für den Fall eines Stromausfalls im öffentlichen Netz in den Batterien vorzuhalten.&lt;br /&gt;
&lt;br /&gt;
;upSoC:oberer Mindest-SoC, Der übliche Wert des optimalen SoC bewegt sich in Perioden mit hohen PV-Überschuß tendenziell zwischen &#039;lowSoC&#039; und &#039;upSoC&#039;, in Perioden mit geringer PV-Ausbeute bzw. geringem PV Energieüberschuß bewegt sich der optimale SoC tendenziell zwischen &#039;upSoC&#039; und &#039;maxSoC&#039;. Die Einstellung von upSoC=50 für ein ausgewogenes Verhalten kann als guter Startwert dienen.&lt;br /&gt;
&lt;br /&gt;
;maxSoC:maximaler Mindest-SoC, d.h. der SoC Wert der mindestens im Abstand von &#039;careCycle&#039; Tagen erreicht werden muß um den Ladungsausgleich im Speicherverbund auszuführen. Die Angabe ist optional (muß &amp;lt;= 100 sein, default: 95)&lt;br /&gt;
&lt;br /&gt;
;careCycle:maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens &#039;maxSoC&#039; auftreten darf. Die Angabe ist optional. (default: 20)&lt;br /&gt;
&lt;br /&gt;
;loadAbort: definiert eine vom Anwender gewünnschte Bedingung für einen generellen Ladeabbruch und Wiederfreigabe der Lademöglichkeit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle Werte sind ganze Zahlen in %. Dabei gilt: &lt;br /&gt;
&lt;br /&gt;
 lowSoc &amp;lt; upSoC &amp;lt; maxSoC&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====  Erläuterung der Batterie-Steuerungsreadings ==== &lt;br /&gt;
&lt;br /&gt;
Für die Steuerung des Batteriesystems gibt es im SolarForecast einen Satz an Readings, die unterschiedliche Zustände signalisieren und für entsprechende Steuerungsaufgaben bezüglich der Batteriesysteme eingesetzt werden können. In den nachfolgenden Abschnitten werden diese Zusammenhänge noch dataillierter beschrieben.&lt;br /&gt;
&lt;br /&gt;
;Hinweis: SolarForecast stellt lediglich Steuerungsinformationen zur Verfügung. Die Umsetzung des Eingriffs in das Batteriesystem erfolgt durch den Anwender selbst über entsprechende Skripte. In den thematischen Abschnitten werden Beispiele für solche Steuerungsskripte vorgestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle erstellten Readings gelten für ein Batteriesystem, es können mehrere Batteriesysteme in SolarForecast integriert sein. Die Endung &#039;&#039;XX&#039;&#039; der Readings beschreibt die Nummer des Batteriesystems und korrespondiert mit der Endung des entsprechenden Attributes &#039;&#039;ctrlBatSocManagementXX&#039;&#039; bzw. &#039;&#039;setupBatteryDevXX&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Battery_OptimumTargetSoC_XX: Mit den im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; hinterlegten Parametern unter Berücksichtigung von PV- und Verbrauchsprognosen wird ein optimaler SOC-Wert errechnet. Dieser Wert dient zur Einstellung des unteren SOC des Batteriesystems.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeRequest_XX: Dieses Reading signalisiert mit 1 eine Anforderung zur Zwangsladung der Batterie um die Batterie vor Schäden zu schützen (wenn der SOC unter ctrlBatSocManagementXX-&amp;gt;lowSoc gefallen ist) oder wenn der aktuelle SOC unter den berechneten Mindest-SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeUnrestricted_XX: Dieses Reading kann den Wert &#039;&#039;&#039;0&#039;&#039;&#039; oder &#039;&#039;&#039;1&#039;&#039;&#039; einnehmen. Ist der Inhalt 0, sollte die Batterie nur geladen werden, wenn der im Attribut &#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039; definierte Wert überschritten wird. Ist der Inhalt 1, sollte die Batterie mit der vollen zur Verfügung stehenden Ladeleistung angesteuert werden, um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
;Battery_ChargeAbort_XX: Im Attribut &#039;&#039;ctrlBatSocManagementXX&#039;&#039; kann mit dem Schlüssel &#039;&#039;loadAbort&#039;&#039; eine Bedingung definiert werden, bei deren Eintritt die Ladung der Batterie abgebrochen werden soll. In diesem Fall wird &#039;&#039;Battery_ChargeAbort_XX=1&#039;&#039; gesetzt. Mit einem entsprechenden Befehl kann der Anwender das Batteriesystem anweisen den Ladevorgang abzubrechen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Nutzung des Batterie SOC-Management ====&lt;br /&gt;
&lt;br /&gt;
Oftmals wird durch die Anlagenhersteller ein hoher statischer SOC eingestellt bzw. empfohlen, der eine längere Verharrungszeit auf einem tiefen SOC-Wert verhindern soll. Allerdings wechseln sich in auch in den Herbst-, Frühlings- und Wintermonaten Zeiten mit wenig PV-Erzeugung mit Phasen stärkerer Solarstrahlung bei klarem Himmel und Sonnenschein ab.&lt;br /&gt;
&lt;br /&gt;
Ein statischer SOC würde dazu führen, dass in den erwähnten Phasen zuviel Energie in das öffentliche Netz eingespeist wird. Dies soll verhindert werden da die wertvolle Energie besser im eigenen Netz gespeichert und in Dunkelphasen verwendet werden kann. Andererseits soll die Batterie nicht zu lange auf einem tiefen SOC verbleiben und außerdem in gewissen Abständen auf einen so hohen SOC geladen werden der den internen Zellausgleich ermöglicht.&lt;br /&gt;
&lt;br /&gt;
Die SOC Kalkulationsroutine des Moduls errechnet unter Berücksichtigung des prognostizierten PV-Ertrages der kommenden Tage, des aktuellen SOC und der im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; (nachfolgend beschrieben) angegebenen Steuerparameter den Vorschlag für eine optimale SOC-Einstellung. Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert.&lt;br /&gt;
&lt;br /&gt;
Durch das Modul selbst findet keine Steuerung der Batterie statt. Es stellt entsprechende Readings zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen SoC.&lt;br /&gt;
&lt;br /&gt;
::* das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SoC unter den optimalen SoC gefallen ist. In diesem Fall sollte die Batterie, unter Umständen mit Netzstrom, zwangsgeladen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Readings können zur Steuerung des SoC (State of Charge) sowie zur Steuerung des verwendeten Ladestroms der Batterie verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ermittlung des optimalen SOC erfolgt nach folgender Logik:&lt;br /&gt;
&lt;br /&gt;
# 	Ausgehend von &#039;lowSoc&#039; wird der Mindest-SoC kurz vor Sonnenuntergang um 5% inkrementiert sofern am laufenden Tag &#039;maxSoC&#039; nicht erreicht wurde und die PV-Prognose keinen hinreichenden Ertrag des kommenden Tages vorhersagt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Wird &#039;maxSoC&#039; (wieder) erreicht, wird Mindest-SoC um 5%, aber nicht tiefer als &#039;lowSoc&#039;, verringert. Ist der berechnete Mindest-SoC größer als &#039;upSoc&#039;, wird der Mindest-SoC auf &#039;upSoc&#039; gesetzt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#   Mindest-SoC wird soweit verringert, dass die prognostizierte PV Energie des aktuellen bzw. des folgenden Tages von der Batterie aufgenommen werden kann. Mindest-SoC wird typisch auf &#039;upSoc&#039; und nicht tiefer als &#039;lowSoc&#039; verringert.  &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Das Modul erfasst den letzten Zeitpunkt am &#039;maxSoC&#039;-Level, um eine Ladung auf &#039;maxSoC&#039; mindestens alle &#039;careCycle&#039; Tage zu realisieren. Zu diesem Zweck wird der optimierte SoC in Abhängigkeit der Resttage bis zum nächsten &#039;careCycle&#039; Zeitpunkt derart verändert, dass durch eine tägliche 5% SoC-Steigerung &#039;maxSoC&#039; am &#039;careCycle&#039; Zeitpunkt rechnerisch erreicht wird. Wird zwischenzeitlich &#039;maxSoC&#039; erreicht, beginnt der &#039;careCycle&#039; Zeitraum erneut. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im fünften Schritt werden die Grenzen &#039;lowSoc&#039; und &#039;upSoc&#039; berücksichtigt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# 	Im letzten Schritt erfolgt Generierung des Readings &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; zur Signalisierung einer eventuell empfohlenen Zwangsladung auf den berechneten Min-SoC. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei sehr wenig Erzeugungungsprognose, d.h. wenn sich der berechnete Min-SoC oberhalb von &#039;upSoC&#039; bewegt, wird &#039;upSoC&#039; eingestellt. Liegt der berechnete Min-SoC unterhalb von &#039;upSoC&#039;, ist jedoch größer als &#039;lowSoC&#039;, wird der berechnete SOC im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; eingestellt. Somit eignet sich die Angabe im Schlüssel &#039;upSoC&#039; um in Zeiten geringer Solarenergieerzeugung die Batterie für eine Notstromerzeugung auf mindestens diesem Wert zu halten. Sollte die PV-Prognose kurzfristig einen größeren Ertrag vorhersagen als die Batterie durch die Einhaltung von &#039;upSoC&#039; aufnehmen kann, wird der Min-SoC unter &#039;upSoC&#039; abgesenkt um möglichst allen PV-Überschuß in der Batterie zu speichern und somit dem Eigenverbrauch zuzuführen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der berechnete Mindest-SoC ist immer nur ein unterer Grenzwert. Die Batterie kann durch Ladevorgänge natürlich jederzeit einen höheren als den im Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; dargestellten optimalen SoC haben. Der optimale SoC sollte nicht unterschritten werden um die oben genannten Zusammenhänge abbilden zu können.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Die dynamische SOC Steuerung mit Umsetzungsbeispiel =====&lt;br /&gt;
Das Modul bietet eine Unterstützung zur automatisierten Einstellung eines optimalen SoC Wertes.&lt;br /&gt;
&lt;br /&gt;
Ziel ist es, den Minimum SoC in Abhängigkeit der zu erwartenden Solarerträge des aktuellen und des folgenden Tages so einzustellen, dass der prognostizierte Solarertrag von der Batterie aufgenommen werden kann. Die Einspeisung in das öffentliche Netz soll minimiert werden.&lt;br /&gt;
&lt;br /&gt;
Weiterhin soll ein unterer SoC nicht unterschritten, sowie ein oberer Minimum SoC im Normalfall nicht überschritten werden. Der obere Grenzwert stellt sicher, dass die Batterie mindestens bis zu diesem Wert wieder entladen werden kann. Dadurch bleibt innerhalb der Batterie immer genügend Kapazität verfügbar um unvorhergesehene PV Energie aufnehmen zu können.&lt;br /&gt;
&lt;br /&gt;
Aktiviert wird die Unterstützung der Batteriesteuerung durch das Setzen des Attributes &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; z.B. mit diesen Angaben:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagementXX lowSoc=x upSoC=x maxSoC=x careCycle=x &lt;br /&gt;
&lt;br /&gt;
so zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
 ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=98 careCycle=20&lt;br /&gt;
&lt;br /&gt;
Dabei steht &#039;XX&#039; für die Nummer der Batterie, welche mit dem Attribut setupBatteryDevXX korrespondiert. &lt;br /&gt;
Ist dieses Attribut gesetzt, werden Steuerungs-Readings erstellt, die der Nutzer auswerten und seine Batterieanlage z.B. via notify oder DOIF steuern kann. &amp;lt;bR&amp;gt;&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; enthält den vom Modul berechneten optimalen Mindest-SoC.&lt;br /&gt;
Das Reading &#039;&#039;&#039;Battery_ChargeRequest_XX&#039;&#039;&#039; wird auf &#039;1&#039; gesetzt, wenn der aktuelle SOC unter den optimalen SOC bzw. minimalen SOC gefallen ist.&lt;br /&gt;
&lt;br /&gt;
Die Schlüssel &#039;&#039;&#039;lowSoc&#039;&#039;&#039; und &#039;&#039;&#039;upSoC&#039;&#039;&#039; sind die unteren und oberen Grenzen, zwischen denen sich der Minimum SoC im normalen Betrieb bewegen soll.&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;maxSoC&#039;&#039;&#039; stellt eine Ladungsgrenze dar, die mindestens alle X (careCycle) Tage erreicht werden soll. Zu diesem Zweck errechnet das Modul die Anzahl der nötigen Erhöhungen der Minimum Batterieladung von 5% pro Tag um ausgehend vom aktuellen SoC-Level. Der resultierende Minimum SoC Wert wird entsprechend angepasst. Wurde der einstellte maxSoC Level erreicht, startet der Wartungszyklus (careCycle) erneut. &amp;lt;br&amp;gt;&lt;br /&gt;
Der maxSoC in Verbindung mit dem durch &#039;&#039;&#039;careCycle&#039;&#039;&#039; definierten Zyklus soll sicherstellen, dass der Batterieverbund in regelmäßigen Abständen einen Ladungsausgleich vollziehen kann. &lt;br /&gt;
&lt;br /&gt;
Durch die Modullogik erfolgt eine 5 protentige Anhebung des Minimum SoC wenn am Vortag maxSoC nicht erreicht wurde. Die Anhebung erfolgt aber nicht über upSoC. upSoC ist die obere Grenze des Minimum SoC. Wird am Vortag mindestens die maxSoC Ladung erreicht, verringert sich der Minimum SoC wieder schrittweise um 5%, aber nicht tiefer als lowSoc.&lt;br /&gt;
&lt;br /&gt;
Ergänzt wird die Logik noch um die PV Vorhersage. Dabei wird die obige Minimum SoC Berechnung um die Erwartung der PV Erwartung am aktuellen und folgenden Tag korrigiert. Das bedeutet, dass der Minimum SoC z.B. von heute 50% auf 10% abgesenkt und dadurch die gespeicherte Energie dem Haushalt zugeführt wird, wenn am heutigen oder kommenden Tag eine entsprechende PV Energie zu erwarten ist um die Batterie wieder vollständig zu zuladen.&lt;br /&gt;
Dadurch ist immer genügend &amp;quot;Freiplatz&amp;quot; in der Batterie und andererseits hat die Batterie in langen Dunkelphasen eine Reserve für einen eventuellen Stromausfall (falls der abgesichert werden soll) und wird vor einem dauerhaften tiefen SoC geschützt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Umsetzungsbeispiel =====&lt;br /&gt;
&lt;br /&gt;
Wie das Reading &#039;&#039;&#039;Battery_OptimumTargetSoC_XX&#039;&#039;&#039; genutzt werden kann, wird am Beispiel einer Victron Batterieanlage gezeigt. Die Anlage wird durch Cerbo GX Gerät gesteuert. Der Cerbo GX ist per MQTT2 in FHEM eingebunden. Umgesetzt ist die Steuerung der Batterie &#039;01&#039;, d.h. die Angabe &#039;XX&#039; ist durch &#039;01&#039; ersetzt.&lt;br /&gt;
&lt;br /&gt;
Die folgende kleine Logik ist in einem &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; File eingebaut und wird regelmäßig mit&lt;br /&gt;
&lt;br /&gt;
 batSocChargeMgmnt (&#039;&amp;lt;Name SolarForecast Device&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
aufgerufen. Der Aufruf erfolgt durch Angabe der Routine im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; des SolarForecast Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
  # Hinweis: die Zeichen &#039;::&#039; vor der Routine sind durch das SolarForecast Package bedingt&lt;br /&gt;
  ::batSocChargeMgmnt ($name);&lt;br /&gt;
  return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Routine wird dadurch automatisch am Ende jedes Zyklus (siehe Attribut plantControl-&amp;gt;cycleInterval) ausgeführt.&lt;br /&gt;
Um die SOC Managementfunktion nach Bedarf ein- bzw. ausschalten zu können wird zunächst im SolarForecast Device ein userattr zur Steuerung der SOC-Logik angelegt:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; userattr userFn_BatterySoCManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
Die Perl Routine &#039;&#039;&#039;batSocChargeMgmnt&#039;&#039;&#039; ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#  Batterie SOC und Max. Ladestrom Management&lt;br /&gt;
############################################################################&lt;br /&gt;
sub batSocChargeMgmnt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vebus   = &#039;MQTT2_cerboGX_c0619ab34e08_vebus&#039;;                            # Victron Vebus Device&lt;br /&gt;
  my $vicsets = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                         # Victron Einstellungen&lt;br /&gt;
&lt;br /&gt;
  my $maxcspc = 105;                                                           # max. Ladestrom (A) Victron MPII Verbund&lt;br /&gt;
  my $actmcc  = ReadingsNum ($vebus, &#039;MaxChargeCurrent&#039;, undef);               # akt. Ladestromeinstellung&lt;br /&gt;
  my $load    = $actmcc // $maxcspc;                                           # Soll-Ladestrom (A)&lt;br /&gt;
&lt;br /&gt;
  ## Battery SoC Management&lt;br /&gt;
  ###########################&lt;br /&gt;
  my $ubsm = AttrVal ($name, &#039;userFn_BatterySoCManagement&#039;, &#039;aus&#039;); &lt;br /&gt;
  &lt;br /&gt;
  if ($ubsm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name,    &#039;Battery_ChargeRequest_01&#039;,     0);&lt;br /&gt;
    my $csoc = ReadingsNum ($vicsets, &#039;MinimumSocLimit&#039;,             10);      # akt. SoC&lt;br /&gt;
    my $osoc = ReadingsNum ($name,    &#039;Battery_OptimumTargetSoC_01&#039;, 10);      # Soll-SoC&lt;br /&gt;
    my $surp = ReadingsNum ($name,    &#039;Current_Surplus&#039;,              0);      # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if ($csoc != $osoc) {&lt;br /&gt;
      CommandSet (undef, &amp;quot;$vicsets MinimumSocLimit $osoc&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn SoCMgmnt -&amp;gt; MinimumSocLimit in $vicsets set to $osoc %});&lt;br /&gt;
    }&lt;br /&gt;
	                                           &lt;br /&gt;
    if ($bcrq &amp;amp;&amp;amp; $surp &amp;lt; 1000) {                                              # max. Strom b. Battery_ChargeRequest &lt;br /&gt;
      $load = 21;&lt;br /&gt;
    }&lt;br /&gt;
	else {&lt;br /&gt;
	  $load = $maxcspc;&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  ## Batterie Einstellung MaxChargeCurrent&lt;br /&gt;
  ##########################################&lt;br /&gt;
  if ($load != $actmcc) {&lt;br /&gt;
    CommandSet (undef, &amp;quot;$vebus MaxChargeCurrent $load&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
    Log3 ($name, 3, qq{$name - userFn ChargeMgmnt -&amp;gt; MaxChargeCurrent in $vebus set }.&lt;br /&gt;
                    qq{from old $actmcc A to $load A});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent_set&#039;, $load, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist im SolarForecast Device das Reading  &#039;&#039;&#039;Battery_ChargeRequest_01&#039;&#039;&#039; gesetzt, ist der aktuelle SOC kleiner als der optimale SOC und die Batterie wird (eventuell aus dem öffentlichen Netz) geladen. Das kann automatisch durch den Cerbo GX bzw. in anderen Anlagen durch einen entsprechenden Befehl erfolgen.&lt;br /&gt;
Damit die Netzbeladung nicht mit der vollen Ladestromstärke geschieht, wird der Ladestrom auf den gewünschten Wert (hier 21 A -&amp;gt; ca. 1000 W bei einem 48V System) reduziert sofern kein oder zu wenig PV-Überschuß vorhanden ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== weitere mögliche Aspekte der SOC- und Batterieladesteuerung ====&lt;br /&gt;
&lt;br /&gt;
SolarForecast liefert durch seine internen Logiken bereits sehr hilfreiche Signale zur Steuerung von Batteriesystemen in Form von Readings an. Abhängig von den individuellen Möglichkeiten der vorhandenen Anlage käme zum Beispiel zusätzlich zu einer Steurung des optimalen SOC oder der Zeitfenster für die Batterieaufladung auch eine Steuerung des Ladestroms bzw. der verwendeten Ladeleistung in Betracht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hintergründe:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Das Laden eines Akkus mit möglichst gleichbleibender und geringer Leistung wirkt sich positiv auf dessen Langlebigkeit aus, was u.a. auch daran liegt, dass der Temperaturstreß im Akku bei langsamer Energiezuführung nur gering ist.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom führt zu einem geringen Absacken der Akkuspannung beim (ggf, temporären) Abschalten des Ladestroms, was sich positiv auf die SOC-Schätzung auswirkt.&lt;br /&gt;
    &lt;br /&gt;
* Ein geringer Ladestrom führt, insb. bei Nutzung passiver Balancer (sind in den Akku-Systemen üblicherweise verbaut), zu einer geringen Differenz zwischen den einzelnen Zellspannungen und damit zu einer besseren Kapazitätsausnutzung eins Akkus.&lt;br /&gt;
&lt;br /&gt;
* Ein geringer Ladestrom kann zu einem zeitlich punktgenauen Zielfüllstand (im Winter 100%, ansonsten natürlich weniger) am Ende des Tages führen.&lt;br /&gt;
    &lt;br /&gt;
* Eine geringer Ladestrom führt auch zu geringen Leitungsverlusten, da der Strom quadratisch zu den Leitungsverlusten beiträgt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann auch die Verweildauer oder die Begrenzung des SOC, auf den die Batterie maximal geladen werden soll, Gegenstand von Optimierungen sein.&lt;br /&gt;
&lt;br /&gt;
Die häufig zu findende Empfehlung, Akkus nicht zu lange bei einem SOC von 100% verweilen zu lassen, liegt weniger an dem SOC als solchem, sondern daran, dass &#039;&#039;SOC=100%&#039;&#039; üblicherweise dadurch ermittelt wird, dass eine Zelle im Akku einen Spannungsschwellenwert überschreitet, der – würde dieser Schwellenwert zeitlich länger überschritten sein – zu einer Schädigung des Akkus führen könnte. Schädlich sind insbesondere häufige Nachladevorgänge bei Werten um die 100% SOC, da Zellen dann ja häufiger und damit - integral gesehen - auch länger den o.g. Schwellenwert überschreiten.&lt;br /&gt;
&lt;br /&gt;
Einige Akku-Hersteller, z.B. BYD, haben auf o.g, Grund in der (neueren) Firmware Ihrer Systeme einen SOC-Threshold (bei BYD liegt dieser bei 95%) eingebaut. Dieser Wert muss nach einem erreichten SOC von 100% unterschritten  werden, bevor überhaupt eine weitere Ladung erfolgt. Insbesondere in der dunklen Jahreszeit kann es daher sinnvoll sein, den Akku unter Verwendung von PV-Leistung so zu füllen, dass dieser möglichst nur einmal vor Einbruch der Dunkelheit auf &#039;&#039;SOC=100%&#039;&#039; geladen wird. Hierbei sollte darauf geachtet werden, dass der Ladeschlussstrom des jeweiligen Systems nicht unterschritten wird. &lt;br /&gt;
&lt;br /&gt;
SolarForecast unterstützt die oben betrachtete Batteriesteuerung durch die optionale Angabe von &#039;&#039;&#039;loadAbort&#039;&#039;&#039; im Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039;. Das in diesem Kontext erstellte Reading &#039;&#039;&#039;Battery_ChargeAbort_XX&#039;&#039;&#039; stellt die auswertbaren Steuerungsinformationen zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== PV-Prognose und Verbrauch optimierte Beladungssteuerung unter Berücksichtigung einer Wirkleistungsbegrenzung ====&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-04-25 143910.png|right|thumb|400px|Batterie Popup &amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Batterie geladen. sobald PV-Überschuß vorhanden ist ohne eine Prognose zu berücksichtigen. Dadurch sind die Batterien im Sommer unter Umständen schon um 10-12 Uhr voll geladen und die Anlage liefert ihre mehr oder weniger volle Energie (je nach Ausrichtung) in das öffentliche Netz. Dann könnte es zu einer Begrenzung der PV-Leistung durch einen Schwellenwert (z.B. 70%-Regelung) oder eventuell Zwangsabregelung durch den Netzbetreiber kommen.&lt;br /&gt;
&lt;br /&gt;
Hintergrund dieser Erweiterung ist das Bestreben, eine optimale Unterstützung bei der Maximierung des Eigenverbrauchs zu geben und einen Beitrag zur Netzstabilität zu leisten.&lt;br /&gt;
Das Ziel der Beladungssteuerung der Batterie ist es, die Ladung der Batterie über den Tag verteilt so zu steuern, dass die Batterie erst dann geladen wird, wenn durch den PV-Überschuß eine Netzeinspeisung erfolgen würde bzw. ein Grenzwert erreicht werden würde, der zu einer Abregelung der PV-Anlage führen könnte.&lt;br /&gt;
Es kann auch zu einer Zwangsabregelung durch den Netzbetreiber führen, was vermieden werden soll.&lt;br /&gt;
 &lt;br /&gt;
Die interne Kalkulationslogik erstellt zu diesem Zweck ein Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039;.&lt;br /&gt;
Dieses Reading gibt dem User ein Signal, ob zu der aktuellen Stunde der Ladevorgang der Batterie freigegeben (1) oder nicht freigegeben werden sollte (0). Die Freigabe zur Ladung bedeutet dass:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; die Batterie mit ihrer vollen Ladeleistung angesteuert werden sollte um wie prognostiziert am Ende des Sonnentages die volle bzw. maximal mögliche Ladung zu erhalten.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=0&#039;&#039;&#039; die Batterie nur geladen werden sollte wenn der im Attribut plantControl-&amp;gt;feedinPowerLimit definierte Wert überschritten wird&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ist keine Freigabe zur Ladung vorhanden, kann bzw. sollte dennoch eine Ladung der Batterie vorgenommen werden, sofern eine über dem im &amp;lt;br&amp;gt;&lt;br /&gt;
Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limit liegende Einspeiseleistung vorhanden ist. In diesem Status sollte die Batterie nur mit der Differenzleistung von vorhandener Einspeiseleistung und dem gesetzen Einspeiselimit geladen werden und damit das gesetzte Einspeiselimit einhalten ohne die Anlage abzuregeln. Ist die Batterie in einer Balkengrafikebene dargestellt, wird im Mouse-Over Popup die Battrie mit &#039;&#039;&amp;quot;nur laden wenn Einspeiselimit überschritten&amp;quot;&#039;&#039; gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Die Möglichkeiten der Batteriesteuerung sind stark von der individuellen Anlage abhängig und können hier nicht beschrieben werden. Ein Umsetzungsbeispiel mit einer Victron-Anlage mit Pylontech Batterie ist weiter unten dargestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Aktivierung und Arbeitsweise =====&lt;br /&gt;
&lt;br /&gt;
Die implementierte Logik zur optimierten Batterie Beladungssteuerung wird aktiviert, wenn folgende Kriterien erfüllt sind: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;capacity&#039;&#039;&#039; in den setupInverterDevXX Atributen ist gesetzt&lt;br /&gt;
* das Attribut &#039;&#039;&#039;ctrlBatSocManagementXX&#039;&#039;&#039; für die jeweilige Batterie ist gesetzt&lt;br /&gt;
* der Schlüssel &#039;&#039;&#039;cap&#039;&#039;&#039; im Attribut setupBatteryDevXX der jeweiligen Batterie ist gesetzt&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Die Logik arbeitet wie folgt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Der resultierende Schwellenwert der Wirkleistungsbegrenzung: der Gesamtanlage wird durch die Auswertung der in den Inverter-Attributen setupInverterDevXX  gesetzen Schlüssel limit (optional) und capacity ermittelt. Inverter mit gesetztem Schlüssel feed = grid (deren Energie wird ausschließlich in das öffentlich Netz eingespeist) werden von der Betrachtung in diesem Kontext ausgeschlossen.&lt;br /&gt;
&lt;br /&gt;
;Die benötigte Beladung bis zu maxSoC (im Attribut setupBatteryDevXX) : wird ermittelt und mit der zu erwartenden PV Tagesprognose in Beziehung gesetzt. Sofern die PV-Erzeugung abzgl. Verbrauch noch nicht das Wirkleistungbegrenzungs-Limit erreicht UND noch genügend PV-Überschuß für eine Ladung auf &#039;&#039;maxSoC&#039;&#039; im Laufe der kommenden Stunden des Tages zu erwarten ist, bleibt das Reading &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 0&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
;Wird das Wirkleistungbegrenzungs-Limit erreicht/überschritten und/oder die PV-Überschußprognose: zzgl. eines Sicherheitspuffers unterschritten, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX = 1&#039;&#039;&#039; gesetzt. Der User kann darauf reagieren und den Batterie Ladevorgang aktivieren. Die Möglichkeiten der Aktivierung sind natürlich von der installierten Anlage abhängig. Das SolarForecast Device greift nicht in die Batteriesteuerung direkt ein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anders ausgedrückt erfolgt immer dann eine Ladefreigabe, wenn einer der nachfolgenden Sachverhalte &#039;&#039;wahr&#039;&#039; ist:&lt;br /&gt;
&lt;br /&gt;
- die benötigte Ladeenergie (aller installierten Batterien) &amp;gt;= PV-Restüberschuß des Tages (Reading RestOfDayPVforecast) zzgl. Sicherheitsaufschlag&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- der Zeitpunkt des PV-Erzeugungszenit des laufenden Tages überschritten ist (Reading Today_MaxPVforecastTime)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn die aktuelle PV Leistung &amp;gt;= einer eventuellen Wechselrichter-Leistungsbegrenzung ist (Summe aller WR-Begrenzungen)&lt;br /&gt;
&lt;br /&gt;
ODER&lt;br /&gt;
&lt;br /&gt;
- wenn das BatSoc-Management _nicht_ aktiviert ist (nicht alle oben genannten Aktivierungskriterien erfüllt sind)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind mehrere Batterien installiert und durch das Management einer Batterie die Einhaltung der genannten Kriterien bzw. Sachverhalte erwirkt wird, bleiben die weiteren Batterien im Modus Ladefreigabe (Battery_ChargeUnrestricted_XX=1).  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Umsetzungsbeispiel Batterie Ladesteuerung mit Victron GX Venus über den Grid Setpoint =====&lt;br /&gt;
&lt;br /&gt;
Ziel der Steuerung ist es abhängig vom Wert des Readings Battery_ChargeUnrestricted_XX (z.B. Battery_ChargeUnrestricted_01) die Ladung des angeschlossenen Batteriesystems zu aktivieren bzw. zu deaktivieren.&lt;br /&gt;
Das vorliegende Beispiel soll umzusetzen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 0 -&amp;gt; Batterie nicht aufladen bzw. nur laden wenn Einspeiselimit überschritten (Attribut plantControl-&amp;gt;feedinPowerLimit)&lt;br /&gt;
* Battery_ChargeUnrestricted_01 = 1 -&amp;gt; Batterie aufladen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Grid Setpoint ist ein Parameter in den Victron Systemeinstellungen. Das Victron System wird den eingestellten Grid Setpoint versuchen einzuhalten und bei einem positiven Wert Energie aus dem Netz beziehen bzw. bei einem negativen Grid Setpoint Energie in das Netz einspeisen.&lt;br /&gt;
&lt;br /&gt;
Normalerweise wird das Victron System die erzeugte PV Energie zunächst zur Deckung des Hausverbrauchs verwenden, ist dann noch ein PV Überschuß vorhanden, die Batterien aufladen und bei weiter vohandenen PV Überschuß diese Energie in das öffentliche Netz einspeisen sofern dem System eine Einspeisung erlaubt ist. Anderenfalls werden die Wechselrichter oder MPPT Smartloader heruntergeregelt bzw. limitiert. &lt;br /&gt;
&lt;br /&gt;
In der Standardeinstellung ist beim Victron System ein Grid Setpoint von ca. 20 bis 50 Watt, d.h. das System strebt danach diese Vorgabe zu erfüllen zieht ständig Energie in diesem Bereich aus dem öffentlich Netz von einem gelegentlichen Überschwingen der Regelung abgesehen. Damit ein eventueller PV Überschuß nicht zum Laden der Batterie verwendet, sondern statt dessen in das öffentliche Netz eingespeist wird, muß der Grid Setpoint um diesen Betrag abgesenkt werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2025-02-24 114403.png|right|thumb|400px|Integration des Grid Setpoint-Managements in den Own_Spec-Bereich]]&lt;br /&gt;
&lt;br /&gt;
Damit man später per Attribut bzw. über den [[#Formatierung_der_Inhalte_im_Bereich_&amp;quot;Graphic_Header_Own_Specification&amp;quot;|Own_Spec-Bereich]] die automatische Ladesteuerung über den Grid Setpoint ein- bzw. ausschalten kann, legen wir ein userattr an:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 userattr &amp;lt;Name&amp;gt; userFn_GridSetpointManagement:ein,aus&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin sind einige Vorbereitungen im Device MQTT2_cerboGX_c0619ab34e08_settings vorzunehmen. Dieses Device ist im vorliegenden Beispiel ein in FHEM vorhandenes MQTT2_DEVICE, über das die Victron CerboGX Einstellungen zugreifbar sowie einstellbar sind. Die Vorgehensweise zur Erstellung des MQTT2_DEVICE ist hier nicht beschrieben und wird vorausgesetzt.&lt;br /&gt;
&lt;br /&gt;
Damit ein entsprechender Set-Befehl zur Einstellung des Grid Setpoints vorhanden ist, werden folgende Attribute gesetzt:&lt;br /&gt;
&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings jsonMap Settings_CGwacs_AcPowerSetPoint_value:GridSetpoint&lt;br /&gt;
 attr MQTT2_cerboGX_c0619ab34e08_settings setList GridSetpoint W/c0619ab34e08/settings/0/Settings/CGwacs/AcPowerSetPoint {&amp;quot;value&amp;quot;:$EVTPART1}&lt;br /&gt;
&lt;br /&gt;
Nach dieser Attributierung kann mit einem &amp;quot;&#039;&#039;set MQTT2_cerboGX_c0619ab34e08_settings GridSetpoint &amp;lt;Wert&amp;gt;&#039;&#039;&amp;quot; der Grid Setpoint eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Das Attribut userFn_GridSetpointManagement kann nun im Perl Code ausgewertet werden um das Grid Setpoint-Management ein- bzw. auszuschalten.&lt;br /&gt;
Der nachfolgende Code wird in die Datei &#039;&#039;&#039;99_mySolarForecastUtils.pm&#039;&#039;&#039; eingefügt. Ist diese Datei nicht vorhanden, legen wir sie vorab als Kopie der ausgelieferten 99_myUtils.pm an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###############################################################################&lt;br /&gt;
#&lt;br /&gt;
# Save this file as 99_mySolarForecastUtils.pm, and create your own functions&lt;br /&gt;
# in the new file. They are then available in every Perl expression.&lt;br /&gt;
#&lt;br /&gt;
###############################################################################&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 mySolarForecastUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
# ab hier eigenen Code eintragen&lt;br /&gt;
###############################################################################&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Steuerung Start/Stop der Batterieladung über den Victron Grid Setpoint&lt;br /&gt;
############################################################################&lt;br /&gt;
sub gridSetpointMgmt {&lt;br /&gt;
  my $name = shift;&lt;br /&gt;
  my $hash = $defs{$name};&lt;br /&gt;
  &lt;br /&gt;
  my $vicsets   = &#039;MQTT2_cerboGX_c0619ab34e08_settings&#039;;                               # Device Victron Einstellungen&lt;br /&gt;
  my $gspdef    = 20;                                                                  # Default Einstellung des Grid Setpoint&lt;br /&gt;
  my $targetgsp = $gspdef;                                                             # Voreinstellung Grid Setpoint&lt;br /&gt;
  my $neggspmax = FHEM::SolarForecast::CurrentVal ($name, &#039;feedinPowerLimit&#039;, 5000);   # max. gewünschte Einspeiseleistung in Watt&lt;br /&gt;
  $neggspmax    = $neggspmax * -1;&lt;br /&gt;
  my $gspm      = AttrVal ($name, &#039;userFn_GridSetpointManagement&#039;, &#039;aus&#039;);             # Freischaltung des Grid Setpoint-Managements&lt;br /&gt;
  my $curgsp    = ReadingsNum ($vicsets, &#039;GridSetpoint&#039;,         $gspdef);             # aktuelle Einstellung Grid Setpoint&lt;br /&gt;
  &lt;br /&gt;
  if ($gspm eq &#039;ein&#039;) { &lt;br /&gt;
    my $bcrq = ReadingsNum ($name, &#039;Battery_ChargeUnrestricted_01&#039;, 0);         # Ladefreigabe (1 -&amp;gt; Bat Ladefreigabe)&lt;br /&gt;
    my $surp = ReadingsNum ($name, &#039;Current_Surplus&#039;,               0);         # aktueller PV-Überschuß&lt;br /&gt;
	&lt;br /&gt;
    if (!$bcrq) {                                                               # Grid Setpoint absenken wenn keine .. &lt;br /&gt;
        $targetgsp = $gspdef - $surp;                                           # ..Batterie Ladefreigabe&lt;br /&gt;
        $targetgsp = $neggspmax if($targetgsp &amp;lt; $neggspmax);                    # Begrenzung der Einspeiseleistung&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if ($curgsp != $targetgsp) {&lt;br /&gt;
	  fhem (&amp;quot;set $vicsets GridSetpoint $targetgsp&amp;quot;);&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn gridSetpointMgmt -&amp;gt; GridSetpoint in $vicsets set to $targetgsp});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Victron_GridSetpoint_set&#039;, $targetgsp, 0);&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
###############################################################################&lt;br /&gt;
# Ende eigener Code&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Vergleich des Setpoints mit der Vorgabe von &#039;&#039;$neggspmax&#039;&#039; dient dazu die maximale Einspeiseleistung in das öffentliche Netz zu begrenzen. Ist diese Grenze erreicht, wird der noch verbleibende Überschuß in die Batterie geladen. Dadurch wird eine Abregelung der Anlage vermieden wenn der Schwellenwert &#039;&#039;$neggspmax&#039;&#039;erreicht ist sofern die Batterie aufnahmefähig ist und nicht voll geladen ist. &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::gridSetpointMgmt  ($name);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zum Management des automatischen Grid Setpoint und der Anzeige des eingestellten Wertes wird das Attribut und die Readinganzeige in den Own_Spec-Bereich eingebunden, z.B.:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; graphicHeaderOwnspec  #Settings&lt;br /&gt;
                                   SetPoint&amp;amp;nbsp;Management:userFn_GridSetpointManagement&lt;br /&gt;
                                   Grid&amp;amp;nbsp;Setpoint:GridSetpoint@MQTT2_cerboGX_c0619ab34e08_settings&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Unterstützung eines netzdienlichen Verhaltens ====&lt;br /&gt;
&lt;br /&gt;
Der Steuerungsprozess der Batterieanlage leistet insgesamt einen kleinen Beitrag zur Netzstabilität, indem die Speicherladung in den Zeitraum der meisten prognostizierten Überschußeinspeisung gelegt wird. Im Sommer kann sich dieser Zeitraum in die Zeit nach dem Maxmimum des prognostizierten PV-Überschusses verlagern, wenn auch danach noch genügend Überschußenergie zu Volladung der Batterie prognostiziert wird. In dem Zusammenhang sollte im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; ein Einspeiselimit gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zur Verdeutlichung soll das Beispiel dienen:&lt;br /&gt;
&lt;br /&gt;
* die Batterie ist zu 60% geladen &lt;br /&gt;
* der User hat upSoC=40 eingestellt&lt;br /&gt;
* der User hat maxSoC=90 eingestellt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Am Vormittag ist genügend Sonne vohanden, das Maximumum der Energie über die Zeit wird aber noch erwartet. &lt;br /&gt;
Zu diesem Zeitpunkt wird das Reading  &#039;&#039;&#039;Battery_ChargeUnrestricted_XX&#039;&#039;&#039; auf den Wert &amp;quot;0&amp;quot; gesetzt. Durch den Nutzer erfolgt daraufhin, zum Beipiel über ein Notify, ein anlagenspezifischer Befehl &amp;quot;Ladestop&amp;quot; an die Batterieanlage. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ab diesem Moment wird:&lt;br /&gt;
&lt;br /&gt;
# die Batterie nicht geladen&lt;br /&gt;
# die erzeugte PV-Energie dem Haushalt zur Verfügung gestellt bzw. der verbleibende Überschuß eingespeist, sofern der Überschuß unterhalb des im Attribut &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; definierten Limits liegt.&lt;br /&gt;
# ein eventuell über dem Limit &#039;&#039;&#039;plantControl-&amp;gt;feedinPowerLimit&#039;&#039;&#039; vorhandener Überschuß in die Batterie geladen und so die Netzlast verringert sowie die Batterie schonend geladen. (dieser Punkt trifft in den Monaten mit wenig PV-Erzeugung eher nicht zu)  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig liefert die Batterie Energie an das Hausnetz und wird von 60% bis maximal einem SoC-Wert entladen, der durch die [[#Die_dynamische_SOC_Steuerung_mit_Umsetzungsbeispiel|dynamische SOC Steuerung]] bestimmt wird. Dazu muß diese Steuerung natürlich implementiert sein. Sofern der berechnete SoC größer als upSoC ist, wird der maximale Entladungs-SoC auf upSoC gesetzt. &lt;br /&gt;
&lt;br /&gt;
Zusätzlich überprüft das Modul permanent bei jedem Zyklus die Differenz des aktuell vorhandenen SoC zum eingestellten maxSoC.&lt;br /&gt;
Sie soll nicht größer sein um mit dem (noch) zu erwartenden PV-überschuß des Tages der eingestellte maxSoC bzw. dessen Nähe wahrscheinlich erreicht werden kann. &lt;br /&gt;
Sollte der Differenz-Grenzwert erreicht sein, wird &#039;&#039;&#039;Battery_ChargeUnrestricted_XX=1&#039;&#039;&#039; gesetzt und der Nutzer sollte dann über einen geeigneten Befehl seine Anlage in den Modus &amp;quot;Laden&amp;quot; umschalten.&lt;br /&gt;
Dieser Vorgang kann beliebig oft während des Tages alternieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Nutzung von batteryTrigger ===&lt;br /&gt;
Ergänzt werden die Möglichkeiten durch das set-Kommando: &lt;br /&gt;
&lt;br /&gt;
 batteryTrigger &amp;lt;1on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;1off&amp;gt;=&amp;lt;Wert&amp;gt; [&amp;lt;2on&amp;gt;=&amp;lt;Wert&amp;gt; &amp;lt;2off&amp;gt;=&amp;lt;Wert&amp;gt; ...] &lt;br /&gt;
&lt;br /&gt;
Das Kommando setzt Triggerpunkte bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %).&lt;br /&gt;
&lt;br /&gt;
Der verwendete SoC wird als resultierender SoC als Summe der aktuellen Ladung aller registrierten Batterie-Geräte im Verhältnis zur installierten Gesamtkapazität gebildet. Das bedeutet, dass alle einzelnen Batterie-Geräte als ein gemeinsamer Cluster betrachtet werden. &lt;br /&gt;
&lt;br /&gt;
Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise definiert werden.&lt;br /&gt;
Überschreiten die letzten drei SoC-Messungen eine definierte Xon-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = on&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
Unterschreiten die letzten drei SoC-Messungen eine definierte Xoff-Bedingung, wird das Reading &#039;&#039;&#039;batteryTrigger_X = off&#039;&#039;&#039; erstellt/gesetzt.&lt;br /&gt;
&lt;br /&gt;
Der Inhalt der Readings kann durch ein User-Programm oder, bei Erzeugung von entsprechenden Events, mittels notify-Device ausgewertet werden um bei Eintreten eines definierten Ereignisses entsprechende Reaktionen auszulösen. Das kann zum Beispiel die Freigabe eines Heizstabes oberhalb eines bestimmten SOC sein oder ein Entladeverbot der Batterie unterhalb eines SOC-Wertes um Reserven für einen eventuellen Stromausfall zu behalten.&lt;br /&gt;
&lt;br /&gt;
Damit die Batterietrigger dynamisch geändert werden können, ist die Einstellung als Set-Kommando und nicht als Attribut ausgeführt.   &lt;br /&gt;
&lt;br /&gt;
Alle Triggerpunkte können mit dem set-Befehl:&lt;br /&gt;
&lt;br /&gt;
 reset batteryTriggerSet&lt;br /&gt;
&lt;br /&gt;
wieder gelöscht werden.&lt;br /&gt;
&lt;br /&gt;
== Verbrauchersteuerung - Registrieren und visualisieren 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;
Die Eigenschaften und das Schaltverhalten wird durch die Angabe der verfügbaren Schlüssel gesteuert. Die Möglichkeiten sind sehr umfangreich. Die nachfolgenden Abschnitte beschreiben die Verwendung am Beispiel oft vorkommender bzw. nachgefragter Sachverhalte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die Phasen der Verbrauchersteuerung ===&lt;br /&gt;
&lt;br /&gt;
Jeder Zyklus eines Verbrauchers durchläuft im Modul die folgenden Phasen:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Planung&#039;&#039;&#039; der Aktivzeiten des Verbrauchers, d.h. wann der Verbraucher geplant eingeschaltet sowie geplant ausgeschaltet wird und damit der Zyklus beendet wird.&lt;br /&gt;
# &#039;&#039;&#039;Start&#039;&#039;&#039; des Zyklus, d.h. Einschalten des Verbrauchers entsprechend der Planungsdaten sofern weitere, in den Consumer-Schlüsseln definierbare Rahmenbedingungen das Einschalten nicht verhindern (z.B. kein oder zu wenig PV-Energieerzeugung / PV-Überschuss)&lt;br /&gt;
# &#039;&#039;&#039;Permanente Überprüfung von&#039;&#039;&#039; eventuell vorhandenen &#039;&#039;&#039;Interruptbedingungen&#039;&#039;&#039; die den Verbraucher temporär ausschalten und, sofern die Interruptbedingung nicht mehr vorliegt, den Verbraucher wieder einschalten und so den gestarteten Zyklus fortsetzen.&lt;br /&gt;
#  &#039;&#039;&#039;Beendigung&#039;&#039;&#039; der Zyklus. Die Beendigung erfolgt entweder (normalerweise) wenn die geplante Endezeit der Zyklus erreicht ist oder eine optionale Endebedingung erfüllt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Steuerung der Phasen ====&lt;br /&gt;
Der Ablauf der Phasen kann durch verschiedene Schlüssel-Wert Paare beeinflusst und gesteuert werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; kann eine &#039;&#039;&#039;zusätzliche externe Bedingung&#039;&#039;&#039; definiert werden um den Einschaltvorgang des Consumers freizugeben. Ist die Bedingung (Regex) nicht erfüllt, erfolgt kein Einschalten des Verbrauchers auch wenn die sonstigen Voraussetzungen wie Zeitplanung, on-Schlüssel, auto-Mode und aktuelle PV-Leistung gegeben sind. Es erfolgt somit eine &#039;&#039;&#039;UND-Verknüpfung&#039;&#039;&#039; des Schlüssels swoncond mit den Planungsdaten und weiteren Einschaltbedingungen.&lt;br /&gt;
&lt;br /&gt;
Der optionale Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; definiert eine &#039;&#039;&#039;vorrangige Ausschaltbedingung&#039;&#039;&#039; (Regex). Sobald diese Bedingung erfüllt ist, wird der Consumer ausgeschaltet auch wenn die geplante Endezeit (consumerXX_planned_stop) noch nicht erreicht ist (&#039;&#039;&#039;ODER-Verknüpfung&#039;&#039;&#039;). Weitere Bedingungen wie off-Schlüssel und auto-Mode müssen zum automatischen Ausschalten erfüllt sein.&lt;br /&gt;
&lt;br /&gt;
Mit dem optionalen Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; kann während der geplanten Einschaltzeit eine automatische Unterbrechung sowie Wiedereinschaltung des Verbrauchers vorgenommen werden. Der Verbraucher wird temporär ausgeschaltet (interrupted) und wieder eingeschaltet (continued) wenn die Interrupt-Bedingung nicht mehr vorliegt. Die verbleibende Laufzeit wird durch einen Interrupt nicht beeinflusst! &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;power&#039;&#039;&#039; gibt die nominale Leistungsaufnahme des Verbrauchers gemäß seines Datenblattes an. Dieser Wert wird verwendet um die Schaltzeiten des Verbrauchers zu planen und das Schalten in Abhängigkeit des tatsächlichen PV-Überschusses zum Einplanungszeitpunkt zu steuern. Ist &#039;&#039;&#039;power=0&#039;&#039;&#039; gesetzt, wird der Verbraucher unabhängig von einem zum Zeitpunkt des Zyklus-Start eventuell nicht ausreichend vorhandenem PV-Überschuss wie geplant eingeschaltet und somit der Zyklus gestartet.&lt;br /&gt;
&lt;br /&gt;
Durch die Schlüssel &#039;&#039;&#039;notbefore&#039;&#039;&#039; und &#039;&#039;&#039;notafter&#039;&#039;&#039; kann der Startzeitpunkt des Verbrauchers so gesteuert werden, dass der Start des Zyklus nicht vor bzw. nach der angegebenen Zeit eingeplant wird. Diese Steuerung bezieht sich auf die &#039;&#039;Planung&#039;&#039;, d.h. der eigentliche Start des Verbrauchers kann sich unter Umständen durch vorhandene Rahmenbedingungen verzögern. &lt;br /&gt;
&lt;br /&gt;
Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; legt die geplanten Einschaltzeit, d.h. die Laufzeit des Zyklus fest. Der Name &#039;&#039;&#039;mintime&#039;&#039;&#039; ist nicht als MInimum-Zeit zu deuten, sondern beschreibt die angegebene Zeit in Minuten die der Zyklus dauern soll.&lt;br /&gt;
&lt;br /&gt;
Dieser Schlüssel ist optional, da sich die Standard-Laufzeit des Verbrauchers von dessen Typ abgeleitet wird. Diese Standard Laufzeiten sind:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|dryer&lt;br /&gt;
|90 Minten&lt;br /&gt;
|-&lt;br /&gt;
|dishwasher&lt;br /&gt;
|180 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|washingmachine&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|heater&lt;br /&gt;
|240 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|charger&lt;br /&gt;
|120 Minuten&lt;br /&gt;
|-&lt;br /&gt;
|other&lt;br /&gt;
|60 Minuten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Der Verbraucher wurde nicht gestartet obwohl die Startzeit der Einplanung erreicht wurde ===&lt;br /&gt;
&lt;br /&gt;
Wenn die Startzeit des Consumers entsprechend der Einplanung erreicht oder überschritten ist, wird der Consumer eingeschaltet wenn die weiteren Voraussetzungen wahr sind:&lt;br /&gt;
&lt;br /&gt;
* es ist aktuell ein PV-Überschuss vorhanden und der PV-Überschuss deckt die kalkulierten Leistungsaufnahme des Verbrauchers ab. Mit den Schlüsseln &#039;&#039;&#039;power&#039;&#039;&#039; und &#039;&#039;&#039;spignorecond&#039;&#039;&#039; kann die Einschaltung trotz fehlendem PV-Überschuss ermöglicht werden. &lt;br /&gt;
&lt;br /&gt;
* die Angabe im Schlüssel &#039;&#039;&#039;swoncond&#039;&#039;&#039; ist wahr (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* das Schalten ist über den Schlüssel &#039;&#039;&#039;auto&#039;&#039;&#039; freigegeben (sofern gesetzt)&lt;br /&gt;
&lt;br /&gt;
* im Schlüssel &#039;&#039;&#039;on&#039;&#039;&#039; ist ein valides Einschaltkommando hinterlegt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind diese zusätzlichen Bedingungen nicht erfüllt, erfolgt kein Start des eingeplanten Zyklus. Der Verbraucher verbleibt in diesem Fall weiterhin im Status &#039;&#039;planned&#039;&#039; oder &#039;&#039;suspended&#039;&#039;. Die Startbedingungen werden regelmäßig reviewed und der Consumer gestartet sobald alle Startbedingungen wahr sind bzw. Start verhindernde Bedingungen entfallen sind. &lt;br /&gt;
&lt;br /&gt;
Dieser Vorgang erfolgt bis das geplante Ende des Verbaucherzyklus erreicht ist oder die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; zutrifft. Sobald die Bedingung im Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; wahr ist, wird der gesamte Planungszyklus des Consumers beendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Kann manuell / automatisiert in den Planungszyklus eines Verbrauchers eingegriffen werden? ===&lt;br /&gt;
&lt;br /&gt;
Die Einplanung und die darauf aufbauenden Schaltprozesse laufen gemäß den hinterlegten Schlüsseloptionen im Modul automatatisch ab ohne dass ein Eingriff durch den Anwender erfolgen muß.&lt;br /&gt;
&lt;br /&gt;
Dennoch kann es gewünscht sein eine Neuplanung oder eine Sofortplanung eines Consumers vorzunehmen weil der Bedarf dazu besteht. Zu diesem Zweck stehen die Set-Kommandos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* consumerNewPlanning &lt;br /&gt;
&lt;br /&gt;
* consumerImmediatePlanning &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
zur Verfügung. &lt;br /&gt;
Beide Befehle initiieren die Consumer-Neuplanung, wobei mit dem Befehl &#039;&#039;consumerImmediatePlanning&#039;&#039; die eventuell im consumerXX Attribut gesetzten Schlüssel notbefore, notafter bzw. mode werden nicht beachtet werden. Dagenen beachtet der Befehl &#039;&#039;consumerNewPlanning&#039;&#039; alle definierten Schlüsseloptionen und dient gewöhnlich dazu einen abgeschlossenen Verbraucherzyklus wiederholt ausführen zu lassen weil die aktuelle Witterungslage dazu geeignet ist. &lt;br /&gt;
&lt;br /&gt;
Ein Anwendungsbeispiel dafür ist zum Beispiel die Ausführung von mehreren Waschmaschinen-Zyklen an einem langen, sonnigen Sommertag.&lt;br /&gt;
Diese beiden Set-Befehle können zum Beispiel über ein auf einen Schalter/Taster reagierendes Notify oder DOIF Device ausgeführt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung eines Verbrauchers mit getrennten Geräten für Messung und Schalten ===&lt;br /&gt;
&lt;br /&gt;
Es existieren in FHEM Geräte, die über verschiedene Kanäle für unterschiedliche Aufgaben verfügen. Diese Kanäle werden jeweils in einem gesonderten Device abgebildet. HomeMatic oder readingsProxy sind Beispiele für solche Varianten.&lt;br /&gt;
&lt;br /&gt;
Um solche Verbraucher einzubinden gibt es im consumerXX Attribut den Schlüssel &#039;&#039;&#039;switchdev&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Bei der Registrierung gibt man als Consumerdevice das Gerät für die Messung an und im Schüssel switchdev das entsprechende FHEM-Device, welches für die Schaltvorgänge benutzt wird. &lt;br /&gt;
Ist switchdev angegeben, beziehen sich die weiteren Schlüssel on, off, swstate, auto und asynchron auf dieses Gerät.&lt;br /&gt;
&lt;br /&gt;
In dem nachfolgenden Beispiel (Homematic) ist &#039;&#039;eg.az.fridge_Pwr&#039;&#039; FHEM Device für die Energiemessung. Die Schlüssel &#039;&#039;pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; geben Readings in diesem Device an damit SolarForecast den Verbrauch und die Energiemengen auslesen kann. Demgegenüber ist im Schlüssel &#039;&#039;switchdev&#039;&#039; das zugehörige Schalter-Device der Kombination angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eg.az.fridge_Pwr&lt;br /&gt;
type=noSchedule switchdev=eg.az.fridge_Sw power=0 icon=fridge pcurr=power:W:5 etotal=energyCalc:Wh &lt;br /&gt;
swstate=state:on:off auto=automatic&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Registrierung von Verbrauchern ohne Zeitplanung und aktivem Schalten ===&lt;br /&gt;
Manchmal besteht der Wunsch, Verbraucher in SolarForecast zu integrieren um lediglich folgende Sachverhalte abzubilden:&lt;br /&gt;
&lt;br /&gt;
* Visualisierung des Schaltstatus in der Consumer Legende und/oder der Energieflußgrafik&lt;br /&gt;
* Darstellung des aktuellen Energieverbrauchs in der Energieflußgrafik&lt;br /&gt;
* Erfassung der (externen) Schaltzeiten, d.h. der Zeiten der Gerätenutzung sowie der Verbrauchsdaten um deren Einfluß bei den Planungszeiten anderer Geräte durch SolarForecast berücksichtigen zu lassen&lt;br /&gt;
&lt;br /&gt;
In solchen Fällen werden bei der Registrierung die Schlüssel &#039;&#039;swstate, pcurr&#039;&#039; und &#039;&#039;etotal&#039;&#039; zur Erfassung der Schaltzustände und der Energieverbrauchs angegeben, jedoch zur Verhinderung der Zeitplanung durch SolarForecast der Schlüssel &#039;&#039;&#039;type=noSchedule&#039;&#039;&#039; gesetzt sowie die Schlüssel &#039;&#039;on&#039;&#039; und &#039;&#039;off&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt eine mögliche Registrierung eines Zwischensteckers (Shelly) zur Erfassung der Daten eines Gefrierschrankes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Shelly.shellyplug4&lt;br /&gt;
type=noSchedule power=65 asynchron=1&lt;br /&gt;
icon=gefrierschrank &lt;br /&gt;
swstate=state:.*on.*:.*off.* &lt;br /&gt;
pcurr=relay_0_power:W:5 etotal=relay_0_energy_Wh:Wh&lt;br /&gt;
&amp;lt;/pre&amp;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;
&lt;br /&gt;
 Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off&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;
&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;
&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. Alternativ kann die Berücksichtigung des zwangsweisen PV Überschuss mit dem Schlüssel &amp;quot;spignorecond&amp;quot; im Consumer-Attribut ausgesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== zusätzliche Readings bzw. Erzeugung von statistischen Readings ==&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den zahlreichen im Modul per Standard erzeugten Readings kann der Anwender weitere Readings generieren lassen.&lt;br /&gt;
Diese zusätzlichen Readings geben entweder einen bestimmten Sachverhalt (Laufzeit, Status der API-Abfragen, etc.) oder einen statistischen Wert, z.B. die Batterieentladung des aktuellen Tages, wieder.&lt;br /&gt;
&lt;br /&gt;
Die zusätzlich erstellten Readings sind durch den Präfix &#039;&#039;&#039;special_&#039;&#039;&#039; im Device gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
Diese zusätzlichen Informationen können durch das Setzen einer oder mehrerer Kennzeichen im Attribut &#039;&#039;&#039;ctrlSpecialReadings&#039;&#039;&#039; erzeugt werden. Die mögliche Auswahl wird je nach Bedarf ausgebaut und umfasst zum aktuellen Zeitpunkt (07.02.2025) diese Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;BatPowerIn_Sum: 	die Summe der momentanen Batterieladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;BatPowerOut_Sum: 	die Summe der momentanen Batterieentladeleistung aller definierten Batterie Geräte&lt;br /&gt;
;allStringsFullfilled: 	Erfüllungsstatus der fehlerfreien Generierung aller Strings&lt;br /&gt;
;conForecastTillNextSunrise: 	Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang&lt;br /&gt;
;currentAPIinterval: 	das aktuelle Abrufintervall der gewählten Strahlungsdaten-API in Sekunden&lt;br /&gt;
;currentRunMtsConsumer_XX: 	die Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; seit dem letzten Einschalten. (letzter Laufzyklus)&lt;br /&gt;
;dayAfterTomorrowPVforecast: 	liefert die Vorhersage der PV Erzeugung für Übermorgen (sofern verfügbar) ohne Autokorrektur (Rohdaten).&lt;br /&gt;
;daysUntilBatteryCare_XX: 	Tage bis zur nächsten Batterie XX Pflege (Erreichen der Ladung &#039;maxSoC&#039; aus Attribut ctrlBatSocManagementXX)&lt;br /&gt;
;lastretrieval_time: 	der letzte Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;lastretrieval_timestamp: 	der Timestamp der letzen Abrufzeitpunkt der gewählten Strahlungsdaten-API&lt;br /&gt;
;response_message: 	die letzte Statusmeldung der gewählten Strahlungsdaten-API&lt;br /&gt;
;runTimeAvgDayConsumer_XX: 	die durchschnittliche Laufzeit (Minuten) des Verbrauchers &amp;quot;XX&amp;quot; an einem Tag&lt;br /&gt;
;runTimeCentralTask: 	die Laufzeit des letzten SolarForecast Intervalls (Gesamtprozess) in Sekunden&lt;br /&gt;
;runTimeTrainAI: 	die Laufzeit des letzten KI Trainingszyklus in Sekunden&lt;br /&gt;
;runTimeLastAPIAnswer: 	die letzte Antwortzeit des Strahlungsdaten-API Abrufs auf einen Request in Sekunden&lt;br /&gt;
;runTimeLastAPIProc: 	die letzte Prozesszeit zur Verarbeitung der empfangenen Strahlungsdaten-API Daten&lt;br /&gt;
;SunMinutes_Remain: 	die verbleibenden Minuten bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;SunHours_Remain: 	die verbleibenden Stunden bis Sonnenuntergang des aktuellen Tages&lt;br /&gt;
;todayConsumptionForecast: 	Verbrauchsprognose pro Stunde des aktuellen Tages (01-24)&lt;br /&gt;
;todayConForecastTillSunset: 	Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang&lt;br /&gt;
;todayDoneAPIcalls: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Calls&lt;br /&gt;
;todayDoneAPIrequests: 	die Anzahl der am aktuellen Tag ausgeführten Strahlungsdaten-API Requests&lt;br /&gt;
;todayConsumption: 	der gesamte Energieverbrauch (Wh) des Hauses am aktuellen Tag&lt;br /&gt;
;todayGridConsumption: 	die aus dem öffentlichen Netz bezogene Energie am aktuellen Tag&lt;br /&gt;
;todayGridFeedIn: 	die in das öffentliche Netz eingespeiste PV Energie am aktuellen Tag&lt;br /&gt;
;todayMaxAPIcalls: 	die maximal mögliche Anzahl Strahlungsdaten-API Calls. Ein Call kann mehrere API Requests enthalten.&lt;br /&gt;
;todayRemainingAPIcalls: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Calls&lt;br /&gt;
;todayRemainingAPIrequests: 	die Anzahl der am aktuellen Tag noch möglichen Strahlungsdaten-API Requests&lt;br /&gt;
;todayBatIn_XX: 	die am aktuellen Tag in die Batterie XX geladene Energie&lt;br /&gt;
;todayBatInSum: 	Summe der am aktuellen Tag in alle Batterien geladene Energie&lt;br /&gt;
;todayBatOut_XX: 	die am aktuellen Tag aus der Batterie XX entnommene Energie&lt;br /&gt;
;todayBatOutSum: 	Summe der am aktuellen Tag aus allen Batterien entnommene Energie&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Manche Angaben sind im Setup des Moduls optional, d.h. sie müssen nicht zwingend beim Setup angegeben werden. Allerdings sind diese Angaben für die Erstellung eines zusätzlichen Readings unter Umständen Voraussetzung. Es empfiehlt sich deshalb bei Setup so viele Informationen wie möglich zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
So ist zum Beispiel für die sinnvolle Erstellung der Informationen &#039;&#039;&#039;todayBatInSum&#039;&#039;&#039; und &#039;&#039;&#039;todayBatOutSum&#039;&#039;&#039; (Readings special_todayBatInSum und special_todayBatOutSum) das Vorhandensein der Schlüssel &#039;&#039;intotal&#039;&#039; und &#039;&#039;outtotal&#039;&#039; im Attribut setupBatteryDevXX notwendig (Beispiel):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; setupBatteryDev01 MQTT2_cerboGX_c0619ab34e08_battery &lt;br /&gt;
                              pin=BatIn:W pout=BatOut:W charge=SOC_value intotal=BatInTotal:Wh outtotal=BatOutTotal:Wh &lt;br /&gt;
                              cap=InstalledCapacity_Wh:Wh asynchron=1 show=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Fehlersuche ==&lt;br /&gt;
Das Modul SolarForecast ist sehr komplex und es die verschiedensten Datenquellen ausgewertet, zusammengeführt und daraus Ergebnisse berechnet und/oder visualisiert. Wird etwas nicht wie erwartet durch das Modul geliefert, können die Ursachen vielfältig sein. Natürlich kann ein Fehler im Modulcode vorliegen, oftmals gibt es aber andere Ursachen.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgenden Hinweise sollen Hilfe zur Selbsthilfe geben und sind eine Zusammenfassung von realen Fällen die mit dem beschriebenen Wegen und Verfahren gelöst wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Die erwartete erzeugte PV-Energie ist im Modul zu gering und wird im Balkendiagramm nicht angezeigt === &lt;br /&gt;
&lt;br /&gt;
Die erzeugte PV-Energie wird nicht richtig angezeigt: Am Vormittag sind keine Werte vorhanden und, wenn dann etwas kommt, ist die Anzeige zu gering. Für 13 und 14 Uhr wurden ca. 5.000Wh erwartet (im Vergleich mit den Daten aus einer anderen Auswertungsquelle). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lösungsweg:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Aus dem List des Devices wurden die für den Fall wesentlichen Readings herausgezogen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVforecast 152 Wh&lt;br /&gt;
    2025-02-02 08:59:55  Today_Hour09_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVforecast 1400 Wh&lt;br /&gt;
    2025-02-02 09:59:55  Today_Hour10_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVforecast 2500 Wh&lt;br /&gt;
    2025-02-02 10:59:55  Today_Hour11_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVforecast 4392 Wh&lt;br /&gt;
    2025-02-02 11:59:55  Today_Hour12_PVreal 0 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVforecast 4000 Wh&lt;br /&gt;
    2025-02-02 12:59:54  Today_Hour13_PVreal 300 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVforecast 6415 Wh&lt;br /&gt;
    2025-02-02 13:59:54  Today_Hour14_PVreal 3200 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVforecast 5629 Wh&lt;br /&gt;
    2025-02-02 14:59:54  Today_Hour15_PVreal 2700 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVforecast 3958 Wh&lt;br /&gt;
    2025-02-02 15:59:54  Today_Hour16_PVreal 900 Wh&lt;br /&gt;
&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVforecast 945 Wh&lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour17_PVreal 500 Wh&lt;br /&gt;
   &lt;br /&gt;
    2025-02-02 16:31:24  Today_Hour18_PVforecast 59 Wh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man sieht dass bis 12:00 keine erzeugte Energie vom WR gemeldet wird. Deswegen wird in der Balkengrafik nichts dargestellt. Auch danach bleibt die registrierte PV-Energie hinter den Erwartungen zurück. Zuständig für die Lieferung der PV-Energie an das Modul ist das Reading im Schlüssel:&lt;br /&gt;
&lt;br /&gt;
 setupInverterDev01 SH10rt pv=Total_DC_Power:W &amp;lt;mark&amp;gt;etotal=Total_Export_Energy_from_PV:kWh&amp;lt;/mark&amp;gt; capacity=10000 strings=Hauptdach,Flachdach&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Welche Änderungen es zwischen den Stunden gab, sieht man mit einem &amp;quot;get ... pvHistory XX&amp;quot; (&amp;quot;XX&amp;quot; steht für das Datum, d.h. den Tag, z.B. 02). &amp;lt;br&amp;gt;&lt;br /&gt;
Hier ein Beispiel für die Stunden 10 (9:00 - 9:59) und 11 (10:00 - 10:59). &amp;lt;br&amp;gt;&lt;br /&gt;
Wichtig ist hier der Key etotali01 für den ersten Inverter. Die Differenz zwischen den Werten beider Stunden ist die in der Stunde erzeugte Energie (hier 380 Wh). Diese 380 Wh findest du auch im Key pvrl01 als PVReal für diese Stunde. Das Modul rechnet intern immer mit Wh, kWh werden vorher in Wh umgerechnet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
10 =&amp;gt; pvfc: 365, pvrl: 530, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63364714&amp;lt;/mark&amp;gt;, etotali02: 3044110, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;pvrl01: 380&amp;lt;/mark&amp;gt;, pvrl02: 150, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 574, con: 518, gcons: 22, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 1, feedprice: 0.1269&lt;br /&gt;
&lt;br /&gt;
            DoN: 1, sunaz: 137, sunalt: 12&lt;br /&gt;
&lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
      11 =&amp;gt; pvfc: 2966, pvrl: 1862, pvrlvd: 1, rad1h: -&lt;br /&gt;
&lt;br /&gt;
            &amp;lt;mark&amp;gt;etotali01: 63365094&amp;lt;/mark&amp;gt;, etotali02: 3044260, etotali03: -&lt;br /&gt;
&lt;br /&gt;
            pvrl01: 1392, pvrl02: 470, pvrl03: -&lt;br /&gt;
&lt;br /&gt;
            etotalp01: -, etotalp02: -, etotalp03: -&lt;br /&gt;
&lt;br /&gt;
            pprl01: -, pprl02: -, pprl03: -&lt;br /&gt;
&lt;br /&gt;
            confc: 774, con: 609, gcons: 25, conprice: 0.2958&lt;br /&gt;
&lt;br /&gt;
            gfeedin: 4, feedprice: 0.1269&lt;br /&gt;
           &lt;br /&gt;
....&lt;br /&gt;
&lt;br /&gt;
D.h. wenn zwischen den beiden Stunden keine Differenzen zu finden sind, liegt es sehr wahrscheinlich am Input des Readings:&lt;br /&gt;
&lt;br /&gt;
 etotal=Total_Export_Energy_from_PV:kWh&lt;br /&gt;
&lt;br /&gt;
welches sich in den ersten Stunden nicht ändert und danach auch nur wenig.&lt;br /&gt;
&lt;br /&gt;
Man kann mit dem Attribut:&lt;br /&gt;
&lt;br /&gt;
 ctrlDebug=collectData&lt;br /&gt;
&lt;br /&gt;
die Datensammlung verfolgen (leider entstehen viele Daten im Log). Man sieht welche Werte von dem Inverter/Reading geliefert werden:&lt;br /&gt;
 &lt;br /&gt;
 ....&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; collect Inverter 01 data - device: STP_5000, delivery: default =&amp;gt;&lt;br /&gt;
 2025.02.02 19:10:10.558 1: SolCast DEBUG&amp;gt; pv: 0 W, &amp;lt;mark&amp;gt;etotal: 63378810 Wh&amp;lt;/mark&amp;gt;&lt;br /&gt;
 ....&lt;br /&gt;
&lt;br /&gt;
Dieser Wert muß bei PV Erzeugung kontinuierlich hochzählen. Wenn nicht, muss das angegebene Reading, d.h. die Quelle überprüft werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ergebnis der Prüfung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tatsächlich wurde ein Reading benutzt, das ungeeignet war: Statt &amp;quot;Total_PV_Generation&amp;quot; wurde &amp;quot;Total_export_energy_from_PV&amp;quot; genutzt. In diesem Reading wurde immer die in die Batterie gespeicherte Energie von der gesamten erzeugten Energie abgezogen. Daher war auch vormittags alles 0, da in dieser Periode alle PV-Energie in die Batterie geladen wurde bzw. in weiteren Stunden ein Anteil der dann bei dem PV-Erzeugungswert fehlte.&lt;br /&gt;
&lt;br /&gt;
Nachdem die Ursache beseitigt war, zeigt SolarForecast wieder die erwarteten PV-Erzeugungswerte an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Konfigurationsbeispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Visualisierung solare Vorhersage und reale Erzeugung ===&lt;br /&gt;
&lt;br /&gt;
Zu Beginn jedes neuen Tages gegen 00:00 Uhr werden durch das SolarForecast Device Events für die initiale PV Prognose des kommenden Tages erstellt.&lt;br /&gt;
Der Readingteil dieser Events heißt&lt;br /&gt;
&lt;br /&gt;
 AllPVforecastsToEvent&lt;br /&gt;
&lt;br /&gt;
Die Uhrzeiten der Events sind so aufbereitet und können direkt geloggt werden um sie in einen SVG Plot zu integrieren.&lt;br /&gt;
Im SolarForecast Device ist dieses Reading nicht sichtbar, nur die Events werden erstellt.&lt;br /&gt;
&lt;br /&gt;
Die meteorologischen Bedingungen verändern sich über den Tag permanent. Je nach gewählter Strahlungsdatenquelle (eine API oder DWD Device) erfolgt eine mehr oder weniger dynamische Anpassung der Prognose an die sich verändernde Umwelt.&lt;br /&gt;
&lt;br /&gt;
Aktuelle Prognosedaten sowie die reale PV Erzeugung der vergangenen Stunde können über die Readings&lt;br /&gt;
&lt;br /&gt;
 LastHourPVforecast&lt;br /&gt;
 LastHourPVreal&lt;br /&gt;
&lt;br /&gt;
[[Datei:Screenshot 2024-10-20 134050.png|right|thumb|400px|Übersicht solare Vorhersage]]&lt;br /&gt;
geloggt werden. &lt;br /&gt;
&lt;br /&gt;
Werden alle drei Werte in einem SVG kombiniert, kann die Entwicklung der Prognose über den Tag und die Beziehung von Prognose zu realer PV Erzeugnung pro Stunde visualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Für das rechts abgebildete Beispiel des Plots aus einer Datenbank &amp;quot;LogDBShort&amp;quot; sieht das gplot-File wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Created by FHEM/98_SVG.pm, 2024-03-08 15:05:31&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;TL&amp;gt;&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid&lt;br /&gt;
set ylabel &amp;quot;Wh&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Wh&amp;quot;&lt;br /&gt;
set yrange [0:7500]&lt;br /&gt;
set y2range [0:7500]&lt;br /&gt;
&lt;br /&gt;
#LogDBShort SolCast:LastHourPVforecast:::&lt;br /&gt;
#LogDBShort SolCast:LastHourPVreal:::&lt;br /&gt;
#LogDBShort SolCast:AllPVforecastsToEvent:::&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;aktuelle PV Vorhersage&#039; ls l6fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;reale PV Erzeugung&#039; ls l2fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;initiale PV Vorhersage&#039; ls l4 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; In manchen Fällen werden die Vorhersagewerte im SVG-Plot nicht angezeigt wenn FileLog verwendet wird. Ein Setzen des Attribute &amp;quot;fixedrange=3days +1&amp;quot; im SVG löst das Problem. Die Definition des SVG-Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_LogDBShort_SolCast SVG LogDBShort:SVG_LogDBShort_SolCast:HISTORY&lt;br /&gt;
attr SVG_LogDBShort_SolCast fixedrange 3days +1&lt;br /&gt;
attr SVG_LogDBShort_SolCast room Energie-&amp;gt;SolarPrognose&lt;br /&gt;
attr SVG_LogDBShort_SolCast sortby 2&lt;br /&gt;
attr SVG_LogDBShort_SolCast title &amp;quot;Übersicht solare Vorhersage&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Technisch bedingt werden an einem Tag X kurz nach 00:00 Uhr die am Vortag für den Tag X erzeugten Events aktualisiert. Diese Daten erzeugen in der Datenbank einen zweiten Satz an Daten mit dem gleichen Timestamp was für die Anzeige unvorteilhaft ist. &lt;br /&gt;
Um nur die aktualisierten Events von &#039;&#039;&#039;AllPVforecastsToEvent&#039;&#039;&#039; in der Datenbank zu erhalten, bietet sich ein DbRep-Device an. Die nachfolgende Vorschlagsdefinition kann per at-Device jeden Tag kurz vor Mitternacht (z.B. 23:57:10) ausgeführt werden. Es werden immer die in der Vergangenheit geschriebenen (veralteten) Daten aus der Datenbank gelöscht, doppelte Datesätze vermieden und immer die aktuellste initiale Prognose gespeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.Del.AllPVforecastsToEvent DbRep LogDBShort&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent alias Löschen Readings AllPVforecastsToEvent des Folgetages&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent comment ermöglicht dass die Readings AllPVforecastsToEvent am Folgetag wieder neu und aktuell geschrieben werden können&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent devStateIcon initialized:control_3dot_hor_s connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent disable 0&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent event-on-update-reading state&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent icon edit_delete&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent showproctime 1&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent device TYPE=SolarForecast&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_begin next_day_begin&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent timestamp_end next_day_end&lt;br /&gt;
attr Rep.Del.AllPVforecastsToEvent verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das angegebene DbLog-Device &#039;&#039;&#039;LogDBShort&#039;&#039;&#039; ist natürlich anzupassen.&lt;br /&gt;
&lt;br /&gt;
Das at-Device zum Starten der Datenbankbereinigung sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define At.Del.AllPVforecastsToEvent at *23:58:10 set Rep.Del.AllPVforecastsToEvent delEntries&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent alias Start Löschen Readings AllPVforecastsToEventn LogDBShort&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent icon clock&lt;br /&gt;
attr At.Del.AllPVforecastsToEvent room Datenbank-&amp;gt;Produktiv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich sind auch hier die eigenen Devicenamen entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
Ab SolarForecast Version 1.51.7 kann die Eventerzeugung für bestimmte SVG Plot-Typen optimiert werden. &amp;lt;br&amp;gt; &lt;br /&gt;
Die Aktivierung dieser Optimierungen ist in der Online Hilfe zum Attribut &#039;&#039;&#039;plantControl-&amp;gt;genPVforecastsToEvent&#039;&#039;&#039; beschrieben. Bei Nutzung des Attributes plantControl-&amp;gt;genPVforecastsToEvent ist ebenfalls das Attribut &#039;&#039;&#039;event-on-update-reading=AllPVforecastsToEvent&#039;&#039;&#039; zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Beispielkonfiguration 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;
Bitte dabei diese DWD-Version aus dem [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter Contrib] von DS_Starter dazu nutzen&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|55_DWD_OpenData.pm&lt;br /&gt;
|136.2 KB ​&lt;br /&gt;
|29260  &lt;br /&gt;
|DS_Starter&lt;br /&gt;
|55_DWD_OpenData: contrib 1.17.7&lt;br /&gt;
|}&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 downloadTimeout 120&lt;br /&gt;
attr DWD comment Im DWD Wetterdevice verwendet Solarforecast : \&lt;br /&gt;
TTT,Neff,RR1c,ww,SunUp,SunRise,SunSet \&lt;br /&gt;
zusätzlich ist jedoch auch noch Rad1h notwendig \&lt;br /&gt;
wenn dieses DWD-Device als Strahlungsdevice genutzt wird.\&lt;br /&gt;
Die Station 10418 (Lüdenscheid) überträgt aktuell am 09.03.2025 (noch) Rad1h.\&lt;br /&gt;
attr DWD downloadTimeout 120&lt;br /&gt;
attr DWD forecastDays 7&lt;br /&gt;
attr DWD forecastProperties SunUp, SunRise, SunSet, Rad1h, R101, RR1c, TTT, Tx, Tn, Tg, DD, FX1, RR6c, R600, RRhc, Rh00, ww, wwd, Neff&lt;br /&gt;
attr DWD forecastRefresh 1&lt;br /&gt;
attr DWD forecastResolution 1&lt;br /&gt;
attr DWD forecastStation 10418&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 fc_description  -(state fc_time)&lt;br /&gt;
attr DWD verbose 2&lt;br /&gt;
&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;
defmod InverterDummy dummy&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;
defmod 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 feedinPrice 0.08&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 powerCost 0.25&lt;br /&gt;
attr SMA_Energymeter room 015_Zaehler,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;
defmod 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;
attr BatteryDummy userReadings total_pac, power_out, power_in, chargestatus, bat_rated_capacity, bat_loadtotal, bat_unloadtotal&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;
defmod N.PV.TotalConsumption.Dum.Energy notify SMA_Energymeter:Saldo_Wirkleistung:.* {\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Bezug -Batterieentnahme_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadIn_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_out&amp;quot;,0)));;\&lt;br /&gt;
 # Batterie-Beladung_2 Batterie mit Strom füllen\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattLoadOut_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;power_in&amp;quot;,0)));;\&lt;br /&gt;
 # Batteriestatus_2\&lt;br /&gt;
fhem &amp;quot;setreading Dum.Energy BattStatusP_2 &amp;quot;.sprintf(&amp;quot;%.1f&amp;quot;,(ReadingsVal(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0)));;\&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;MB_USRW610_004&amp;quot;,&amp;quot;Power_Sum__W&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;
fhem &amp;quot;setreading InverterDummy total_pac &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,(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;
#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;
 # Batterie-total_pac  InverterDummy\&lt;br /&gt;
my $wert7 = sprintf(&amp;quot;%.3f&amp;quot;,((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))+(ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))));; \&lt;br /&gt;
fhem (&amp;quot;setreading BatteryDummy bat_rated_capacity &amp;quot;.sprintf(&amp;quot;%.3f&amp;quot;,$wert7));;\&lt;br /&gt;
 # möglicher Aufruf einer Batterie-Bebladung-Routine....SMABatteryChargewithTibber();;\&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;
defmod Forecast SolarForecast&lt;br /&gt;
attr Forecast DbLogExclude .*&lt;br /&gt;
attr Forecast DbLogInclude Current_BatCharge999&lt;br /&gt;
attr Forecast affectBatteryPreferredCharge 30&lt;br /&gt;
attr Forecast affectConsForecastLastDays 31&lt;br /&gt;
attr Forecast affect70percentRule 0&lt;br /&gt;
attr Forecast comment &amp;quot;wget -qO ./FHEM/76_SolarForecast.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/76_SolarForecast.pm&amp;quot;\&lt;br /&gt;
&amp;quot;wget -qO ./FHEM/55_DWD_OpenData.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/55_DWD_OpenData.pm&amp;quot;\&lt;br /&gt;
&amp;quot;13.01.2025 mit der Version 76_SolarForecast.pm:v1.43.2-s29518/2025-01-12&amp;quot;&lt;br /&gt;
attr Forecast graphicHeaderOwnspec PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal Verbrauch&amp;amp;nbsp;;bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast  Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest FCU-Erzeugung&amp;amp;nbsp;;:Current_PP01\&lt;br /&gt;
attr Forecast consumer01 FBDECT_fbahahttp_11657_0127183 icon=scene_washing_machine@orange type=washingmachine power=10 swstate:state notbefore=09 notafter=20 pcurr=power:W:3 etotal=energy:Wh interruptable=1 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer02 FBDECT_fbahahttp_E8_DF_70_07_3E_57 icon=light_floor_lamp@orange type=other power=15 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer03 FBDECT_fbahahttp_E8_DF_70_07_42_0B icon=raspberrypi@orange type=other power=8 swstate:state pcurr=power:W:1 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer04 FBDECT_fbahahttp_11657_0067275 icon=springbrunnen_icon@orange type=other power=50 swstate:state pcurr=power:W:10 etotal=energy:Wh interruptable=0 auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer05 FBDECT_fbahahttp_34_31_C4_D4_31_37 icon=sani_domestic_waterworks@orange type=other power=10 swstate:state pcurr=power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer06 tuya_local_bf5037060f450bdbd4rl0q icon=scene_clothes_dryer@orange type=dryer power=10 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumer07 tuya_local_bfac44fb487476efd1vhdu icon=weather_sunset@orange type=noSchedule power=5 swstate:state pcurr=cur_power:W:3 etotal=energy:Wh auto=solarforecast_auto surpmeth=default&lt;br /&gt;
attr Forecast consumerControl adviceIcon=light_light_dim_100@gold&lt;br /&gt;
attr Forecast consumerControl showLegend=icon_top&lt;br /&gt;
attr Forecast consumerControl detailLink=1&lt;br /&gt;
attr Forecast ctrlAIdataStorageDuration 1825&lt;br /&gt;
attr Forecast ctrlAIshiftTrainStart 2&lt;br /&gt;
attr Forecast ctrlBatSocManagement01 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlBatSocManagement02 lowSoc=10 upSoC=30 maxSoC=99 careCycle=20&lt;br /&gt;
attr Forecast ctrlDebug none&lt;br /&gt;
attr Forecast plantControl genPVdeviation=continuously&lt;br /&gt;
attr Forecast plantControl cycleInterval=15&lt;br /&gt;
attr Forecast ctrlNextDayForecastReadings 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24&lt;br /&gt;
attr Forecast ctrlNextHoursSoCForecastReadings 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23&lt;br /&gt;
attr Forecast ctrlSpecialReadings BatPowerIn_Sum,BatPowerOut_Sum,SunHours_Remain,SunMinutes_Remain,allStringsFullfilled,conForecastTillNextSunrise,currentAPIinterval,currentRunMtsConsumer_01,currentRunMtsConsumer_02,currentRunMtsConsumer_03,currentRunMtsConsumer_04,currentRunMtsConsumer_05,currentRunMtsConsumer_06,currentRunMtsConsumer_07,dayAfterTomorrowPVforecast,daysUntilBatteryCare_01,daysUntilBatteryCare_02,lastretrieval_time,lastretrieval_timestamp,response_message,runTimeAvgDayConsumer_01,runTimeAvgDayConsumer_02,runTimeAvgDayConsumer_03,runTimeAvgDayConsumer_04,runTimeAvgDayConsumer_05,runTimeAvgDayConsumer_06,runTimeAvgDayConsumer_07,runTimeCentralTask,runTimeLastAPIAnswer,runTimeLastAPIProc,runTimeTrainAI,todayBatIn_01,todayBatIn_02,todayBatOut_01,todayBatOut_02,todayConForecastTillSunset,todayConsumptionForecast,todayDoneAPIcalls,todayDoneAPIrequests,todayGridConsumption,todayGridFeedIn,todayMaxAPIcalls,todayRemainingAPIcalls,todayRemainingAPIrequests&lt;br /&gt;
attr Forecast disable 0&lt;br /&gt;
attr Forecast event-min-interval .*:1800&lt;br /&gt;
attr Forecast event-on-change-reading .*&lt;br /&gt;
attr Forecast flowGraphicControl animate=1 consumerdist=80 h2consumerdist=50 shiftx=0  shifty=0 showconsumer=1 showconsumerdummy=1 showconsumerpower=1 showconsumerremaintime=0 size=400 strokewidth=12&lt;br /&gt;
attr Forecast graphicBeam1Color 3C14FF&lt;br /&gt;
attr Forecast graphicBeam1Content pvReal&lt;br /&gt;
attr Forecast graphicBeam2Color 19FF29&lt;br /&gt;
attr Forecast graphicBeam2Content pvForecast&lt;br /&gt;
attr Forecast graphicBeam3Color D60924&lt;br /&gt;
attr Forecast graphicBeam3Content batsocforecast_02&lt;br /&gt;
attr Forecast graphicBeam3FontColor FFFF0D&lt;br /&gt;
attr Forecast graphicBeam4Color FFFF1F&lt;br /&gt;
attr Forecast graphicBeam4Content batsocforecast_01&lt;br /&gt;
attr Forecast graphicBeam4FontColor 000000&lt;br /&gt;
attr Forecast graphicBeamHeightLevel1 200&lt;br /&gt;
attr Forecast graphicBeamHeightLevel2 200&lt;br /&gt;
attr Forecast graphicHeaderDetail all&lt;br /&gt;
attr Forecast graphicHeaderOwnspec #PV\&lt;br /&gt;
PV&amp;amp;nbsp;;Heute&amp;amp;nbsp;;real:Today_PVreal\&lt;br /&gt;
PV&amp;amp;nbsp;;Morgen&amp;amp;nbsp;;erwartet:Tomorrow_PVforecast\&lt;br /&gt;
PV&amp;amp;nbsp;;Uebermorgen&amp;amp;nbsp;;erwartet:special_dayAfterTomorrowPVforecast\&lt;br /&gt;
:\&lt;br /&gt;
#\&lt;br /&gt;
AutarkyRate:Current_AutarkyRate\&lt;br /&gt;
Überschuss:Current_Surplus\&lt;br /&gt;
aktueller&amp;amp;nbsp;;Netzbezug:Current_GridConsumption\&lt;br /&gt;
:\&lt;br /&gt;
#Verbrauch\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenuntergang:special_todayConForecastTillSunset\&lt;br /&gt;
bis&amp;amp;nbsp;;Sonnenaufgang&amp;amp;nbsp;;:special_conForecastTillNextSunrise\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie01\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_01\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_01\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_01\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_01\&lt;br /&gt;
#Batterie01_tmp\&lt;br /&gt;
Current_PowerBatIn_01:Current_PowerBatIn_01\&lt;br /&gt;
Current_PowerBatOut_01:Current_PowerBatOut_01\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Batterie02\&lt;br /&gt;
Batt.-Ladeanforderung&amp;amp;nbsp;;:Battery_ChargeRequest_02\&lt;br /&gt;
Batt.-Ladung&amp;amp;nbsp;;empfohlen:Battery_ChargeUnrestricted_02\&lt;br /&gt;
Ladung&amp;amp;nbsp;;heute:special_todayBatIn_02\&lt;br /&gt;
Entladung&amp;amp;nbsp;;heute:special_todayBatOut_02\&lt;br /&gt;
#Batterie02_tmp\&lt;br /&gt;
Current_PowerBatIn_02:Current_PowerBatIn_02\&lt;br /&gt;
Current_PowerBatOut_02:Current_PowerBatOut_02\&lt;br /&gt;
:\&lt;br /&gt;
:\&lt;br /&gt;
#Settings\&lt;br /&gt;
Autokorrektur:pvCorrectionFactor_Auto \&lt;br /&gt;
Wetter:graphicShowWeather\&lt;br /&gt;
History:graphicHistoryHour\&lt;br /&gt;
ShowNight:graphicShowNight\&lt;br /&gt;
Debug:ctrlDebug\&lt;br /&gt;
FCU-Modus:FCU-Betriebsmodus@FCU&lt;br /&gt;
attr Forecast graphicHistoryHour 4&lt;br /&gt;
attr Forecast graphicHourCount 24&lt;br /&gt;
attr Forecast graphicLayoutType double&lt;br /&gt;
attr Forecast graphicShowDiff top&lt;br /&gt;
attr Forecast graphicShowNight 1&lt;br /&gt;
attr Forecast graphicShowWeather 1&lt;br /&gt;
attr Forecast group Energy Meter&lt;br /&gt;
attr Forecast room 020_PV,Energie&lt;br /&gt;
attr Forecast setupBatteryDev01 SBS25 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupBatteryDev02 SBS25_2 pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus cap=9800 show=2&lt;br /&gt;
attr Forecast setupInverterDev01 SB25 pv=total_pac:kW etotal=etotal:kWh capacity=2500 strings=GarageSE limit=70&lt;br /&gt;
attr Forecast setupInverterDev02 SB30 pv=total_pac:kW etotal=etotal:kWh capacity=3000 strings=GarageNW,HausNW limit=70&lt;br /&gt;
attr Forecast setupInverterDev03 SB40 pv=total_pac:kW etotal=etotal:kWh capacity=4000 strings=HausSE1,HausSE2,HausSW limit=70&lt;br /&gt;
attr Forecast setupInverterStrings GarageSE,GarageNW,HausNW,HausSW,HausSE1,HausSE2&lt;br /&gt;
attr Forecast setupMeterDev SMA_Energymeter gcon=Bezug_Wirkleistung:W contotal=Bezug_Wirkleistung_Zaehler:kWh gfeedin=Einspeisung_Wirkleistung:W feedtotal=Einspeisung_Wirkleistung_Zaehler:kWh conprice=0.25:€ feedprice=0.08123:€&lt;br /&gt;
attr Forecast setupOtherProducer01 icon=Heizung_FCU_green@red MB_USRW610_004 pcurr=Power_L1__W:W etotal=Energy_L1_import__kWh:kWh&lt;br /&gt;
attr Forecast setupRadiationAPI DWD&lt;br /&gt;
attr Forecast setupStringPeak GarageSE=2.75 GarageNW=3.200 HausNW=2.230 HausSW=2.230 HausSE1=2.200 HausSE2=2.200&lt;br /&gt;
attr Forecast setupWeatherDev1 DWD&lt;br /&gt;
attr Forecast stateFormat Current_PV&lt;br /&gt;
attr Forecast userReadings Current_BatCharge999 {((ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;chargestatus&amp;quot;,0) * 10 * ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0))) / ( (ReadingsNum(&amp;quot;SBS25&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0) * 1000)  + (ReadingsNum(&amp;quot;SBS25_2&amp;quot;,&amp;quot;bat_rated_capacity&amp;quot;,0)*1000))*100}&lt;br /&gt;
attr Forecast verbose 2&lt;br /&gt;
&lt;br /&gt;
setstate Forecast 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .FCU_FCU-Betriebsmodus 2&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_ctrlDebug none&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicHistoryHour 4&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowNight 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 .Forecast_graphicShowWeather 1&lt;br /&gt;
setstate Forecast 2025-01-13 08:24:25 .associatedWith SMA_Energymeter FBDECT_fbahahttp_11657_0127183 FBDECT_fbahahttp_E8_DF_70_07_3E_57 FBDECT_fbahahttp_E8_DF_70_07_42_0B FBDECT_fbahahttp_11657_0067275 FBDECT_fbahahttp_34_31_C4_D4_31_37 tuya_local_bf5037060f450bdbd4rl0q tuya_local_bfac44fb487476efd1vhdu SBS25 SBS25_2 SB25 SB30 SB40 DWD MB_USRW610_004&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .lastupdateForecastValues 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .pvCorrectionFactor_01_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .pvCorrectionFactor_02_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .pvCorrectionFactor_03_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .pvCorrectionFactor_04_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .pvCorrectionFactor_05_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .pvCorrectionFactor_06_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .pvCorrectionFactor_07_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .pvCorrectionFactor_08_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .pvCorrectionFactor_09_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .pvCorrectionFactor_10_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .pvCorrectionFactor_11_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .pvCorrectionFactor_12_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .pvCorrectionFactor_13_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .pvCorrectionFactor_14_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .pvCorrectionFactor_15_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .pvCorrectionFactor_16_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .pvCorrectionFactor_17_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_apipercentil done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .pvCorrectionFactor_18_cloudcover done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 .pvCorrectionFactor_Auto_Soll on_complex_ai&lt;br /&gt;
setstate Forecast 2025-01-13 01:00:05 .signaldone_01 done&lt;br /&gt;
setstate Forecast 2025-01-13 02:00:04 .signaldone_02 done&lt;br /&gt;
setstate Forecast 2025-01-13 03:00:04 .signaldone_03 done&lt;br /&gt;
setstate Forecast 2025-01-13 04:00:05 .signaldone_04 done&lt;br /&gt;
setstate Forecast 2025-01-13 05:00:05 .signaldone_05 done&lt;br /&gt;
setstate Forecast 2025-01-13 06:00:06 .signaldone_06 done&lt;br /&gt;
setstate Forecast 2025-01-13 07:00:04 .signaldone_07 done&lt;br /&gt;
setstate Forecast 2025-01-13 08:00:03 .signaldone_08 done&lt;br /&gt;
setstate Forecast 2025-01-13 09:00:04 .signaldone_09 done&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 .signaldone_10 done&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 .signaldone_11 done&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 .signaldone_12 done&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 .signaldone_13 done&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 .signaldone_14 done&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 .signaldone_15 done&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 .signaldone_16 done&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 .signaldone_17 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:04 .signaldone_18 done&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeUnrestricted_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_01 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_ChargeRequest_02 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour00_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour01_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour02_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour03_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour04_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour05_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour06_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour07_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour08_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour09_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour10_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour11_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour12_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour13_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour14_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour15_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour16_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_01 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour17_SoCforecast_02 10.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour18_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour19_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_01 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour20_SoCforecast_02 42.6 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour21_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour22_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_01 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_NextHour23_SoCforecast_02 40.0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_01 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Battery_OptimumTargetSoC_02 40 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_AutarkyRate 83 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 Current_BatCharge999 10&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_01 12 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_BatCharge_02 8 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Consumption 626 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridConsumption 2 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_GridFeedIn 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PP_01 746.0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PV 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_01 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatIn_02 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_01 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_PowerBatOut_02 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumption 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_SelfConsumptionRate 0 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Current_Surplus 120 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourGridconsumptionReal 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:00:00 LastHourPVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_ConsumptionForecast 2944 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 NextHours_Sum04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayConsumptionForecast 3609 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 RestOfDayPVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_01 272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PPreal_01 748 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 Today_Hour01_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PPreal_01 787 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 Today_Hour02_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_01 271 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PPreal_01 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 Today_Hour03_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_01 266 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PPreal_01 745 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 Today_Hour04_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_01 267 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PPreal_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 Today_Hour05_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_01 255 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridConsumption 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_GridFeedIn 1 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PPreal_01 752 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 Today_Hour06_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_01 226 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_01 50 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridConsumption 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_GridFeedIn 2 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PPreal_01 681 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 Today_Hour07_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatIn_02 233 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_01 845 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridConsumption 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 Today_Hour08_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_01 37 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatIn_02 90 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_01 351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_BatOut_02 188 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridConsumption 447 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_GridFeedIn 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVforecast 127 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 Today_Hour09_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridConsumption 1650 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVforecast 478 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 Today_Hour10_PVreal 26 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridConsumption 513 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVforecast 868 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 Today_Hour11_PVreal 97 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatIn_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridConsumption 576 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_GridFeedIn 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVforecast 1157 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 Today_Hour12_PVreal 320 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_01 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatIn_02 4 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridConsumption 1272 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_GridFeedIn 7 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PPreal_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVforecast 1238 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 Today_Hour13_PVreal 945 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_01 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatIn_02 53 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_BatOut_02 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridConsumption 955 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_GridFeedIn 31 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PPreal_01 562 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVforecast 1168 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 Today_Hour14_PVreal 1410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_01 703 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatIn_02 500 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_01 22 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_BatOut_02 18 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridConsumption 32 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_GridFeedIn 71 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PPreal_01 777 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 Today_Hour15_PVreal 1416 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_01 296 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatIn_02 70 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_01 74 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_BatOut_02 258 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridConsumption 13 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_GridFeedIn 17 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PPreal_01 732 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVforecast 880 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 Today_Hour16_PVreal 1051 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_01 47 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatIn_02 126 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_01 102 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_BatOut_02 75 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridConsumption 15 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_GridFeedIn 23 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PPreal_01 771 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVforecast 117 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 Today_Hour17_PVreal 86 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_01 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatIn_02 410 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_01 758 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_BatOut_02 67 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridConsumption 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_GridFeedIn 5 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PPreal_01 723 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 Today_Hour18_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_01 349 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatIn_02 124 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_01 73 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_BatOut_02 450 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridConsumption 8 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_GridFeedIn 6 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PPreal_01 671 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_Hour19_PVreal 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecast 1630 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_MaxPVforecastTime 2025-01-13 14:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVdeviation 30.17 %&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVforecast 7663 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_PVreal 5351 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunRise 08:28&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Today_SunSet 16:46&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_ConsumptionForecast 17043 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour01_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour02_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour03_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour04_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour05_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour06_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour07_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour08_PVforecast 10 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour09_PVforecast 161 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour10_PVforecast 275 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour11_PVforecast 532 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour12_PVforecast 730 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour13_PVforecast 1252 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour14_PVforecast 818 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour15_PVforecast 1465 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour16_PVforecast 303 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour17_PVforecast 20 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour18_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour19_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour20_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour21_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour22_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour23_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_Hour24_PVforecast 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_PVforecast 5566 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunRise 08:27&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 Tomorrow_SunSet 16:47&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01 name=&#039;_Waschmaschine&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_start 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer01_planned_stop 14.01.2025 11:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02 name=&#039;_Esszimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_currentPower 15.3 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer02_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03 name=&#039;_FCU&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_currentPower 7.15 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer03_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04 name=&#039;_Brunnen&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_start 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer04_planned_stop 14.01.2025 09:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05 name=&#039;_Zisterne&#039; state=&#039;off&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer05_planned_stop 14.01.2025 08:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06 name=&#039;SW Trockner&#039; state=&#039;unknown&#039; mode=&#039;can&#039; planningstate=&#039;planned&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_start 14.01.2025 07:00:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer06_planned_stop 14.01.2025 08:30:00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07 name=&#039;SW Urlaubslicht-Wohnzimmer&#039; state=&#039;on&#039; mode=&#039;can&#039; planningstate=&#039;noSchedule&#039; info=&#039;von extern umgeschaltet&#039;&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 consumer07_currentPower 0 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 nextCycletime 18:54:09&lt;br /&gt;
setstate Forecast 2025-01-13 10:00:05 pvCorrectionFactor_10 0.53 (automatic - old factor: 1.00, Sun Alt range: 5, Cloud range: 75, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 11:00:05 pvCorrectionFactor_11 0.56 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 70, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 12:00:02 pvCorrectionFactor_12 0.64 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 13:00:02 pvCorrectionFactor_13 0.88 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 60, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 14:00:03 pvCorrectionFactor_14 1.10 (automatic - old factor: 1.00, Sun Alt range: 15, Cloud range: 50, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 15:00:05 pvCorrectionFactor_15 1.01 (automatic - old factor: 1.06, Sun Alt range: 15, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 16:00:06 pvCorrectionFactor_16 1.09 (automatic - old factor: 1.00, Sun Alt range: 10, Cloud range: 45, Days in range: 1)&lt;br /&gt;
setstate Forecast 2025-01-13 17:00:05 pvCorrectionFactor_17 0.28 (automatic - old factor: 0.52, Sun Alt range: 0, Cloud range: 45, Days in range: 2)&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 pvCorrectionFactor_Auto on_complex_ai&lt;br /&gt;
setstate Forecast 2024-10-30 19:42:19 setupStringAzimuth GarageSE=-55 GarageNW=125 HausNW=125 HausSW=35 HausSE1=-55 HausSE2=-55&lt;br /&gt;
setstate Forecast 2024-10-30 19:37:38 setupStringDeclination GarageSE=40 GarageNW=40 HausNW=50 HausSW=50 HausSE1=50 HausSE2=50&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerIn_Sum 132 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_BatPowerOut_Sum 10 W&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunHours_Remain 0.00&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_SunMinutes_Remain 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_allStringsFullfilled 1&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_conForecastTillNextSunrise 9467 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentAPIinterval 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_01 132 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_02 184 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_03 329512 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_04 200 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_05 27 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_06 193 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_currentRunMtsConsumer_07 106 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_dayAfterTomorrowPVforecast 7344 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_01 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_daysUntilBatteryCare_02 12&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_time 2025-01-13 18:53:54&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_lastretrieval_timestamp 1736790834&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_response_message success&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_01 545.94 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_02 382.10 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_03 1430.13 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_04 262.05 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_05 28.80 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_06 622.63 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeAvgDayConsumer_07 276.51 min&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeCentralTask 0.3744&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIAnswer -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeLastAPIProc -&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_runTimeTrainAI 1.2529&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_01 3683.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatIn_02 1617.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_01 2287.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayBatOut_02 1057.0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConForecastTillSunset 0 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 00:59:59 special_todayConsumptionForecast_01 509 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 01:59:58 special_todayConsumptionForecast_02 499 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 02:59:53 special_todayConsumptionForecast_03 501 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 03:59:52 special_todayConsumptionForecast_04 511 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 04:59:56 special_todayConsumptionForecast_05 503 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 05:59:59 special_todayConsumptionForecast_06 495 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 06:59:52 special_todayConsumptionForecast_07 504 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 07:59:50 special_todayConsumptionForecast_08 561 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 08:59:57 special_todayConsumptionForecast_09 768 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 09:59:58 special_todayConsumptionForecast_10 783 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 10:59:58 special_todayConsumptionForecast_11 692 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 11:59:49 special_todayConsumptionForecast_12 791 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 12:59:49 special_todayConsumptionForecast_13 910 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 13:59:49 special_todayConsumptionForecast_14 1022 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 14:59:49 special_todayConsumptionForecast_15 965 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 15:59:50 special_todayConsumptionForecast_16 812 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 16:59:49 special_todayConsumptionForecast_17 884 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 17:59:54 special_todayConsumptionForecast_18 928 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_19 874 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_20 763 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_21 750 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_22 765 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_23 643 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayConsumptionForecast_24 601 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIcalls 0&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayDoneAPIrequests 4532&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridConsumption 5500.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayGridFeedIn 178.9 Wh&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayMaxAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIcalls n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:54 special_todayRemainingAPIrequests n.a.&lt;br /&gt;
setstate Forecast 2025-01-13 18:53:55 state updated&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
So sollte es dann als Ergebnis aussehen:&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13.png|zentriert|mini|Ergebnis nach kompletter Einrichtung]]&lt;br /&gt;
[[Datei:Bildschirmfoto 2025-01-13 Teil II.png|alternativtext=Unterer Teil der Anzeige|zentriert|mini]]&lt;br /&gt;
&lt;br /&gt;
== Praxisbeispiele und Lösungsansätze für Steuerungen ==&lt;br /&gt;
=== Fallstudie: Trockner darf pausiert werden, wenn nicht genug PV-Überschuss vorhanden ist, soll aber nach spätestens X Stunden fertig sein ===&lt;br /&gt;
Für diese Aufgabenstellung sind mehrere Schlüssel essentiell wichtig, &#039;&#039;&#039;power&#039;&#039;&#039;, &#039;&#039;&#039;mintime&#039;&#039;&#039;, &#039;&#039;&#039;mode&#039;&#039;&#039; und &#039;&#039;&#039;interruptable&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Die Bedingung, dass der Trockner nach spätestens X Stunden fertig sein soll, steht in einem Widerspruch zu der Möglichkeit den Trockner bei zu wenig PV-Überschuss unterbrechen zu können. Im Extremfall könnte nach dem Start die gesamte Planungszeit ungenügender Überschuss vorliegen und der Trockner nicht arbeiten. Der Schlüssel &#039;&#039;&#039;mintime&#039;&#039;&#039; (in Minuten) wird nun wie folgt angesetzt:&lt;br /&gt;
&lt;br /&gt;
 mintime = 2,5 x &amp;lt;gewöhnliche Betriebszeit für einen Trockengang (mneed, z.B. 120)&amp;gt; = 300 Minuten&lt;br /&gt;
&lt;br /&gt;
Das bedeutet, der Trockner wird nach 300 Minuten Laufzeit abgeschaltet werden bzw. vom Netz getrennt. Der Trockenvorgang wird natürlich bereits nach 120 Minuten beendet sein, sofern nach Start keine Unterbrechnung des Vorganges erfolgte. Wurde der Vorgang unterbrochen, soll der Trockner innerhalb &lt;br /&gt;
&lt;br /&gt;
 X+120 bis X+300 &lt;br /&gt;
&lt;br /&gt;
fertig sein. &lt;br /&gt;
&lt;br /&gt;
Demnach ist die ausgeführte Laufzeit des Trockners permanent zu überwachen, zu summieren (rtsum) und die notwendige Restzeit (mneed - rtsum) mit der noch verbleibenden Restzeit (mrest) bis zur geplanten Abschaltung des Consumers zu vergleichen. Ist der Consumer gestartet, wird die Laufzeit in der pvHistory für jede Stunde des Tages im Schlüssel &#039;&#039;minutescsmXX&#039;&#039; (XX = Consumernummer) aufgezeichnet und kann darüber ausgewertet werden. Somit ist:&lt;br /&gt;
&lt;br /&gt;
 msum = for (01 .. 24) {Summe von minutescsmXX} des aktuellen Tages&lt;br /&gt;
&lt;br /&gt;
Solange die Bedingung &lt;br /&gt;
&lt;br /&gt;
 mrest &amp;gt;= (mneed - msum)&lt;br /&gt;
&lt;br /&gt;
zutrifft, darf der Trockner unterbrochen werden, anderenfalls darf er nicht mehr unterbrochen werden da die Restzeit evtl. nicht ausreichen könnte um den Vorgang abzuschließen. Für die Planung des Trockners wird der Consumer wie gewöhnlich nach dem Bedarf im Modul registriert. Für die Steuerung der Unterbrechbarkeit wird noch ein Code erstellt, welcher im Trockner-Device &#039;&#039;Dryerdev&#039;&#039; das Reading &#039;&#039;SF_Int&#039;&#039; zur Unterbrechnungssteuerung verwaltet. Dieses Reading wird dem Schlüssel &#039;&#039;&#039;interruptable&#039;&#039;&#039; übergeben. Für das Beispiel wird der Consumer &#039;07&#039; verwendet, es kann natürlich jede andere freie Nummer verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Dryerdev:Trockner&lt;br /&gt;
                        icon=scene_cloves_dryer type=dryer power=2000 mode=must mintime=300 &lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic asynchron=1&lt;br /&gt;
                        interruptable=Dryerdev:SF_Int:1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Kombination &#039;&#039;&#039;auto=automatic&#039;&#039;&#039; eröffnet die Möglickeit, in der Consumer-Legende den Trockner-Start zusätzlich manuell freizugeben oder zu verbieten. &lt;br /&gt;
&lt;br /&gt;
Im nachfolgenden Code werden modulinterne Subroutinen verwendet. Diese sind inklusive dem Paket &#039;&#039;FHEM::SolarForecast::&#039;&#039; anzugeben. Die erstellte Subroutine wird in die 99_mySolarForecastUtils.pm eingefügt. Die Datei 99_mySolarForecastUtils.pm wird vorher von 99_myUtils.pm kopiert und enthält für die Übersichtlichkeit nur Routinen für SolarForecast.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Trocknersteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub dryControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # gewöhlich benötigte Zeit für &lt;br /&gt;
                                                                                  # einen Trockengang, z.B. 120 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $dryer     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename des Trockners&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Trockner-Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit des Trockners&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      my $dhash = $defs{$dryer};&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 1, 0);                        # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Int&#039;, 0, 0);                        # keine Interrupt-Freigabe&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die gewöhnliche Laufzeit des Trockners für einen Trockenvorgang (120 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::dryControl ($name, &#039;07&#039;, 120);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Fallstudie: Umwälzpumpe Pool soll X Stunden am Tag laufen. Ist kein PV-Überschuß vorhanden, müssen die X Stunden/Tag trotzdem erreicht werden ===&lt;br /&gt;
&lt;br /&gt;
Die Vorgehensweise ähnelt der Fallstudie zuvor. Verändernd kommt hinzu, dass der Planungszeitraum bewusst sehr lang angesetzt wird mit der Option, den Zyklus des Consumers vorfristig zu beenden sobald die Laufzeit von X Stunden am Tag erreicht ist. &lt;br /&gt;
Im folgenden Beispiel soll die Pumpe 5 Stunden am Tag (300 Minuten) laufen und dabei mögliche PV-Überschüsse ausnutzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;Name&amp;gt; consumer07 Pump:Zirkulationspumpe&lt;br /&gt;
                        icon=sani_pump type=other power=50 mode=must mintime=780 notafter=09&lt;br /&gt;
                        on=on off=off etotal=energy_Wh:Wh pcurr=power:W&lt;br /&gt;
                        auto=automatic &lt;br /&gt;
                        interruptable=1 swoffcond=Pump:SF_Abort:1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit dieser Registrierung wird die Pumpe ca. 09 Uhr täglich starten. Wenn kein bzw. ungenügender PV-Überschuß vorhanden ist, erfolgt eine Unterbrechung nach dem Start. Ist genügender PV-Überschuß (wieder) vorhanden, erfolgt keine Unterbrechnung (mehr). Zusätzlich wird über den Schlüssel &#039;&#039;&#039;swoffcond&#039;&#039;&#039; eine vorfristige Beendigung veranlasst, sobald die gewünschte Tageslaufzeit erreicht ist.&lt;br /&gt;
&lt;br /&gt;
Zur Verwaltung des Schlüssels &#039;&#039;interruptable&#039;&#039; und des Readings &#039;&#039;SF_Abort&#039;&#039; verwenden wir eine leicht veränderte Subroutine aus dem vorhergehenden Fallbeispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
#   Pumpensteuerung (einfügen in 99_mySolarForecastUtils.pm) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub pumpControl {&lt;br /&gt;
  my $name  = shift;&lt;br /&gt;
  my $c     = shift;                                                              # Nummer des Verbrauchers, z.B. 07&lt;br /&gt;
  my $mneed = shift;                                                              # Soll-Pumpenzeit, z.B. 300 (Minuten)&lt;br /&gt;
  &lt;br /&gt;
  $c            = sprintf &amp;quot;%02d&amp;quot;, $c;                                             # falls führende 0 vergessen wird&lt;br /&gt;
  my $pump      = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;name&#039;, &#039;&#039;);       # Devicename der Pumpe&lt;br /&gt;
  my $plstate   = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planstate&#039;, &#039;&#039;);&lt;br /&gt;
  my $intbl     = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;interruptable&#039;, 1); &lt;br /&gt;
  my $simpCstat = FHEM::SolarForecast::simplifyCstate ($plstate);                 # akt. Status des Consumers&lt;br /&gt;
  my $dhash     = $defs{$pump};&lt;br /&gt;
&lt;br /&gt;
  readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 0, 0);                                # default keine Zyklusbeendigung&lt;br /&gt;
&lt;br /&gt;
  if ($simpCstat =~ /started|interrupt|continu/xs) {                              # Vorgang ist gestartet&lt;br /&gt;
      my $t       = time;&lt;br /&gt;
      my $startts = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchon&#039;,  &#039;&#039;);&lt;br /&gt;
      my $stopts  = FHEM::SolarForecast::ConsumerVal ($name, $c, &#039;planswitchoff&#039;, &#039;&#039;);&lt;br /&gt;
      return if(!$startts || !$stopts);&lt;br /&gt;
      &lt;br /&gt;
      my $mrest = sprintf &#039;%.0f&#039;, (($stopts - $t) / 60);                         # Restlaufzeit (Minuten)      &lt;br /&gt;
      my $dt     = FHEM::SolarForecast::timestringsFromOffset ($startts, 0);&lt;br /&gt;
      my $day    = $dt-&amp;gt;{day};&lt;br /&gt;
      my $hstart = int $dt-&amp;gt;{hour} + 1;                                          # lfd. Stunde bei Pumpen Start &lt;br /&gt;
      my $msum   = 0;&lt;br /&gt;
	  &lt;br /&gt;
      for my $hod (1..24) {                                                      # bisherige Laufzeit der Pumpe&lt;br /&gt;
          next if($hod &amp;lt; $hstart);&lt;br /&gt;
          $hod = sprintf &amp;quot;%02d&amp;quot;, $hod;&lt;br /&gt;
          $msum += FHEM::SolarForecast::HistoryVal ($name, $day, $hod, &amp;quot;minutescsm${c}&amp;quot;, 0);&lt;br /&gt;
      }&lt;br /&gt;
     &lt;br /&gt;
      if ($msum &amp;gt;= $mneed) {&lt;br /&gt;
          readingsSingleUpdate ($dhash, &#039;SF_Abort&#039;, 1, 0);                       # vorfristige Zyklusbeendigung&lt;br /&gt;
          return;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if ($mrest &amp;gt;= ($mneed - $msum)) {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=1&amp;quot;) if(!$intbl);  # Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
      else {                        &lt;br /&gt;
          fhem (&amp;quot;set $name attrKeyVal consumer$c interruptable=0&amp;quot;) if($intbl);   # keine Interrupt-Freigabe&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Befehl &#039;&#039;attrKeyVal&#039;&#039; setzt den Schlüssel &#039;&#039;interruptable&#039;&#039; im Attribut &#039;&#039;consumer07&#039;&#039; dynamisch. Diese Strukturänderung wird automatisch im System gespeichert, sofern &#039;&#039;global-&amp;gt;autosave=1&#039;&#039; gesetzt ist. Diese Einstellung ist der FHEM default.  &lt;br /&gt;
&lt;br /&gt;
Damit die Routine mit jedem Zyklus im Modul ausgeführt wird, legen wir sie im Attribut &#039;&#039;&#039;ctrlUserExitFn&#039;&#039;&#039; an. Es werden der Name des SolarForecast-Devices, die Verbrauchernummer (07) und die Mindestlaufzeit der Umwälzpumpe (300 Minuten) übergeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr &amp;lt;Name&amp;gt; ctrlUserExitFn  {  &lt;br /&gt;
                               ::pumpControl ($name, &#039;07&#039;, 300);&lt;br /&gt;
                            }&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamische Ladestromsteuerung eines Victron MultiPlus II Chargers mit Pylontech Batterie ===&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;
&lt;br /&gt;
 set &amp;lt;Device&amp;gt; MaxChargeCurrent &amp;lt;Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
eingestellt bzw. variiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Modul bietet dem Nutzer die Möglichkeit in dem Attribut &#039;&#039;ctrlUserExitFn&#039;&#039; eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltene Code wird am Ende jedes Zyklus (siehe Attribut &#039;&#039;plantControl-&amp;gt;cycleInterval&#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;
&lt;br /&gt;
&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 $mppt1   = &#039;MQTT2_cerboGX_c0619ab34e08_solarcharger_Common&#039;;              # SmartLoader Device&lt;br /&gt;
  my $maxcspc = 105;                        # max. Ladesollstrom (A) nominal&lt;br /&gt;
  my $spcorr  = 0.9;                        # Korrekturfaktor Überschuss 90%&lt;br /&gt;
  my $sch     = 0.25;                       # Verkürzungsfaktor Zeit bis Vollladung vor Sunset             &lt;br /&gt;
  &lt;br /&gt;
  my $cclvl0  = 15;                         # Ladestrom Level 0 max. 5  A (240 W) pro WR  (720  W)&lt;br /&gt;
  my $cclvl1  = 27;                         # Ladestrom Level 1 max. 9  A (432 W) pro WR  (1296 W)&lt;br /&gt;
  my $cclvl2  = 54;                         # Ladestrom Level 2 max. 18 A (864 W) pro WR  (2592 W)&lt;br /&gt;
  my $cclvl3  = 81;                         # Ladestrom Level 3 max. 27 A (1296 W) pro WR (3888 W)&lt;br /&gt;
  ###############&lt;br /&gt;
  &lt;br /&gt;
  my $cofc   = ReadingsNum ($name,  &#039;special_todayConForecastTillSunset&#039;, 0);&lt;br /&gt;
  my $pvfc   = ReadingsNum ($name,  &#039;RestOfDayPVforecast&#039;, 0);&lt;br /&gt;
  my $cpv    = ReadingsNum ($name,  &#039;Current_PV&#039;,          0);&lt;br /&gt;
  my $mppt1c = ReadingsNum ($mppt1, &#039;DC_0_Current_value&#039;,  0);             # Load I MPPT1 (max. 44 A)&lt;br /&gt;
  my $ssts   = CurrentVal  ($hash,  &#039;sunsetTodayTs&#039;,        0);&lt;br /&gt;
  my $srts   = CurrentVal  ($hash,  &#039;sunriseTodayTs&#039;,       0);&lt;br /&gt;
  my $sdiff  = ($ssts - $srts) / 3600;                                     # Sonnengang heute in h &lt;br /&gt;
  &lt;br /&gt;
  my $solh   = ReadingsNum ($name, &#039;special_SunHours_Remain&#039;, 0);          # h bis SunSet&lt;br /&gt;
  $solh      = $solh - ($sdiff * $sch);                                    # h bis SunSet - X&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;              # Ah Bat bis SOC&lt;br /&gt;
  $ahrem     = sprintf &amp;quot;%.0f&amp;quot;, $ahrem;&lt;br /&gt;
  &lt;br /&gt;
  my $fcdiff = ($pvfc - $cofc) * $spcorr;     # Korrektur d. noch prognostizierten Überschussenergie &lt;br /&gt;
  $fcdiff    = $fcdiff &amp;lt; 0 ? 0 : $fcdiff;     # Wh&lt;br /&gt;
  &lt;br /&gt;
  my $loadcur = $maxcspc;&lt;br /&gt;
  &lt;br /&gt;
  if ($cpv &amp;amp;&amp;amp; $solh &amp;amp;&amp;amp; $ahrem &amp;amp;&amp;amp; $fcdiff &amp;gt; $ahrem) {  # Ladeanforderung und Überschuss übersteigt &lt;br /&gt;
                                                      # Lademenge&lt;br /&gt;
      my $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($ahrem / $solh);    # A = Ah / h -&amp;gt; A Soll Schätzung&lt;br /&gt;
&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Battery charging process should be completed }.&lt;br /&gt;
                      qq{in &amp;gt;$solh&amp;lt; hours});&lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; raw Target charging current: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $cspc = sprintf &amp;quot;%.2f&amp;quot;, ($cspc - $mppt1c);      # SmartLoader IST berücksichtigen&lt;br /&gt;
	  &lt;br /&gt;
      Log3 ($name, 3, qq{$name - userFn -&amp;gt; Charge Current minus MPPT load Current &amp;gt;$mppt1c&amp;lt;: $cspc});&lt;br /&gt;
	  &lt;br /&gt;
      $loadcur = $cspc &amp;lt;= 0       ? 0       :     # nur MPPT Ladung&lt;br /&gt;
                 $cspc &amp;lt;= $cclvl0 ? $cclvl0 :     # Übergangsbereich&lt;br /&gt;
                 $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;
	  Log3 ($name, 3, qq{$name - userFn -&amp;gt; MaxChargeCurrent calculated: $loadcur});&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_MaxChargeCurrent&#039;,       $loadcur.&#039; A&#039;,          1);&lt;br /&gt;
  readingsSingleUpdate ($hash, &#039;userFn_Bat_HoursUntilChargeFinish&#039;, sprintf (&amp;quot;%.2f&amp;quot;,$solh), 1);&lt;br /&gt;
  CommandSet           (undef, &amp;quot;$vebus MaxChargeCurrent $loadcur&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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. 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;special_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;special_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;Verkürzungsfaktor Zeit bis Vollladung vor Sunset&#039;&#039;) reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche mindest Ladestromstärke ermittelt.&lt;br /&gt;
&lt;br /&gt;
&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 auch während der MQTT Intergration 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;
=== Poolheizung in Abhängigkeit von vorhandenem Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren) ===&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;consumer01&#039;&#039; wird beispielhaft wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr Forecast consumer01 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;&lt;br /&gt;
&lt;br /&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. &lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
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, einen 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 Überschuss 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;. &lt;br /&gt;
&lt;br /&gt;
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;
=== PV-Vorhersage an evcc übertragen (PV-Überschussladen von E-Autos über steuerbare Wallboxen) ===&lt;br /&gt;
[https://evcc.io evcc] ist ein Energie-Management-System, mit dem u.a. Überschussladen von Elektroautos möglich ist. Hier ist beschreiben, wie die PV-Vorhersage von SolarForecast per API an evcc gesendet wird.&lt;br /&gt;
&lt;br /&gt;
Lege im SolarForecast-Device ein User-Reading mit dem Namen forecast_json an. Es wandelt die Forecast-Werte in JSON und ins UTC-Zeitformat um, so dass evcc die Daten verwenden kann:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
forecast_json {&lt;br /&gt;
&lt;br /&gt;
    use strict;&lt;br /&gt;
    use warnings;&lt;br /&gt;
    use JSON;&lt;br /&gt;
    use DateTime;&lt;br /&gt;
    use DateTime::Format::Strptime;&lt;br /&gt;
&lt;br /&gt;
    my $hour = 0;&lt;br /&gt;
    my @output;&lt;br /&gt;
&lt;br /&gt;
    # Parser für Datum mit CET/CEST&lt;br /&gt;
    my $parser = DateTime::Format::Strptime-&amp;gt;new(&lt;br /&gt;
        pattern   =&amp;gt; &#039;%Y-%m-%d %H:%M:%S&#039;,&lt;br /&gt;
        time_zone =&amp;gt; &#039;Europe/Berlin&#039;,&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    # Alle NextHour-Daten durchsuchen&lt;br /&gt;
    while ($hour &amp;lt; 100) {&lt;br /&gt;
        my $hour_str = sprintf(&#039;NextHour%02d&#039;, $hour);&lt;br /&gt;
        my $start_str = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;starttime&#039;, &#039;na&#039;); &lt;br /&gt;
        my $pvfc = FHEM::SolarForecast::NexthoursVal (&#039;sol.forecast_ai&#039;, $hour_str, &#039;pvfc&#039;, &#039;na&#039;);&lt;br /&gt;
&lt;br /&gt;
        # Schleife beenden, wenn keine Werte mehr vorhanden sind&lt;br /&gt;
        last if $start_str eq &#039;na&#039; or $pvfc eq &#039;na&#039;;&lt;br /&gt;
&lt;br /&gt;
        # parse und konvertiere Zeit&lt;br /&gt;
        my $start_dt = $parser-&amp;gt;parse_datetime($start_str);&lt;br /&gt;
        my $end_dt   = $start_dt-&amp;gt;clone-&amp;gt;add(hours =&amp;gt; 1);&lt;br /&gt;
&lt;br /&gt;
        # nach UTC konvertieren&lt;br /&gt;
        $start_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
        $end_dt-&amp;gt;set_time_zone(&#039;UTC&#039;);&lt;br /&gt;
&lt;br /&gt;
        push @output, {&lt;br /&gt;
            start =&amp;gt; $start_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            end   =&amp;gt; $end_dt-&amp;gt;iso8601() . &#039;Z&#039;,&lt;br /&gt;
            value =&amp;gt; 0 + $pvfc,&lt;br /&gt;
        };&lt;br /&gt;
        &lt;br /&gt;
        $hour++;&lt;br /&gt;
    }  &lt;br /&gt;
&lt;br /&gt;
    # Ausgabe als JSON&lt;br /&gt;
    my $json = JSON-&amp;gt;new-&amp;gt;utf8-&amp;gt;pretty-&amp;gt;encode(\@output);&lt;br /&gt;
    return $json;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Die Kommunikation von FHEM zu evcc läuft über den integrierten FHEM-Webserver, der die JSON-Daten aus dem Reading forecast_json veröffentlicht. Dazu wird in FHEM eine separate Webinstanz auf einem neuen Port erstellt, die ohne [[CsrfToken-HowTo|CSFR-Token]] (Achtung, Auswirkungen auf die Sicherheit beachten!) und nur von localhost aufrufbar ist (Voraussetzung: evcc läuft auf derselben Maschine wie FHEM):&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
defmod WEBapi FHEMWEB 8089&lt;br /&gt;
attr WEBapi csrfToken none&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;In der [https://docs.evcc.io/docs/tariffs#pv-vorhersage evcc-Konfig unter tariffs] steht die Quelle für die Solar-Vorhersage. Der FHEM-Befehl {ReadingsVal(&#039;solarforecast_dev&#039;,&#039;forecast_json&#039;,&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;)} wird dazu encoded und in die uri eingetragen. Trage statt solarforecast_dev den passenden Namen des SolarForecast-Device ein.&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
solar:&lt;br /&gt;
  type: custom&lt;br /&gt;
  interval: 2m    &lt;br /&gt;
  forecast:&lt;br /&gt;
    source: http&lt;br /&gt;
    uri: http://localhost:8089/fhem?cmd=%7BReadingsVal%28%27solarforecast_dev%27%2C%27forecast_json%27%2C%27%27%29%7D&amp;amp;XHR=1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Zur Verbesserung der Sicherheit kann das neue WEBapi Device auch ein [[CsrfToken-HowTo#csrfToken festlegen|festes CSFR-Token]] verwenden. Dieses Token muss dann in der evcc-Konfiguration an die uri mittels &amp;amp;fwcsrf=&amp;lt;festes token&amp;gt; angehängt werden.&lt;br /&gt;
&lt;br /&gt;
== weiterführende Links ==&lt;br /&gt;
* Forenthema &amp;quot;{{Link2Forum|Topic=137058|LinkText=76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support}}&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;
* Photovoltaik Ingenieurbüro Junge: https://www.ing-büro-junge.de/html/photovoltaik.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Energieerzeugungsmessung]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Statistics&amp;diff=39062</id>
		<title>Statistics</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Statistics&amp;diff=39062"/>
		<updated>2024-01-30T19:10:39Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: set setStatistics hinzugefügt (vgl. https://forum.fhem.de/index.php?msg=1274253)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{SEITENTITEL:statistics}} &lt;br /&gt;
&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Erzeugung von Verbrauchs-, und Wetterstatistiken&lt;br /&gt;
|ModType=h&lt;br /&gt;
|ModCmdRef=statistics&lt;br /&gt;
|ModForumArea=Unterstützende Dienste&lt;br /&gt;
|ModTechName=98_statistics.pm&lt;br /&gt;
|ModOwner=tupol ({{Link2FU|5432|Forum}})&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Das Modul statistics ist zur Erzeugung von diversen Statistiken gedacht. Es muss nur einmal definiert werden und kann mithilfe von Regexp auf beliebig viele Devices angewendet werden. Die Ergebnisse dieser Statistiken werden nicht im Modul selbst dargestellt, sondern den jeweiligen Devices als zusätzliches Reading hinzugefügt. &lt;br /&gt;
&lt;br /&gt;
== define == &lt;br /&gt;
&lt;br /&gt;
Bei der Definition werden die gewünschten Geräte angegeben, von denen das Modul Statistiken bilden soll. &lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define myStatDevice statistics Wetterstation|Stromzaehler|Thermometer_.* &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Optional ist noch die Angabe eines Prefixes möglich, wenn man nicht möchte, dass die Reading stat&amp;lt;ReadingName&amp;gt; heissen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Attribute ==&lt;br /&gt;
&lt;br /&gt;
Die Attribute sind soweit gut in der {{Link2CmdRef|Anker=statisticsattr}} dokumentiert.&lt;br /&gt;
&lt;br /&gt;
=== singularReadings === &lt;br /&gt;
Bei Verwendung von singularReadings ist darauf zu achten, dass für das entsprechende Device die entsprechende Statistik entweder durch die standardmäßig vorgegebenen Gerätewerte oder durch durationReadings,deltaReadings,minAvgMaxReadings oder tendencyReadings definiert ist. Anderenfalls werden die singularReadings weder angelegt, noch mit Daten gefüllt.&lt;br /&gt;
Um vom Reading Stromzaehler:total_energy singularReadings anzulegen, muss folgendes definiert werden. Dabei ist darauf zu achten, dass bei singularReadings an keiner Stelle ein Leerzeichen steht:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;attr myStatDevice deltaReadings total_energy&lt;br /&gt;
attr myStatDevice singularReadings Stromzaehler:total_energy:Delta:Hour|Stromzaehler:total_energy:Delta:Day|Stromzaehler:total_energy:Delta:Month|Stromzaehler:total_energy:Delta:Year&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ignoreDefaultAssignments ===&lt;br /&gt;
Mit diesem Attribut kann die Erkennung und Verwendung der standardmäßig eingebauten Readings unterdrückt werden. Zur Funktion ist es in diesem Fall notwendig, selbst Readings zu definieren.&lt;br /&gt;
&lt;br /&gt;
=== tendencyReadings  ===&lt;br /&gt;
Dieses Attribut erwartet eine durch Kommas getrennte Liste von weiteren Gerätewerten, für die innerhalb bestimmter Zeiträume (1h, 2h, 3h, 6h) die Differenz zwischen Anfangs- und Endwert ermittelt wird. Eine Kombination mit dem Attribut &amp;lt;code&amp;gt;minAvgMaxReadings&amp;lt;/code&amp;gt; der gleichen Gerätewerte führt dazu, dass diese Readings nicht aktualisiert bzw. erstellt werden. Möchte man jedoch sowohl den Trend als auch die avg/min/max Werte für die gleichen Gerätewerte verwenden (z.B. für Temperatur / Druck), kann dies durch die Verwendung einer zweiten &amp;quot;statistics&amp;quot; Instanz &lt;br /&gt;
umgangen werden.&lt;br /&gt;
&lt;br /&gt;
== Gerätewerte (Readings) ==&lt;br /&gt;
=== monitoredDevicesUnsupported ===&lt;br /&gt;
Listet Geräte, die vom statistics-Modul aufgrund des Namens bearbeitet werden, aber keine Readings enthalten, die statistisch ausgewertet werden können. In diesem Fall müssen die entsprechenden Readings per &#039;&#039;durationReadings&#039;&#039;, &#039;&#039;deltaReadings&#039;&#039;, &#039;&#039;tendencyReadings&#039;&#039; oder &#039;&#039;minAvgMaxReadings&#039;&#039; angelegt werden.&lt;br /&gt;
&lt;br /&gt;
=== monitoredDevicesUnknown ===&lt;br /&gt;
Listet Geräte, für welches das statistics-Modul zwar statistische Daten vorhält, die aber nicht mehr in der Geräteliste (per RegExp der Modul-Definition) gefunden wurden. Dies kann z.B. durch eine Änderung des Gerätenamens, Wegfall des Gerätes oder Änderung der Definition des statistics-Moduls passiert sein.&lt;br /&gt;
&lt;br /&gt;
Wenn die statistischen Daten nicht mehr benötigt werden, können sie gelöscht werden mit:&lt;br /&gt;
 set &amp;lt;device&amp;gt; &#039;&#039;&#039;resetStatistics&#039;&#039;&#039; &amp;lt;Gerätename&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Falls ein Statistik-Wert geändert werden soll (z.B. weil das Statistics-Modul erst später hinzugefügt wurde und deshalb zu wenig anzeigt), geht das so:&lt;br /&gt;
 set &amp;lt;device&amp;gt; &#039;&#039;&#039;setStatistics&#039;&#039;&#039; &amp;lt;Gerätename dessen Statistik geändert werden soll&amp;gt; &amp;lt;Reading-Name dessen Statistik geändert werden soll (ohne stat)&amp;gt; &amp;lt;Hour|Day|Month|Year&amp;gt; &amp;lt;neuer Wert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Fehlersuche ==&lt;br /&gt;
&lt;br /&gt;
=== Löschen der erzeugten statistischen Readings ===&lt;br /&gt;
Durch das Modul erzeugte Readings können durch den FHEM-Befehl &lt;br /&gt;
&amp;lt;code&amp;gt;deleteReading &amp;amp;lt;device&amp;amp;gt; &amp;amp;lt;reading&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
wieder entfernt werden.&lt;br /&gt;
&lt;br /&gt;
=== Events, Logs ===&lt;br /&gt;
Das Modul löst beim Schreiben der Last-Readings und der singularReadings jeweils ein Update-Event aus, welches auch zum Loggen dieser Werte genutzt werden kann. Wenn für die Geräte die event-on-Attribute nicht gesetzt sind, kann dies zu unerwünschten Nebenwirkungen führen. Z. B. bei den userreadings.&lt;br /&gt;
&lt;br /&gt;
Die Aktualisierung der normalen statistischen Summary-Readings führt nicht zu einem Event, um die Systembelastung niedrig zu halten.&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Chart&amp;diff=31355</id>
		<title>FTUI Widget Chart</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Chart&amp;diff=31355"/>
		<updated>2019-10-15T18:06:39Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Standardwert bei data-legendpos war vertauscht&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Chart Widget]] ist ein Widget für [[FHEM Tablet UI]], mit dem sich verschiedenste Diagramme darstellen lassen. Die Aneinanderreihung mehrerer Werte eines Device-Readings zu einem zeitlichen Verlauf wird dabei als Graph bezeichnet.&lt;br /&gt;
&lt;br /&gt;
Es können beliebige Werte dargestellt und entsprechend der Sinnhaftigkeit, oder persönlichem Geschmack, formatiert werden. Farbe und Form der Linien sind je Graph einstellbar, auch wenn mehrere gleichzeitig in einem Diagramm angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
Jedes Diagramm kann zwei Y-Achsen besitzen. Die primäre Y-Achse (primary) wird auf der linken Seite angezeigt, die sekundäre Y-Achse (secondary) auf der rechten Seite. Beide Achsen können unterschiedlich formatiert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Chart_tabletUI.png&lt;br /&gt;
Datei:FTUI Widget Chart Stacked.png&lt;br /&gt;
Datei:FTUI Widget Chart-fc-Proplanta.png&lt;br /&gt;
Datei:Wetterchart2.png&lt;br /&gt;
Datei:PieChart.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:150px&amp;quot;|Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-device&#039;&#039;&#039;||Name des FHEM-Device, das die Aktualisierung des Charts triggert||||data-device=&amp;quot;WohnzimmerHeizung&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get&#039;&#039;&#039;||Reading, das das Update des Diagramms triggert||&#039;STATE&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-logdevice&#039;&#039;&#039;||Name des Log-Device, das dargestellt werden soll, oder ein Array, um mehrere Werte in einem Diagramm darzustellen||||data-logdevice=&amp;quot;FileLog_WohnzimmerHeizung&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-logfile&#039;&#039;&#039;|| Name des Log-Files, aus dem die Daten entnommen werden sollen (oder Array)||&#039;-&#039; = aktuelle Datei||data-logfile=&amp;quot;WohnzimmerHeizung-2015.log&amp;quot;&amp;lt;br&amp;gt;Beachte: Der Wert &amp;quot;CURRENT&amp;quot; ermöglicht die Navigation auch zu älterne Logfiles (Jahreswechsel)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-columnspec&#039;&#039;&#039;||Ermittelt den Wert aus dem Log-File, der angezeigt werden soll (oder Array)||||data-columnspec=&amp;quot;4:meas.*&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-style&#039;&#039;&#039;||Stil, wie die Graph-Linien dargestellt werden sollen (z.B. &#039;SVGplot l0&#039; oder &#039;ftui l0dash&#039;), oder ein Array, wenn mehrere Linien unterschiedlich dargestellt werden sollen (siehe [[#Aussehen_der_Linien|Hinweise]])||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-ptype&#039;&#039;&#039;||Form, wie die Graphen dargestellt werden sollen (z.B. &#039;lines&#039;, &#039;cubic&#039; oder &#039;fa-cog&#039;), oder ein Array (siehe [[#Form_der_Linien|Hinweise]])||&#039;lines&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-uaxis&#039;&#039;&#039;||Name der Achse, die verwendet werden soll (&#039;primary&#039; = links, oder &#039;secondary&#039; = rechts), oder ein Array||&#039;primary&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-legend&#039;&#039;&#039;||Bezeichnung des Graphen (wird in Legende und am Cursor angezeigt), oder ein Array||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-minvalue&#039;&#039;&#039;||Minimaler Wert, der auf der linken Y-Achse (&#039;primary&#039;) angezeigt werden soll. &#039;auto&#039; = automatische Berechnung||&#039;10&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-maxvalue&#039;&#039;&#039;||Maximaler Wert, der auf der linken Y-Achse (&#039;primary&#039;) angezeigt werden soll. &#039;auto&#039; = automatische Berechnung||&#039;30&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-minvalue_sec&#039;&#039;&#039;||Minimaler Wert, der auf der rechten Y-Achse (&#039;secondary&#039;) angezeigt werden soll. &#039;auto&#039; = automatische Berechnung||&#039;auto&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-maxvalue_sec&#039;&#039;&#039;||Maximaler Wert, der auf der rechten Y-Achse (&#039;secondary&#039;) angezeigt werden soll. &#039;auto&#039; = automatische Berechnung||&#039;auto&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-xticks&#039;&#039;&#039;||Abstand zwischen den vertikalen Hilfslinien (bezogen auf die X-Achse) in Minuten. &#039;auto&#039; = automatische Berechnung||&#039;auto&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yticks&#039;&#039;&#039;||Abstand zwischen den horizontalen Hilfslinien (bezogen auf die linke Y-Achse). Kann auch ein Array mit Werte-Paaren enthalten, um die Linien mit Text zu beschriften.||&#039;auto&#039;||data-yticks=&#039;[[0,&amp;quot;open&amp;quot;],[1,&amp;quot;closed&amp;quot;]]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yticks_format&#039;&#039;&#039;||Dient zur Formatierung der Ticks der Y-Achse. Die Formatierung geschieht über Platzhalter, Trenner und einen beliebigen durch &#039; &#039; getrennten Text. Als Platzhalter dient ein oder mehrere &#039;#&#039;, als Trenner können &#039;.&#039;, &#039;,&#039; und &#039;:&#039; verwendet werden. Ist ein Trenner enthalten (z.B. &#039;#.##&#039;) dann bedeutet das in dem Beispiel, dass der Ytick mit 2 Nachkommastellen versehen wird und vorne Platz für eine Stelle vor dem Komma vorgehalten wird (führende Nullen werden nicht dargestellt, aber de Platz wird reserviert so dass das ganze rechtsbündig immer passt). Ist kein Trenner vorhanden, dann wird der Ytick auf die Summe der Platzhalter mit einer festen Gesamtbreite gesetzt (#### würde also bedeuten, dass immer 4 Stellen (ohne Trenner) verwendet werden. aus 0.4 würde 0.400 aus 10.437 würde 10.44). Als Trenner kann man z.B. für Zeiten auch einen &#039;:&#039; verwenden und dadurch auch so etwas wie &amp;quot;12:00 Uhr&amp;quot; realisieren (in dem Beispiel wäre data-yticks_format=&amp;quot;##:## Uhr&amp;quot; und kein data-yunit oder data-yticks=&amp;quot;##:##&amp;quot; und data-yunit=&amp;quot;Uhr&amp;quot;).||||data-yticks_format=&amp;quot;#.##&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yticks_sec&#039;&#039;&#039;||Abstand zwischen den horizontalen Hilfslinien (bezogen auf die rechte Y-Achse). Kann auch ein Array mit Werte-Paaren enthalten, um die Linien mit Text zu beschriften.||&#039;auto&#039;||data-yticks=&#039;[[0,&amp;quot;open&amp;quot;],[1,&amp;quot;closed&amp;quot;]]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yticks_format_sec&#039;&#039;&#039;||Dient zur Formatierung der Ticks der Y-Achse. Die Formatierung geschieht über Platzhalter, Trenner und einen beliebigen durch &#039; &#039; getrennten Text. Als Platzhalter dient ein oder mehrere &#039;#&#039;, als Trenner können &#039;.&#039;, &#039;,&#039; und &#039;:&#039; verwendet werden. Ist ein Trenner enthalten (z.B. &#039;#.##&#039;) dann bedeutet das in dem Beispiel, dass der Ytick mit 2 Nachkommastellen versehen wird und vorne Platz für eine Stelle vor dem Komma vorgehalten wird (führende Nullen werden nicht dargestellt, aber de Platz wird reserviert so dass das ganze rechtsbündig immer passt). Ist kein Trenner vorhanden, dann wird der Ytick auf die Summe der Platzhalter mit einer festen Gesamtbreite gesetzt (#### würde also bedeuten, dass immer 4 Stellen (ohne Trenner) verwendet werden. aus 0.4 würde 0.400 aus 10.437 würde 10.44). Als Trenner kann man z.B. für Zeiten auch einen &#039;:&#039; verwenden und dadurch auch so etwas wie &amp;quot;12:00 Uhr&amp;quot; realisieren (in dem Beispiel wäre data-yticks_format=&amp;quot;##:## Uhr&amp;quot; und kein data-yunit oder data-yticks=&amp;quot;##:##&amp;quot; und data-yunit=&amp;quot;Uhr&amp;quot;).||||data-yticks_format_sec=&amp;quot;#.##&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yticks_prio&#039;&#039;&#039;||Legt fest, ob die horizontalen Hilfslinien der linken (primary) oder der rechten (secondary) Y-Achse zugeordnet werden sollen||||data-yticks_prio=&#039;secondary&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-ytype&#039;&#039;&#039;||Legt fest, ob die primäre y Achse logarithmisch sein soll (wert &amp;quot;log&amp;quot;)||||data-ytype=&amp;quot;log&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-ytype_sec&#039;&#039;&#039;||Legt fest, ob die sekundäre y Achse logarithmisch sein soll (wert &amp;quot;log&amp;quot;)||||data-ytype_sec=&amp;quot;log&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-y_margin&#039;&#039;&#039;|||Gibt die Möglichkeit, Abstände zwischen den Graphen und dem oberen Rand des Plots zu definieren (Einheit Pixel). Falls der Wert skalar ist, werden oben und unten die gleichen Abstände eingehalten. Falls ein 2D Array angegeben wird, können die Werte unten (erster Wert im Array) und oben (zweiter Wert im Array) getrennt festgelegt werden||&amp;quot;0&amp;quot;|||data-y_margin=&#039;[&amp;quot;10&amp;quot;,&amp;quot;20&amp;quot;]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-y_margin_sec&#039;&#039;&#039;|||Gibt die Möglichkeit, Abstände zwischen den Graphen und dem oberen Rand des Plots zu definieren (Einheit Pixel). Falls der Wert skalar ist, werden oben und unten die gleichen Abstände eingehalten. Falls ein 2D Array angegeben wird, können die Werte unten (erster Wert im Array) und oben (zweiter Wert im Array) getrennt festgelegt werden||&amp;quot;0&amp;quot;|||data-y_margin=&#039;[&amp;quot;10&amp;quot;,&amp;quot;20&amp;quot;]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-daysago_start&#039;&#039;&#039;||Anzahl der vergangenen Tage, wo das Diagramm beginnen soll. &#039;0&#039; = Beginn heute 0:00 Uhr. (siehe [[#Zeitstrahl_.2F_Start_.26_Ende_auf_der_X-Achse|Hinweise]])||&#039;0&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-daysago_end&#039;&#039;&#039;||Anzahl der vergangenen Tage, wo das Diagramm enden soll. &#039;-1&#039; = Ende heute 24:00 Uhr. (siehe [[#Zeitstrahl_.2F_Start_.26_Ende_auf_der_X-Achse|Hinweise]])||&#039;-1&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-xticks_round&#039;&#039;&#039;||Wenn vorhanden und entweder &#039;h&#039;, &#039;d&#039;, &#039;w&#039;, wird auf Stunde, Tag oder Woche bei den xticks gerundet (also die Tickmarks und die Gridlines bei den entsprechend gerundeten Zeiten gesetzt). Es kann auch &#039;auto&#039; angegeben werden, um eine autmoatische Rundung durchzuführen||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-nofulldays&#039;&#039;&#039;||Aktiviert/deaktiviert die Rundung der X-Achse auf ganze Tage. Binärwert (&#039;true&#039; oder &#039;false&#039;)||&#039;false&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-timeformat&#039;&#039;&#039;||Zeitformat für die Anzeige an der X-Achse (siehe [[#Zeitformat_der_X-Achse|Hinweise]])||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-timeranges&#039;&#039;&#039;||Hierdurch können vordefinierte Zeiträume für die X-Achse festgelegt werden, die dann durch eine pulldown menu (neuer Button oben neben dem &amp;quot;-&amp;quot; Button) direkt ausgewählt werden können. Der Parameter ist ein Array aus Array Einträgen, welche jeweils [&amp;lt;Name&amp;gt;,&amp;lt;daysago_start&amp;gt;,&amp;lt;daysago_end&amp;gt;] enthalten)||&lt;br /&gt;
||data-timeranges=&#039;[&amp;lt;br&amp;gt;&lt;br /&gt;
[&amp;quot;Actual Year&amp;quot;,&amp;quot;0Y&amp;quot;,&amp;quot;-1Y&amp;quot;],&amp;lt;br&amp;gt;&lt;br /&gt;
[&amp;quot;Last Year&amp;quot;,&amp;quot;1Y&amp;quot;,&amp;quot;0Y&amp;quot;],&amp;lt;br&amp;gt;&lt;br /&gt;
[&amp;quot;Actual Month&amp;quot;,&amp;quot;0M&amp;quot;,&amp;quot;-1M&amp;quot;],&amp;lt;br&amp;gt;&lt;br /&gt;
[&amp;quot;Last Month&amp;quot;,&amp;quot;1M&amp;quot;,&amp;quot;0M&amp;quot;],&amp;lt;br&amp;gt;&lt;br /&gt;
[&amp;quot;Actual Week&amp;quot;,&amp;quot;0W&amp;quot;,&amp;quot;-1W&amp;quot;],&amp;lt;br&amp;gt;&lt;br /&gt;
[&amp;quot;Last Week&amp;quot;,&amp;quot;1W&amp;quot;,&amp;quot;0W&amp;quot;],&amp;lt;br&amp;gt;&lt;br /&gt;
[&amp;quot;Today&amp;quot;,&amp;quot;0D&amp;quot;,&amp;quot;-1D&amp;quot;],&amp;lt;br&amp;gt;&lt;br /&gt;
[&amp;quot;Yesterday&amp;quot;,&amp;quot;1D&amp;quot;,&amp;quot;0D&amp;quot;]&amp;lt;br&amp;gt;&lt;br /&gt;
]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-ytext&#039;&#039;&#039;||Text, der neben der linken Y-Achse angezeigt wird||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-ytext_sec&#039;&#039;&#039;||Text, der neben der rechten Y-Achse angezeigt wird||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yunit&#039;&#039;&#039;||Einheit, die an der linken Y-Achse angezeigt wird||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yunit_sec&#039;&#039;&#039;||Einheit, die an der rechten Y-Achse angezeigt wird||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-show_both_axes&#039;&#039;&#039;||Legt fest ob beide Y-Achsen Linien gezeichnet werden sollen||false||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-crosshair&#039;&#039;&#039;||Aktiviert/deaktiviert den Fadenkreuz-Cursor. Binärwert (&#039;true&#039; oder &#039;false&#039;)||&#039;false&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-cursorgroup&#039;&#039;&#039;||Zahl zur Gruppierung der Werte am Fadenkreuz-Cursor ([[#Fadenkreuz-Cursor|Hinweise]])||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-scrollgroup&#039;&#039;&#039;||Zahl zur Gruppierung der Graphen beim Bewegen und Zoomen. Alle Linien mit der selben Zahl werden miteinander gekoppelt und bewegen sich gemeinsam.||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-showlegend&#039;&#039;&#039;||Aktiviert/deaktiviert die Anzeige der Legene. Binärwert (&#039;true&#039; oder &#039;false&#039;)||&#039;false&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-legendpos&#039;&#039;&#039;||Array von zwei Werten, die die horizontale und vertikale Position der Legende festlegen ([[#Legende|Hinweise]])||&#039;[&amp;quot;right&amp;quot;,&amp;quot;top&amp;quot;]&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-legend_horiz&#039;&#039;&#039;||legt fest, dass die Legendeneinträge horizontal angeordnet sind (anstatt vertikal wie im default Fall)||false||data-legend_horiz=&amp;quot;true&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-width&#039;&#039;&#039;||Breite des Diagramms (in % oder px)||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-height&#039;&#039;&#039;||Höhe des Diagramms (in % oder px)||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-graphsshown&#039;&#039;&#039;||Aktiviert/deaktiviert die initiale Anzeige von Graphen. Binärwert (&#039;true&#039; oder &#039;false&#039;). Array, wenn mehrere Linien angezeigt werden sollen.||||data-graphsshown=&#039;[true,false,true]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-ddd&#039;&#039;&#039;||Einstellung für die 3D-Drehung ([[#3-dimensionale_Drehung|Hinweise]])||||data-ddd=&#039;[&amp;quot;40&amp;quot;,&amp;quot;60&amp;quot;,&amp;quot;0&amp;quot;]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-dddspace&#039;&#039;&#039;||Abstand zwischen zwei Graphen, wenn die 3D-Anzeige aktiviert wurde (px)||&#039;15&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-dddwidth&#039;&#039;&#039;||Breite, bzw. Tiefe der Graphen, wenn diese 3-dimensional angezeigt werden (px)||&#039;10&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-title&#039;&#039;&#039;||Titel, der über dem Diagramm angezeigt werden soll. Der Inhalt kann auch dynamisch erzeugt werden ([[#Diagrammtitel|Hinweise]])||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-title_class&#039;&#039;&#039;||Klassenname für die Formatierung des Titels. Die Eigenschaften müssen dann entsprechend in einem CSS File angegeben werden (z.B. in fhem-tablet-ui-user.css)||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-prefetch&#039;&#039;&#039;||Legt fest, ob zusätzliche Daten rechts und links des Plots im Hintergrund vom Server geholt werden sollen||false||data-prefetch=&amp;quot;true&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
Einige Parameter (style, maxvalue, minvalue, maxvalue_sec, minvalue_sec) können auch aus Readings dynamisch gesetzt werden wenn &amp;quot;&amp;lt;device&amp;gt;:&amp;lt;reading&amp;gt;&amp;quot; als Parameter gesetzt wird. Damit kann man z.B. in FHEM über notify etc. die Linientypen dynamisch anpassen (z.B. wenn der Wert eines Devices in einem bestimmten Bereich liegt, ändert sich die Farbe des Graphen).&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|fullsize}}{{FTUI Klasse|noticks}}{{FTUI Klasse|nobuttons}}{{FTUI Klasse|small}}{{FTUI Klasse|normal}}{{FTUI Klasse|big}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Folgende Widget-spezifsche Klassen können zusätzlich in einer eigenen CSS-Datei definiert werden:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Klasse&lt;br /&gt;
!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;chart-background&#039;&#039;&#039;||Hintergrundfarbe des Diagramms&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;buttons&#039;&#039;&#039;||Größe und Farbe der Buttons&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;text.axes&#039;&#039;&#039;||Generelle Schriftart und Farbe der Achsen&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;gridlines&#039;&#039;&#039;||Generelle Farbe und Größe der Gitternetzlinien&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;xaxis&#039;&#039;&#039;||Schriftart, Größe und Farbe der X-Achse&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;yaxis&#039;&#039;&#039;||Schriftart, Größe und Farbe der Y-Achse&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;xticks&#039;&#039;&#039;||Schriftart, Größe und Farbe der X-Achse (Zwischenlinien)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;yticks&#039;&#039;&#039;||Schriftart, Größe und Farbe der Y-Achse (Zwischenlinien)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;crosshair&#039;&#039;&#039;||Schriftart, Größe und Vordergrund/Hintergrundfarbe der Momentanwerte am Fadenkreuzcursor&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;caption&#039;&#039;&#039;||Schriftart, Größe und Farbe der Text-Buttons für Legende und Cursor&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;legend&#039;&#039;&#039;||Schriftart, Größe und Farbe der Legende&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die Standardwerte sind in der Datei &amp;lt;code&amp;gt;css/ftui_chart.css&amp;lt;/code&amp;gt; zu finden.&lt;br /&gt;
&lt;br /&gt;
==Datenquellen==&lt;br /&gt;
Beim Chart-Widget können die gleichen Datenquellen genutzt werden, die auch für SVG-Plots verwendet werden können:&lt;br /&gt;
# [[FileLog]]: Verlaufsdaten einer Textdatei entnehmen&lt;br /&gt;
# [[DbLog]]: Verlaufsdaten einer Datenbank entnehmen&lt;br /&gt;
# [[LogProxy]]: Daten dynamisch berechnet&lt;br /&gt;
&lt;br /&gt;
===FileLog===&lt;br /&gt;
Um [[FileLog]] zu nutzen, wird als &#039;&#039;&#039;data-logdevice&#039;&#039;&#039; das FHEM-Device für das FileLog angegeben. In der Regel entstehen hier im Laufe der Zeit mehrere Log-Dateien. Name und Anzahl sind von der Definition abhängig - meist wird jeden Monat oder jedes Jahr eine neue Datei angelegt. Die gewünschte Datei kann mit &#039;&#039;&#039;data-logfile&#039;&#039;&#039; ausgewählt werden. Möchte man stets die aktuelle Datei verwenden (macht vor allem dann Sinn, wenn man die neusten Daten anzeigen will), kann das Attribut weggelassen, oder explizit &amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt; eingetragen werden. Zuletzt wird &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; benötigt, um die gewünschten Daten zu in der Logdatei zu identifizieren. Hier wird die Spalte, in der die Daten stehen, gefolgt von Doppelpunkt und Readingname angegeben.&lt;br /&gt;
&lt;br /&gt;
Für ein Heizungsthermostat von Homematic mit dem Namen &#039;&#039;DG.wz.HZ.Heizungsventil&#039;&#039; ergibt sich somit beispielhaft folgende Definition, um gemessene Temperatur, Sollwert und Ventilstellung im Diagramm darzustellen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	 data-device=&amp;quot;DG.wz.HZ.Heizungsventil&amp;quot;&lt;br /&gt;
	 data-logdevice=&amp;quot;FileLog_DG.wz.HZ.Heizungsventil&amp;quot;&lt;br /&gt;
	 data-logfile=&amp;quot;-&amp;quot;&lt;br /&gt;
	 data-columnspec=&#039;[&amp;quot;4:measured-temp&amp;quot;,&amp;quot;4:desired-temp&amp;quot;,&amp;quot;4:actuator&amp;quot;]&#039;&lt;br /&gt;
	 ...&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollen Daten von unterschiedlichen Geräten in einem Diagramm angezeigt werden, muss &#039;&#039;&#039;data-logdevice&#039;&#039;&#039; als Array nach dem Schema &amp;lt;code&amp;gt;data-logdevice=&#039;[&amp;quot;&amp;lt;Logdatei_1&amp;gt;&amp;quot;,&amp;quot;&amp;lt;Logdatei_2&amp;gt;&amp;quot;,&amp;quot;&amp;lt;Logdatei_3&amp;gt;&amp;quot;]&#039;&amp;lt;/code&amp;gt; definiert werden. Für jeden Eintrag in &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; muss es auch den passenden Eintrag in &#039;&#039;&#039;data-logdevice&#039;&#039;&#039; geben (auch die Reihenfolge ist relevant).&lt;br /&gt;
&lt;br /&gt;
===DbLog===&lt;br /&gt;
Um die Daten aus [[DbLog]] anzeigen zu können, werden die gleichen Attribute verwendet und mit für die Datenbank angepassten Werten beschrieben. Bei &#039;&#039;&#039;data-logdevice&#039;&#039;&#039; das FHEM-Device für die Datenbank angegeben. Im nachfolgenden Beispiel heißt diese &amp;lt;code&amp;gt;logdb&amp;lt;/code&amp;gt; und besitzt wie üblich zwei Tabellen: &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;history&amp;lt;/code&amp;gt; (der zeitliche Verlauf liegt in letzterer). Der Tabellenname wird bei &#039;&#039;&#039;data-logfile&#039;&#039;&#039; eingetragen. Da die Daten in der Datenbank etwas anders abgelegt werden, muss auch &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; entsprechend angepasst werden. Statt der Spalte wird hier das FHEM-Device, gefolgt von Doppelpunkt und Readingname angegeben.&lt;br /&gt;
&lt;br /&gt;
Für das oben beschriebene Homematic-Heizungsthermostat ergibt sich dann folgende Definition, um die gleichen Daten aus einer Datenbank, statt einem LogFile zu lesen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	 data-device=&amp;quot;DG.wz.HZ.Heizungsventil&amp;quot;&lt;br /&gt;
         data-get=&amp;quot;measured-temp&amp;quot;&lt;br /&gt;
         data-style=&#039;[&amp;quot;ftui l0&amp;quot;]&#039;&lt;br /&gt;
	 data-logdevice=&amp;quot;logdb&amp;quot;&lt;br /&gt;
	 data-logfile=&amp;quot;HISTORY&amp;quot;&lt;br /&gt;
	 data-columnspec=&#039;[&amp;quot;DG.wz.HZ.Heizungsventil:measured-temp&amp;quot;,&amp;quot;DG.wz.HZ.Heizungsventil:desired-temp&amp;quot;,&amp;quot;DG.wz.HZ.Heizungsventil:actuator&amp;quot;]&#039;&lt;br /&gt;
	 ...&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für die Anzeige von unterschiedlichen Geräten in einem Diagramm, muss nur &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; entsprechend angepasst werden, solange sich alle Daten in der Datenbank befinden.&lt;br /&gt;
&lt;br /&gt;
===LogProxy===&lt;br /&gt;
Um die Daten mittels [[LogProxy]] berechnen und anzeigen zu können, muss in FHEM ein LogProxy-Device definiert sein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define myLogProxy logProxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Einstellungen am LogProxy sind nicht nötig, die bloße Existenz reicht.&lt;br /&gt;
&lt;br /&gt;
Bei &#039;&#039;&#039;data-logdevice&#039;&#039;&#039; wird das FHEM-Device für den LogProxy angegeben. Im nachfolgenden Beispiel heißt dieses &amp;lt;code&amp;gt;myLogProxy&amp;lt;/code&amp;gt;. Das Attribut &#039;&#039;&#039;data-logfile&#039;&#039;&#039; wird für LogProxy nicht benötigt. Befinden sich nur LogProxy-Werte im Diagramm kann das Attribut komplett entfallen. Sollen weitere Werte angezeigt werden, bleibt die Definition im Array einfach leer.&lt;br /&gt;
&lt;br /&gt;
Im Attribut &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; wird eine Formel angegeben, wie die Werte berechnet werden sollen. Hier können die Formeln 1:1 von einem eventuell vorhandenen SVG-Plot übernommen werden. &#039;&#039;&#039;Dabei gibt es jedoch folgendes zu beachten:&#039;&#039;&#039; Befindet sich die Formel in einem Array, dürfen die Formeln keine Anführungszeichen (&amp;lt;code&amp;gt;&amp;quot;&amp;lt;/code&amp;gt;) beinhalten. Stattdessen müssen sie als escapter Ascii-Code (&amp;lt;code&amp;gt;\\x22&amp;lt;/code&amp;gt;) eingefügt werden.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt, wie Vorhersagewerte aus einem FHEM-Device vom Typ Proplanta (Name hier &amp;lt;code&amp;gt;AU.xx.WE.Proplanta&amp;lt;/code&amp;gt;) angezeigt werden können.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	 data-device=&amp;quot;AU.xx.WE.Proplanta&amp;quot;&lt;br /&gt;
	 data-logdevice=&#039;[&lt;br /&gt;
						&amp;quot;myLogProxy&amp;quot;,&lt;br /&gt;
						&amp;quot;myLogProxy&amp;quot;,&lt;br /&gt;
						&amp;quot;myLogProxy&amp;quot;,&lt;br /&gt;
						&amp;quot;myLogProxy&amp;quot;&lt;br /&gt;
					]&#039;&lt;br /&gt;
	 data-columnspec=&#039;[&lt;br /&gt;
						&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22temp_\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;,&lt;br /&gt;
						&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22rain_\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;,&lt;br /&gt;
						&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22chOfRain_\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;,&lt;br /&gt;
						&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22cloud_\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;&lt;br /&gt;
					]&#039;&lt;br /&gt;
	 ...&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Auch alle anderen Funktionen, die [[LogProxy]] bietet, können hier angewendet werden.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
===Aktualisierung des Charts===&lt;br /&gt;
Damit der Refresh des Charts funktioniert, muss auch ein Device angegeben werden, der das Refresh triggert. Das Diagramm wird immer dann aktualisiert, wenn sich der Inhalt von &#039;&#039;&#039;data-get&#039;&#039;&#039; ändert.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	data-device=&amp;quot;WohnzimmerHeizung&amp;quot;&lt;br /&gt;
	data-logdevice=&amp;quot;FileLog_WohnzimmerHeizung&amp;quot;&lt;br /&gt;
	...&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Aussehen der Linien===&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;data-style&#039;&#039;&#039; kann das Aussehen der Linien des jeweiligen Graphen verändert werden. Hierfür können die Standard-FHEM-Styles verwendet werden. Dazu wird das Attribut mit &amp;lt;code&amp;gt;SVGplot&amp;lt;/code&amp;gt;, gefolgt von einem Leerzeichen und der gewünschten Farbe/Stil befüllt. Es existieren jedoch auch noch weitere, an FTUI angepasste Styles, zu finden in der CSS-Datei &amp;lt;code&amp;gt;css/ftui_chart.css&amp;lt;/code&amp;gt;. Um diese zu verwenden, wird das Attribut mit &amp;lt;code&amp;gt;ftui&amp;lt;/code&amp;gt;, gefolgt von einem Leerzeichen und der gewünschten Farbe/Stil befüllt. Eigene Styles können zum Beispiel in der Datei &amp;lt;code&amp;gt;css/fhem-table-ui-user.css&amp;lt;/code&amp;gt; definiert werden.&lt;br /&gt;
&lt;br /&gt;
Folgende Übersicht zeigt die im Standard verfügbaren &#039;&#039;&#039;Farben&#039;&#039;&#039;, alle Abbildungen sind mit im FTUI-Style entstanden:&lt;br /&gt;
&amp;lt;div&amp;gt;&amp;lt;ul&amp;gt; &lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Farbe-f0.png|thumb|none|150px|Farbe &amp;quot;l0&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Farbe-f1.png|thumb|none|150px|Farbe &amp;quot;l1&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Farbe-f2.png|thumb|none|150px|Farbe &amp;quot;l2&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Farbe-f3.png|thumb|none|150px|Farbe &amp;quot;l3&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Farbe-f4.png|thumb|none|150px|Farbe &amp;quot;l4&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Farbe-f5.png|thumb|none|150px|Farbe &amp;quot;l5&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Farbe-f6.png|thumb|none|150px|Farbe &amp;quot;l6&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Angabe zur Farbe kann dann mit der Linienart kombiniert werden. Dazu stehen folgende &#039;&#039;&#039;Stile&#039;&#039;&#039; zur Verfügung:&lt;br /&gt;
&amp;lt;div&amp;gt;&amp;lt;ul&amp;gt; &lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-2D-normal.png|thumb|none|225px|Darstellung in 2D: Stil &amp;quot;normal&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-2D-dot.png|thumb|none|225px|Darstellung in 2D: Stil &amp;quot;dot&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-2D-dash.png|thumb|none|225px|Darstellung in 2D: Stil &amp;quot;dash&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-2D-fill.png|thumb|none|225px|Darstellung in 2D: Stil &amp;quot;fill&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-2D-sym.png|thumb|none|225px|Darstellung in 2D: Stil &amp;quot;sym&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div&amp;gt;&amp;lt;ul&amp;gt; &lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-3D-normal.png|thumb|none|225px|Darstellung in 3D: Stil &amp;quot;normal&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-3D-dot.png|thumb|none|225px|Darstellung in 3D: Stil &amp;quot;dot&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-3D-dash.png|thumb|none|225px|Darstellung in 3D: Stil &amp;quot;dash&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-3D-fill.png|thumb|none|225px|Darstellung in 3D: Stil &amp;quot;fill&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-3D-sym.png|thumb|none|225px|Darstellung in 3D: Stil &amp;quot;sym&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Farbe und Stil werden kombiniert (zusammengeschrieben) beim Attribut &#039;&#039;&#039;data-style&#039;&#039;&#039; angegeben, sodass sich beispielsweise für eine graue Punktlinie folgendes ergibt: &amp;lt;code&amp;gt;data-style=&amp;quot;ftui l1dot&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
Um die Darstellung als normale Linie zu erhalten, darf im Gegensatz zu den anderen Linienformen der Stil &amp;lt;code&amp;gt;normal&amp;lt;/code&amp;gt; nicht angegeben werden. Für eine einfache graue Linie ist also die Angabe &amp;lt;code&amp;gt;data-style=&amp;quot;ftui l1&amp;quot;&amp;lt;/code&amp;gt; korrekt, wohingegen &amp;lt;code&amp;gt;data-style=&amp;quot;ftui l1normal&amp;quot;&amp;lt;/code&amp;gt; zu einer fehlerhaften Anzeige führt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Der Stil &#039;&#039;sym&#039;&#039; ist speziell dafür geeignet, Symbole statt Linien zu zeichnen. Dazu kann beim Attribut &#039;&#039;&#039;data-ptype&#039;&#039;&#039; als Linienform ein beliebiges Font-Awsome-, oder Open Automation-Icon angegeben werden. Alle in diesem Abschnitt enthaltenen Abbildungen sind mit &amp;lt;code&amp;gt;data-ptype=&amp;quot;lines&amp;quot;&amp;lt;/code&amp;gt; entstanden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Übergänge mit datenabhängigen Grenzen:&#039;&#039;&#039; Plotstile (data-style) können auch direkt als Gradienten auf Basis von Plot-Datenwerten definiert werden. Dazu muss der Plotstil als Array angegeben werden. Der erste Wert des Arrays gibt an, ob nur die Linie gezeichnet werden soll (Zahl angeben, die die Dicke der Linie definiert) oder gefüllt (&amp;quot;fill&amp;quot; eintragen). Alle danach folgenden Array Elemente sind beliebig viele Stopp Punkte für die Farbübergänge, welche wiederum aus Arrays mit 3 Parametern bestehen. Für jeden Stopp Punkt werden der Datenwert, die Farbe und die Durchsichtigkeit gesetzt. Hierdurch lassen sich z.B. Einfärbungen setzen, die für Temperaturplots immer negative Werte blau einfärben und positive Werte rot. Zwischen den Stop Punkten wird die Farbe interpoliert, also ein weicher Übergang generiert. Will man harte Übergänge muss man Zwei Stopp Punkte mit unterschiedlichen Farbwerten aber dem gleichen Datenwert erzeugen.&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel 1 für einen weichen Gradienten, der bei 0 von blau nach rot übergeht, bei diesem Übergang durchsichtig ist und von dort nach negativen bzw. positiven Werden immer deckender wird:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;data-style=&#039;[&amp;quot;fill&amp;quot;,[&amp;quot;-20&amp;quot;,&amp;quot;#0000ff&amp;quot;,&amp;quot;0.7&amp;quot;],[&amp;quot;0&amp;quot;,&amp;quot;#0000ff&amp;quot;,&amp;quot;0&amp;quot;],[&amp;quot;0&amp;quot;,&amp;quot;#ff0000&amp;quot;,&amp;quot;0&amp;quot;],[&amp;quot;302&amp;quot;,&amp;quot;#ff0000&amp;quot;,&amp;quot;0.7&amp;quot;]]&#039;&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel 2 mit einem harten Übergang von blau nach rot bei 0:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;data-style=&#039;[&amp;quot;fill&amp;quot;,[&amp;quot;-20&amp;quot;,&amp;quot;#0000ff&amp;quot;,&amp;quot;0.7&amp;quot;],[&amp;quot;0&amp;quot;,&amp;quot;#0000ff&amp;quot;,&amp;quot;0.7&amp;quot;],[&amp;quot;0&amp;quot;,&amp;quot;#ff0000&amp;quot;,&amp;quot;0.7&amp;quot;],[&amp;quot;50&amp;quot;,&amp;quot;#ff0000&amp;quot;,&amp;quot;0.7&amp;quot;]]&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
Es gibt auch die Möglichkeit den Bereich zwischen zwei Graphen einzufärben. Dazu muss ein Wert in Columnspec als Array angegeben werden. Ist dies der Fall, dann wird der zweite Graph umgekehrt an den ersten angehängt.&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
data-columnspec=&#039;[&lt;br /&gt;
    &amp;quot;Func:logProxy_proplanta2Plot(\\x22AgroWeather\\x22,\\x22weatherIcon\\x22,$from,$to,12)&amp;quot;,&lt;br /&gt;
    [&lt;br /&gt;
        &amp;quot;Func:logProxy_proplanta2Plot(\\x22AgroWeather\\x22,\\x22tempMax\\x22,$from,$to,12)&amp;quot;,&lt;br /&gt;
        &amp;quot;Func:logProxy_proplanta2Plot(\\x22AgroWeather\\x22,\\x22tempMin\\x22,$from,$to,12)&amp;quot;&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;Func:logProxy_proplanta2Plot(\\x22AgroWeather\\x22,\\x22rain\\x22,$from,$to,0,\\x22day\\x22)&amp;quot;&lt;br /&gt;
]&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Datei:FTUI Widget Chart DynamicStyles.png|thumb|none|225px|dynamischer Übergang]]&lt;br /&gt;
&lt;br /&gt;
===Form der Linien===&lt;br /&gt;
Das Attribut &#039;&#039;&#039;data-ptype&#039;&#039;&#039; beeinflusst die Form der Linien. Hier sind folgende Werte möglich:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;lines&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;points&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;steps&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;fsteps&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;histeps&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;bars&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ibars&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;cubic&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;quadratic&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;quadraticSmooth&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich ist es möglich, Symbole anzeigen zu lassen. Unterstützt werden Font-Awesome (&#039;fa-...&#039;), Open Automation (&#039;oa-...&#039;) und FHEM-Symbole (&#039;fs-...&#039;)). Damit die Symbole korrekt angezeigt werden, muss  im Attribut &#039;&#039;&#039;data-style&#039;&#039;&#039; der Stil &amp;lt;code&amp;gt;sym&amp;lt;/code&amp;gt; gewählt werden, da sonst nur Punkte, statt der Symbole gezeichnet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	 data-device=&amp;quot;DG.wz.HZ.Heizungsventil&amp;quot;&lt;br /&gt;
	 data-logdevice=&amp;quot;FileLog_DG.wz.HZ.Heizungsventil&amp;quot;&lt;br /&gt;
	 ...&lt;br /&gt;
	 data-style=&amp;quot;ftui l1sym&amp;quot;&lt;br /&gt;
	 data-ptype=&amp;quot;fa-cog&amp;quot;&lt;br /&gt;
	 ...&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Größe der Symbole ist in der Datei &amp;lt;code&amp;gt;css/ftui_chart.css&amp;lt;/code&amp;gt; auf 12px festgelegt. Dieser Wert kann in einer eigenen CSS-Datei durch Anpassung von &amp;lt;code&amp;gt;stroke-width&amp;lt;/code&amp;gt; überschrieben werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
.ftui.l0sym		{ stroke:#DDA400; stroke-width:12px; fill:none; }&lt;br /&gt;
.ftui.l1sym		{ stroke:#BBBBBB; stroke-width:12px; fill:none; }&lt;br /&gt;
.ftui.l2sym		{ stroke:#CC0000; stroke-width:12px; fill:none; }&lt;br /&gt;
.ftui.l3sym		{ stroke:#CCCC00; stroke-width:12px; fill:none; }&lt;br /&gt;
.ftui.l4sym		{ stroke:#33CC33; stroke-width:12px; fill:none; }&lt;br /&gt;
.ftui.l5sym		{ stroke:#33CCCC; stroke-width:12px; fill:none; }&lt;br /&gt;
.ftui.l6sym		{ stroke:#3333CC; stroke-width:12px; fill:none; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;data-ptype&#039;&#039;&#039; kann auch Inhalt im Format &amp;lt;code&amp;gt;&#039;icon:1&#039;&amp;lt;/code&amp;gt; verarbeiten. Dann muss der zugehörige Wert in &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; den Pfad zu einem Icon (z.B. für Wettervorhersagen) beinhalten. Der Y-Wert wird dann vom ersten Graphen übernommen. Weitere Ausführungen hierzu im Beispiel [[#Darstellung der Wetter Icons im Diagramm]].&lt;br /&gt;
&lt;br /&gt;
===Stapeln von Linien===&lt;br /&gt;
Über &#039;&#039;&#039;data-ptype&#039;&#039;&#039; kann zusätzlich festgelegt werden, ob Graphen übereinander gestapelt werden sollen. &amp;lt;code&amp;gt;data-ptype=&#039;lines:1&#039;&amp;lt;/code&amp;gt; bedeutet, dass der zugehörige Graph auf den Graph mit der Nummer 1 gestapelt werden soll. So etwas kann z.B. Sinn machen, wenn man den Stromverbrauch einzelner Devices darstellen und zusätzlich sehen will, wie hoch die Summe ist. Beispiel siehe unten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:FTUI Widget Chart Stacked.png]]&lt;br /&gt;
&lt;br /&gt;
===Zeitstrahl / Start &amp;amp; Ende auf der X-Achse===&lt;br /&gt;
Die Attribute &#039;&#039;&#039;data-daysago_start&#039;&#039;&#039; und &#039;&#039;&#039;data-daysago_end&#039;&#039;&#039; dienen der Definition von Anfang und Ende der X-Achse. Im einfachsten Fall wird eine Anzahl an Tagen eingegeben, die sich auf das aktuelle Datum beziehen. Dabei gilt es zu beachten, dass es sich um &#039;&#039;vergangene Tage&#039;&#039; handelt. Das bedeutet, dass Tage in der Vergangenheit als positive Zahl angegeben werden, Tage in der Zukunft hingegen als negative Zahl. Es kann jeweils  auch ein fixes Datum (z.B. &#039;2013-10-23&#039;) angegeben werden. Uhrzeitangaben werden nur berücksichtigt, wenn &#039;&#039;&#039;data-nofulldays=&#039;true&#039; &#039;&#039;&#039; verwendet wird.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Relative Zeitangabe in Stunden/Tagen/Wochen/Monaten/Jahren&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Zur Ausgabe einer Anzahl an zurückliegenden Stunden bis zum aktuellen Zeitpunkt wird als Startzeitpunkt die Anzahl der Stunden/Tage/Wochen/Monate/Jahre angegeben, die angezeigt werden sollen, gefolgt vom Kleinbuchstaben &#039;&#039;&#039;h&#039;&#039;&#039; für Stunden, &#039;&#039;&#039;d&#039;&#039;&#039; für Tage, &#039;&#039;&#039;w&#039;&#039;&#039; für Wochen, &#039;&#039;&#039;m&#039;&#039;&#039; für Monate, &#039;&#039;&#039;y&#039;&#039;&#039; für Jahre, . Als Endzeitpunkt wird &#039;&#039;&#039;now&#039;&#039;&#039; gewählt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das nachfolgende Beispiel zeigt die Werte der vergangenen 3 Stunden an:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
data-nofulldays=&amp;quot;true&amp;quot;&lt;br /&gt;
data-daysago_start=&amp;quot;3h&amp;quot;&lt;br /&gt;
data-daysago_end=&amp;quot;now&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Fester Zeitbereich des heutigen Tages (Stunden/Tage/Wochen/Monate/Jahre)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Um ein festes Stunden/Tages/Wochen/Monats/Jahresfenster anzuzeigen, werden die absoluten Stunden/Tages/Wochen/Monats/Jahreszahlen mit negativem Vorzeichen, gefolgt vom Großbuchstaben &#039;&#039;&#039;H&#039;&#039;&#039; (entsprechend D/W/M/Y für Tage/Wochen/Monate/Jahre) angegeben. Wird &#039;&#039;&#039;data-daysago_start&#039;&#039;&#039; als positiver Wert angegeben, wird die Anzahl der Stunden/Tage/Wochen/Monate/Jahre von heute 0:00 Uhr subtrahiert (siehe Rechenweg weiter unten).&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Beispiel zeigt den Zeitbereich von heute 5:00 Uhr bis heute 22:00 Uhr:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
data-nofulldays=&amp;quot;true&amp;quot;&lt;br /&gt;
data-daysago_start=&amp;quot;-5H&amp;quot;&lt;br /&gt;
data-daysago_end=&amp;quot;-22H&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Fester Zeitbereich Tage-übergreifend&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Die Zeit in Tagen kann als Gleitkommazahl angegeben werden. Damit ist es möglich, Tage und Uhrzeiten zu kombinieren. Die Werte sind dann als Teil eines ganzen Tages, bezogen auf heute 0:00 Uhr zu errechnen und mit &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt; als Teiler anzugeben.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das nachfolgende Beispiel zeigt einen Zeitbereich von &#039;&#039;&#039;gestern 15:00 Uhr&#039;&#039;&#039; bis &#039;&#039;&#039;morgen 3:00 Uhr&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
data-nofulldays=&amp;quot;true&amp;quot;&lt;br /&gt;
data-daysago_start=&amp;quot;0.375&amp;quot;&lt;br /&gt;
data-daysago_end=&amp;quot;-1.125&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für die nachfolgenden Rechenwege sind die Einheiten nur zur Verdeutlichung angegeben. Die Einheiten werden im Attribut nicht angegeben.&lt;br /&gt;
&lt;br /&gt;
Der Wert für &#039;&#039;&#039;GESTERN&#039;&#039;&#039; wird wie folgt ermittelt:&amp;lt;br /&amp;gt;&lt;br /&gt;
Ausgangspunkt ist heute 0:00 Uhr, gestern 15:00 Uhr liegt also 9 Stunden davor. Diese 9 Stunden sind ein &amp;lt;code&amp;gt;9/24 Tag&amp;lt;/code&amp;gt; und errechnet sich so:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1d / 24h = 0.0416666...d/h&lt;br /&gt;
0.0416d/h * 9h = 0.375d&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Wert für &#039;&#039;&#039;MORGEN&#039;&#039;&#039; wird wie folgt ermittelt:&amp;lt;br /&amp;gt;&lt;br /&gt;
Ausgangspunkt ist wieder heute 0:00 Uhr, morgen 3:00 Uhr liegt dann 27 Stunden dahinter. Der Einfachheit halber werden hier nur die 3 Stunden errechnet und dann ein ganzer Tag addiert:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1d / 24h = 0.0416666...d/h&lt;br /&gt;
0.0416d/h * 3h = 0.125d&lt;br /&gt;
&lt;br /&gt;
0.125d + 1d = 1.125d&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Da das Attribut Tage in der Vergangenheit erwartet, muss für einen Wert in der Zukunft wieder eine negative Zahl angegeben werden.&lt;br /&gt;
&lt;br /&gt;
===Zeitformat der X-Achse===&lt;br /&gt;
Die Zeitanzeige auf der X-Achse kann sehr flexibel eingestellt werden. Dafür stehen verschiedene Platzhalter zur Verfügung, die durch spezielle Zeichen (&amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt; &amp;lt;/code&amp;gt; (Leerzeichen), &amp;lt;code&amp;gt;:&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;,&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt;) getrennt werden. Alle Zeichen werden trotz Escape-Zeichen (&amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt;) in der Ausgabe angezeigt.&lt;br /&gt;
&lt;br /&gt;
Folgende Platzhalter werden unterstützt:&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;mm&#039;&amp;lt;/code&amp;gt;: Minuten als zweistellige Zahl&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;hh&#039;&amp;lt;/code&amp;gt;: Stunden als zweistellige Zahl&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;dd&#039;&amp;lt;/code&amp;gt;: Tag als zweistellige Zahl (Kalenderdatum)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;MM&#039;&amp;lt;/code&amp;gt;: Monat als zweistellige Zahl (z.B. 02 für Februar)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;MMM&#039;&amp;lt;/code&amp;gt;: Monat als dreistellige Abkürzung (z.B. Dec für Dezember)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;MMMM&#039;&amp;lt;/code&amp;gt;: Langname des Monats (z.B. March)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;ee&#039;&amp;lt;/code&amp;gt;: Wochentag als zweistellige Zahl (z.B. 00 für Sonntag)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;eee&#039;&amp;lt;/code&amp;gt;: Wochentag als dreistellige Abkürzung (z.B. Mon für Montag)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;eeee&#039;&amp;lt;/code&amp;gt;: Langname des Wochentags (z.B. Tuesday)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;yy&#039;&amp;lt;/code&amp;gt;: Jahr als zweistellige Zahl (z.B. 16 für 2016)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;yyyy&#039;&amp;lt;/code&amp;gt;: Jahr als vierstellige Zahl (z.B. 2016)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;LF&#039;&amp;lt;/code&amp;gt;: Fügt einen Zeilenumbruch hinzu&lt;br /&gt;
&lt;br /&gt;
Beispiel: Der String &amp;lt;code&amp;gt;&#039;MMM\LF\yyyy&#039;&amp;lt;/code&amp;gt; zeigt &amp;lt;code&amp;gt;&#039;Jan&#039;&amp;lt;/code&amp;gt; in der ersten, und &amp;lt;code&amp;gt;&#039;2016&#039;&amp;lt;/code&amp;gt; in der zweiten Zeile. &amp;lt;code&amp;gt;&#039;MM.dd 2016&#039;&amp;lt;/code&amp;gt; wird zu &amp;lt;code&amp;gt;&#039;03.05 2016&#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Fadenkreuz-Cursor===&lt;br /&gt;
Der Fadenkreuz-Cursor zeigt die Momentanwerte, indem man ihn über die Graphen bewegt. In Desktop-Browsern reicht einfaches Bewegen des Maus. Unter iOS und Android kann der Cursor wird der Cursor durch einfaches Tippen auf die neue Position bewegt.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;data-cursorgroup&#039;&#039;&#039; können Graphen gruppiert werden. Am Cursor werden dann die Momentanwerte aller Graphen gleichzeitig angezeigt, die die selbe Zahl besitzen, sobald man die Maus über einen aus der Gruppe bewegt.&lt;br /&gt;
&lt;br /&gt;
===Legende===&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;data-legendpos&#039;&#039;&#039; kann die Position der Legende innerhalb des Diagramms festgelegt werden. Die Position wird mit einem Array, bestehend aus zwei Werten im Format &amp;lt;code&amp;gt;&#039;[&amp;quot;&amp;lt;horizontal&amp;gt;&amp;quot;,&amp;quot;&amp;lt;vertikal&amp;gt;&amp;quot;]&#039;&amp;lt;/code&amp;gt; angegeben. Für die horizontale Positionierung sind &amp;lt;code&amp;gt;&#039;left&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;right&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;before&#039;&amp;lt;/code&amp;gt;, und &amp;lt;code&amp;gt;&#039;behind&#039;&amp;lt;/code&amp;gt;, die vertikale Positionierung &amp;lt;code&amp;gt;&#039;top&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;bottom&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;above&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;below&#039;&amp;lt;/code&amp;gt; erlaubt (der Unterschied zwischen &amp;lt;code&amp;gt;&#039;left&#039;&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;&#039;before&#039;&amp;lt;/code&amp;gt; liegt darin, dass im zweiten Fall die Legende nicht in den Zeichenbereich gesetzt wird sondern vor das ganze Chart (entsprechend für &amp;lt;code&amp;gt;&#039;after&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;above&#039;&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;&#039;below&#039;&amp;lt;/code&amp;gt;). Alternativ können auch Zahlen verwendet werden, die die Position in Prozent angeben. Durch verschieben mit der Maus oder durch verschieben mit dem Finger oder Stift auf Touch Devices kann die Legende auch an eine andere Position verschoben werden.&lt;br /&gt;
&lt;br /&gt;
Wenn die Legende eingeblendet ist, kann mittels Klick auf einen Legendeneintrag der zugehörige Graph ein- und ausgeblendet werden.&lt;br /&gt;
&lt;br /&gt;
===3-dimensionale Drehung===&lt;br /&gt;
&#039;&#039;&#039;data-ddd&#039;&#039;&#039; ermöglicht, den Graphen 3-dimensional zu drehen. Als Wert wird ein Array mit den 3 Winkeln für x, y und z erwartet, wobei z selbst bisher nicht unterstützt wird.&lt;br /&gt;
&lt;br /&gt;
Beispiel: &amp;lt;code&amp;gt;data-ddd=&#039;[&amp;quot;40&amp;quot;,&amp;quot;60&amp;quot;,&amp;quot;0&amp;quot;]&#039;&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Wenn der 3D Modus aktiv ist (&#039;&#039;&#039;data-ddd&#039;&#039;&#039; gesetzt) sind 2 zusätzliche Parameter verfügbar um das Aussehen der Graphen zu beeinflussen. &#039;&#039;&#039;data-dddspace&#039;&#039;&#039; gibt an, wie viele pixel der Raum zwischen den einzelnen in z-Richtung hintereinander angeordneten Graphen betragen soll.&lt;br /&gt;
&#039;&#039;&#039;data-dddwidth&#039;&#039;&#039; legt fest, wie viele pixel die einzelnen Graphen tief (oder dick) sein sollen.&lt;br /&gt;
&lt;br /&gt;
Wenn das Array angegeben wird, erscheinen zwei zusätzliche Buttons im Diagramm, mit denen die Drehung in X- und Y-Richtung verändert werden kann.&lt;br /&gt;
&lt;br /&gt;
===Diagrammtitel===&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;data-title&#039;&#039;&#039; kann dem Diagramm, ähnlich wie in FHEM-SVG-Plots, ein Titel hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
Folgende Platzhalter werden unterstützt:&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;min1&#039;&amp;lt;/code&amp;gt;: Minimaler Y-Wert des ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;max1&#039;&amp;lt;/code&amp;gt;: Maximaler Y-Wert des ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;avg1&#039;&amp;lt;/code&amp;gt;: Mittlerer Y-Wert des ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;cnt1&#039;&amp;lt;/code&amp;gt;: Anzahl der dargestellten Einzelwerte im ersten Graph&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;currval1&#039;&amp;lt;/code&amp;gt;: Letzter, bzw. aktuellster Y-Wert des ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;mindate1&#039;&amp;lt;/code&amp;gt;: Niedrigster Wert auf der X-Achse des ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;maxdate1&#039;&amp;lt;/code&amp;gt;: Höchster Wert auf der X-Achse vom ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;currdate1&#039;&amp;lt;/code&amp;gt;: Letzter, bzw. aktuellster Wert auf der X-Achse des ersten Graphs&lt;br /&gt;
&lt;br /&gt;
Durch Einsetzen einer anderen Zahl statt &#039;1&#039; können auch die Werte der anderen Graphen angezeigt werden. Das Weglassen der Zahl bewirkt, dass der jeweils zutreffende Wert automatisch ermittelt wird. Bedeutet: &amp;lt;code&amp;gt;max&amp;lt;/code&amp;gt; führt dazu, dass der höchste Wert aller angezeigter Graphen verwendet wird.&lt;br /&gt;
Zusätzlich ist es möglich durch &amp;quot;$eval(&amp;lt;regexp&amp;gt;)&amp;quot; regular Expressions auszuwerten (also z.B. Berechnungen durchzuführen). In &amp;lt;regexp&amp;gt; können auch &amp;quot;$data()&amp;quot; vorkommen.&lt;br /&gt;
&lt;br /&gt;
Beispiel: &amp;lt;code&amp;gt;data-title=&amp;quot;Klima Wohnzimmer Average: $eval(parseInt($data{avg1}*10)/10)°C / Max: $eval(parseInt($data{max1}*10)/10)°C&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Buttons im Diagramm===&lt;br /&gt;
Es gibt mehrere Buttons, mit denen sich die Anzeige des Diagramms verändern lässt. &amp;lt;code&amp;gt;&amp;lt;-&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;-&amp;gt;&amp;lt;/code&amp;gt; bewegen die Graphen nach links und rechts. &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt; zoomen die Anzeige. &amp;lt;code&amp;gt;legend&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;cursor&amp;lt;/code&amp;gt; schalten die zugehörigen Anzeigen ein und aus. Falls der 3D Modus eingeschaltet ist, gibt es Buttons zum Drehen der Darstellung um die X- und Y-Achse. Falls &amp;lt;code&amp;gt;data-timeranges&amp;lt;/code&amp;gt; gesetzt ist, wird ein Pulldown Menü dargestellt, welches die Auswahl von dort definierten Zeiträumen für die X-Achse erlaubt.&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===Einfaches Diagramm===&lt;br /&gt;
Das Beispiel zeigt ein einfaches Diagramm mit 4 unterschiedlich formatierten Graphen, Legende und Momentanwerten am Fadenkreuz-Cursor.&lt;br /&gt;
&lt;br /&gt;
[[File:Chart_tabletUI.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	data-logdevice=&#039;[&amp;quot;Log.Garden&amp;quot;,&amp;quot;Log.Garden&amp;quot;,&amp;quot;Log.Garden&amp;quot;,&amp;quot;Log.Predicted&amp;quot;]&#039;&lt;br /&gt;
	data-columnspec=&#039;[&amp;quot;4:Garden.T:15:&amp;quot;,&amp;quot;10:Garden.T:0:delta-h&amp;quot;,&amp;quot;10:Garden.T:0:delta-d&amp;quot;,&amp;quot;4:predicted.*:15:&amp;quot;]&#039;&lt;br /&gt;
	data-style=&#039;[&amp;quot;ftui l0fill&amp;quot;,&amp;quot;ftui l1fill&amp;quot;,&amp;quot;ftui l2&amp;quot;,&amp;quot;ftui l3dot&amp;quot;]&#039;&lt;br /&gt;
	data-ptype=&#039;[&amp;quot;lines&amp;quot;,&amp;quot;histeps&amp;quot;,&amp;quot;histeps&amp;quot;,&amp;quot;cubic&amp;quot;]&#039;&lt;br /&gt;
	data-uaxis=&#039;[&amp;quot;primary&amp;quot;,&amp;quot;secondary&amp;quot;,&amp;quot;secondary&amp;quot;,&amp;quot;primary&amp;quot;]&#039;&lt;br /&gt;
	data-legend=&#039;[&amp;quot;Temperature&amp;quot;,&amp;quot;Rain/hour&amp;quot;,&amp;quot;Rain/day&amp;quot;,&amp;quot;Predicted Temp.&amp;quot;]&#039;&lt;br /&gt;
	data-yunit=&amp;quot;°C&amp;quot;&lt;br /&gt;
	data-ytext=&amp;quot;Temperature&amp;quot;&lt;br /&gt;
	data-minvalue=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-maxvalue=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-yunit_sec=&amp;quot;mm&amp;quot;&lt;br /&gt;
	data-ytext_sec=&amp;quot;Rain (mm)&amp;quot;&lt;br /&gt;
	data-height=&amp;quot;250&amp;quot;&lt;br /&gt;
	data-yticks=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-minvalue_sec=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-maxvalue_sec=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-nofulldays=&amp;quot;true&amp;quot;&lt;br /&gt;
	data-daysago_start=&amp;quot;2013-08-13T00:00:00&amp;quot;&lt;br /&gt;
	data-daysago_end=&amp;quot;2013-08-14T00:00:00&amp;quot;&lt;br /&gt;
	data-cursorgroup=&amp;quot;1&amp;quot;&lt;br /&gt;
	data-scrollgroup=&amp;quot;1&amp;quot;&lt;br /&gt;
	data-xticks=&amp;quot;auto&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===7-Tage-Wettervorhersage mit Proplanta===&lt;br /&gt;
In diesem Beispiel wird gezeigt, wie die Vorhersagewerte von [[PROPLANTA]] in einem Diagramm dargestellt werden können. Da die Werte nicht in einer Datenbank oder einem FileLog vorliegen, müssen sie über [[LogProxy]] verarbeitet werden. Dafür sind einige Vorbereitungen in FHEM nötig.&lt;br /&gt;
&lt;br /&gt;
[[File:FTUI_Widget_Chart-fc-Proplanta.png|941px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Ein LogProxy-Device muss vorhanden sein:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define myLogProxy logProxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; In der Datei &amp;lt;code&amp;gt;99_myUtils.pm&amp;lt;/code&amp;gt; muss folgende Routine hinzugefügt werden, die die Daten bereitstellt:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#---------------------------------------&lt;br /&gt;
# Proplanta LogProxy-Funktion&lt;br /&gt;
#---------------------------------------&lt;br /&gt;
sub logProxy_proplanta2Plot($$$$;$$) {&lt;br /&gt;
	my ($device, $fcValue, $from, $to, $fcHour, $expMode) = @_;&lt;br /&gt;
    my $regex;&lt;br /&gt;
    my @rl;&lt;br /&gt;
    &lt;br /&gt;
	return undef if(!$device);&lt;br /&gt;
    &lt;br /&gt;
    if($fcValue =~ s/_$//) {&lt;br /&gt;
        $regex = &amp;quot;^fc[\\d]+_&amp;quot;.$fcValue.&amp;quot;[\\d]{2}\$&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        $regex = &amp;quot;^fc[\\d]+_&amp;quot;.$fcValue.&amp;quot;\$&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    $fcHour = 12 if(!defined $fcHour);&lt;br /&gt;
    $expMode = &amp;quot;point&amp;quot; if(!defined $expMode);&lt;br /&gt;
&lt;br /&gt;
	if( defined($defs{$device}) ) {&lt;br /&gt;
		if( $defs{$device}{TYPE} eq &amp;quot;PROPLANTA&amp;quot; ) {&lt;br /&gt;
            @rl = sort{&lt;br /&gt;
                my ($an) = ($a =~ m/fc(\d+)_.*/);&lt;br /&gt;
                my ($bn) = ($b =~ m/fc(\d+)_.*/);&lt;br /&gt;
                $an &amp;lt;=&amp;gt; $bn or $a cmp $b;&lt;br /&gt;
                }( grep /${regex}/,keys %{$defs{$device}{READINGS}} );&lt;br /&gt;
			return undef if( !@rl );&lt;br /&gt;
		} else {&lt;br /&gt;
			Log3 undef, 2, &amp;quot;logProxy_proplanta2Plot: $device is not a PROPLANTA device&amp;quot;;&lt;br /&gt;
			return undef;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	my $fromsec = SVG_time_to_sec($from);&lt;br /&gt;
	my $tosec   = SVG_time_to_sec($to);&lt;br /&gt;
	my $sec = $fromsec;&lt;br /&gt;
	my ($h,$fcDay,$mday,$mon,$year);&lt;br /&gt;
	my $timestamp;&lt;br /&gt;
    &lt;br /&gt;
	my $reading;&lt;br /&gt;
	my $value;&lt;br /&gt;
	my $prev_value;&lt;br /&gt;
	my $min = 999999;&lt;br /&gt;
	my $max = -999999;&lt;br /&gt;
	my $ret = &amp;quot;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	# while not end of plot range reached&lt;br /&gt;
	while(($sec &amp;lt; $tosec) &amp;amp;&amp;amp; @rl) {&lt;br /&gt;
		#remember previous value for start of plot range&lt;br /&gt;
		$prev_value = $value;&lt;br /&gt;
&lt;br /&gt;
		$reading = shift @rl;&lt;br /&gt;
        ($fcDay) = $reading =~ m/^fc(\d+).*/;&lt;br /&gt;
   		$h = ($reading =~ m/.*(\d\d)$/)?$1:$fcHour;&lt;br /&gt;
		$value = ReadingsVal($device,$reading,undef);&lt;br /&gt;
        &lt;br /&gt;
		($mday,$mon,$year) = split(&#039;\.&#039;,ReadingsVal($device,&amp;quot;fc&amp;quot;.$fcDay.&amp;quot;_date&amp;quot;,undef));&lt;br /&gt;
		$timestamp = sprintf(&amp;quot;%04d-%02d-%02d_%02d:%02d:%02d&amp;quot;, $year, $mon, $mday, $h, 0, 0);&lt;br /&gt;
		$sec = SVG_time_to_sec($timestamp);&lt;br /&gt;
        &lt;br /&gt;
		# skip all values before start of plot range&lt;br /&gt;
		next if( SVG_time_to_sec($timestamp) &amp;lt; $fromsec );&lt;br /&gt;
&lt;br /&gt;
		# add first value at start of plot range&lt;br /&gt;
		if( !$ret &amp;amp;&amp;amp; $prev_value ) {&lt;br /&gt;
		  $min = $prev_value if( (looks_like_number($prev_value) &amp;amp;&amp;amp; ($prev_value &amp;lt; $min)) || ($prev_value lt $min) );&lt;br /&gt;
		  $max = $prev_value if( (looks_like_number($prev_value) &amp;amp;&amp;amp; ($prev_value &amp;gt; $max)) || ($prev_value gt $max) );&lt;br /&gt;
		  $ret .= &amp;quot;$from $prev_value\n&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		# done if after end of plot range&lt;br /&gt;
		last if($sec &amp;gt; $tosec);&lt;br /&gt;
&lt;br /&gt;
		$min = $value if( (looks_like_number($value) &amp;amp;&amp;amp; ($value &amp;lt; $min )) || ($value lt $min) );&lt;br /&gt;
		$max = $value if( (looks_like_number($value) &amp;amp;&amp;amp; ($value &amp;gt; $max )) || ($value gt $max) );&lt;br /&gt;
&lt;br /&gt;
		# add actual controll point&lt;br /&gt;
		$ret .= &amp;quot;$timestamp $value\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
#		Log 1, &amp;quot;$timestamp $value -0- $reading&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
    if(($sec &amp;lt; $tosec) &amp;amp;&amp;amp; !@rl &amp;amp;&amp;amp; ($expMode eq &amp;quot;day&amp;quot;)) {&lt;br /&gt;
    	$timestamp = sprintf(&amp;quot;%04d-%02d-%02d_%02d:%02d:%02d&amp;quot;, $year, $mon, $mday, 23, 59, 59);&lt;br /&gt;
    	if(SVG_time_to_sec($timestamp) &amp;lt; $tosec) {&lt;br /&gt;
        	$ret .= &amp;quot;$timestamp $value\n&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        else {&lt;br /&gt;
			$ret .= &amp;quot;$to $value\n&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    elsif(($sec &amp;gt; $tosec) &amp;amp;&amp;amp; ($expMode eq &amp;quot;day&amp;quot;)) {&lt;br /&gt;
       	$value = $prev_value + ($value - $prev_value)*(86400 + ($tosec - $sec))/86400;&lt;br /&gt;
       	$ret .= &amp;quot;$to $value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
	return ($ret,$min,$max,$prev_value);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anschließend können die Daten im Chart-Widget angezeigt werden. Der Device-Name von Proplanta heißt hier im Beispiel &amp;lt;code&amp;gt;AU.xx.WE.Proplanta&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	 data-device=&amp;quot;AU.xx.WE.Proplanta&amp;quot;&lt;br /&gt;
	 data-logdevice=&#039;[&lt;br /&gt;
	 					&amp;quot;myLogProxy&amp;quot;,&lt;br /&gt;
	 					&amp;quot;myLogProxy&amp;quot;,&lt;br /&gt;
	 					&amp;quot;myLogProxy&amp;quot;&lt;br /&gt;
	 				]&#039;&lt;br /&gt;
	 data-columnspec=&#039;[&lt;br /&gt;
	 					&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22rain_\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;,&lt;br /&gt;
	 					&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22chOfRain_\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;,&lt;br /&gt;
	 					&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22cloud_\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;&lt;br /&gt;
	 				]&#039;&lt;br /&gt;
	 data-style=&#039;[&lt;br /&gt;
	 					&amp;quot;ftui l6fill&amp;quot;,&lt;br /&gt;
	 					&amp;quot;ftui l5fill&amp;quot;,&lt;br /&gt;
	 					&amp;quot;ftui l1fill&amp;quot;&lt;br /&gt;
	 			]&#039;&lt;br /&gt;
	 data-ptype=&#039;[&lt;br /&gt;
	 					&amp;quot;steps&amp;quot;,&lt;br /&gt;
	 					&amp;quot;quadraticSmooth&amp;quot;,&lt;br /&gt;
	 					&amp;quot;quadraticSmooth&amp;quot;&lt;br /&gt;
	 			]&#039;&lt;br /&gt;
	 data-uaxis=&#039;[&lt;br /&gt;
	 					&amp;quot;primary&amp;quot;,&lt;br /&gt;
	 					&amp;quot;secondary&amp;quot;,&lt;br /&gt;
	 					&amp;quot;secondary&amp;quot;&lt;br /&gt;
	 			]&#039;&lt;br /&gt;
	 data-legend=&#039;[&lt;br /&gt;
	 					&amp;quot;Regen&amp;quot;,&lt;br /&gt;
	 					&amp;quot;Regenwahrscheinlichkeit&amp;quot;,&lt;br /&gt;
	 					&amp;quot;Wolken&amp;quot;&lt;br /&gt;
	 			]&#039;&lt;br /&gt;
	 data-yunit=&amp;quot;mm&amp;quot;&lt;br /&gt;
	 data-ytext=&amp;quot;Regen&amp;quot;&lt;br /&gt;
	 data-yunit_sec=&amp;quot;%&amp;quot;&lt;br /&gt;
	 data-ytext_sec=&amp;quot;Chance auf Regen / Wolken&amp;quot;&lt;br /&gt;
	 data-timeformat=&amp;quot;eeee&amp;quot;&lt;br /&gt;
	 data-minvalue=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-maxvalue=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-minvalue_sec=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-maxvalue_sec=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-daysago_start = &amp;quot;0&amp;quot;&lt;br /&gt;
	 data-daysago_end = &amp;quot;-7&amp;quot;&lt;br /&gt;
	 data-xticks=&amp;quot;1440&amp;quot;&lt;br /&gt;
	 data-yticks=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-title=&amp;quot;7-Tage-Wettervorhersage&amp;quot;&lt;br /&gt;
	 data-showlegend=&amp;quot;true&amp;quot;&lt;br /&gt;
	 class=&amp;quot;nobuttons fullsize&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hilfreiche Links und Quellen zu diesem Beispiel:&#039;&#039;&#039;&lt;br /&gt;
*[[LogProxy|LogProxy im FHEM-Wiki]]&lt;br /&gt;
*{{Link2Forum|Topic=22967|Message=246973|LinkText=Stundengenaue Wettervorhersage (#1) im FHEM-Forum}}&lt;br /&gt;
*{{Link2Forum|Topic=22967|Message=334713|LinkText=Stundengenaue Wettervorhersage (#2) im FHEM-Forum}}&lt;br /&gt;
&lt;br /&gt;
===Darstellung der Wetter Icons im Diagramm===&lt;br /&gt;
&lt;br /&gt;
[[File:Wetterchart2.png]]&lt;br /&gt;
&lt;br /&gt;
Wie oben bereits beschrieben, gibt es beim Chart grundsätzlich die Möglichkeit, Icons, welche in Form von URLs in den Logs abgelegt sind oder welche per logProxy generiert werden, darzustellen. Die Icons werden auf genau dem gleichen Weg von FHEM gelesen, wie alle anderen Datenpunkte. Im Folgenden wird ein Beispiel gezeigt, mit dem die im Proplanta Modul als Readings abgelegten Icons per logProxy Funktion gelesen und in ein Chart eingebaut werden könnnen.&lt;br /&gt;
Da es beim Proplanta Modul für die ersten 7 Tage nicht das Reading &amp;lt;code&amp;gt;fc#_weatherIcon&amp;lt;/code&amp;gt; gibt, sondern mehrere Readings für unterschiedliche Tageszeiten wogegen für die zweiten 7 Tage ausschließlich das Reading &amp;lt;code&amp;gt;fc#_weatherIcon&amp;lt;/code&amp;gt; vorhanden ist, sollte per &amp;lt;code&amp;gt;attr device userReading&amp;lt;/code&amp;gt; mit folgendem Eintrag dafür gesorgt werden, dass für alle Tage ein Reading &amp;lt;code&amp;gt;fc#_weatherIcon&amp;lt;/code&amp;gt; vorhanden ist (alternativ könnten auch 2 Graphen gezeichnet werden, wobei der erste dann nur die ersten 7 Tage enthält und der zweite die letzen 7 Tage, will man nur die ersten 7 Tage darstellen braucht man das userReading nicht unbedingt).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
fc0_weatherIcon {ReadingsVal(&amp;quot;AU.xx.WE.Proplanta&amp;quot;,&amp;quot;fc0_weatherDayIcon&amp;quot;,&amp;quot;&amp;quot;);},&lt;br /&gt;
fc1_weatherIcon {ReadingsVal(&amp;quot;AU.xx.WE.Proplanta&amp;quot;,&amp;quot;fc1_weatherDayIcon&amp;quot;,&amp;quot;&amp;quot;);},&lt;br /&gt;
fc2_weatherIcon {ReadingsVal(&amp;quot;AU.xx.WE.Proplanta&amp;quot;,&amp;quot;fc2_weatherDayIcon&amp;quot;,&amp;quot;&amp;quot;);},&lt;br /&gt;
fc3_weatherIcon {ReadingsVal(&amp;quot;AU.xx.WE.Proplanta&amp;quot;,&amp;quot;fc3_weatherDayIcon&amp;quot;,&amp;quot;&amp;quot;);},&lt;br /&gt;
fc4_weatherIcon {ReadingsVal(&amp;quot;AU.xx.WE.Proplanta&amp;quot;,&amp;quot;fc4_weatherDayIcon&amp;quot;,&amp;quot;&amp;quot;);},&lt;br /&gt;
fc5_weatherIcon {ReadingsVal(&amp;quot;AU.xx.WE.Proplanta&amp;quot;,&amp;quot;fc5_weatherDayIcon&amp;quot;,&amp;quot;&amp;quot;);},&lt;br /&gt;
fc6_weatherIcon {ReadingsVal(&amp;quot;AU.xx.WE.Proplanta&amp;quot;,&amp;quot;fc6_weatherDayIcon&amp;quot;,&amp;quot;&amp;quot;);}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Um die Icons darzustellen muss ein zusätzlicher Graph definiert werden. Dieser nutzt neben der Columnspec, die die URLs abruft den Parameter &amp;lt;code&amp;gt;data-ptype=&amp;quot;icons:#&amp;quot;&amp;lt;/code&amp;gt; (# ist eine Zahl und steht für die Nummer, beginnend bei 0 des Graphen, welcher für die y-Position der Icons verwendet werden soll) und den Stil &amp;lt;code&amp;gt;sym&amp;lt;/code&amp;gt;. Der Wert für die Symbolgröße sollte z.B. durch eine zusätzliche Definition im File fhem-tablet-ui-user.css in der Form:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
/* icon lines */&lt;br /&gt;
.ftui.l99icon	{ stroke:#DDA400; stroke-width:48px; fill:none; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
angepasst werden.&lt;br /&gt;
&lt;br /&gt;
Im folgenden ein Beispiel, welches eine Linie für die Maximale Tagestemperatur zeichnet und auf dieser Linie die Wetter Icons darstellt.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	 data-device=&amp;quot;AU.xx.WE.Proplanta&amp;quot;&lt;br /&gt;
	 data-logdevice=&#039;[&lt;br /&gt;
	 					&amp;quot;myLogProxy&amp;quot;,&lt;br /&gt;
	 					&amp;quot;myLogProxy&amp;quot;&lt;br /&gt;
	 				]&#039;&lt;br /&gt;
	 data-columnspec=&#039;[&lt;br /&gt;
	 					&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22weatherIcon\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;,&lt;br /&gt;
	 					&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22tempMax\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;&lt;br /&gt;
	 				]&#039;&lt;br /&gt;
	 data-style=&#039;[&lt;br /&gt;
	 					&amp;quot;ftui l99icon&amp;quot;,&lt;br /&gt;
	 					&amp;quot;ftui l1fill&amp;quot;&lt;br /&gt;
	 			]&#039;&lt;br /&gt;
	 data-ptype=&#039;[&lt;br /&gt;
	 					&amp;quot;icons:1&amp;quot;,&lt;br /&gt;
	 					&amp;quot;quadraticSmooth&amp;quot;&lt;br /&gt;
	 			]&#039;&lt;br /&gt;
	 data-uaxis=&#039;[&lt;br /&gt;
	 					&amp;quot;primary&amp;quot;,&lt;br /&gt;
	 					&amp;quot;primary&amp;quot;&lt;br /&gt;
	 			]&#039;&lt;br /&gt;
	 data-legend=&#039;[&lt;br /&gt;
	 					&amp;quot;Wetterbedingung&amp;quot;,&lt;br /&gt;
	 					&amp;quot;Max. Temperature&amp;quot;&lt;br /&gt;
	 			]&#039;&lt;br /&gt;
	 data-yunit=&amp;quot;°C&amp;quot;&lt;br /&gt;
	 data-ytext=&amp;quot;Temperature (°C)&amp;quot;&lt;br /&gt;
	 data-timeformat=&amp;quot;ee\LF\dd.MM&amp;quot;&lt;br /&gt;
	 data-minvalue=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-maxvalue=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-minvalue_sec=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-maxvalue_sec=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-daysago_start=&amp;quot;-1w&amp;quot;&lt;br /&gt;
	 data-y_margin=&amp;quot;20&amp;quot;&lt;br /&gt;
	 data-daysago_end=&amp;quot;-3w&amp;quot;&lt;br /&gt;
	 data-xticks=&amp;quot;1440&amp;quot;&lt;br /&gt;
	 data-yticks=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-title=&amp;quot;14-Tage-Wettervorhersage&amp;quot;&lt;br /&gt;
	 data-showlegend=&amp;quot;true&amp;quot;&lt;br /&gt;
	 class=&amp;quot;nobuttons fullsize&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Kuchendiagramme===&lt;br /&gt;
In folgendem Beispiel wird gezeigt, wie man ein &amp;quot;Kuchendiagramm&amp;quot; darstellen kann.&lt;br /&gt;
&lt;br /&gt;
[[File:PieChart.png]]&lt;br /&gt;
&lt;br /&gt;
Ähnlich wie bei den Beispielen für die Wetter Darstellungen wird hierzu auch wieder logProxy benötigt. Zunächst muss die folgende zusätzliche Funktion in &amp;lt;code&amp;gt;99_myUtils.pm&amp;lt;/code&amp;gt; einfügen.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#---------------------------------------&lt;br /&gt;
# Funktion zum Erzeugen der Inputs für Kuchendiagramme&lt;br /&gt;
#---------------------------------------&lt;br /&gt;
sub logProxy_values2PieChart($$$$;$$) {&lt;br /&gt;
	my ($device, $reading, $angle_start, $angle_dif, $inner_rad, $show_text) = @_;&lt;br /&gt;
	Log3 undef, 1, &amp;quot;$device, $reading, $angle_start, $angle_dif, $inner_rad, $show_text\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	use constant PI =&amp;gt; 4 * atan2(1,1);&lt;br /&gt;
	&lt;br /&gt;
	my $value=ReadingsVal($device,$reading,0);&lt;br /&gt;
&lt;br /&gt;
	my $angle_delta = $value/100*360;&lt;br /&gt;
	$angle_start = $angle_start/100*360;&lt;br /&gt;
	&lt;br /&gt;
	my $rad=10;&lt;br /&gt;
	my $irad=0;&lt;br /&gt;
	if ($inner_rad) {&lt;br /&gt;
		$irad = $rad*$inner_rad;&lt;br /&gt;
	}&lt;br /&gt;
	my $angle=$angle_start/360*2.0*PI;&lt;br /&gt;
	my $x=$irad*sin($angle);&lt;br /&gt;
	my $y=$irad*cos($angle);&lt;br /&gt;
	my $ret .= &amp;quot;;p &amp;quot;.$x.&amp;quot; &amp;quot;.$y.&amp;quot;\n&amp;quot;; # add segment at angle $angle&lt;br /&gt;
	&lt;br /&gt;
	for (my $i=$angle_start; $i&amp;lt;=$angle_start+$angle_delta; $i+=$angle_dif) {&lt;br /&gt;
		$angle = $i/360*2.0*PI;&lt;br /&gt;
		$x = $rad*sin($angle);&lt;br /&gt;
		$y = $rad*cos($angle);&lt;br /&gt;
		$ret .= &amp;quot;;p &amp;quot;.$x.&amp;quot; &amp;quot;.$y.&amp;quot;\n&amp;quot;; # add segment at angle $angle&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	$angle = ($angle_start+$angle_delta)/360*2.0*PI; # add last segment &lt;br /&gt;
	$ret .= &amp;quot;;p &amp;quot;.$rad*sin($angle).&amp;quot; &amp;quot;.$rad*cos($angle).&amp;quot;\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	if ($inner_rad) {&lt;br /&gt;
		for (my $i=$angle_start; $i&amp;lt;$angle_start+$angle_delta; $i+=$angle_dif) {&lt;br /&gt;
			$angle = ($angle_start+$angle_start+$angle_delta-$i)/360*2.0*PI;&lt;br /&gt;
			$x = $irad*sin($angle);&lt;br /&gt;
			$y = $irad*cos($angle);&lt;br /&gt;
			$ret .= &amp;quot;;p &amp;quot;.$x.&amp;quot; &amp;quot;.$y.&amp;quot;\n&amp;quot;; # add segment at angle $angle&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	$angle = ($angle_start)/360*2.0*PI; # add last segment &lt;br /&gt;
	$ret .= &amp;quot;;p &amp;quot;.$irad*sin($angle).&amp;quot; &amp;quot;.$irad*cos($angle).&amp;quot;\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	if ($show_text) { # show text values&lt;br /&gt;
		$x = ($rad+$irad)/2*sin((2*$angle_start+$angle_delta)/2/360*2.0*PI);&lt;br /&gt;
		$y = ($rad+$irad)/2*cos((2*$angle_start+$angle_delta)/2/360*2.0*PI);&lt;br /&gt;
&lt;br /&gt;
		$ret .= &amp;quot;;t &amp;quot;.$x.&amp;quot; &amp;quot;.$y.&amp;quot; middle &amp;quot;.$show_text.&amp;quot;:&amp;quot;.$value.&amp;quot;%\n&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return($ret);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In FHEM braucht man Readings, welche eine Zahl enthalten, die als Prozentwert interpretiert wird. Für jeden Prozentwert (also für jedes Reading) generiert die o.a. Funktion nun den Chart Input für ein Kuchenstück und liefert diesen als Antwort auf das GET, welches das Chart Widget auslöst. Dazu braucht die Funktion folgende Parameter: (Name des FHEM Devices, Name des Readings, Start Winkel des Kuchenstücks (Mathematisch gegen den Uhrzeigersinn in Grad), Delta Winkel zum Zeichnen (legt fest in welchen Schritten der Teilkreis des Kuchenstücks gezeichnet wird), Skalierungsfaktor für inneren Ring wenn ein Ring gezeichtnet werden soll (0 bedeutet komplette Kuchenstücke), optionaler Text der ins Kuchenstück vor die Prozentzahl geschrieben wird).&lt;br /&gt;
Im Folgenden eine Beispielkonfiguration für die Darstellung als Kuchendiagramm, die Readings heißen hier dPer1 bis dPer4. Der Startwinkel wird duch Aufsummierung der jeweils vorher schon gezeichneten Kuchenstücke gebildet, dadurch entstehen aneinander hängende Stücke.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
[[Datei:[[Datei:Beispiel.jpg]]]]&amp;lt;div class=&amp;quot;normal noaxes nobuttons&amp;quot;&lt;br /&gt;
        data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
        data-logdevice=&#039;[&amp;quot;lp&amp;quot;]&#039;&lt;br /&gt;
		data-logfile=&amp;quot;CURRENT&amp;quot;&lt;br /&gt;
        data-columnspec=&#039;[&lt;br /&gt;
			&amp;quot;Func:logProxy_values2PieChart(\&amp;quot;dPer1\&amp;quot;,\&amp;quot;state\&amp;quot;,ReadingsVal(\&amp;quot;dPer4\&amp;quot;,\&amp;quot;state\&amp;quot;,0)+ReadingsVal(\&amp;quot;dPer3\&amp;quot;,\&amp;quot;state\&amp;quot;,0),5,0,\&amp;quot;first\&amp;quot;)&amp;quot;,&lt;br /&gt;
			&amp;quot;Func:logProxy_values2PieChart(\&amp;quot;dPer2\&amp;quot;,\&amp;quot;state\&amp;quot;,ReadingsVal(\&amp;quot;dPer4\&amp;quot;,\&amp;quot;state\&amp;quot;,0)+ReadingsVal(\&amp;quot;dPer3\&amp;quot;,\&amp;quot;state\&amp;quot;,0)+ReadingsVal(\&amp;quot;dPer1\&amp;quot;,\&amp;quot;state\&amp;quot;,0),5,0,\&amp;quot;second\&amp;quot;)&amp;quot;,&lt;br /&gt;
			&amp;quot;Func:logProxy_values2PieChart(\&amp;quot;dPer3\&amp;quot;,\&amp;quot;state\&amp;quot;,ReadingsVal(\&amp;quot;dPer4\&amp;quot;,\&amp;quot;state\&amp;quot;,0),5,0,\&amp;quot;third\&amp;quot;)&amp;quot;,&lt;br /&gt;
			&amp;quot;Func:logProxy_values2PieChart(\&amp;quot;dPer4\&amp;quot;,\&amp;quot;state\&amp;quot;,0,5,0,\&amp;quot;fourth\&amp;quot;)&amp;quot;&lt;br /&gt;
		]&#039;&lt;br /&gt;
        data-style=&#039;[&amp;quot;ftui l0fill&amp;quot;,&amp;quot;ftui l1fill&amp;quot;,&amp;quot;ftui l2fill&amp;quot;,&amp;quot;ftui l3fill&amp;quot;]&#039;&lt;br /&gt;
        data-ptype=&#039;[&amp;quot;lines&amp;quot;]&#039;&lt;br /&gt;
        data-uaxis=&#039;[&amp;quot;primary&amp;quot;]&#039;&lt;br /&gt;
        data-legend=&#039;[&amp;quot;First&amp;quot;,&amp;quot;Second&amp;quot;,&amp;quot;Third&amp;quot;,&amp;quot;Fourth&amp;quot;]&#039;&lt;br /&gt;
		data-legendpos=&#039;[&amp;quot;left&amp;quot;,&amp;quot;top&amp;quot;]&#039;&lt;br /&gt;
        data-yunit=&amp;quot;&amp;quot;&lt;br /&gt;
        data-height=&amp;quot;300&amp;quot;&lt;br /&gt;
        data-width=&amp;quot;300&amp;quot;&lt;br /&gt;
		data-ddd=&#039;[&amp;quot;-40&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;0&amp;quot;]&#039;&lt;br /&gt;
		data-dddspace=&#039;[&amp;quot;-10&amp;quot;]&#039;&lt;br /&gt;
		data-dddwidth=&#039;[&amp;quot;10&amp;quot;]&#039;&lt;br /&gt;
		data-showlegend=&amp;quot;true&amp;quot;&lt;br /&gt;
		data-legend_horiz=&amp;quot;true&amp;quot;&lt;br /&gt;
        data-xticks=&amp;quot;auto&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Fensterstatus offen/geschlossen===&lt;br /&gt;
Dieses Beispiel zeigt, wie ein Fensterkontakt, dessen Reading die Werte &amp;lt;code&amp;gt;closed&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt; einnimmt, als Graph gezeichnet werden kann. Technisch gesehen werden hier die Werte &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; gezeichnet, indem über das Attribut &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; dem Zustand &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt; der Wert &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; und allen anderen Zuständen der Wert &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; zugeordnet wird. Über das Attribut &#039;&#039;&#039;data-yticks&#039;&#039;&#039; wird die Beschriftung an der Y-Achse (&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;) gegen einen frei definierbaren Text ausgetauscht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	data-device=&amp;quot;wz_fensterstatus&amp;quot;&lt;br /&gt;
	data-logdevice=&#039;[&amp;quot;myDbLog&amp;quot;]&#039;&lt;br /&gt;
	data-logfile=&#039;[&amp;quot;HISTORY&amp;quot;]&#039;&lt;br /&gt;
	data-columnspec=&#039;[&amp;quot;wz_fensterstatus:state:0::$val=($val=~\\x22open\\x22?1:0)&amp;quot;]&#039;&lt;br /&gt;
	data-style=&#039;[&amp;quot;ftui l4fill&amp;quot;]&#039;&lt;br /&gt;
	data-ptype=&#039;[&amp;quot;steps&amp;quot;]&#039;&lt;br /&gt;
	data-height=&amp;quot;290&amp;quot;&lt;br /&gt;
	data-yticks=&#039;[[0,&amp;quot;geschlossen&amp;quot;],[1,&amp;quot;offen&amp;quot;]]&#039;&lt;br /&gt;
	data-minvalue=&amp;quot;0&amp;quot;&lt;br /&gt;
	data-maxvalue=&amp;quot;1.1&amp;quot;&lt;br /&gt;
	data-nofulldays=&amp;quot;true&amp;quot;&lt;br /&gt;
	data-daysago_start=&amp;quot;1&amp;quot;&lt;br /&gt;
	data-daysago_end=&amp;quot;-1&amp;quot;&lt;br /&gt;
	data-cursorgroup=&amp;quot;1&amp;quot;&lt;br /&gt;
	data-scrollgroup=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Das Beispiel funktioniert nur mit DbLog. Falls Logfiles verwendet werden muss statt &#039;$val&#039; &#039;$fld[&#039;&#039;num&#039;&#039;]&#039; verwendet werden. Hierbei steht &#039;&#039;num&#039;&#039; für die Spalte (beginnend bei 0) in der die Daten stehen.&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
{{Link2Forum|Topic= 48450 |Message=401006|LinkText=Thread im FHEM-Forum}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI|Chart]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Chart&amp;diff=27600</id>
		<title>FTUI Widget Chart</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Chart&amp;diff=27600"/>
		<updated>2018-08-04T09:00:30Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Beispiel für data-graphsshown ergänzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Chart Widget]] ist ein Widget für [[FHEM Tablet UI]], mit dem sich verschiedenste Diagramme darstellen lassen. Die Aneinanderreihung mehrerer Werte eines Device-Readings zu einem zeitlichen Verlauf wird dabei als Graph bezeichnet.&lt;br /&gt;
&lt;br /&gt;
Es können beliebige Werte dargestellt und entsprechend der Sinnhaftigkeit, oder persönlichem Geschmack, formatiert werden. Farbe und Form der Linien sind je Graph einstellbar, auch wenn mehrere gleichzeitig in einem Diagramm angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
Jedes Diagramm kann zwei Y-Achsen besitzen. Die primäre Y-Achse (primary) wird auf der linken Seite angezeigt, die sekundäre Y-Achse (secondary) auf der rechten Seite. Beide Achsen können unterschiedlich formatiert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Chart_tabletUI.png&lt;br /&gt;
Datei:FTUI Widget Chart Stacked.png&lt;br /&gt;
Datei:FTUI Widget Chart-fc-Proplanta.png&lt;br /&gt;
Datei:Wetterchart2.png&lt;br /&gt;
Datei:PieChart.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:150px&amp;quot;|Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-device&#039;&#039;&#039;||Name des FHEM-Device, das die Aktualisierung des Charts triggert||||data-device=&amp;quot;WohnzimmerHeizung&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get&#039;&#039;&#039;||Reading, das das Update des Diagramms triggert||&#039;STATE&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-logdevice&#039;&#039;&#039;||Name des Log-Device, das dargestellt werden soll, oder ein Array, um mehrere Werte in einem Diagramm darzustellen||||data-logdevice=&amp;quot;FileLog_WohnzimmerHeizung&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-logfile&#039;&#039;&#039;|| Name des Log-Files, aus dem die Daten entnommen werden sollen (oder Array)||&#039;-&#039; = aktuelle Datei||data-logfile=&amp;quot;WohnzimmerHeizung-2015.log&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-columnspec&#039;&#039;&#039;||Ermittelt den Wert aus dem Log-File, der angezeigt werden soll (oder Array)||||data-columnspec=&amp;quot;4:meas.*&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-style&#039;&#039;&#039;||Stil, wie die Graph-Linien dargestellt werden sollen (z.B. &#039;SVGplot l0&#039; oder &#039;ftui l0dash&#039;), oder ein Array, wenn mehrere Linien unterschiedlich dargestellt werden sollen (siehe [[#Aussehen_der_Linien|Hinweise]])||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-ptype&#039;&#039;&#039;||Form, wie die Graphen dargestellt werden sollen (z.B. &#039;lines&#039;, &#039;cubic&#039; oder &#039;fa-cog&#039;), oder ein Array (siehe [[#Form_der_Linien|Hinweise]])||&#039;lines&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-uaxis&#039;&#039;&#039;||Name der Achse, die verwendet werden soll (&#039;primary&#039; = links, oder &#039;secondary&#039; = rechts), oder ein Array||&#039;primary&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-legend&#039;&#039;&#039;||Bezeichnung des Graphen (wird in Legende und am Cursor angezeigt), oder ein Array||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-minvalue&#039;&#039;&#039;||Minimaler Wert, der auf der linken Y-Achse (&#039;primary&#039;) angezeigt werden soll. &#039;auto&#039; = automatische Berechnung||&#039;10&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-maxvalue&#039;&#039;&#039;||Maximaler Wert, der auf der linken Y-Achse (&#039;primary&#039;) angezeigt werden soll. &#039;auto&#039; = automatische Berechnung||&#039;30&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-minvalue_sec&#039;&#039;&#039;||Minimaler Wert, der auf der rechten Y-Achse (&#039;secondary&#039;) angezeigt werden soll. &#039;auto&#039; = automatische Berechnung||&#039;auto&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-maxvalue_sec&#039;&#039;&#039;||Maximaler Wert, der auf der rechten Y-Achse (&#039;secondary&#039;) angezeigt werden soll. &#039;auto&#039; = automatische Berechnung||&#039;auto&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-xticks&#039;&#039;&#039;||Abstand zwischen den vertikalen Hilfslinien (bezogen auf die X-Achse) in Minuten. &#039;auto&#039; = automatische Berechnung||&#039;auto&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yticks&#039;&#039;&#039;||Abstand zwischen den horizontalen Hilfslinien (bezogen auf die linke Y-Achse). Kann auch ein Array mit Werte-Paaren enthalten, um die Linien mit Text zu beschriften.||&#039;auto&#039;||data-yticks=&#039;[[0,&amp;quot;open&amp;quot;],[1,&amp;quot;closed&amp;quot;]]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yticks_format&#039;&#039;&#039;||Dient zur Formatierung der Ticks der Y-Achse. Die Formatierung geschieht über Platzhalter, Trenner und einen beliebigen durch &#039; &#039; getrennten Text. Als Platzhalter dient ein oder mehrere &#039;#&#039;, als Trenner können &#039;.&#039;, &#039;,&#039; und &#039;:&#039; verwendet werden. Ist ein Trenner enthalten (z.B. &#039;#.##&#039;) dann bedeutet das in dem Beispiel, dass der Ytick mit 2 Nachkommastellen versehen wird und vorne Platz für eine Stelle vor dem Komma vorgehalten wird (führende Nullen werden nicht dargestellt, aber de Platz wird reserviert so dass das ganze rechtsbündig immer passt). Ist kein Trenner vorhanden, dann wird der Ytick auf die Summe der Platzhalter mit einer festen Gesamtbreite gesetzt (#### würde also bedeuten, dass immer 4 Stellen (ohne Trenner) verwendet werden. aus 0.4 würde 0.400 aus 10.437 würde 10.44). Als Trenner kann man z.B. für Zeiten auch einen &#039;:&#039; verwenden und dadurch auch so etwas wie &amp;quot;12:00 Uhr&amp;quot; realisieren (in dem Beispiel wäre data-yticks_format=&amp;quot;##:## Uhr&amp;quot; und kein data-yunit oder data-yticks=&amp;quot;##:##&amp;quot; und data-yunit=&amp;quot;Uhr&amp;quot;).||||data-yticks_format=&amp;quot;#.##&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yticks_sec&#039;&#039;&#039;||Abstand zwischen den horizontalen Hilfslinien (bezogen auf die rechte Y-Achse). Kann auch ein Array mit Werte-Paaren enthalten, um die Linien mit Text zu beschriften.||&#039;auto&#039;||data-yticks=&#039;[[0,&amp;quot;open&amp;quot;],[1,&amp;quot;closed&amp;quot;]]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yticks_format_sec&#039;&#039;&#039;||Dient zur Formatierung der Ticks der Y-Achse. Die Formatierung geschieht über Platzhalter, Trenner und einen beliebigen durch &#039; &#039; getrennten Text. Als Platzhalter dient ein oder mehrere &#039;#&#039;, als Trenner können &#039;.&#039;, &#039;,&#039; und &#039;:&#039; verwendet werden. Ist ein Trenner enthalten (z.B. &#039;#.##&#039;) dann bedeutet das in dem Beispiel, dass der Ytick mit 2 Nachkommastellen versehen wird und vorne Platz für eine Stelle vor dem Komma vorgehalten wird (führende Nullen werden nicht dargestellt, aber de Platz wird reserviert so dass das ganze rechtsbündig immer passt). Ist kein Trenner vorhanden, dann wird der Ytick auf die Summe der Platzhalter mit einer festen Gesamtbreite gesetzt (#### würde also bedeuten, dass immer 4 Stellen (ohne Trenner) verwendet werden. aus 0.4 würde 0.400 aus 10.437 würde 10.44). Als Trenner kann man z.B. für Zeiten auch einen &#039;:&#039; verwenden und dadurch auch so etwas wie &amp;quot;12:00 Uhr&amp;quot; realisieren (in dem Beispiel wäre data-yticks_format=&amp;quot;##:## Uhr&amp;quot; und kein data-yunit oder data-yticks=&amp;quot;##:##&amp;quot; und data-yunit=&amp;quot;Uhr&amp;quot;).||||data-yticks_format_sec=&amp;quot;#.##&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yticks_prio&#039;&#039;&#039;||Legt fest, ob die horizontalen Hilfslinien der linken (primary) oder der rechten (secondary) Y-Achse zugeordnet werden sollen||||data-yticks_prio=&#039;secondary&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-ytype&#039;&#039;&#039;||Legt fest, ob die primäre y Achse logarithmisch sein soll (wert &amp;quot;log&amp;quot;)||||data-ytype=&amp;quot;log&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-ytype_sec&#039;&#039;&#039;||Legt fest, ob die sekundäre y Achse logarithmisch sein soll (wert &amp;quot;log&amp;quot;)||||data-ytype_sec=&amp;quot;log&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-y_margin&#039;&#039;&#039;|||Gibt die Möglichkeit, Abstände zwischen den Graphen und dem oberen Rand des Plots zu definieren (Einheit Pixel). Falls der Wert skalar ist, werden oben und unten die gleichen Abstände eingehalten. Falls ein 2D Array angegeben wird, können die Werte unten (erster Wert im Array) und oben (zweiter Wert im Array) getrennt festgelegt werden||&amp;quot;0&amp;quot;|||data-y_margin=&#039;[&amp;quot;10&amp;quot;,&amp;quot;20&amp;quot;]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-y_margin_sec&#039;&#039;&#039;|||Gibt die Möglichkeit, Abstände zwischen den Graphen und dem oberen Rand des Plots zu definieren (Einheit Pixel). Falls der Wert skalar ist, werden oben und unten die gleichen Abstände eingehalten. Falls ein 2D Array angegeben wird, können die Werte unten (erster Wert im Array) und oben (zweiter Wert im Array) getrennt festgelegt werden||&amp;quot;0&amp;quot;|||data-y_margin=&#039;[&amp;quot;10&amp;quot;,&amp;quot;20&amp;quot;]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-daysago_start&#039;&#039;&#039;||Anzahl der vergangenen Tage, wo das Diagramm beginnen soll. &#039;0&#039; = Beginn heute 0:00 Uhr. (siehe [[#Zeitstrahl_.2F_Start_.26_Ende_auf_der_X-Achse|Hinweise]])||&#039;0&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-daysago_end&#039;&#039;&#039;||Anzahl der vergangenen Tage, wo das Diagramm enden soll. &#039;-1&#039; = Ende heute 24:00 Uhr. (siehe [[#Zeitstrahl_.2F_Start_.26_Ende_auf_der_X-Achse|Hinweise]])||&#039;-1&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-xticks_round&#039;&#039;&#039;||Wenn vorhanden und entweder &#039;h&#039;, &#039;d&#039;, &#039;w&#039;, wird auf Stunde, Tag oder Woche bei den xticks gerundet (also die Tickmarks und die Gridlines bei den entsprechend gerundeten Zeiten gesetzt). Es kann auch &#039;auto&#039; angegeben werden, um eine autmoatische Rundung durchzuführen||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-nofulldays&#039;&#039;&#039;||Aktiviert/deaktiviert die Rundung der X-Achse auf ganze Tage. Binärwert (&#039;true&#039; oder &#039;false&#039;)||&#039;false&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-timeformat&#039;&#039;&#039;||Zeitformat für die Anzeige an der X-Achse (siehe [[#Zeitformat_der_X-Achse|Hinweise]])||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-timeranges&#039;&#039;&#039;||Hierdurch können vordefinierte Zeiträume für die X-Achse festgelegt werden, die dann durch eine pulldown menu (neuer Button oben neben dem &amp;quot;-&amp;quot; Button) direkt ausgewählt werden können. Der Parameter ist ein Array aus Array Einträgen, welche jeweils [&amp;lt;Name&amp;gt;,&amp;lt;daysago_start&amp;gt;,&amp;lt;daysago_end&amp;gt;] enthalten)||&lt;br /&gt;
||data-timeranges=&#039;[&amp;lt;br&amp;gt;&lt;br /&gt;
[&amp;quot;Actual Year&amp;quot;,&amp;quot;0Y&amp;quot;,&amp;quot;-1Y&amp;quot;],&amp;lt;br&amp;gt;&lt;br /&gt;
[&amp;quot;Last Year&amp;quot;,&amp;quot;1Y&amp;quot;,&amp;quot;0Y&amp;quot;],&amp;lt;br&amp;gt;&lt;br /&gt;
[&amp;quot;Actual Month&amp;quot;,&amp;quot;0M&amp;quot;,&amp;quot;-1M&amp;quot;],&amp;lt;br&amp;gt;&lt;br /&gt;
[&amp;quot;Last Month&amp;quot;,&amp;quot;1M&amp;quot;,&amp;quot;0M&amp;quot;],&amp;lt;br&amp;gt;&lt;br /&gt;
[&amp;quot;Actual Week&amp;quot;,&amp;quot;0W&amp;quot;,&amp;quot;-1W&amp;quot;],&amp;lt;br&amp;gt;&lt;br /&gt;
[&amp;quot;Last Week&amp;quot;,&amp;quot;1W&amp;quot;,&amp;quot;0W&amp;quot;],&amp;lt;br&amp;gt;&lt;br /&gt;
[&amp;quot;Today&amp;quot;,&amp;quot;0D&amp;quot;,&amp;quot;-1D&amp;quot;],&amp;lt;br&amp;gt;&lt;br /&gt;
[&amp;quot;Yesterday&amp;quot;,&amp;quot;1D&amp;quot;,&amp;quot;0D&amp;quot;]&amp;lt;br&amp;gt;&lt;br /&gt;
]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-ytext&#039;&#039;&#039;||Text, der neben der linken Y-Achse angezeigt wird||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-ytext_sec&#039;&#039;&#039;||Text, der neben der rechten Y-Achse angezeigt wird||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yunit&#039;&#039;&#039;||Einheit, die an der linken Y-Achse angezeigt wird||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yunit_sec&#039;&#039;&#039;||Einheit, die an der rechten Y-Achse angezeigt wird||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-show_both_axes&#039;&#039;&#039;||Legt fest ob beide Y-Achsen Linien gezeichnet werden sollen||false||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-crosshair&#039;&#039;&#039;||Aktiviert/deaktiviert den Fadenkreuz-Cursor. Binärwert (&#039;true&#039; oder &#039;false&#039;)||&#039;false&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-cursorgroup&#039;&#039;&#039;||Zahl zur Gruppierung der Werte am Fadenkreuz-Cursor ([[#Fadenkreuz-Cursor|Hinweise]])||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-scrollgroup&#039;&#039;&#039;||Zahl zur Gruppierung der Graphen beim Bewegen und Zoomen. Alle Linien mit der selben Zahl werden miteinander gekoppelt und bewegen sich gemeinsam.||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-showlegend&#039;&#039;&#039;||Aktiviert/deaktiviert die Anzeige der Legene. Binärwert (&#039;true&#039; oder &#039;false&#039;)||&#039;false&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-legendpos&#039;&#039;&#039;||Array von zwei Werten, die die horizontale und vertikale Position der Legende festlegen ([[#Legende|Hinweise]])||&#039;[&amp;quot;top&amp;quot;,&amp;quot;right&amp;quot;]&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-legend_horiz&#039;&#039;&#039;||legt fest, dass die Legendeneinträge horizontal angeordnet sind (anstatt vertikal wie im default Fall)||false||data-legend_horiz=&amp;quot;true&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-width&#039;&#039;&#039;||Breite des Diagramms (in % oder px)||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-height&#039;&#039;&#039;||Höhe des Diagramms (in % oder px)||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-graphsshown&#039;&#039;&#039;||Aktiviert/deaktiviert die initiale Anzeige von Graphen. Binärwert (&#039;true&#039; oder &#039;false&#039;). Array, wenn mehrere Linien angezeigt werden sollen.||||data-graphsshown=&#039;[true,false,true]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-ddd&#039;&#039;&#039;||Einstellung für die 3D-Drehung ([[#3-dimensionale_Drehung|Hinweise]])||||data-ddd=&#039;[&amp;quot;40&amp;quot;,&amp;quot;60&amp;quot;,&amp;quot;0&amp;quot;]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-dddspace&#039;&#039;&#039;||Abstand zwischen zwei Graphen, wenn die 3D-Anzeige aktiviert wurde (px)||&#039;15&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-dddwidth&#039;&#039;&#039;||Breite, bzw. Tiefe der Graphen, wenn diese 3-dimensional angezeigt werden (px)||&#039;10&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-title&#039;&#039;&#039;||Titel, der über dem Diagramm angezeigt werden soll. Der Inhalt kann auch dynamisch erzeugt werden ([[#Diagrammtitel|Hinweise]])||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-title_class&#039;&#039;&#039;||Klassenname für die Formatierung des Titels. Die Eigenschaften müssen dann entsprechend in einem CSS File angegeben werden (z.B. in fhem-tablet-ui-user.css)||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-prefetch&#039;&#039;&#039;||Legt fest, ob zusätzliche Daten rechts und links des Plots im Hintergrund vom Server geholt werden sollen||false||data-prefetch=&amp;quot;true&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
Einige Parameter (style, maxvalue, minvalue, maxvalue_sec, minvalue_sec) können auch aus Readings dynamisch gesetzt werden wenn &amp;quot;&amp;lt;device&amp;gt;:&amp;lt;reading&amp;gt;&amp;quot; als Parameter gesetzt wird. Damit kann man z.B. in FHEM über notify etc. die Linientypen dynamisch anpassen (z.B. wenn der Wert eines Devices in einem bestimmten Bereich liegt, ändert sich die Farbe des Graphen).&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|fullsize}}{{FTUI Klasse|noticks}}{{FTUI Klasse|nobuttons}}{{FTUI Klasse|small}}{{FTUI Klasse|normal}}{{FTUI Klasse|big}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Folgende Widget-spezifsche Klassen können zusätzlich in einer eigenen CSS-Datei definiert werden:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Klasse&lt;br /&gt;
!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;chart-background&#039;&#039;&#039;||Hintergrundfarbe des Diagramms&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;buttons&#039;&#039;&#039;||Größe und Farbe der Buttons&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;text.axes&#039;&#039;&#039;||Generelle Schriftart und Farbe der Achsen&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;gridlines&#039;&#039;&#039;||Generelle Farbe und Größe der Gitternetzlinien&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;xaxis&#039;&#039;&#039;||Schriftart, Größe und Farbe der X-Achse&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;yaxis&#039;&#039;&#039;||Schriftart, Größe und Farbe der Y-Achse&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;xticks&#039;&#039;&#039;||Schriftart, Größe und Farbe der X-Achse (Zwischenlinien)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;yticks&#039;&#039;&#039;||Schriftart, Größe und Farbe der Y-Achse (Zwischenlinien)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;crosshair&#039;&#039;&#039;||Schriftart, Größe und Vordergrund/Hintergrundfarbe der Momentanwerte am Fadenkreuzcursor&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;caption&#039;&#039;&#039;||Schriftart, Größe und Farbe der Text-Buttons für Legende und Cursor&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;legend&#039;&#039;&#039;||Schriftart, Größe und Farbe der Legende&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die Standardwerte sind in der Datei &amp;lt;code&amp;gt;css/ftui_chart.css&amp;lt;/code&amp;gt; zu finden.&lt;br /&gt;
&lt;br /&gt;
==Datenquellen==&lt;br /&gt;
Beim Chart-Widget können die gleichen Datenquellen genutzt werden, die auch für SVG-Plots verwendet werden können:&lt;br /&gt;
# [[FileLog]]: Verlaufsdaten einer Textdatei entnehmen&lt;br /&gt;
# [[DbLog]]: Verlaufsdaten einer Datenbank entnehmen&lt;br /&gt;
# [[LogProxy]]: Daten dynamisch berechnet&lt;br /&gt;
&lt;br /&gt;
===FileLog===&lt;br /&gt;
Um [[FileLog]] zu nutzen, wird als &#039;&#039;&#039;data-logdevice&#039;&#039;&#039; das FHEM-Device für das FileLog angegeben. In der Regel entstehen hier im Laufe der Zeit mehrere Log-Dateien. Name und Anzahl sind von der Definition abhängig - meist wird jeden Monat oder jedes Jahr eine neue Datei angelegt. Die gewünschte Datei kann mit &#039;&#039;&#039;data-logfile&#039;&#039;&#039; ausgewählt werden. Möchte man stets die aktuelle Datei verwenden (macht vor allem dann Sinn, wenn man die neusten Daten anzeigen will), kann das Attribut weggelassen, oder explizit &amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt; eingetragen werden. Zuletzt wird &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; benötigt, um die gewünschten Daten zu in der Logdatei zu identifizieren. Hier wird die Spalte, in der die Daten stehen, gefolgt von Doppelpunkt und Readingname angegeben.&lt;br /&gt;
&lt;br /&gt;
Für ein Heizungsthermostat von Homematic mit dem Namen &#039;&#039;DG.wz.HZ.Heizungsventil&#039;&#039; ergibt sich somit beispielhaft folgende Definition, um gemessene Temperatur, Sollwert und Ventilstellung im Diagramm darzustellen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	 data-device=&amp;quot;DG.wz.HZ.Heizungsventil&amp;quot;&lt;br /&gt;
	 data-logdevice=&amp;quot;FileLog_DG.wz.HZ.Heizungsventil&amp;quot;&lt;br /&gt;
	 data-logfile=&amp;quot;-&amp;quot;&lt;br /&gt;
	 data-columnspec=&#039;[&amp;quot;4:measured-temp&amp;quot;,&amp;quot;4:desired-temp&amp;quot;,&amp;quot;4:actuator&amp;quot;]&#039;&lt;br /&gt;
	 ...&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollen Daten von unterschiedlichen Geräten in einem Diagramm angezeigt werden, muss &#039;&#039;&#039;data-logdevice&#039;&#039;&#039; als Array nach dem Schema &amp;lt;code&amp;gt;data-logdevice=&#039;[&amp;quot;&amp;lt;Logdatei_1&amp;gt;&amp;quot;,&amp;quot;&amp;lt;Logdatei_2&amp;gt;&amp;quot;,&amp;quot;&amp;lt;Logdatei_3&amp;gt;&amp;quot;]&#039;&amp;lt;/code&amp;gt; definiert werden. Für jeden Eintrag in &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; muss es auch den passenden Eintrag in &#039;&#039;&#039;data-logdevice&#039;&#039;&#039; geben (auch die Reihenfolge ist relevant).&lt;br /&gt;
&lt;br /&gt;
===DbLog===&lt;br /&gt;
Um die Daten aus [[DbLog]] anzeigen zu können, werden die gleichen Attribute verwendet und mit für die Datenbank angepassten Werten beschrieben. Bei &#039;&#039;&#039;data-logdevice&#039;&#039;&#039; das FHEM-Device für die Datenbank angegeben. Im nachfolgenden Beispiel heißt diese &amp;lt;code&amp;gt;logdb&amp;lt;/code&amp;gt; und besitzt wie üblich zwei Tabellen: &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;history&amp;lt;/code&amp;gt; (der zeitliche Verlauf liegt in letzterer). Der Tabellenname wird bei &#039;&#039;&#039;data-logfile&#039;&#039;&#039; eingetragen. Da die Daten in der Datenbank etwas anders abgelegt werden, muss auch &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; entsprechend angepasst werden. Statt der Spalte wird hier das FHEM-Device, gefolgt von Doppelpunkt und Readingname angegeben.&lt;br /&gt;
&lt;br /&gt;
Für das oben beschriebene Homematic-Heizungsthermostat ergibt sich dann folgende Definition, um die gleichen Daten aus einer Datenbank, statt einem LogFile zu lesen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	 data-device=&amp;quot;DG.wz.HZ.Heizungsventil&amp;quot;&lt;br /&gt;
	 data-logdevice=&amp;quot;logdb&amp;quot;&lt;br /&gt;
	 data-logfile=&amp;quot;HISTORY&amp;quot;&lt;br /&gt;
	 data-columnspec=&#039;[&amp;quot;DG.wz.HZ.Heizungsventil:measured-temp&amp;quot;,&amp;quot;DG.wz.HZ.Heizungsventil:desired-temp&amp;quot;,&amp;quot;DG.wz.HZ.Heizungsventil:actuator&amp;quot;]&#039;&lt;br /&gt;
	 ...&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für die Anzeige von unterschiedlichen Geräten in einem Diagramm, muss nur &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; entsprechend angepasst werden, solange sich alle Daten in der Datenbank befinden.&lt;br /&gt;
&lt;br /&gt;
===LogProxy===&lt;br /&gt;
Um die Daten mittels [[LogProxy]] berechnen und anzeigen zu können, muss in FHEM ein LogProxy-Device definiert sein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define myLogProxy logProxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Einstellungen am LogProxy sind nicht nötig, die bloße Existenz reicht.&lt;br /&gt;
&lt;br /&gt;
Bei &#039;&#039;&#039;data-logdevice&#039;&#039;&#039; wird das FHEM-Device für den LogProxy angegeben. Im nachfolgenden Beispiel heißt dieses &amp;lt;code&amp;gt;myLogProxy&amp;lt;/code&amp;gt;. Das Attribut &#039;&#039;&#039;data-logfile&#039;&#039;&#039; wird für LogProxy nicht benötigt. Befinden sich nur LogProxy-Werte im Diagramm kann das Attribut komplett entfallen. Sollen weitere Werte angezeigt werden, bleibt die Definition im Array einfach leer.&lt;br /&gt;
&lt;br /&gt;
Im Attribut &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; wird eine Formel angegeben, wie die Werte berechnet werden sollen. Hier können die Formeln 1:1 von einem eventuell vorhandenen SVG-Plot übernommen werden. &#039;&#039;&#039;Dabei gibt es jedoch folgendes zu beachten:&#039;&#039;&#039; Befindet sich die Formel in einem Array, dürfen die Formeln keine Anführungszeichen (&amp;lt;code&amp;gt;&amp;quot;&amp;lt;/code&amp;gt;) beinhalten. Stattdessen müssen sie als escapter Ascii-Code (&amp;lt;code&amp;gt;\\x22&amp;lt;/code&amp;gt;) eingefügt werden.&lt;br /&gt;
&lt;br /&gt;
Das nachfolgende Beispiel zeigt, wie Vorhersagewerte aus einem FHEM-Device vom Typ Proplanta (Name hier &amp;lt;code&amp;gt;AU.xx.WE.Proplanta&amp;lt;/code&amp;gt;) angezeigt werden können.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	 data-device=&amp;quot;AU.xx.WE.Proplanta&amp;quot;&lt;br /&gt;
	 data-logdevice=&#039;[&lt;br /&gt;
						&amp;quot;myLogProxy&amp;quot;,&lt;br /&gt;
						&amp;quot;myLogProxy&amp;quot;,&lt;br /&gt;
						&amp;quot;myLogProxy&amp;quot;,&lt;br /&gt;
						&amp;quot;myLogProxy&amp;quot;&lt;br /&gt;
					]&#039;&lt;br /&gt;
	 data-columnspec=&#039;[&lt;br /&gt;
						&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22temp_\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;,&lt;br /&gt;
						&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22rain_\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;,&lt;br /&gt;
						&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22chOfRain_\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;,&lt;br /&gt;
						&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22cloud_\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;&lt;br /&gt;
					]&#039;&lt;br /&gt;
	 ...&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Auch alle anderen Funktionen, die [[LogProxy]] bietet, können hier angewendet werden.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
===Aktualisierung des Charts===&lt;br /&gt;
Damit der Refresh des Charts funktioniert, muss auch ein Device angegeben werden, der das Refresh triggert. Das Diagramm wird immer dann aktualisiert, wenn sich der Inhalt von &#039;&#039;&#039;data-get&#039;&#039;&#039; ändert.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	data-device=&amp;quot;WohnzimmerHeizung&amp;quot;&lt;br /&gt;
	data-logdevice=&amp;quot;FileLog_WohnzimmerHeizung&amp;quot;&lt;br /&gt;
	...&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Aussehen der Linien===&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;data-style&#039;&#039;&#039; kann das Aussehen der Linien des jeweiligen Graphen verändert werden. Hierfür können die Standard-FHEM-Styles verwendet werden. Dazu wird das Attribut mit &amp;lt;code&amp;gt;SVGplot&amp;lt;/code&amp;gt;, gefolgt von einem Leerzeichen und der gewünschten Farbe/Stil befüllt. Es existieren jedoch auch noch weitere, an FTUI angepasste Styles, zu finden in der CSS-Datei &amp;lt;code&amp;gt;css/ftui_chart.css&amp;lt;/code&amp;gt;. Um diese zu verwenden, wird das Attribut mit &amp;lt;code&amp;gt;ftui&amp;lt;/code&amp;gt;, gefolgt von einem Leerzeichen und der gewünschten Farbe/Stil befüllt. Eigene Styles können zum Beispiel in der Datei &amp;lt;code&amp;gt;css/fhem-table-ui-user.css&amp;lt;/code&amp;gt; definiert werden.&lt;br /&gt;
&lt;br /&gt;
Folgende Übersicht zeigt die im Standard verfügbaren &#039;&#039;&#039;Farben&#039;&#039;&#039;, alle Abbildungen sind mit im FTUI-Style entstanden:&lt;br /&gt;
&amp;lt;div&amp;gt;&amp;lt;ul&amp;gt; &lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Farbe-f0.png|thumb|none|150px|Farbe &amp;quot;l0&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Farbe-f1.png|thumb|none|150px|Farbe &amp;quot;l1&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Farbe-f2.png|thumb|none|150px|Farbe &amp;quot;l2&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Farbe-f3.png|thumb|none|150px|Farbe &amp;quot;l3&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Farbe-f4.png|thumb|none|150px|Farbe &amp;quot;l4&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Farbe-f5.png|thumb|none|150px|Farbe &amp;quot;l5&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Farbe-f6.png|thumb|none|150px|Farbe &amp;quot;l6&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Angabe zur Farbe kann dann mit der Linienart kombiniert werden. Dazu stehen folgende &#039;&#039;&#039;Stile&#039;&#039;&#039; zur Verfügung:&lt;br /&gt;
&amp;lt;div&amp;gt;&amp;lt;ul&amp;gt; &lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-2D-normal.png|thumb|none|225px|Darstellung in 2D: Stil &amp;quot;normal&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-2D-dot.png|thumb|none|225px|Darstellung in 2D: Stil &amp;quot;dot&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-2D-dash.png|thumb|none|225px|Darstellung in 2D: Stil &amp;quot;dash&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-2D-fill.png|thumb|none|225px|Darstellung in 2D: Stil &amp;quot;fill&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-2D-sym.png|thumb|none|225px|Darstellung in 2D: Stil &amp;quot;sym&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div&amp;gt;&amp;lt;ul&amp;gt; &lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-3D-normal.png|thumb|none|225px|Darstellung in 3D: Stil &amp;quot;normal&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-3D-dot.png|thumb|none|225px|Darstellung in 3D: Stil &amp;quot;dot&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-3D-dash.png|thumb|none|225px|Darstellung in 3D: Stil &amp;quot;dash&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-3D-fill.png|thumb|none|225px|Darstellung in 3D: Stil &amp;quot;fill&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;display: inline-block;&amp;quot;&amp;gt; [[File:FTUI_Widget_Chart_Form-3D-sym.png|thumb|none|225px|Darstellung in 3D: Stil &amp;quot;sym&amp;quot;]] &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Farbe und Stil werden kombiniert (zusammengeschrieben) beim Attribut &#039;&#039;&#039;data-style&#039;&#039;&#039; angegeben, sodass sich beispielsweise für eine graue Punktlinie folgendes ergibt: &amp;lt;code&amp;gt;data-style=&amp;quot;ftui l1dot&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
Um die Darstellung als normale Linie zu erhalten, darf im Gegensatz zu den anderen Linienformen der Stil &amp;lt;code&amp;gt;normal&amp;lt;/code&amp;gt; nicht angegeben werden. Für eine einfache graue Linie ist also die Angabe &amp;lt;code&amp;gt;data-style=&amp;quot;ftui l1&amp;quot;&amp;lt;/code&amp;gt; korrekt, wohingegen &amp;lt;code&amp;gt;data-style=&amp;quot;ftui l1normal&amp;quot;&amp;lt;/code&amp;gt; zu einer fehlerhaften Anzeige führt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Der Stil &#039;&#039;sym&#039;&#039; ist speziell dafür geeignet, Symbole statt Linien zu zeichnen. Dazu kann beim Attribut &#039;&#039;&#039;data-ptype&#039;&#039;&#039; als Linienform ein beliebiges Font-Awsome-, oder Open Automation-Icon angegeben werden. Alle in diesem Abschnitt enthaltenen Abbildungen sind mit &amp;lt;code&amp;gt;data-ptype=&amp;quot;lines&amp;quot;&amp;lt;/code&amp;gt; entstanden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Übergänge mit datenabhängigen Grenzen:&#039;&#039;&#039; Plotstile (data-style) können auch direkt als Gradienten auf Basis von Plot-Datenwerten definiert werden. Dazu muss der Plotstil als Array angegeben werden. Der erste Wert des Arrays gibt an, ob nur die Linie gezeichnet werden soll (Zahl angeben, die die Dicke der Linie definiert) oder gefüllt (&amp;quot;fill&amp;quot; eintragen). Alle danach folgenden Array Elemente sind beliebig viele Stopp Punkte für die Farbübergänge, welche wiederum aus Arrays mit 3 Parametern bestehen. Für jeden Stopp Punkt werden der Datenwert, die Farbe und die Durchsichtigkeit gesetzt. Hierdurch lassen sich z.B. Einfärbungen setzen, die für Temperaturplots immer negative Werte blau einfärben und positive Werte rot. Zwischen den Stop Punkten wird die Farbe interpoliert, also ein weicher Übergang generiert. Will man harte Übergänge muss man Zwei Stopp Punkte mit unterschiedlichen Farbwerten aber dem gleichen Datenwert erzeugen.&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel 1 für einen weichen Gradienten, der bei 0 von blau nach rot übergeht, bei diesem Übergang durchsichtig ist und von dort nach negativen bzw. positiven Werden immer deckender wird:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;data-style=&#039;[&amp;quot;fill&amp;quot;,[&amp;quot;-20&amp;quot;,&amp;quot;#0000ff&amp;quot;,&amp;quot;0.7&amp;quot;],[&amp;quot;0&amp;quot;,&amp;quot;#0000ff&amp;quot;,&amp;quot;0&amp;quot;],[&amp;quot;0&amp;quot;,&amp;quot;#ff0000&amp;quot;,&amp;quot;0&amp;quot;],[&amp;quot;302&amp;quot;,&amp;quot;#ff0000&amp;quot;,&amp;quot;0.7&amp;quot;]]&#039;&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel 2 mit einem harten Übergang von blau nach rot bei 0:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;data-style=&#039;[&amp;quot;fill&amp;quot;,[&amp;quot;-20&amp;quot;,&amp;quot;#0000ff&amp;quot;,&amp;quot;0.7&amp;quot;],[&amp;quot;0&amp;quot;,&amp;quot;#0000ff&amp;quot;,&amp;quot;0.7&amp;quot;],[&amp;quot;0&amp;quot;,&amp;quot;#ff0000&amp;quot;,&amp;quot;0.7&amp;quot;],[&amp;quot;50&amp;quot;,&amp;quot;#ff0000&amp;quot;,&amp;quot;0.7&amp;quot;]]&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
Es gibt auch die Möglichkeit den Bereich zwischen zwei Graphen einzufärben. Dazu muss ein Wert in Columnspec als Array angegeben werden. Ist dies der Fall, dann wird der zweite Graph umgekehrt an den ersten angehängt.&amp;lt;br&amp;gt;&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
data-columnspec=&#039;[&lt;br /&gt;
    &amp;quot;Func:logProxy_proplanta2Plot(\\x22AgroWeather\\x22,\\x22weatherIcon\\x22,$from,$to,12)&amp;quot;,&lt;br /&gt;
    [&lt;br /&gt;
        &amp;quot;Func:logProxy_proplanta2Plot(\\x22AgroWeather\\x22,\\x22tempMax\\x22,$from,$to,12)&amp;quot;,&lt;br /&gt;
        &amp;quot;Func:logProxy_proplanta2Plot(\\x22AgroWeather\\x22,\\x22tempMin\\x22,$from,$to,12)&amp;quot;&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;Func:logProxy_proplanta2Plot(\\x22AgroWeather\\x22,\\x22rain\\x22,$from,$to,0,\\x22day\\x22)&amp;quot;&lt;br /&gt;
]&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Datei:FTUI Widget Chart DynamicStyles.png|thumb|none|225px|dynamischer Übergang]]&lt;br /&gt;
&lt;br /&gt;
===Form der Linien===&lt;br /&gt;
Das Attribut &#039;&#039;&#039;data-ptype&#039;&#039;&#039; beeinflusst die Form der Linien. Hier sind folgende Werte möglich:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;lines&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;steps&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;fsteps&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;histeps&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;bars&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ibars&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;cubic&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;quadratic&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;quadraticSmooth&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich ist es möglich, Symbole anzeigen zu lassen. Unterstützt werden Font-Awesome (&#039;fa-...&#039;), Open Automation (&#039;oa-...&#039;) und FHEM-Symbole (&#039;fs-...&#039;)). Damit die Symbole korrekt angezeigt werden, muss  im Attribut &#039;&#039;&#039;data-style&#039;&#039;&#039; der Stil &amp;lt;code&amp;gt;sym&amp;lt;/code&amp;gt; gewählt werden, da sonst nur Punkte, statt der Symbole gezeichnet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	 data-device=&amp;quot;DG.wz.HZ.Heizungsventil&amp;quot;&lt;br /&gt;
	 data-logdevice=&amp;quot;FileLog_DG.wz.HZ.Heizungsventil&amp;quot;&lt;br /&gt;
	 ...&lt;br /&gt;
	 data-style=&amp;quot;ftui l1sym&amp;quot;&lt;br /&gt;
	 data-ptype=&amp;quot;fa-cog&amp;quot;&lt;br /&gt;
	 ...&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Größe der Symbole ist in der Datei &amp;lt;code&amp;gt;css/ftui_chart.css&amp;lt;/code&amp;gt; auf 12px festgelegt. Dieser Wert kann in einer eigenen CSS-Datei durch Anpassung von &amp;lt;code&amp;gt;stroke-width&amp;lt;/code&amp;gt; überschrieben werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
.ftui.l0sym		{ stroke:#DDA400; stroke-width:12px; fill:none; }&lt;br /&gt;
.ftui.l1sym		{ stroke:#BBBBBB; stroke-width:12px; fill:none; }&lt;br /&gt;
.ftui.l2sym		{ stroke:#CC0000; stroke-width:12px; fill:none; }&lt;br /&gt;
.ftui.l3sym		{ stroke:#CCCC00; stroke-width:12px; fill:none; }&lt;br /&gt;
.ftui.l4sym		{ stroke:#33CC33; stroke-width:12px; fill:none; }&lt;br /&gt;
.ftui.l5sym		{ stroke:#33CCCC; stroke-width:12px; fill:none; }&lt;br /&gt;
.ftui.l6sym		{ stroke:#3333CC; stroke-width:12px; fill:none; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;data-ptype&#039;&#039;&#039; kann auch Inhalt im Format &amp;lt;code&amp;gt;&#039;icon:1&#039;&amp;lt;/code&amp;gt; verarbeiten. Dann muss der zugehörige Wert in &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; den Pfad zu einem Icon (z.B. für Wettervorhersagen) beinhalten. Der Y-Wert wird dann vom ersten Graphen übernommen. Weitere Ausführungen hierzu im Beispiel [[#Darstellung der Wetter Icons im Diagramm]]. &lt;br /&gt;
&lt;br /&gt;
===Stapeln von Linien===&lt;br /&gt;
Über &#039;&#039;&#039;data-ptype&#039;&#039;&#039; kann zusätzlich festgelegt werden, ob Graphen übereinander gestapelt werden sollen. &amp;lt;code&amp;gt;data-ptype=&#039;lines:1&#039;&amp;lt;/code&amp;gt; bedeutet, dass der zugehörige Graph auf den Graph mit der Nummer 1 gestapelt werden soll. So etwas kann z.B. Sinn machen, wenn man den Stromverbrauch einzelner Devices darstellen und zusätzlich sehen will, wie hoch die Summe ist. Beispiel siehe unten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:FTUI Widget Chart Stacked.png]]&lt;br /&gt;
&lt;br /&gt;
===Zeitstrahl / Start &amp;amp; Ende auf der X-Achse===&lt;br /&gt;
Die Attribute &#039;&#039;&#039;data-daysago_start&#039;&#039;&#039; und &#039;&#039;&#039;data-daysago_end&#039;&#039;&#039; dienen der Definition von Anfang und Ende der X-Achse. Im einfachsten Fall wird eine Anzahl an Tagen eingegeben, die sich auf das aktuelle Datum beziehen. Dabei gilt es zu beachten, dass es sich um &#039;&#039;vergangene Tage&#039;&#039; handelt. Das bedeutet, dass Tage in der Vergangenheit als positive Zahl angegeben werden, Tage in der Zukunft hingegen als negative Zahl. Es kann jeweils  auch ein fixes Datum (z.B. &#039;2013-10-23&#039;) angegeben werden. Uhrzeitangaben werden nur berücksichtigt, wenn &#039;&#039;&#039;data-nofulldays=&#039;true&#039; &#039;&#039;&#039; verwendet wird.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Relative Zeitangabe in Stunden&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Zur Ausgabe einer Anzahl an zurückliegenden Stunden bis zum aktuellen Zeitpunkt wird als Startzeitpunkt die Anzahl der Stunden angegeben werden, die angezeigt werden sollen, gefolgt vom Kleinbuchstaben &#039;&#039;&#039;h&#039;&#039;&#039;. Als Endzeitpunkt wird &#039;&#039;&#039;now&#039;&#039;&#039; gewählt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das nachfolgende Beispiel zeigt die Werte der vergangenen 3 Stunden an:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
data-nofulldays=&amp;quot;true&amp;quot;&lt;br /&gt;
data-daysago_start=&amp;quot;3h&amp;quot;&lt;br /&gt;
data-daysago_end=&amp;quot;now&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Fester Zeitbereich des heutigen Tages (Stunden)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Um ein festes Stundenfenster des heutigen Tages anzuzeigen, werden die absoluten Stundenzahlen mit negativem Vorzeichen, gefolgt vom Großbuchstaben &#039;&#039;&#039;H&#039;&#039;&#039; angegeben. Wird &#039;&#039;&#039;data-daysago_start&#039;&#039;&#039; als positiver Wert angegeben, wird die Anzahl der Stunden von heute 0:00 Uhr subtrahiert (siehe Rechenweg weiter unten).&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Beispiel zeigt den Zeitbereich von heute 5:00 Uhr bis heute 22:00 Uhr:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
data-nofulldays=&amp;quot;true&amp;quot;&lt;br /&gt;
data-daysago_start=&amp;quot;-5H&amp;quot;&lt;br /&gt;
data-daysago_end=&amp;quot;-22H&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Fester Zeitbereich Tage-übergreifend&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Die Zeit in Tagen kann als Gleitkommazahl angegeben werden. Damit ist es möglich, Tage und Uhrzeiten zu kombinieren. Die Werte sind dann als Teil eines ganzen Tages, bezogen auf heute 0:00 Uhr zu errechnen und mit &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt; als Teiler anzugeben.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das nachfolgende Beispiel zeigt einen Zeitbereich von &#039;&#039;&#039;gestern 15:00 Uhr&#039;&#039;&#039; bis &#039;&#039;&#039;morgen 3:00 Uhr&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
data-nofulldays=&amp;quot;true&amp;quot;&lt;br /&gt;
data-daysago_start=&amp;quot;0.375&amp;quot;&lt;br /&gt;
data-daysago_end=&amp;quot;-1.125&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für die nachfolgenden Rechenwege sind die Einheiten nur zur Verdeutlichung angegeben. Die Einheiten werden im Attribut nicht angegeben.&lt;br /&gt;
&lt;br /&gt;
Der Wert für &#039;&#039;&#039;GESTERN&#039;&#039;&#039; wird wie folgt ermittelt:&amp;lt;br /&amp;gt;&lt;br /&gt;
Ausgangspunkt ist heute 0:00 Uhr, gestern 15:00 Uhr liegt also 9 Stunden davor. Diese 9 Stunden sind ein &amp;lt;code&amp;gt;9/24 Tag&amp;lt;/code&amp;gt; und errechnet sich so:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1d / 24h = 0.0416666...d/h&lt;br /&gt;
0.0416d/h * 9h = 0.375d&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Wert für &#039;&#039;&#039;MORGEN&#039;&#039;&#039; wird wie folgt ermittelt:&amp;lt;br /&amp;gt;&lt;br /&gt;
Ausgangspunkt ist wieder heute 0:00 Uhr, morgen 3:00 Uhr liegt dann 27 Stunden dahinter. Der Einfachheit halber werden hier nur die 3 Stunden errechnet und dann ein ganzer Tag addiert:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1d / 24h = 0.0416666...d/h&lt;br /&gt;
0.0416d/h * 3h = 0.125d&lt;br /&gt;
&lt;br /&gt;
0.125d + 1d = 1.125d&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Da das Attribut Tage in der Vergangenheit erwartet, muss für einen Wert in der Zukunft wieder eine negative Zahl angegeben werden.&lt;br /&gt;
&lt;br /&gt;
===Zeitformat der X-Achse===&lt;br /&gt;
Die Zeitanzeige auf der X-Achse kann sehr flexibel eingestellt werden. Dafür stehen verschiedene Platzhalter zur Verfügung, die durch spezielle Zeichen (&amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt; &amp;lt;/code&amp;gt; (Leerzeichen), &amp;lt;code&amp;gt;:&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;,&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt;) getrennt werden. Alle Zeichen werden trotz Escape-Zeichen (&amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt;) in der Ausgabe angezeigt.&lt;br /&gt;
&lt;br /&gt;
Folgende Platzhalter werden unterstützt:&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;mm&#039;&amp;lt;/code&amp;gt;: Minuten als zweistellige Zahl&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;hh&#039;&amp;lt;/code&amp;gt;: Stunden als zweistellige Zahl&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;dd&#039;&amp;lt;/code&amp;gt;: Tag als zweistellige Zahl (Kalenderdatum)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;MM&#039;&amp;lt;/code&amp;gt;: Monat als zweistellige Zahl (z.B. 02 für Februar)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;MMM&#039;&amp;lt;/code&amp;gt;: Monat als dreistellige Abkürzung (z.B. Dec für Dezember)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;MMMM&#039;&amp;lt;/code&amp;gt;: Langname des Monats (z.B. March)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;ee&#039;&amp;lt;/code&amp;gt;: Wochentag als zweistellige Zahl (z.B. 00 für Sonntag)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;eee&#039;&amp;lt;/code&amp;gt;: Wochentag als dreistellige Abkürzung (z.B. Mon für Montag)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;eeee&#039;&amp;lt;/code&amp;gt;: Langname des Wochentags (z.B. Tuesday)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;yy&#039;&amp;lt;/code&amp;gt;: Jahr als zweistellige Zahl (z.B. 16 für 2016)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;yyyy&#039;&amp;lt;/code&amp;gt;: Jahr als vierstellige Zahl (z.B. 2016)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;LF&#039;&amp;lt;/code&amp;gt;: Fügt einen Zeilenumbruch hinzu&lt;br /&gt;
&lt;br /&gt;
Beispiel: Der String &amp;lt;code&amp;gt;&#039;MMM\LF\yyyy&#039;&amp;lt;/code&amp;gt; zeigt &amp;lt;code&amp;gt;&#039;Jan&#039;&amp;lt;/code&amp;gt; in der ersten, und &amp;lt;code&amp;gt;&#039;2016&#039;&amp;lt;/code&amp;gt; in der zweiten Zeile. &amp;lt;code&amp;gt;&#039;MM.dd 2016&#039;&amp;lt;/code&amp;gt; wird zu &amp;lt;code&amp;gt;&#039;03.05 2016&#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Fadenkreuz-Cursor===&lt;br /&gt;
Der Fadenkreuz-Cursor zeigt die Momentanwerte, indem man ihn über die Graphen bewegt. In Desktop-Browsern reicht einfaches Bewegen des Maus. Unter iOS und Android kann der Cursor wird der Cursor durch einfaches Tippen auf die neue Position bewegt.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;data-cursorgroup&#039;&#039;&#039; können Graphen gruppiert werden. Am Cursor werden dann die Momentanwerte aller Graphen gleichzeitig angezeigt, die die selbe Zahl besitzen, sobald man die Maus über einen aus der Gruppe bewegt.&lt;br /&gt;
&lt;br /&gt;
===Legende===&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;data-legendpos&#039;&#039;&#039; kann die Position der Legende innerhalb des Diagramms festgelegt werden. Die Position wird mit einem Array, bestehend aus zwei Werten im Format &amp;lt;code&amp;gt;&#039;[&amp;quot;&amp;lt;horizontal&amp;gt;&amp;quot;,&amp;quot;&amp;lt;vertikal&amp;gt;&amp;quot;]&#039;&amp;lt;/code&amp;gt; angegeben. Für die horizontale Positionierung sind &amp;lt;code&amp;gt;&#039;left&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;right&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;before&#039;&amp;lt;/code&amp;gt;, und &amp;lt;code&amp;gt;&#039;behind&#039;&amp;lt;/code&amp;gt;, die vertikale Positionierung &amp;lt;code&amp;gt;&#039;top&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;bottom&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;above&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;below&#039;&amp;lt;/code&amp;gt; erlaubt (der Unterschied zwischen &amp;lt;code&amp;gt;&#039;left&#039;&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;&#039;before&#039;&amp;lt;/code&amp;gt; liegt darin, dass im zweiten Fall die Legende nicht in den Zeichenbereich gesetzt wird sondern vor das ganze Chart (entsprechend für &amp;lt;code&amp;gt;&#039;after&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;above&#039;&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;&#039;below&#039;&amp;lt;/code&amp;gt;). Alternativ können auch Zahlen verwendet werden, die die Position in Prozent angeben. Durch verschieben mit der Maus oder durch verschieben mit dem Finger oder Stift auf Touch Devices kann die Legende auch an eine andere Position verschoben werden.&lt;br /&gt;
&lt;br /&gt;
Wenn die Legende eingeblendet ist, kann mittels Klick auf einen Legendeneintrag der zugehörige Graph ein- und ausgeblendet werden.&lt;br /&gt;
&lt;br /&gt;
===3-dimensionale Drehung===&lt;br /&gt;
&#039;&#039;&#039;data-ddd&#039;&#039;&#039; ermöglicht, den Graphen 3-dimensional zu drehen. Als Wert wird ein Array mit den 3 Winkeln für x, y und z erwartet, wobei z selbst bisher nicht unterstützt wird.&lt;br /&gt;
&lt;br /&gt;
Beispiel: &amp;lt;code&amp;gt;data-ddd=&#039;[&amp;quot;40&amp;quot;,&amp;quot;60&amp;quot;,&amp;quot;0&amp;quot;]&#039;&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Wenn der 3D Modus aktiv ist (&#039;&#039;&#039;data-ddd&#039;&#039;&#039; gesetzt) sind 2 zusätzliche Parameter verfügbar um das Aussehen der Graphen zu beeinflussen. &#039;&#039;&#039;data-dddspace&#039;&#039;&#039; gibt an, wie viele pixel der Raum zwischen den einzelnen in z-Richtung hintereinander angeordneten Graphen betragen soll.&lt;br /&gt;
&#039;&#039;&#039;data-dddwidth&#039;&#039;&#039; legt fest, wie viele pixel die einzelnen Graphen tief (oder dick) sein sollen.&lt;br /&gt;
&lt;br /&gt;
Wenn das Array angegeben wird, erscheinen zwei zusätzliche Buttons im Diagramm, mit denen die Drehung in X- und Y-Richtung verändert werden kann.&lt;br /&gt;
&lt;br /&gt;
===Diagrammtitel===&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;data-title&#039;&#039;&#039; kann dem Diagramm, ähnlich wie in FHEM-SVG-Plots, ein Titel hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
Folgende Platzhalter werden unterstützt:&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;min1&#039;&amp;lt;/code&amp;gt;: Minimaler Y-Wert des ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;max1&#039;&amp;lt;/code&amp;gt;: Maximaler Y-Wert des ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;avg1&#039;&amp;lt;/code&amp;gt;: Mittlerer Y-Wert des ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;cnt1&#039;&amp;lt;/code&amp;gt;: Anzahl der dargestellten Einzelwerte im ersten Graph&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;currval1&#039;&amp;lt;/code&amp;gt;: Letzter, bzw. aktuellster Y-Wert des ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;mindate1&#039;&amp;lt;/code&amp;gt;: Niedrigster Wert auf der X-Achse des ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;maxdate1&#039;&amp;lt;/code&amp;gt;: Höchster Wert auf der X-Achse vom ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;currdate1&#039;&amp;lt;/code&amp;gt;: Letzter, bzw. aktuellster Wert auf der X-Achse des ersten Graphs&lt;br /&gt;
&lt;br /&gt;
Durch Einsetzen einer anderen Zahl statt &#039;1&#039; können auch die Werte der anderen Graphen angezeigt werden. Das Weglassen der Zahl bewirkt, dass der jeweils zutreffende Wert automatisch ermittelt wird. Bedeutet: &amp;lt;code&amp;gt;max&amp;lt;/code&amp;gt; führt dazu, dass der höchste Wert aller angezeigter Graphen verwendet wird.&lt;br /&gt;
Zusätzlich ist es möglich durch &amp;quot;$eval(&amp;lt;regexp&amp;gt;)&amp;quot; regular Expressions auszuwerten (also z.B. Berechnungen durchzuführen). In &amp;lt;regexp&amp;gt; können auch &amp;quot;$data()&amp;quot; vorkommen.&lt;br /&gt;
&lt;br /&gt;
Beispiel: &amp;lt;code&amp;gt;data-title=&amp;quot;Klima Wohnzimmer Average: $eval(parseInt($data{avg1}*10)/10)°C / Max: $eval(parseInt($data{max1}*10)/10)°C&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Buttons im Diagramm===&lt;br /&gt;
Es gibt mehrere Buttons, mit denen sich die Anzeige des Diagramms verändern lässt. &amp;lt;code&amp;gt;&amp;lt;-&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;-&amp;gt;&amp;lt;/code&amp;gt; bewegen die Graphen nach links und rechts. &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt; zoomen die Anzeige. &amp;lt;code&amp;gt;legend&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;cursor&amp;lt;/code&amp;gt; schalten die zugehörigen Anzeigen ein und aus. Falls der 3D Modus eingeschaltet ist, gibt es Buttons zum Drehen der Darstellung um die X- und Y-Achse. Falls &amp;lt;code&amp;gt;data-timeranges&amp;lt;/code&amp;gt; gesetzt ist, wird ein Pulldown Menü dargestellt, welches die Auswahl von dort definierten Zeiträumen für die X-Achse erlaubt.&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===Einfaches Diagramm===&lt;br /&gt;
Das Beispiel zeigt ein einfaches Diagramm mit 4 unterschiedlich formatierten Graphen, Legende und Momentanwerten am Fadenkreuz-Cursor.&lt;br /&gt;
&lt;br /&gt;
[[File:Chart_tabletUI.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	data-logdevice=&#039;[&amp;quot;Log.Garden&amp;quot;,&amp;quot;Log.Garden&amp;quot;,&amp;quot;Log.Garden&amp;quot;,&amp;quot;Log.Predicted&amp;quot;]&#039;&lt;br /&gt;
	data-columnspec=&#039;[&amp;quot;4:Garden.T:15:&amp;quot;,&amp;quot;10:Garden.T:0:delta-h&amp;quot;,&amp;quot;10:Garden.T:0:delta-d&amp;quot;,&amp;quot;4:predicted.*:15:&amp;quot;]&#039;&lt;br /&gt;
	data-style=&#039;[&amp;quot;ftui l0fill&amp;quot;,&amp;quot;ftui l1fill&amp;quot;,&amp;quot;ftui l2&amp;quot;,&amp;quot;ftui l3dot&amp;quot;]&#039;&lt;br /&gt;
	data-ptype=&#039;[&amp;quot;lines&amp;quot;,&amp;quot;histeps&amp;quot;,&amp;quot;histeps&amp;quot;,&amp;quot;cubic&amp;quot;]&#039;&lt;br /&gt;
	data-uaxis=&#039;[&amp;quot;primary&amp;quot;,&amp;quot;secondary&amp;quot;,&amp;quot;secondary&amp;quot;,&amp;quot;primary&amp;quot;]&#039;&lt;br /&gt;
	data-legend=&#039;[&amp;quot;Temperature&amp;quot;,&amp;quot;Rain/hour&amp;quot;,&amp;quot;Rain/day&amp;quot;,&amp;quot;Predicted Temp.&amp;quot;]&#039;&lt;br /&gt;
	data-yunit=&amp;quot;°C&amp;quot;&lt;br /&gt;
	data-ytext=&amp;quot;Temperature&amp;quot;&lt;br /&gt;
	data-minvalue=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-maxvalue=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-yunit_sec=&amp;quot;mm&amp;quot;&lt;br /&gt;
	data-ytext_sec=&amp;quot;Rain (mm)&amp;quot;&lt;br /&gt;
	data-height=&amp;quot;250&amp;quot;&lt;br /&gt;
	data-yticks=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-minvalue_sec=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-maxvalue_sec=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-nofulldays=&amp;quot;true&amp;quot;&lt;br /&gt;
	data-daysago_start=&amp;quot;2013-08-13T00:00:00&amp;quot;&lt;br /&gt;
	data-daysago_end=&amp;quot;2013-08-14T00:00:00&amp;quot;&lt;br /&gt;
	data-cursorgroup=&amp;quot;1&amp;quot;&lt;br /&gt;
	data-scrollgroup=&amp;quot;1&amp;quot;&lt;br /&gt;
	data-xticks=&amp;quot;auto&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===7-Tage-Wettervorhersage mit Proplanta===&lt;br /&gt;
In diesem Beispiel wird gezeigt, wie die Vorhersagewerte von [[PROPLANTA]] in einem Diagramm dargestellt werden können. Da die Werte nicht in einer Datenbank oder einem FileLog vorliegen, müssen sie über [[LogProxy]] verarbeitet werden. Dafür sind einige Vorbereitungen in FHEM nötig.&lt;br /&gt;
&lt;br /&gt;
[[File:FTUI_Widget_Chart-fc-Proplanta.png|941px]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Ein LogProxy-Device muss vorhanden sein:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define myLogProxy logProxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; In der Datei &amp;lt;code&amp;gt;99_myUtils.pm&amp;lt;/code&amp;gt; muss folgende Routine hinzugefügt werden, die die Daten bereitstellt:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#---------------------------------------&lt;br /&gt;
# Proplanta LogProxy-Funktion&lt;br /&gt;
#---------------------------------------&lt;br /&gt;
sub logProxy_proplanta2Plot($$$$;$$) {&lt;br /&gt;
	my ($device, $fcValue, $from, $to, $fcHour, $expMode) = @_;&lt;br /&gt;
    my $regex;&lt;br /&gt;
    my @rl;&lt;br /&gt;
    &lt;br /&gt;
	return undef if(!$device);&lt;br /&gt;
    &lt;br /&gt;
    if($fcValue =~ s/_$//) {&lt;br /&gt;
        $regex = &amp;quot;^fc[\\d]+_&amp;quot;.$fcValue.&amp;quot;[\\d]{2}\$&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        $regex = &amp;quot;^fc[\\d]+_&amp;quot;.$fcValue.&amp;quot;\$&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    $fcHour = 12 if(!defined $fcHour);&lt;br /&gt;
    $expMode = &amp;quot;point&amp;quot; if(!defined $expMode);&lt;br /&gt;
&lt;br /&gt;
	if( defined($defs{$device}) ) {&lt;br /&gt;
		if( $defs{$device}{TYPE} eq &amp;quot;PROPLANTA&amp;quot; ) {&lt;br /&gt;
            @rl = sort{&lt;br /&gt;
                my ($an) = ($a =~ m/fc(\d+)_.*/);&lt;br /&gt;
                my ($bn) = ($b =~ m/fc(\d+)_.*/);&lt;br /&gt;
                $an &amp;lt;=&amp;gt; $bn or $a cmp $b;&lt;br /&gt;
                }( grep /${regex}/,keys %{$defs{$device}{READINGS}} );&lt;br /&gt;
			return undef if( !@rl );&lt;br /&gt;
		} else {&lt;br /&gt;
			Log3 undef, 2, &amp;quot;logProxy_proplanta2Plot: $device is not a PROPLANTA device&amp;quot;;&lt;br /&gt;
			return undef;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	my $fromsec = SVG_time_to_sec($from);&lt;br /&gt;
	my $tosec   = SVG_time_to_sec($to);&lt;br /&gt;
	my $sec = $fromsec;&lt;br /&gt;
	my ($h,$fcDay,$mday,$mon,$year);&lt;br /&gt;
	my $timestamp;&lt;br /&gt;
    &lt;br /&gt;
	my $reading;&lt;br /&gt;
	my $value;&lt;br /&gt;
	my $prev_value;&lt;br /&gt;
	my $min = 999999;&lt;br /&gt;
	my $max = -999999;&lt;br /&gt;
	my $ret = &amp;quot;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	# while not end of plot range reached&lt;br /&gt;
	while(($sec &amp;lt; $tosec) &amp;amp;&amp;amp; @rl) {&lt;br /&gt;
		#remember previous value for start of plot range&lt;br /&gt;
		$prev_value = $value;&lt;br /&gt;
&lt;br /&gt;
		$reading = shift @rl;&lt;br /&gt;
        ($fcDay) = $reading =~ m/^fc(\d+).*/;&lt;br /&gt;
   		$h = ($reading =~ m/.*(\d\d)$/)?$1:$fcHour;&lt;br /&gt;
		$value = ReadingsVal($device,$reading,undef);&lt;br /&gt;
        &lt;br /&gt;
		($mday,$mon,$year) = split(&#039;\.&#039;,ReadingsVal($device,&amp;quot;fc&amp;quot;.$fcDay.&amp;quot;_date&amp;quot;,undef));&lt;br /&gt;
		$timestamp = sprintf(&amp;quot;%04d-%02d-%02d_%02d:%02d:%02d&amp;quot;, $year, $mon, $mday, $h, 0, 0);&lt;br /&gt;
		$sec = SVG_time_to_sec($timestamp);&lt;br /&gt;
        &lt;br /&gt;
		# skip all values before start of plot range&lt;br /&gt;
		next if( SVG_time_to_sec($timestamp) &amp;lt; $fromsec );&lt;br /&gt;
&lt;br /&gt;
		# add first value at start of plot range&lt;br /&gt;
		if( !$ret &amp;amp;&amp;amp; $prev_value ) {&lt;br /&gt;
		  $min = $prev_value if( (looks_like_number($prev_value) &amp;amp;&amp;amp; ($prev_value &amp;lt; $min)) || ($prev_value lt $min) );&lt;br /&gt;
		  $max = $prev_value if( (looks_like_number($prev_value) &amp;amp;&amp;amp; ($prev_value &amp;gt; $max)) || ($prev_value gt $max) );&lt;br /&gt;
		  $ret .= &amp;quot;$from $prev_value\n&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		# done if after end of plot range&lt;br /&gt;
		last if($sec &amp;gt; $tosec);&lt;br /&gt;
&lt;br /&gt;
		$min = $value if( (looks_like_number($value) &amp;amp;&amp;amp; ($value &amp;lt; $min )) || ($value lt $min) );&lt;br /&gt;
		$max = $value if( (looks_like_number($value) &amp;amp;&amp;amp; ($value &amp;gt; $max )) || ($value gt $max) );&lt;br /&gt;
&lt;br /&gt;
		# add actual controll point&lt;br /&gt;
		$ret .= &amp;quot;$timestamp $value\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
#		Log 1, &amp;quot;$timestamp $value -0- $reading&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
    if(($sec &amp;lt; $tosec) &amp;amp;&amp;amp; !@rl &amp;amp;&amp;amp; ($expMode eq &amp;quot;day&amp;quot;)) {&lt;br /&gt;
    	$timestamp = sprintf(&amp;quot;%04d-%02d-%02d_%02d:%02d:%02d&amp;quot;, $year, $mon, $mday, 23, 59, 59);&lt;br /&gt;
    	if(SVG_time_to_sec($timestamp) &amp;lt; $tosec) {&lt;br /&gt;
        	$ret .= &amp;quot;$timestamp $value\n&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        else {&lt;br /&gt;
			$ret .= &amp;quot;$to $value\n&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    elsif(($sec &amp;gt; $tosec) &amp;amp;&amp;amp; ($expMode eq &amp;quot;day&amp;quot;)) {&lt;br /&gt;
       	$value = $prev_value + ($value - $prev_value)*(86400 + ($tosec - $sec))/86400;&lt;br /&gt;
       	$ret .= &amp;quot;$to $value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
	return ($ret,$min,$max,$prev_value);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anschließend können die Daten im Chart-Widget angezeigt werden. Der Device-Name von Proplanta heißt hier im Beispiel &amp;lt;code&amp;gt;AU.xx.WE.Proplanta&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	 data-device=&amp;quot;AU.xx.WE.Proplanta&amp;quot;&lt;br /&gt;
	 data-logdevice=&#039;[&lt;br /&gt;
	 					&amp;quot;myLogProxy&amp;quot;,&lt;br /&gt;
	 					&amp;quot;myLogProxy&amp;quot;,&lt;br /&gt;
	 					&amp;quot;myLogProxy&amp;quot;&lt;br /&gt;
	 				]&#039;&lt;br /&gt;
	 data-columnspec=&#039;[&lt;br /&gt;
	 					&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22rain_\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;,&lt;br /&gt;
	 					&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22chOfRain_\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;,&lt;br /&gt;
	 					&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22cloud_\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;&lt;br /&gt;
	 				]&#039;&lt;br /&gt;
	 data-style=&#039;[&lt;br /&gt;
	 					&amp;quot;ftui l6fill&amp;quot;,&lt;br /&gt;
	 					&amp;quot;ftui l5fill&amp;quot;,&lt;br /&gt;
	 					&amp;quot;ftui l1fill&amp;quot;&lt;br /&gt;
	 			]&#039;&lt;br /&gt;
	 data-ptype=&#039;[&lt;br /&gt;
	 					&amp;quot;steps&amp;quot;,&lt;br /&gt;
	 					&amp;quot;quadraticSmooth&amp;quot;,&lt;br /&gt;
	 					&amp;quot;quadraticSmooth&amp;quot;&lt;br /&gt;
	 			]&#039;&lt;br /&gt;
	 data-uaxis=&#039;[&lt;br /&gt;
	 					&amp;quot;primary&amp;quot;,&lt;br /&gt;
	 					&amp;quot;secondary&amp;quot;,&lt;br /&gt;
	 					&amp;quot;secondary&amp;quot;&lt;br /&gt;
	 			]&#039;&lt;br /&gt;
	 data-legend=&#039;[&lt;br /&gt;
	 					&amp;quot;Regen&amp;quot;,&lt;br /&gt;
	 					&amp;quot;Regenwahrscheinlichkeit&amp;quot;,&lt;br /&gt;
	 					&amp;quot;Wolken&amp;quot;&lt;br /&gt;
	 			]&#039;&lt;br /&gt;
	 data-yunit=&amp;quot;mm&amp;quot;&lt;br /&gt;
	 data-ytext=&amp;quot;Regen&amp;quot;&lt;br /&gt;
	 data-yunit_sec=&amp;quot;%&amp;quot;&lt;br /&gt;
	 data-ytext_sec=&amp;quot;Chance auf Regen / Wolken&amp;quot;&lt;br /&gt;
	 data-timeformat=&amp;quot;eeee&amp;quot;&lt;br /&gt;
	 data-minvalue=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-maxvalue=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-minvalue_sec=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-maxvalue_sec=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-daysago_start = &amp;quot;0&amp;quot;&lt;br /&gt;
	 data-daysago_end = &amp;quot;-7&amp;quot;&lt;br /&gt;
	 data-xticks=&amp;quot;1440&amp;quot;&lt;br /&gt;
	 data-yticks=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-title=&amp;quot;7-Tage-Wettervorhersage&amp;quot;&lt;br /&gt;
	 data-showlegend=&amp;quot;true&amp;quot;&lt;br /&gt;
	 class=&amp;quot;nobuttons fullsize&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hilfreiche Links und Quellen zu diesem Beispiel:&#039;&#039;&#039;&lt;br /&gt;
*[[LogProxy|LogProxy im FHEM-Wiki]]&lt;br /&gt;
*{{Link2Forum|Topic=22967|Message=246973|LinkText=Stundengenaue Wettervorhersage (#1) im FHEM-Forum}}&lt;br /&gt;
*{{Link2Forum|Topic=22967|Message=334713|LinkText=Stundengenaue Wettervorhersage (#2) im FHEM-Forum}}&lt;br /&gt;
&lt;br /&gt;
===Darstellung der Wetter Icons im Diagramm===&lt;br /&gt;
&lt;br /&gt;
[[File:Wetterchart2.png]]&lt;br /&gt;
&lt;br /&gt;
Wie oben bereits beschrieben, gibt es beim Chart grundsätzlich die Möglichkeit, Icons, welche in Form von URLs in den Logs abgelegt sind oder welche per logProxy generiert werden, darzustellen. Die Icons werden auf genau dem gleichen Weg von FHEM gelesen, wie alle anderen Datenpunkte. Im Folgenden wird ein Beispiel gezeigt, mit dem die im Proplanta Modul als Readings abgelegten Icons per logProxy Funktion gelesen und in ein Chart eingebaut werden könnnen.&lt;br /&gt;
Da es beim Proplanta Modul für die ersten 7 Tage nicht das Reading &amp;lt;code&amp;gt;fc#_weatherIcon&amp;lt;/code&amp;gt; gibt, sondern mehrere Readings für unterschiedliche Tageszeiten wogegen für die zweiten 7 Tage ausschließlich das Reading &amp;lt;code&amp;gt;fc#_weatherIcon&amp;lt;/code&amp;gt; vorhanden ist, sollte per &amp;lt;code&amp;gt;attr device userReading&amp;lt;/code&amp;gt; mit folgendem Eintrag dafür gesorgt werden, dass für alle Tage ein Reading &amp;lt;code&amp;gt;fc#_weatherIcon&amp;lt;/code&amp;gt; vorhanden ist (alternativ könnten auch 2 Graphen gezeichnet werden, wobei der erste dann nur die ersten 7 Tage enthält und der zweite die letzen 7 Tage, will man nur die ersten 7 Tage darstellen braucht man das userReading nicht unbedingt).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
fc0_weatherIcon {ReadingsVal(&amp;quot;AU.xx.WE.Proplanta&amp;quot;,&amp;quot;fc0_weatherDayIcon&amp;quot;,&amp;quot;&amp;quot;);},&lt;br /&gt;
fc1_weatherIcon {ReadingsVal(&amp;quot;AU.xx.WE.Proplanta&amp;quot;,&amp;quot;fc1_weatherDayIcon&amp;quot;,&amp;quot;&amp;quot;);},&lt;br /&gt;
fc2_weatherIcon {ReadingsVal(&amp;quot;AU.xx.WE.Proplanta&amp;quot;,&amp;quot;fc2_weatherDayIcon&amp;quot;,&amp;quot;&amp;quot;);},&lt;br /&gt;
fc3_weatherIcon {ReadingsVal(&amp;quot;AU.xx.WE.Proplanta&amp;quot;,&amp;quot;fc3_weatherDayIcon&amp;quot;,&amp;quot;&amp;quot;);},&lt;br /&gt;
fc4_weatherIcon {ReadingsVal(&amp;quot;AU.xx.WE.Proplanta&amp;quot;,&amp;quot;fc4_weatherDayIcon&amp;quot;,&amp;quot;&amp;quot;);},&lt;br /&gt;
fc5_weatherIcon {ReadingsVal(&amp;quot;AU.xx.WE.Proplanta&amp;quot;,&amp;quot;fc5_weatherDayIcon&amp;quot;,&amp;quot;&amp;quot;);},&lt;br /&gt;
fc6_weatherIcon {ReadingsVal(&amp;quot;AU.xx.WE.Proplanta&amp;quot;,&amp;quot;fc6_weatherDayIcon&amp;quot;,&amp;quot;&amp;quot;);}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Um die Icons darzustellen muss ein zusätzlicher Graph definiert werden. Dieser nutzt neben der Columnspec, die die URLs abruft den Parameter &amp;lt;code&amp;gt;data-ptype=&amp;quot;icons:#&amp;quot;&amp;lt;/code&amp;gt; (# ist eine Zahl und steht für die Nummer, beginnend bei 0 des Graphen, welcher für die y-Position der Icons verwendet werden soll) und den Stil &amp;lt;code&amp;gt;sym&amp;lt;/code&amp;gt;. Der Wert für die Symbolgröße sollte z.B. durch eine zusätzliche Definition im File fhem-tablet-ui-user.css in der Form:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
/* icon lines */&lt;br /&gt;
.ftui.l99icon	{ stroke:#DDA400; stroke-width:48px; fill:none; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
angepasst werden.&lt;br /&gt;
&lt;br /&gt;
Im folgenden ein Beispiel, welches eine Linie für die Maximale Tagestemperatur zeichnet und auf dieser Linie die Wetter Icons darstellt.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	 data-device=&amp;quot;AU.xx.WE.Proplanta&amp;quot;&lt;br /&gt;
	 data-logdevice=&#039;[&lt;br /&gt;
	 					&amp;quot;myLogProxy&amp;quot;,&lt;br /&gt;
	 					&amp;quot;myLogProxy&amp;quot;&lt;br /&gt;
	 				]&#039;&lt;br /&gt;
	 data-columnspec=&#039;[&lt;br /&gt;
	 					&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22weatherIcon\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;,&lt;br /&gt;
	 					&amp;quot;Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22tempMax\\x22,$from,$to,12,\\x22day\\x22)&amp;quot;&lt;br /&gt;
	 				]&#039;&lt;br /&gt;
	 data-style=&#039;[&lt;br /&gt;
	 					&amp;quot;ftui l99icon&amp;quot;,&lt;br /&gt;
	 					&amp;quot;ftui l1fill&amp;quot;&lt;br /&gt;
	 			]&#039;&lt;br /&gt;
	 data-ptype=&#039;[&lt;br /&gt;
	 					&amp;quot;icons:1&amp;quot;,&lt;br /&gt;
	 					&amp;quot;quadraticSmooth&amp;quot;&lt;br /&gt;
	 			]&#039;&lt;br /&gt;
	 data-uaxis=&#039;[&lt;br /&gt;
	 					&amp;quot;primary&amp;quot;,&lt;br /&gt;
	 					&amp;quot;primary&amp;quot;&lt;br /&gt;
	 			]&#039;&lt;br /&gt;
	 data-legend=&#039;[&lt;br /&gt;
	 					&amp;quot;Wetterbedingung&amp;quot;,&lt;br /&gt;
	 					&amp;quot;Max. Temperature&amp;quot;&lt;br /&gt;
	 			]&#039;&lt;br /&gt;
	 data-yunit=&amp;quot;°C&amp;quot;&lt;br /&gt;
	 data-ytext=&amp;quot;Temperature (°C)&amp;quot;&lt;br /&gt;
	 data-timeformat=&amp;quot;ee\LF\dd.MM&amp;quot;&lt;br /&gt;
	 data-minvalue=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-maxvalue=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-minvalue_sec=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-maxvalue_sec=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-daysago_start=&amp;quot;-1w&amp;quot;&lt;br /&gt;
	 data-y_margin=&amp;quot;20&amp;quot;&lt;br /&gt;
	 data-daysago_end=&amp;quot;-3w&amp;quot;&lt;br /&gt;
	 data-xticks=&amp;quot;1440&amp;quot;&lt;br /&gt;
	 data-yticks=&amp;quot;auto&amp;quot;&lt;br /&gt;
	 data-title=&amp;quot;14-Tage-Wettervorhersage&amp;quot;&lt;br /&gt;
	 data-showlegend=&amp;quot;true&amp;quot;&lt;br /&gt;
	 class=&amp;quot;nobuttons fullsize&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Kuchendiagramme===&lt;br /&gt;
In folgendem Beispiel wird gezeigt, wie man ein &amp;quot;Kuchendiagramm&amp;quot; darstellen kann.&lt;br /&gt;
&lt;br /&gt;
[[File:PieChart.png]]&lt;br /&gt;
&lt;br /&gt;
Ähnlich wie bei den Beispielen für die Wetter Darstellungen wird hierzu auch wieder logProxy benötigt. Zunächst muss die folgende zusätzliche Funktion in &amp;lt;code&amp;gt;99_myUtils.pm&amp;lt;/code&amp;gt; einfügen.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#---------------------------------------&lt;br /&gt;
# Funktion zum Erzeugen der Inputs für Kuchendiagramme&lt;br /&gt;
#---------------------------------------&lt;br /&gt;
sub logProxy_values2PieChart($$$$;$$) {&lt;br /&gt;
	my ($device, $reading, $angle_start, $angle_dif, $inner_rad, $show_text) = @_;&lt;br /&gt;
	Log3 undef, 1, &amp;quot;$device, $reading, $angle_start, $angle_dif, $inner_rad, $show_text\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	use constant PI =&amp;gt; 4 * atan2(1,1);&lt;br /&gt;
	&lt;br /&gt;
	my $value=ReadingsVal($device,$reading,0);&lt;br /&gt;
&lt;br /&gt;
	my $angle_delta = $value/100*360;&lt;br /&gt;
	$angle_start = $angle_start/100*360;&lt;br /&gt;
	&lt;br /&gt;
	my $rad=10;&lt;br /&gt;
	my $irad=0;&lt;br /&gt;
	if ($inner_rad) {&lt;br /&gt;
		$irad = $rad*$inner_rad;&lt;br /&gt;
	}&lt;br /&gt;
	my $angle=$angle_start/360*2.0*PI;&lt;br /&gt;
	my $x=$irad*sin($angle);&lt;br /&gt;
	my $y=$irad*cos($angle);&lt;br /&gt;
	my $ret .= &amp;quot;;p &amp;quot;.$x.&amp;quot; &amp;quot;.$y.&amp;quot;\n&amp;quot;; # add segment at angle $angle&lt;br /&gt;
	&lt;br /&gt;
	for (my $i=$angle_start; $i&amp;lt;=$angle_start+$angle_delta; $i+=$angle_dif) {&lt;br /&gt;
		$angle = $i/360*2.0*PI;&lt;br /&gt;
		$x = $rad*sin($angle);&lt;br /&gt;
		$y = $rad*cos($angle);&lt;br /&gt;
		$ret .= &amp;quot;;p &amp;quot;.$x.&amp;quot; &amp;quot;.$y.&amp;quot;\n&amp;quot;; # add segment at angle $angle&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	$angle = ($angle_start+$angle_delta)/360*2.0*PI; # add last segment &lt;br /&gt;
	$ret .= &amp;quot;;p &amp;quot;.$rad*sin($angle).&amp;quot; &amp;quot;.$rad*cos($angle).&amp;quot;\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	if ($inner_rad) {&lt;br /&gt;
		for (my $i=$angle_start; $i&amp;lt;$angle_start+$angle_delta; $i+=$angle_dif) {&lt;br /&gt;
			$angle = ($angle_start+$angle_start+$angle_delta-$i)/360*2.0*PI;&lt;br /&gt;
			$x = $irad*sin($angle);&lt;br /&gt;
			$y = $irad*cos($angle);&lt;br /&gt;
			$ret .= &amp;quot;;p &amp;quot;.$x.&amp;quot; &amp;quot;.$y.&amp;quot;\n&amp;quot;; # add segment at angle $angle&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	$angle = ($angle_start)/360*2.0*PI; # add last segment &lt;br /&gt;
	$ret .= &amp;quot;;p &amp;quot;.$irad*sin($angle).&amp;quot; &amp;quot;.$irad*cos($angle).&amp;quot;\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	if ($show_text) { # show text values&lt;br /&gt;
		$x = ($rad+$irad)/2*sin((2*$angle_start+$angle_delta)/2/360*2.0*PI);&lt;br /&gt;
		$y = ($rad+$irad)/2*cos((2*$angle_start+$angle_delta)/2/360*2.0*PI);&lt;br /&gt;
&lt;br /&gt;
		$ret .= &amp;quot;;t &amp;quot;.$x.&amp;quot; &amp;quot;.$y.&amp;quot; middle &amp;quot;.$show_text.&amp;quot;:&amp;quot;.$value.&amp;quot;%\n&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return($ret);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In FHEM braucht man Readings, welche eine Zahl enthalten, die als Prozentwert interpretiert wird. Für jeden Prozentwert (also für jedes Reading) generiert die o.a. Funktion nun den Chart Input für ein Kuchenstück und liefert diesen als Antwort auf das GET, welches das Chart Widget auslöst. Dazu braucht die Funktion folgende Parameter: (Name des FHEM Devices, Name des Readings, Start Winkel des Kuchenstücks (Mathematisch gegen den Uhrzeigersinn in Grad), Delta Winkel zum Zeichnen (legt fest in welchen Schritten der Teilkreis des Kuchenstücks gezeichnet wird), Skalierungsfaktor für inneren Ring wenn ein Ring gezeichtnet werden soll (0 bedeutet komplette Kuchenstücke), optionaler Text der ins Kuchenstück vor die Prozentzahl geschrieben wird).&lt;br /&gt;
Im Folgenden eine Beispielkonfiguration für die Darstellung als Kuchendiagramm, die Readings heißen hier dPer1 bis dPer4. Der Startwinkel wird duch Aufsummierung der jeweils vorher schon gezeichneten Kuchenstücke gebildet, dadurch entstehen aneinander hängende Stücke.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
[[Datei:[[Datei:Beispiel.jpg]]]]&amp;lt;div class=&amp;quot;normal noaxes nobuttons&amp;quot;&lt;br /&gt;
        data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
        data-logdevice=&#039;[&amp;quot;lp&amp;quot;]&#039;&lt;br /&gt;
		data-logfile=&amp;quot;CURRENT&amp;quot;&lt;br /&gt;
        data-columnspec=&#039;[&lt;br /&gt;
			&amp;quot;Func:logProxy_values2PieChart(\&amp;quot;dPer1\&amp;quot;,\&amp;quot;state\&amp;quot;,ReadingsVal(\&amp;quot;dPer4\&amp;quot;,\&amp;quot;state\&amp;quot;,0)+ReadingsVal(\&amp;quot;dPer3\&amp;quot;,\&amp;quot;state\&amp;quot;,0),5,0,\&amp;quot;first\&amp;quot;)&amp;quot;,&lt;br /&gt;
			&amp;quot;Func:logProxy_values2PieChart(\&amp;quot;dPer2\&amp;quot;,\&amp;quot;state\&amp;quot;,ReadingsVal(\&amp;quot;dPer4\&amp;quot;,\&amp;quot;state\&amp;quot;,0)+ReadingsVal(\&amp;quot;dPer3\&amp;quot;,\&amp;quot;state\&amp;quot;,0)+ReadingsVal(\&amp;quot;dPer1\&amp;quot;,\&amp;quot;state\&amp;quot;,0),5,0,\&amp;quot;second\&amp;quot;)&amp;quot;,&lt;br /&gt;
			&amp;quot;Func:logProxy_values2PieChart(\&amp;quot;dPer3\&amp;quot;,\&amp;quot;state\&amp;quot;,ReadingsVal(\&amp;quot;dPer4\&amp;quot;,\&amp;quot;state\&amp;quot;,0),5,0,\&amp;quot;third\&amp;quot;)&amp;quot;,&lt;br /&gt;
			&amp;quot;Func:logProxy_values2PieChart(\&amp;quot;dPer4\&amp;quot;,\&amp;quot;state\&amp;quot;,0,5,0,\&amp;quot;fourth\&amp;quot;)&amp;quot;&lt;br /&gt;
		]&#039;&lt;br /&gt;
        data-style=&#039;[&amp;quot;ftui l0fill&amp;quot;,&amp;quot;ftui l1fill&amp;quot;,&amp;quot;ftui l2fill&amp;quot;,&amp;quot;ftui l3fill&amp;quot;]&#039;&lt;br /&gt;
        data-ptype=&#039;[&amp;quot;lines&amp;quot;]&#039;&lt;br /&gt;
        data-uaxis=&#039;[&amp;quot;primary&amp;quot;]&#039;&lt;br /&gt;
        data-legend=&#039;[&amp;quot;First&amp;quot;,&amp;quot;Second&amp;quot;,&amp;quot;Third&amp;quot;,&amp;quot;Fourth&amp;quot;]&#039;&lt;br /&gt;
		data-legendpos=&#039;[&amp;quot;left&amp;quot;,&amp;quot;top&amp;quot;]&#039;&lt;br /&gt;
        data-yunit=&amp;quot;&amp;quot;&lt;br /&gt;
        data-height=&amp;quot;300&amp;quot;&lt;br /&gt;
        data-width=&amp;quot;300&amp;quot;&lt;br /&gt;
		data-ddd=&#039;[&amp;quot;-40&amp;quot;,&amp;quot;0&amp;quot;,&amp;quot;0&amp;quot;]&#039;&lt;br /&gt;
		data-dddspace=&#039;[&amp;quot;-10&amp;quot;]&#039;&lt;br /&gt;
		data-dddwidth=&#039;[&amp;quot;10&amp;quot;]&#039;&lt;br /&gt;
		data-showlegend=&amp;quot;true&amp;quot;&lt;br /&gt;
		data-legend_horiz=&amp;quot;true&amp;quot;&lt;br /&gt;
        data-xticks=&amp;quot;auto&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Fensterstatus offen/geschlossen===&lt;br /&gt;
Dieses Beispiel zeigt, wie ein Fensterkontakt, dessen Reading die Werte &amp;lt;code&amp;gt;closed&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt; einnimmt, als Graph gezeichnet werden kann. Technisch gesehen werden hier die Werte &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; gezeichnet, indem über das Attribut &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; dem Zustand &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt; der Wert &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; und allen anderen Zuständen der Wert &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; zugeordnet wird. Über das Attribut &#039;&#039;&#039;data-yticks&#039;&#039;&#039; wird die Beschriftung an der Y-Achse (&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;) gegen einen frei definierbaren Text ausgetauscht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	data-device=&amp;quot;wz_fensterstatus&amp;quot;&lt;br /&gt;
	data-logdevice=&#039;[&amp;quot;myDbLog&amp;quot;]&#039;&lt;br /&gt;
	data-logfile=&#039;[&amp;quot;HISTORY&amp;quot;]&#039;&lt;br /&gt;
	data-columnspec=&#039;[&amp;quot;wz_fensterstatus:state:0::$val=($val=~\\x22open\\x22?1:0)&amp;quot;]&#039;&lt;br /&gt;
	data-style=&#039;[&amp;quot;ftui l4fill&amp;quot;]&#039;&lt;br /&gt;
	data-ptype=&#039;[&amp;quot;steps&amp;quot;]&#039;&lt;br /&gt;
	data-height=&amp;quot;290&amp;quot;&lt;br /&gt;
	data-yticks=&#039;[[0,&amp;quot;geschlossen&amp;quot;],[1,&amp;quot;offen&amp;quot;]]&#039;&lt;br /&gt;
	data-minvalue=&amp;quot;0&amp;quot;&lt;br /&gt;
	data-maxvalue=&amp;quot;1.1&amp;quot;&lt;br /&gt;
	data-nofulldays=&amp;quot;true&amp;quot;&lt;br /&gt;
	data-daysago_start=&amp;quot;1&amp;quot;&lt;br /&gt;
	data-daysago_end=&amp;quot;-1&amp;quot;&lt;br /&gt;
	data-cursorgroup=&amp;quot;1&amp;quot;&lt;br /&gt;
	data-scrollgroup=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Das Beispiel funktioniert nur mit DbLog. Falls Logfiles verwendet werden muss statt &#039;$val&#039; &#039;$fld[&#039;&#039;num&#039;&#039;]&#039; verwendet werden. Hierbei steht &#039;&#039;num&#039;&#039; für die Spalte (beginnend bei 0) in der die Daten stehen.&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
{{Link2Forum|Topic= 48450 |Message=401006|LinkText=Thread im FHEM-Forum}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI|Chart]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-ES-PMSw1-Pl_Funk-Schaltaktor_1-fach_mit_Leistungsmessung&amp;diff=22379</id>
		<title>HM-ES-PMSw1-Pl Funk-Schaltaktor 1-fach mit Leistungsmessung</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-ES-PMSw1-Pl_Funk-Schaltaktor_1-fach_mit_Leistungsmessung&amp;diff=22379"/>
		<updated>2017-08-26T16:05:27Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Versehentliches Ausschalter mit dem Taster verhindern&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Hardware&lt;br /&gt;
|Bild=HM-ES-PMSw1-PI-Frontansicht.jpg&lt;br /&gt;
|Bildbeschreibung=Frontansicht&lt;br /&gt;
|HWProtocol=HomeMatic&lt;br /&gt;
|HWType=[[HomeMatic Type powerMeter|powerMeter]]&lt;br /&gt;
|HWCategory=HomeMatic&lt;br /&gt;
|HWComm=868MHz&lt;br /&gt;
|HWChannels=6&lt;br /&gt;
|HWVoltage=230V&lt;br /&gt;
|HWPowerConsumption=&amp;lt;0,6W&lt;br /&gt;
|HWPoweredBy=Netz&lt;br /&gt;
|HWSize=59 x 123 x 40mm&lt;br /&gt;
|HWDeviceFHEM=[[CUL_HM]]&lt;br /&gt;
|HWManufacturer=ELV / eQ-3 &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--  &#039;&#039;&#039;HM-ES-PMSw1-Pl&#039;&#039;&#039;  --&amp;gt;&lt;br /&gt;
[[HM-ES-PMSw1-Pl Funk-Schaltaktor 1-fach mit Leistungsmessung|HM-ES-PMSw1-Pl]] ist ein [[HomeMatic]] Funk-Schaltaktor in Zwischenstecker-Ausführung, der über die Schaltfunktion hinaus auch Informationen über den aktuellen Verbrauch der angeschlossenen Verbraucher sowie über die anliegende Spannung und Netzfrequenz liefert. Dieser Aktor ist seit dem 20.12.2013 verfügbar. &lt;br /&gt;
&lt;br /&gt;
Ein Gerät mit gleichem Funktionsumfang ist als [[HM-ES-PMSw1-DR Hutschienen-Schaltaktor mit Leistungsmessung|HM-ES-PMSw1-DR]] für die Hutschienenmontage verfügbar.&lt;br /&gt;
&lt;br /&gt;
[[Datei:HM-ES-PMSw1-PI-Seitenansicht.jpg|thumb|HM-ES-PMSw1-PI Seitenansicht]]&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
HomeMatic Funk-Schaltaktor mit Leistungsmessung für zwei Funktionsbereiche:&lt;br /&gt;
* Schalten von angeschlossenen Verbrauchern (Schaltkanal)&lt;br /&gt;
* Messen von Spannung, Strom, Wirkleistung, Frequenz und Energieverbrauch (Messkanal)&lt;br /&gt;
* Automatische Schalten von angelernten Aktoren beim Über- oder Unterschreiten von definierten Schwellwerten (Sensorkanäle)&lt;br /&gt;
&lt;br /&gt;
Der Schaltkanal kann angeschlossene Verbraucher oder angelernte HomeMatic Aktoren ein- bzw. ausschalten.&lt;br /&gt;
Der Messkanal verfügt über eine Messfunktion und Empfangs- sowie Übertragungsmöglichkeit von Messdaten (z.B. Spannung, Strom, Wirkleistung, Frequenz und Energieverbrauch bis 3680 Watt/16 A). Die Messdaten werden je nach Verbraucherverhalten in Abständen von einigen Sekunden bis mehreren Minuten übertragen, der Sendezyklus kann durch verschiedene Register konfiguriert werden (Änderungsschwellwerte). Des weiteren kann er - in Abhängigkeit von definierbaren Schwellwerten (Über- / Unterschreitung) - andere Aktoren schalten.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Technische Daten:&#039;&#039;&#039;&lt;br /&gt;
* Spannungsversorgung: 230 V/50 Hz&lt;br /&gt;
* Stromaufnahme: 16 A max.&lt;br /&gt;
* Leistungsaufnahme Ruhebetrieb: &amp;lt; 0,6 W&lt;br /&gt;
* Max. Schaltleistung: 3680 W (ohmsche Last)&lt;br /&gt;
* Schutzart: IP 20&lt;br /&gt;
* Relais: Schließer&lt;br /&gt;
* Schaltzyklen: 50.000 bei cosφ=1&lt;br /&gt;
* Abmessungen (B x H x T): 59 x 123 x 40 mm&lt;br /&gt;
* Gewicht: 165 g (ohne Netzstecker)&lt;br /&gt;
* Messauflösung Leistung: 0,01 W&lt;br /&gt;
* Messbereich Leistung: 0–3.680 W&lt;br /&gt;
* Messgenauigkeit Leistung: 1 % ±0,03 W&lt;br /&gt;
* Messauflösung Strom: 1 mA&lt;br /&gt;
* Messbereich Strom: 0–16 A&lt;br /&gt;
* Messgenauigkeit Strom: 1 % ±1 mA&lt;br /&gt;
* Messauflösung Spannung: 0,1 V&lt;br /&gt;
* Messbereich Spannung: 200–255 V&lt;br /&gt;
* Messgenauigkeit Spannung: 0,5 % ±0,1 V&lt;br /&gt;
* Messauflösung Frequenz: 0,01 Hz&lt;br /&gt;
* Messbereich Frequenz: 48,72–51,27 Hz&lt;br /&gt;
* Messgenauigkeit Frequenz: 0,1 % ±0,01 Hz&lt;br /&gt;
&lt;br /&gt;
(Angaben ohne Gewähr)&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Inbetriebnahme und Installation ==&lt;br /&gt;
Der PMSw1 funktioniert &amp;quot;out-of-the-box&amp;quot;, nachdem er an FHEM angelernt (gepairt) worden ist.&lt;br /&gt;
&lt;br /&gt;
Das [[Pairing (HomeMatic)|Pairing]] sollte wie in [[HomeMatic Devices pairen]] beschrieben durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit FHEM ==&lt;br /&gt;
Der PMSw1 verfügt über insgesamt 6 Kanäle (HM-Jargon: channels), von denen der Schaltkanal (Kanal 1) und der Messkanal (Kanal 2) in FHEM primär genutzt werden. Die Kanäle 3 - 6 sind zur Konfiguration der Schaltvorgänge [[Peering (HomeMatic)|gepeerter]] Aktoren bei Änderungen des Leistungsverbrauchs (Kanal 3), des Stromverbrauchs (Kanal 4), der elektrischen Spannung (Kanal 5) oder der Frequenz (Kanal 6). Diese Kanäle können ausschließlich über Register konfiguriert werden. &lt;br /&gt;
&lt;br /&gt;
=== Channels (Kanäle) 01 bis 06 ===&lt;br /&gt;
==== Channel 01 (_Sw) ====&lt;br /&gt;
Der eigentliche Schaltkanal, über den die am PMSw1 eingesteckten Verbraucher ein- und ausgeschaltet werden können.&lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw set_on&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw level: 100 %&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw pct: 100&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw deviceMsg: on (to HMLAN1)&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw timedOn: off&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw set_off&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw level: 0 %&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw pct: 0&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw deviceMsg: off (to HMLAN1)&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw timedOn: off&lt;br /&gt;
&lt;br /&gt;
==== Channel 02 (_Pwr) ====&lt;br /&gt;
&lt;br /&gt;
Der Messkanal des PMSw1, über den die momentane Netzspannung, die Frequenz (in Hz), die aktuellen Verbrauchswerte (Last, Watt) sowie die seit Inbetriebnahme umgewandelte Leistung (&amp;quot;Verbrauch&amp;quot;, Wh) usw. an die Zentrale (hier FHEM) übermittelt werden.&lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr energy: 153.2&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr power: 90.92&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr current: 427&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr voltage: 233.4&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr 50: -&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr boot: on&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr energy: 153.8&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr power: 80.85&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr current: 384&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr voltage: 232.2&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr 50: -&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr boot: on&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr energy: 157.5&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr power: 86.41&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr current: 409&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr voltage: 232.6&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr 50: -&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr boot: on&lt;br /&gt;
&lt;br /&gt;
==== Channel 03 (_SenPwr) ====&lt;br /&gt;
&lt;br /&gt;
Dieser Sensorkanal beinhaltet die Logik für eine automatische Schaltung aller angelernten Aktoren auf Basis des &#039;&#039;&#039;momentanen Leistungsverbrauchs&#039;&#039;&#039; (Überschreitung oder Unterschreitung) der angeschlossenen Verbraucher. Mittels der verfügbaren Register kann man genau einstellen, nach welchen Bedingungen aufgrund des &#039;&#039;&#039;momentanen Leistungsverbrauches&#039;&#039;&#039; ein Schaltbefehl gesendet werden soll.&lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals (verfügbaren Register):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-cndTxCycBelow: 0 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-txThrLoPwr: 200 W&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-transmitTryMax: 6 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-cndTxCycAbove: 200 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-cndTxFalling: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-txThrHiPwr: 100 W&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-cndTxRising: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-ledOnTime: 0.5 s&lt;br /&gt;
&lt;br /&gt;
Dieser Kanal dient nur zum Auslesen und Setzen der Register für die Schaltautomaik und stellt daher keine Readings oder speziellen Kommandos zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==== Channel 04 (_SenI) ====&lt;br /&gt;
Dieser Sensorkanal beinhaltet die Logik für eine automatische Schaltung aller angelernten Aktoren auf Basis des &#039;&#039;&#039;momentanen Stromverbrauchs&#039;&#039;&#039; (Überschreitung oder Unterschreitung) der angeschlossenen Verbraucher. Mittels der verfügbaren Register kann man genau einstellen, nach welchen Bedingungen aufgrund des &#039;&#039;&#039;momentanen Stromverbrauchs&#039;&#039;&#039; ein Schaltbefehl gesendet werden soll.&lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals (verfügbaren Register):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-cndTxCycBelow: 0 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-txThrLoCur: 20 mA&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-transmitTryMax: 6 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-cndTxCycAbove: 200 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-cndTxFalling: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-txThrHiCur: 10 mA&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-cndTxRising: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-ledOnTime: 0.5 s&lt;br /&gt;
&lt;br /&gt;
Dieser Kanal dient nur zum Auslesen und Setzen der Register für die Abschaltautomatik und stellt daher keine Readings oder speziellen Kommandos zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==== Channel 05 (_SenU) ====&lt;br /&gt;
Dieser Sensorkanal beinhaltet die Logik für eine automatische Schaltung aller angelernten Aktoren auf Basis der aktuell anliegenden &#039;&#039;&#039;elektrischen Spannung&#039;&#039;&#039; (Überschreitung oder Unterschreitung). Mittels der verfügbaren Register kann man genau einstellen, nach welchen Bedingungen auf Basis der &#039;&#039;&#039;elektrischen Spannung&#039;&#039;&#039; ein Schaltbefehl durchgeführt werden soll.&lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals (verfügbaren Register):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-cndTxCycBelow: 0 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-transmitTryMax: 6 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-txThrLoVlt: 24 V&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-cndTxCycAbove: 200 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-cndTxFalling: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-txThrHiVlt: 22 V&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-cndTxRising: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-ledOnTime: 0.5 s&lt;br /&gt;
&lt;br /&gt;
==== Channel 06 (_SenF) ====&lt;br /&gt;
Dieser Sensorkanal beinhaltet die Logik für eine automatische Schaltung aller angelernten Aktoren auf Basis der &#039;&#039;&#039;Frequenz&#039;&#039;&#039; (Überschreitung oder Unterschreitung) der anliegenden Spannung. Mittels der verfügbaren Register kann man genau einstellen, nach welchen Bedingungen auf Basis der &#039;&#039;&#039;Frequenz&#039;&#039;&#039; ein Schaltbefehl durchgeführt werden soll.&lt;br /&gt;
&lt;br /&gt;
Die Abschaltung erfolgt dann selbstständig durch den Aktor. &lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals (verfügbaren Register):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-cndTxCycBelow: 0 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-txThrHiFrq: 49.8 Hz&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-txThrLoFrq: 50.2 Hz&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-transmitTryMax: 6 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-cndTxCycAbove: 200 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-cndTxFalling: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-cndTxRising: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-ledOnTime: 0.5 s&lt;br /&gt;
&lt;br /&gt;
Dieser Kanal dient nur zum Auslesen und Setzen der Register für die Abschaltautomatik und stellt daher keine Readings oder speziellen Kommandos zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
=== Beispielkonfiguration ===&lt;br /&gt;
Ein Master-Slave-Beispiel aus dem {{Link2Forum|Topic=32840|Message=253040|LinkText=Forum}} um einen HM-ES-PMSw1-Pl mit einem HM Aktor zu [[Peering (HomeMatic)|peeren]]:&lt;br /&gt;
&lt;br /&gt;
Es gibt vier Sensorkanäle: Leistung (03), Strom (04), Spannung (05) und Frequenz (06). Wenn in Abhängigkeit vom Strom geschaltet werden soll, wird der  Strom-Komparator-Channel mit einem Aktor gepeert.&lt;br /&gt;
&lt;br /&gt;
 set HM-ES-PMSw1-Pl_Senl peerChan 0 hm_aktor set&lt;br /&gt;
&lt;br /&gt;
Dann wird der Komparator eingestellt. Hier werden die Events konfiguriert die der Komparator an den Aktor senden soll. Eine Übersicht gibt es mit &amp;lt;code&amp;gt;get regList&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 list:         register | range              | peer     | description &lt;br /&gt;
    1: cndTxCycAbove    |     literal        |          | cyclic trigger if level is above cndTxDecAbove options:on,off &lt;br /&gt;
    1: cndTxCycBelow    |     literal        |          | cyclic trigger if level is below cndTxCycBelow options:on,off &lt;br /&gt;
    1: cndTxDecAbove    |   0 to 255         |          | level for cndTxCycAbove &lt;br /&gt;
    1: cndTxDecBelow    |   0 to 255         |          | level for cndTxCycBelow &lt;br /&gt;
    1: cndTxFalling     |     literal        |          | trigger if falling options:on,off &lt;br /&gt;
    1: cndTxRising      |     literal        |          | trigger if rising options:on,off &lt;br /&gt;
    1: ledOnTime        |   0 to 1.275s      |          | LED ontime &lt;br /&gt;
    1: sign             |     literal        |          | signature (AES) options:on,off &lt;br /&gt;
    1: transmitTryMax   |   1 to 10          |          | max message re-transmit &lt;br /&gt;
    1: txThrHiCur       |   0 to 16000mA     |          | threshold low current &lt;br /&gt;
    1: txThrLoCur       |   0 to 16000mA     |          | threshold high current &lt;br /&gt;
    4: expectAES        |     literal        | required | expect AES options:on,off &lt;br /&gt;
    4: peerNeedsBurst   |     literal        | required | peer expects burst options:on,off &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst musst entschieden werden, was wie geschaltet werden soll: bei welchem Strom soll ein-/ausgeschaltet werden. Bei positiver oder negativer Flanke. Sollen die Schaltbefehle permanent wiederholt werden, oder nur bei Änderung kommen und welche Schaltwerte sollen bei den Ereignissen gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiel, 2 Events erzeugen:&lt;br /&gt;
#wenn i von unter 10mA nach über 100mA wechselt, wird ein Event mit dem Wert 200 gesendet (daraus machen wir später im Aktor ein on).&lt;br /&gt;
#wenn i von über 100mA nach unter 10mA wechselt, wird ein Event mit dem Wert 0 gesendet (daraus machen wir später im Aktor ein off).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Schaltschwellen definieren:&lt;br /&gt;
&lt;br /&gt;
 txThrHiCur       100&lt;br /&gt;
 txThrLoCur       10&lt;br /&gt;
&lt;br /&gt;
Cyclisches Senden abschalten:&lt;br /&gt;
&lt;br /&gt;
 cndTxCycAbove    off&lt;br /&gt;
 cndTxCycBelow    off&lt;br /&gt;
&lt;br /&gt;
Beide Schaltflanken auswerten, positiv soll anschalten, negativ soll ausschalten:&lt;br /&gt;
&lt;br /&gt;
 cndTxFalling     on&lt;br /&gt;
 cndTxRising      on&lt;br /&gt;
&lt;br /&gt;
und zum Schluss die Werte setzen, die der Messsensor bei den Events übermitteln soll. Zur Erinnerung: positive Flanke =&amp;gt; 200 und negative Flanke =&amp;gt; 0:&lt;br /&gt;
&lt;br /&gt;
 cndTxDecAbove    200&lt;br /&gt;
 cndTxDecBelow    0&lt;br /&gt;
&lt;br /&gt;
Danach wird im Aktor festgelegt, was beim Eintreffen von den Werten 0,200 geschehen soll.&lt;br /&gt;
&lt;br /&gt;
=== event Monitor ===&lt;br /&gt;
&amp;lt;Bitte ergänzen&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== fhem.log Auszug ===&lt;br /&gt;
&lt;br /&gt;
 2013.12.29 19:06:11.957 3: CUL_HM Unknown device CUL_HM_HM_ES_PMSw1_Pl_24A920, please define it&lt;br /&gt;
 2013.12.29 19:06:11.976 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920 CUL_HM 24A920 A1A5B840024A9200000001400AC4B455130393635383038513F0100&lt;br /&gt;
 2013.12.29 19:06:11.994 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920 FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920&lt;br /&gt;
 2013.12.29 19:06:16.879 3: Device CUL_HM_HM_ES_PMSw1_Pl_24A920 added to ActionDetector with 000:10 time&lt;br /&gt;
 2013.12.29 19:06:16.889 3: CUL_HM pair: CUL_HM_HM_ES_PMSw1_Pl_24A920 powerMeter, model HM-ES-PMSw1-Pl serialNr KEQ0965808&lt;br /&gt;
 2013.12.29 19:06:16.998 3: Device CUL_HM_HM_ES_PMSw1_Pl_24A920 added to ActionDetector with 000:10 time&lt;br /&gt;
 2013.12.29 19:06:17.905 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw CUL_HM 24A92001&lt;br /&gt;
 2013.12.29 19:06:17.909 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw&lt;br /&gt;
 2013.12.29 19:06:18.906 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr CUL_HM 24A92002&lt;br /&gt;
 2013.12.29 19:06:18.909 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr&lt;br /&gt;
 2013.12.29 19:06:19.906 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr CUL_HM 24A92003&lt;br /&gt;
 2013.12.29 19:06:19.909 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr&lt;br /&gt;
 2013.12.29 19:06:20.906 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI CUL_HM 24A92004&lt;br /&gt;
 2013.12.29 19:06:20.910 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI&lt;br /&gt;
 2013.12.29 19:06:21.907 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU CUL_HM 24A92005&lt;br /&gt;
 2013.12.29 19:06:21.974 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU&lt;br /&gt;
 2013.12.29 19:06:22.096 2: CUL_HM set CUL_HM_HM_ES_PMSw1_Pl_24A920 getConfig&lt;br /&gt;
 2013.12.29 19:06:22.917 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF CUL_HM 24A92006&lt;br /&gt;
 2013.12.29 19:06:22.921 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF&lt;br /&gt;
 2013.12.29 19:06:28.968 2: CUL_HM set CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw statusRequest&lt;br /&gt;
 2013.12.29 19:06:29.980 2: CUL_HM set CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU getConfig&lt;br /&gt;
 2013.12.29 19:06:33.990 2: CUL_HM set CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF getConfig&lt;br /&gt;
&lt;br /&gt;
=== fhem.cfg ===&lt;br /&gt;
&amp;lt;pre&amp;gt;define CUL_HM_HM_ES_PMSw1_Pl_24A920 CUL_HM 24A920&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 .devInfo 3F0100&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 .stc 51&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 IODev LANCUL&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 actCycle 000:10&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 actStatus alive&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 autoReadReg 4_reqStatus&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 expert 2_full&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 firmware 1.4&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 peerIDs &lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 room CUL_HM&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 serialNr KEQ0965808&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 subType powerMeter&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 webCmd getConfig&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920 FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920 logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920 room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw CUL_HM 24A92001&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw peerIDs 00000000,&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr CUL_HM 24A92002&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr peerIDs &lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr CUL_HM 24A92003&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr peerIDs 00000000,&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI CUL_HM 24A92004&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI peerIDs 00000000,&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU CUL_HM 24A92005&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU peerIDs 00000000,&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF CUL_HM 24A92006&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF peerIDs 00000000,&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF room CUL_HM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Loggen von Werten ===&lt;br /&gt;
Leider werden die Verbauchswerte nicht automatisch geloggt, das von FHEM angelegte Log sammelt nur Informationen des Haupt-Devices.&lt;br /&gt;
&lt;br /&gt;
Damit hier auch die Verbrauchs- und Stromwerte mitgeloggt werden, muss man dies dem Log des Haupt-Device (bevorzugt per WebInterface) hinzufügen.&lt;br /&gt;
&lt;br /&gt;
Am Ende sollte die entsprechende Definition wie folgt aussehen:&lt;br /&gt;
:&amp;lt;code&amp;gt;define FileLog_Keller.Waeschetrockner FileLog ./log/Keller.Waeschetrockner-%Y.log Keller.Waeschetrockner|Keller.Waeschetrockner_Pwr:.*&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Die Devicenamen sind natürlich an die vorliegenden Gegebenheiten anzupassen.&lt;br /&gt;
&lt;br /&gt;
=== Plots/Grafiken ===&lt;br /&gt;
Hier ein Beispielplot für den Channel 02 (Pwr):&lt;br /&gt;
&lt;br /&gt;
[[Datei:HM-ES-PMSw1-PI cut.jpg|Plot des HM-ES-PMSw1-PI (Channel 02)]]&lt;br /&gt;
&lt;br /&gt;
Inhalt der zugehörigen gplot-Datei (SVG_FileLog_HMPMSW_01_Pwr_1.gplot):&lt;br /&gt;
&lt;br /&gt;
 set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
 set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
 set xdata time&lt;br /&gt;
 set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
 set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
 set title &#039;&amp;lt;TL&amp;gt;&#039;&lt;br /&gt;
 set ytics &lt;br /&gt;
 set y2tics &lt;br /&gt;
 set grid&lt;br /&gt;
 set ylabel &amp;quot;Energie&amp;quot;&lt;br /&gt;
 set y2label &amp;quot;Power&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 #FileLog 4:HMPMSW_01_Pwr.energy\x3a::&lt;br /&gt;
 #FileLog 4:HMPMSW_01_Pwr.power\x3a::&lt;br /&gt;
 &lt;br /&gt;
 plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y1 title &#039;Energie&#039; ls l0 lw 1 with lines,\&lt;br /&gt;
      &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Power&#039; ls l1 lw 1 with lines&lt;br /&gt;
&lt;br /&gt;
und die Definitionen dafür beim Device (fhem.cfg):&lt;br /&gt;
&lt;br /&gt;
 define SVG_FileLog_HMPMSW_01_Pwr_1 SVG FileLog_HMPMSW_01_Pwr:SVG_FileLog_HMPMSW_01_Pwr_1:CURRENT&lt;br /&gt;
&lt;br /&gt;
== Tipps ==&lt;br /&gt;
&lt;br /&gt;
=== Aktor nach Stromausfall automatisch einschalten ===&lt;br /&gt;
Um dafür zu sorgen, dass nach einem Stromausfall der Aktor den Schaltausgang von sich aus auf &amp;quot;An&amp;quot; stellt (Default ist &amp;quot;Aus&amp;quot;), kann man seit Firmware Version 2.5 wie folgt vorgehen:&lt;br /&gt;
&lt;br /&gt;
Im Kanal 1 des Devices (_Sw) das Register R-powerUpAction auf on setzen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;deviceName&amp;gt;_Sw regSet powerUpAction on&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die folgende Variante ist für ältere Firmware-Versionen möglich:&lt;br /&gt;
&lt;br /&gt;
# Device auf übliche Weise mit FHEM pairen&lt;br /&gt;
# Interne Peers/Register für FHEM aktivieren &amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;set &amp;lt;deviceName&amp;gt; regSet intKeyVisib visib&amp;lt;/code&amp;gt;&lt;br /&gt;
# Erneutes getConfig auf das Device durchführen &amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;set &amp;lt;deviceName&amp;gt; getConfig&amp;lt;/code&amp;gt;&lt;br /&gt;
# Ch01 (Sw) mit Ch05 (SenU) peeren &amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;set &amp;lt;deviceName&amp;gt;_SenU peerChan 0 &amp;lt;deviceName&amp;gt;_Sw single set&amp;lt;/code&amp;gt;&lt;br /&gt;
# Erneutes getConfig auf das Device durchführen &amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;set &amp;lt;deviceName&amp;gt; getConfig&amp;lt;/code&amp;gt;&lt;br /&gt;
# Register auf Ch01 (Sw) setzen &amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet lgSwJtDlyOff on self01 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet lgSwJtOn on self01 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet shSwJtDlyOff on self01 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet shSwJtOn on self01 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet lgSwJtDlyOff on self05 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet lgSwJtOn on self05 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet shSwJtDlyOff on self05 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet shSwJtOn on self05 &amp;lt;/code&amp;gt;&lt;br /&gt;
# Register auf Ch05 (SenU) setzen &amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_SenU regSet cndTxRising on &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!-- &lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_SenU regSet txThrHiVlt 200 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_SenU regSet txThrLoVlt 180 &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Versehentliches Ausschalten mit dem Taster verhindern ===&lt;br /&gt;
&lt;br /&gt;
So kann verhindert werden, dass mit dem eingebauten Taster das angeschlossene Gerät versehentlich ausgeschaltet wird. Das Einschalten per Taster ist weiterhin möglich:&lt;br /&gt;
&lt;br /&gt;
Zunächst die internen Peers sichtbar machen: https://wiki.fhem.de/wiki/HomeMatic_Register_programmieren#Tasten_sichtbar_machen&lt;br /&gt;
&lt;br /&gt;
Dann im Kanal 1 des Devices (_Sw) shSwJtOn auf dlyOn setzen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;deviceName&amp;gt;_Sw regSet shSwJtOn dlyOn self01&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
* Sobald der PMSw1 selbst von der Spannungsversorgung getrennt worden ist, verliert er die bisherigen Verbrauchswerte.&lt;br /&gt;
* Nach einem Stromausfall steht der Schalter auf &amp;quot;Aus&amp;quot;, das angeschlossene Gerät ist also ebenfalls aus. Dies kann - falls man den Aktor nur zur reinen Verbrauchsmessung verwendet - bei der Messung von z.B. Kühlschrank, Kühltruhe oder Heizung zu unerfreulichen Auswirkungen führen. Eine Abhilfe schaffen die unter [[#Tipps|Tipps]] aufgeführten Register-Einstellungen.&lt;br /&gt;
: Mit der Firmware 2.5 wurde am 16.3.2015 im Switch-Channel das Register powerUpAction eingeführt.&lt;br /&gt;
&lt;br /&gt;
== Firmware Update ==&lt;br /&gt;
Empfohlene und erprobte Vorgehensweise beim [[HomeMatic Firmware Update|Update der Firmware]] wie {{Link2Forum|Topic=59000|Message=503989|LinkText=hier im Forum}} beschrieben. Besonders zu beachten:&lt;br /&gt;
* IO Device verwenden, das für Updates geeignet ist (Attribute IODev und IOgrp), ggf. andere IO Devices vorübergehend auf inaktiv setzen&lt;br /&gt;
* Aktor in Steckdose stecken und einschalten&lt;br /&gt;
* fwUpdate Kommando aus FHEM heraus absetzen&lt;br /&gt;
* Update kann zwei bis drei Minuten dauern (schnelles Blinken der LED (rot) am Aktor)&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://files.elv.de/Assets/Produkte/13/1302/130248/Downloads/130248_schaltaktor_messen_um.pdf Manual]&lt;br /&gt;
* [http://files.elv.de/Assets/Produkte/13/1302/130248/Downloads/130248_schaltaktor_messfunktion_data.pdf Datenblatt]&lt;br /&gt;
* [http://www.eq-3.de/produkte/homematic/licht/homematic-funk-schaltaktor-1-fach-mit-leistungsmessung-typ-f.html Produktinfo]&lt;br /&gt;
* [http://www.meintechblog.de/2014/01/homematic-funk-steckdose-mit-leistungsmessung-deine-waschmaschine-ist-fertig/ Beispiel-Anwendung]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;br /&gt;
[[Kategorie:Schalter (Empfänger)]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-ES-PMSw1-Pl_Funk-Schaltaktor_1-fach_mit_Leistungsmessung&amp;diff=22378</id>
		<title>HM-ES-PMSw1-Pl Funk-Schaltaktor 1-fach mit Leistungsmessung</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-ES-PMSw1-Pl_Funk-Schaltaktor_1-fach_mit_Leistungsmessung&amp;diff=22378"/>
		<updated>2017-08-26T15:26:25Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* Tipps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Hardware&lt;br /&gt;
|Bild=HM-ES-PMSw1-PI-Frontansicht.jpg&lt;br /&gt;
|Bildbeschreibung=Frontansicht&lt;br /&gt;
|HWProtocol=HomeMatic&lt;br /&gt;
|HWType=[[HomeMatic Type powerMeter|powerMeter]]&lt;br /&gt;
|HWCategory=HomeMatic&lt;br /&gt;
|HWComm=868MHz&lt;br /&gt;
|HWChannels=6&lt;br /&gt;
|HWVoltage=230V&lt;br /&gt;
|HWPowerConsumption=&amp;lt;0,6W&lt;br /&gt;
|HWPoweredBy=Netz&lt;br /&gt;
|HWSize=59 x 123 x 40mm&lt;br /&gt;
|HWDeviceFHEM=[[CUL_HM]]&lt;br /&gt;
|HWManufacturer=ELV / eQ-3 &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--  &#039;&#039;&#039;HM-ES-PMSw1-Pl&#039;&#039;&#039;  --&amp;gt;&lt;br /&gt;
[[HM-ES-PMSw1-Pl Funk-Schaltaktor 1-fach mit Leistungsmessung|HM-ES-PMSw1-Pl]] ist ein [[HomeMatic]] Funk-Schaltaktor in Zwischenstecker-Ausführung, der über die Schaltfunktion hinaus auch Informationen über den aktuellen Verbrauch der angeschlossenen Verbraucher sowie über die anliegende Spannung und Netzfrequenz liefert. Dieser Aktor ist seit dem 20.12.2013 verfügbar. &lt;br /&gt;
&lt;br /&gt;
Ein Gerät mit gleichem Funktionsumfang ist als [[HM-ES-PMSw1-DR Hutschienen-Schaltaktor mit Leistungsmessung|HM-ES-PMSw1-DR]] für die Hutschienenmontage verfügbar.&lt;br /&gt;
&lt;br /&gt;
[[Datei:HM-ES-PMSw1-PI-Seitenansicht.jpg|thumb|HM-ES-PMSw1-PI Seitenansicht]]&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
HomeMatic Funk-Schaltaktor mit Leistungsmessung für zwei Funktionsbereiche:&lt;br /&gt;
* Schalten von angeschlossenen Verbrauchern (Schaltkanal)&lt;br /&gt;
* Messen von Spannung, Strom, Wirkleistung, Frequenz und Energieverbrauch (Messkanal)&lt;br /&gt;
* Automatische Schalten von angelernten Aktoren beim Über- oder Unterschreiten von definierten Schwellwerten (Sensorkanäle)&lt;br /&gt;
&lt;br /&gt;
Der Schaltkanal kann angeschlossene Verbraucher oder angelernte HomeMatic Aktoren ein- bzw. ausschalten.&lt;br /&gt;
Der Messkanal verfügt über eine Messfunktion und Empfangs- sowie Übertragungsmöglichkeit von Messdaten (z.B. Spannung, Strom, Wirkleistung, Frequenz und Energieverbrauch bis 3680 Watt/16 A). Die Messdaten werden je nach Verbraucherverhalten in Abständen von einigen Sekunden bis mehreren Minuten übertragen, der Sendezyklus kann durch verschiedene Register konfiguriert werden (Änderungsschwellwerte). Des weiteren kann er - in Abhängigkeit von definierbaren Schwellwerten (Über- / Unterschreitung) - andere Aktoren schalten.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Technische Daten:&#039;&#039;&#039;&lt;br /&gt;
* Spannungsversorgung: 230 V/50 Hz&lt;br /&gt;
* Stromaufnahme: 16 A max.&lt;br /&gt;
* Leistungsaufnahme Ruhebetrieb: &amp;lt; 0,6 W&lt;br /&gt;
* Max. Schaltleistung: 3680 W (ohmsche Last)&lt;br /&gt;
* Schutzart: IP 20&lt;br /&gt;
* Relais: Schließer&lt;br /&gt;
* Schaltzyklen: 50.000 bei cosφ=1&lt;br /&gt;
* Abmessungen (B x H x T): 59 x 123 x 40 mm&lt;br /&gt;
* Gewicht: 165 g (ohne Netzstecker)&lt;br /&gt;
* Messauflösung Leistung: 0,01 W&lt;br /&gt;
* Messbereich Leistung: 0–3.680 W&lt;br /&gt;
* Messgenauigkeit Leistung: 1 % ±0,03 W&lt;br /&gt;
* Messauflösung Strom: 1 mA&lt;br /&gt;
* Messbereich Strom: 0–16 A&lt;br /&gt;
* Messgenauigkeit Strom: 1 % ±1 mA&lt;br /&gt;
* Messauflösung Spannung: 0,1 V&lt;br /&gt;
* Messbereich Spannung: 200–255 V&lt;br /&gt;
* Messgenauigkeit Spannung: 0,5 % ±0,1 V&lt;br /&gt;
* Messauflösung Frequenz: 0,01 Hz&lt;br /&gt;
* Messbereich Frequenz: 48,72–51,27 Hz&lt;br /&gt;
* Messgenauigkeit Frequenz: 0,1 % ±0,01 Hz&lt;br /&gt;
&lt;br /&gt;
(Angaben ohne Gewähr)&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Inbetriebnahme und Installation ==&lt;br /&gt;
Der PMSw1 funktioniert &amp;quot;out-of-the-box&amp;quot;, nachdem er an FHEM angelernt (gepairt) worden ist.&lt;br /&gt;
&lt;br /&gt;
Das [[Pairing (HomeMatic)|Pairing]] sollte wie in [[HomeMatic Devices pairen]] beschrieben durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit FHEM ==&lt;br /&gt;
Der PMSw1 verfügt über insgesamt 6 Kanäle (HM-Jargon: channels), von denen der Schaltkanal (Kanal 1) und der Messkanal (Kanal 2) in FHEM primär genutzt werden. Die Kanäle 3 - 6 sind zur Konfiguration der Schaltvorgänge [[Peering (HomeMatic)|gepeerter]] Aktoren bei Änderungen des Leistungsverbrauchs (Kanal 3), des Stromverbrauchs (Kanal 4), der elektrischen Spannung (Kanal 5) oder der Frequenz (Kanal 6). Diese Kanäle können ausschließlich über Register konfiguriert werden. &lt;br /&gt;
&lt;br /&gt;
=== Channels (Kanäle) 01 bis 06 ===&lt;br /&gt;
==== Channel 01 (_Sw) ====&lt;br /&gt;
Der eigentliche Schaltkanal, über den die am PMSw1 eingesteckten Verbraucher ein- und ausgeschaltet werden können.&lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw set_on&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw level: 100 %&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw pct: 100&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw deviceMsg: on (to HMLAN1)&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw timedOn: off&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw set_off&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw level: 0 %&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw pct: 0&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw deviceMsg: off (to HMLAN1)&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw timedOn: off&lt;br /&gt;
&lt;br /&gt;
==== Channel 02 (_Pwr) ====&lt;br /&gt;
&lt;br /&gt;
Der Messkanal des PMSw1, über den die momentane Netzspannung, die Frequenz (in Hz), die aktuellen Verbrauchswerte (Last, Watt) sowie die seit Inbetriebnahme umgewandelte Leistung (&amp;quot;Verbrauch&amp;quot;, Wh) usw. an die Zentrale (hier FHEM) übermittelt werden.&lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr energy: 153.2&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr power: 90.92&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr current: 427&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr voltage: 233.4&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr 50: -&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr boot: on&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr energy: 153.8&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr power: 80.85&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr current: 384&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr voltage: 232.2&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr 50: -&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr boot: on&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr energy: 157.5&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr power: 86.41&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr current: 409&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr voltage: 232.6&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr 50: -&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr boot: on&lt;br /&gt;
&lt;br /&gt;
==== Channel 03 (_SenPwr) ====&lt;br /&gt;
&lt;br /&gt;
Dieser Sensorkanal beinhaltet die Logik für eine automatische Schaltung aller angelernten Aktoren auf Basis des &#039;&#039;&#039;momentanen Leistungsverbrauchs&#039;&#039;&#039; (Überschreitung oder Unterschreitung) der angeschlossenen Verbraucher. Mittels der verfügbaren Register kann man genau einstellen, nach welchen Bedingungen aufgrund des &#039;&#039;&#039;momentanen Leistungsverbrauches&#039;&#039;&#039; ein Schaltbefehl gesendet werden soll.&lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals (verfügbaren Register):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-cndTxCycBelow: 0 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-txThrLoPwr: 200 W&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-transmitTryMax: 6 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-cndTxCycAbove: 200 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-cndTxFalling: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-txThrHiPwr: 100 W&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-cndTxRising: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-ledOnTime: 0.5 s&lt;br /&gt;
&lt;br /&gt;
Dieser Kanal dient nur zum Auslesen und Setzen der Register für die Schaltautomaik und stellt daher keine Readings oder speziellen Kommandos zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==== Channel 04 (_SenI) ====&lt;br /&gt;
Dieser Sensorkanal beinhaltet die Logik für eine automatische Schaltung aller angelernten Aktoren auf Basis des &#039;&#039;&#039;momentanen Stromverbrauchs&#039;&#039;&#039; (Überschreitung oder Unterschreitung) der angeschlossenen Verbraucher. Mittels der verfügbaren Register kann man genau einstellen, nach welchen Bedingungen aufgrund des &#039;&#039;&#039;momentanen Stromverbrauchs&#039;&#039;&#039; ein Schaltbefehl gesendet werden soll.&lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals (verfügbaren Register):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-cndTxCycBelow: 0 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-txThrLoCur: 20 mA&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-transmitTryMax: 6 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-cndTxCycAbove: 200 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-cndTxFalling: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-txThrHiCur: 10 mA&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-cndTxRising: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-ledOnTime: 0.5 s&lt;br /&gt;
&lt;br /&gt;
Dieser Kanal dient nur zum Auslesen und Setzen der Register für die Abschaltautomatik und stellt daher keine Readings oder speziellen Kommandos zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==== Channel 05 (_SenU) ====&lt;br /&gt;
Dieser Sensorkanal beinhaltet die Logik für eine automatische Schaltung aller angelernten Aktoren auf Basis der aktuell anliegenden &#039;&#039;&#039;elektrischen Spannung&#039;&#039;&#039; (Überschreitung oder Unterschreitung). Mittels der verfügbaren Register kann man genau einstellen, nach welchen Bedingungen auf Basis der &#039;&#039;&#039;elektrischen Spannung&#039;&#039;&#039; ein Schaltbefehl durchgeführt werden soll.&lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals (verfügbaren Register):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-cndTxCycBelow: 0 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-transmitTryMax: 6 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-txThrLoVlt: 24 V&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-cndTxCycAbove: 200 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-cndTxFalling: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-txThrHiVlt: 22 V&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-cndTxRising: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-ledOnTime: 0.5 s&lt;br /&gt;
&lt;br /&gt;
==== Channel 06 (_SenF) ====&lt;br /&gt;
Dieser Sensorkanal beinhaltet die Logik für eine automatische Schaltung aller angelernten Aktoren auf Basis der &#039;&#039;&#039;Frequenz&#039;&#039;&#039; (Überschreitung oder Unterschreitung) der anliegenden Spannung. Mittels der verfügbaren Register kann man genau einstellen, nach welchen Bedingungen auf Basis der &#039;&#039;&#039;Frequenz&#039;&#039;&#039; ein Schaltbefehl durchgeführt werden soll.&lt;br /&gt;
&lt;br /&gt;
Die Abschaltung erfolgt dann selbstständig durch den Aktor. &lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals (verfügbaren Register):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-cndTxCycBelow: 0 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-txThrHiFrq: 49.8 Hz&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-txThrLoFrq: 50.2 Hz&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-transmitTryMax: 6 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-cndTxCycAbove: 200 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-cndTxFalling: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-cndTxRising: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-ledOnTime: 0.5 s&lt;br /&gt;
&lt;br /&gt;
Dieser Kanal dient nur zum Auslesen und Setzen der Register für die Abschaltautomatik und stellt daher keine Readings oder speziellen Kommandos zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
=== Beispielkonfiguration ===&lt;br /&gt;
Ein Master-Slave-Beispiel aus dem {{Link2Forum|Topic=32840|Message=253040|LinkText=Forum}} um einen HM-ES-PMSw1-Pl mit einem HM Aktor zu [[Peering (HomeMatic)|peeren]]:&lt;br /&gt;
&lt;br /&gt;
Es gibt vier Sensorkanäle: Leistung (03), Strom (04), Spannung (05) und Frequenz (06). Wenn in Abhängigkeit vom Strom geschaltet werden soll, wird der  Strom-Komparator-Channel mit einem Aktor gepeert.&lt;br /&gt;
&lt;br /&gt;
 set HM-ES-PMSw1-Pl_Senl peerChan 0 hm_aktor set&lt;br /&gt;
&lt;br /&gt;
Dann wird der Komparator eingestellt. Hier werden die Events konfiguriert die der Komparator an den Aktor senden soll. Eine Übersicht gibt es mit &amp;lt;code&amp;gt;get regList&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 list:         register | range              | peer     | description &lt;br /&gt;
    1: cndTxCycAbove    |     literal        |          | cyclic trigger if level is above cndTxDecAbove options:on,off &lt;br /&gt;
    1: cndTxCycBelow    |     literal        |          | cyclic trigger if level is below cndTxCycBelow options:on,off &lt;br /&gt;
    1: cndTxDecAbove    |   0 to 255         |          | level for cndTxCycAbove &lt;br /&gt;
    1: cndTxDecBelow    |   0 to 255         |          | level for cndTxCycBelow &lt;br /&gt;
    1: cndTxFalling     |     literal        |          | trigger if falling options:on,off &lt;br /&gt;
    1: cndTxRising      |     literal        |          | trigger if rising options:on,off &lt;br /&gt;
    1: ledOnTime        |   0 to 1.275s      |          | LED ontime &lt;br /&gt;
    1: sign             |     literal        |          | signature (AES) options:on,off &lt;br /&gt;
    1: transmitTryMax   |   1 to 10          |          | max message re-transmit &lt;br /&gt;
    1: txThrHiCur       |   0 to 16000mA     |          | threshold low current &lt;br /&gt;
    1: txThrLoCur       |   0 to 16000mA     |          | threshold high current &lt;br /&gt;
    4: expectAES        |     literal        | required | expect AES options:on,off &lt;br /&gt;
    4: peerNeedsBurst   |     literal        | required | peer expects burst options:on,off &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst musst entschieden werden, was wie geschaltet werden soll: bei welchem Strom soll ein-/ausgeschaltet werden. Bei positiver oder negativer Flanke. Sollen die Schaltbefehle permanent wiederholt werden, oder nur bei Änderung kommen und welche Schaltwerte sollen bei den Ereignissen gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiel, 2 Events erzeugen:&lt;br /&gt;
#wenn i von unter 10mA nach über 100mA wechselt, wird ein Event mit dem Wert 200 gesendet (daraus machen wir später im Aktor ein on).&lt;br /&gt;
#wenn i von über 100mA nach unter 10mA wechselt, wird ein Event mit dem Wert 0 gesendet (daraus machen wir später im Aktor ein off).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Schaltschwellen definieren:&lt;br /&gt;
&lt;br /&gt;
 txThrHiCur       100&lt;br /&gt;
 txThrLoCur       10&lt;br /&gt;
&lt;br /&gt;
Cyclisches Senden abschalten:&lt;br /&gt;
&lt;br /&gt;
 cndTxCycAbove    off&lt;br /&gt;
 cndTxCycBelow    off&lt;br /&gt;
&lt;br /&gt;
Beide Schaltflanken auswerten, positiv soll anschalten, negativ soll ausschalten:&lt;br /&gt;
&lt;br /&gt;
 cndTxFalling     on&lt;br /&gt;
 cndTxRising      on&lt;br /&gt;
&lt;br /&gt;
und zum Schluss die Werte setzen, die der Messsensor bei den Events übermitteln soll. Zur Erinnerung: positive Flanke =&amp;gt; 200 und negative Flanke =&amp;gt; 0:&lt;br /&gt;
&lt;br /&gt;
 cndTxDecAbove    200&lt;br /&gt;
 cndTxDecBelow    0&lt;br /&gt;
&lt;br /&gt;
Danach wird im Aktor festgelegt, was beim Eintreffen von den Werten 0,200 geschehen soll.&lt;br /&gt;
&lt;br /&gt;
=== event Monitor ===&lt;br /&gt;
&amp;lt;Bitte ergänzen&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== fhem.log Auszug ===&lt;br /&gt;
&lt;br /&gt;
 2013.12.29 19:06:11.957 3: CUL_HM Unknown device CUL_HM_HM_ES_PMSw1_Pl_24A920, please define it&lt;br /&gt;
 2013.12.29 19:06:11.976 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920 CUL_HM 24A920 A1A5B840024A9200000001400AC4B455130393635383038513F0100&lt;br /&gt;
 2013.12.29 19:06:11.994 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920 FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920&lt;br /&gt;
 2013.12.29 19:06:16.879 3: Device CUL_HM_HM_ES_PMSw1_Pl_24A920 added to ActionDetector with 000:10 time&lt;br /&gt;
 2013.12.29 19:06:16.889 3: CUL_HM pair: CUL_HM_HM_ES_PMSw1_Pl_24A920 powerMeter, model HM-ES-PMSw1-Pl serialNr KEQ0965808&lt;br /&gt;
 2013.12.29 19:06:16.998 3: Device CUL_HM_HM_ES_PMSw1_Pl_24A920 added to ActionDetector with 000:10 time&lt;br /&gt;
 2013.12.29 19:06:17.905 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw CUL_HM 24A92001&lt;br /&gt;
 2013.12.29 19:06:17.909 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw&lt;br /&gt;
 2013.12.29 19:06:18.906 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr CUL_HM 24A92002&lt;br /&gt;
 2013.12.29 19:06:18.909 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr&lt;br /&gt;
 2013.12.29 19:06:19.906 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr CUL_HM 24A92003&lt;br /&gt;
 2013.12.29 19:06:19.909 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr&lt;br /&gt;
 2013.12.29 19:06:20.906 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI CUL_HM 24A92004&lt;br /&gt;
 2013.12.29 19:06:20.910 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI&lt;br /&gt;
 2013.12.29 19:06:21.907 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU CUL_HM 24A92005&lt;br /&gt;
 2013.12.29 19:06:21.974 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU&lt;br /&gt;
 2013.12.29 19:06:22.096 2: CUL_HM set CUL_HM_HM_ES_PMSw1_Pl_24A920 getConfig&lt;br /&gt;
 2013.12.29 19:06:22.917 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF CUL_HM 24A92006&lt;br /&gt;
 2013.12.29 19:06:22.921 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF&lt;br /&gt;
 2013.12.29 19:06:28.968 2: CUL_HM set CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw statusRequest&lt;br /&gt;
 2013.12.29 19:06:29.980 2: CUL_HM set CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU getConfig&lt;br /&gt;
 2013.12.29 19:06:33.990 2: CUL_HM set CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF getConfig&lt;br /&gt;
&lt;br /&gt;
=== fhem.cfg ===&lt;br /&gt;
&amp;lt;pre&amp;gt;define CUL_HM_HM_ES_PMSw1_Pl_24A920 CUL_HM 24A920&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 .devInfo 3F0100&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 .stc 51&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 IODev LANCUL&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 actCycle 000:10&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 actStatus alive&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 autoReadReg 4_reqStatus&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 expert 2_full&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 firmware 1.4&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 peerIDs &lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 room CUL_HM&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 serialNr KEQ0965808&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 subType powerMeter&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 webCmd getConfig&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920 FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920 logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920 room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw CUL_HM 24A92001&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw peerIDs 00000000,&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr CUL_HM 24A92002&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr peerIDs &lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr CUL_HM 24A92003&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr peerIDs 00000000,&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI CUL_HM 24A92004&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI peerIDs 00000000,&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU CUL_HM 24A92005&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU peerIDs 00000000,&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF CUL_HM 24A92006&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF peerIDs 00000000,&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF room CUL_HM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Loggen von Werten ===&lt;br /&gt;
Leider werden die Verbauchswerte nicht automatisch geloggt, das von FHEM angelegte Log sammelt nur Informationen des Haupt-Devices.&lt;br /&gt;
&lt;br /&gt;
Damit hier auch die Verbrauchs- und Stromwerte mitgeloggt werden, muss man dies dem Log des Haupt-Device (bevorzugt per WebInterface) hinzufügen.&lt;br /&gt;
&lt;br /&gt;
Am Ende sollte die entsprechende Definition wie folgt aussehen:&lt;br /&gt;
:&amp;lt;code&amp;gt;define FileLog_Keller.Waeschetrockner FileLog ./log/Keller.Waeschetrockner-%Y.log Keller.Waeschetrockner|Keller.Waeschetrockner_Pwr:.*&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Die Devicenamen sind natürlich an die vorliegenden Gegebenheiten anzupassen.&lt;br /&gt;
&lt;br /&gt;
=== Plots/Grafiken ===&lt;br /&gt;
Hier ein Beispielplot für den Channel 02 (Pwr):&lt;br /&gt;
&lt;br /&gt;
[[Datei:HM-ES-PMSw1-PI cut.jpg|Plot des HM-ES-PMSw1-PI (Channel 02)]]&lt;br /&gt;
&lt;br /&gt;
Inhalt der zugehörigen gplot-Datei (SVG_FileLog_HMPMSW_01_Pwr_1.gplot):&lt;br /&gt;
&lt;br /&gt;
 set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
 set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
 set xdata time&lt;br /&gt;
 set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
 set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
 set title &#039;&amp;lt;TL&amp;gt;&#039;&lt;br /&gt;
 set ytics &lt;br /&gt;
 set y2tics &lt;br /&gt;
 set grid&lt;br /&gt;
 set ylabel &amp;quot;Energie&amp;quot;&lt;br /&gt;
 set y2label &amp;quot;Power&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 #FileLog 4:HMPMSW_01_Pwr.energy\x3a::&lt;br /&gt;
 #FileLog 4:HMPMSW_01_Pwr.power\x3a::&lt;br /&gt;
 &lt;br /&gt;
 plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y1 title &#039;Energie&#039; ls l0 lw 1 with lines,\&lt;br /&gt;
      &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Power&#039; ls l1 lw 1 with lines&lt;br /&gt;
&lt;br /&gt;
und die Definitionen dafür beim Device (fhem.cfg):&lt;br /&gt;
&lt;br /&gt;
 define SVG_FileLog_HMPMSW_01_Pwr_1 SVG FileLog_HMPMSW_01_Pwr:SVG_FileLog_HMPMSW_01_Pwr_1:CURRENT&lt;br /&gt;
&lt;br /&gt;
== Tipps ==&lt;br /&gt;
Um dafür zu sorgen, dass nach einem Stromausfall der Aktor den Schaltausgang von sich aus auf &amp;quot;An&amp;quot; stellt (Default ist &amp;quot;Aus&amp;quot;), kann man seit Firmware Version 2.5 wie folgt vorgehen:&lt;br /&gt;
&lt;br /&gt;
Im Kanal 1 des Devices (_sw) das Register R-powerUpAction auf on setzen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device_channel01&amp;gt; regSet powerUpAction on&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die folgende Variante ist für ältere Firmware-Versionen möglich:&lt;br /&gt;
&lt;br /&gt;
# Device auf übliche Weise mit FHEM pairen&lt;br /&gt;
# Interne Peers/Register für FHEM aktivieren &amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;set &amp;lt;deviceName&amp;gt; regSet intKeyVisib visib&amp;lt;/code&amp;gt;&lt;br /&gt;
# Erneutes getConfig auf das Device durchführen &amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;set &amp;lt;deviceName&amp;gt; getConfig&amp;lt;/code&amp;gt;&lt;br /&gt;
# Ch01 (Sw) mit Ch05 (SenU) peeren &amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;set &amp;lt;deviceName&amp;gt;_SenU peerChan 0 &amp;lt;deviceName&amp;gt;_Sw single set&amp;lt;/code&amp;gt;&lt;br /&gt;
# Erneutes getConfig auf das Device durchführen &amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;set &amp;lt;deviceName&amp;gt; getConfig&amp;lt;/code&amp;gt;&lt;br /&gt;
# Register auf Ch01 (Sw) setzen &amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet lgSwJtDlyOff on self01 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet lgSwJtOn on self01 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet shSwJtDlyOff on self01 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet shSwJtOn on self01 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet lgSwJtDlyOff on self05 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet lgSwJtOn on self05 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet shSwJtDlyOff on self05 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet shSwJtOn on self05 &amp;lt;/code&amp;gt;&lt;br /&gt;
# Register auf Ch05 (SenU) setzen &amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_SenU regSet cndTxRising on &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!-- &lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_SenU regSet txThrHiVlt 200 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_SenU regSet txThrLoVlt 180 &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
* Sobald der PMSw1 selbst von der Spannungsversorgung getrennt worden ist, verliert er die bisherigen Verbrauchswerte.&lt;br /&gt;
* Nach einem Stromausfall steht der Schalter auf &amp;quot;Aus&amp;quot;, das angeschlossene Gerät ist also ebenfalls aus. Dies kann - falls man den Aktor nur zur reinen Verbrauchsmessung verwendet - bei der Messung von z.B. Kühlschrank, Kühltruhe oder Heizung zu unerfreulichen Auswirkungen führen. Eine Abhilfe schaffen die unter [[#Tipps|Tipps]] aufgeführten Register-Einstellungen.&lt;br /&gt;
: Mit der Firmware 2.5 wurde am 16.3.2015 im Switch-Channel das Register powerUpAction eingeführt.&lt;br /&gt;
&lt;br /&gt;
== Firmware Update ==&lt;br /&gt;
Empfohlene und erprobte Vorgehensweise beim [[HomeMatic Firmware Update|Update der Firmware]] wie {{Link2Forum|Topic=59000|Message=503989|LinkText=hier im Forum}} beschrieben. Besonders zu beachten:&lt;br /&gt;
* IO Device verwenden, das für Updates geeignet ist (Attribute IODev und IOgrp), ggf. andere IO Devices vorübergehend auf inaktiv setzen&lt;br /&gt;
* Aktor in Steckdose stecken und einschalten&lt;br /&gt;
* fwUpdate Kommando aus FHEM heraus absetzen&lt;br /&gt;
* Update kann zwei bis drei Minuten dauern (schnelles Blinken der LED (rot) am Aktor)&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://files.elv.de/Assets/Produkte/13/1302/130248/Downloads/130248_schaltaktor_messen_um.pdf Manual]&lt;br /&gt;
* [http://files.elv.de/Assets/Produkte/13/1302/130248/Downloads/130248_schaltaktor_messfunktion_data.pdf Datenblatt]&lt;br /&gt;
* [http://www.eq-3.de/produkte/homematic/licht/homematic-funk-schaltaktor-1-fach-mit-leistungsmessung-typ-f.html Produktinfo]&lt;br /&gt;
* [http://www.meintechblog.de/2014/01/homematic-funk-steckdose-mit-leistungsmessung-deine-waschmaschine-ist-fertig/ Beispiel-Anwendung]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;br /&gt;
[[Kategorie:Schalter (Empfänger)]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-ES-PMSw1-Pl_Funk-Schaltaktor_1-fach_mit_Leistungsmessung&amp;diff=22377</id>
		<title>HM-ES-PMSw1-Pl Funk-Schaltaktor 1-fach mit Leistungsmessung</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-ES-PMSw1-Pl_Funk-Schaltaktor_1-fach_mit_Leistungsmessung&amp;diff=22377"/>
		<updated>2017-08-26T15:25:40Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: powerUpAction ergänzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Hardware&lt;br /&gt;
|Bild=HM-ES-PMSw1-PI-Frontansicht.jpg&lt;br /&gt;
|Bildbeschreibung=Frontansicht&lt;br /&gt;
|HWProtocol=HomeMatic&lt;br /&gt;
|HWType=[[HomeMatic Type powerMeter|powerMeter]]&lt;br /&gt;
|HWCategory=HomeMatic&lt;br /&gt;
|HWComm=868MHz&lt;br /&gt;
|HWChannels=6&lt;br /&gt;
|HWVoltage=230V&lt;br /&gt;
|HWPowerConsumption=&amp;lt;0,6W&lt;br /&gt;
|HWPoweredBy=Netz&lt;br /&gt;
|HWSize=59 x 123 x 40mm&lt;br /&gt;
|HWDeviceFHEM=[[CUL_HM]]&lt;br /&gt;
|HWManufacturer=ELV / eQ-3 &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--  &#039;&#039;&#039;HM-ES-PMSw1-Pl&#039;&#039;&#039;  --&amp;gt;&lt;br /&gt;
[[HM-ES-PMSw1-Pl Funk-Schaltaktor 1-fach mit Leistungsmessung|HM-ES-PMSw1-Pl]] ist ein [[HomeMatic]] Funk-Schaltaktor in Zwischenstecker-Ausführung, der über die Schaltfunktion hinaus auch Informationen über den aktuellen Verbrauch der angeschlossenen Verbraucher sowie über die anliegende Spannung und Netzfrequenz liefert. Dieser Aktor ist seit dem 20.12.2013 verfügbar. &lt;br /&gt;
&lt;br /&gt;
Ein Gerät mit gleichem Funktionsumfang ist als [[HM-ES-PMSw1-DR Hutschienen-Schaltaktor mit Leistungsmessung|HM-ES-PMSw1-DR]] für die Hutschienenmontage verfügbar.&lt;br /&gt;
&lt;br /&gt;
[[Datei:HM-ES-PMSw1-PI-Seitenansicht.jpg|thumb|HM-ES-PMSw1-PI Seitenansicht]]&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
HomeMatic Funk-Schaltaktor mit Leistungsmessung für zwei Funktionsbereiche:&lt;br /&gt;
* Schalten von angeschlossenen Verbrauchern (Schaltkanal)&lt;br /&gt;
* Messen von Spannung, Strom, Wirkleistung, Frequenz und Energieverbrauch (Messkanal)&lt;br /&gt;
* Automatische Schalten von angelernten Aktoren beim Über- oder Unterschreiten von definierten Schwellwerten (Sensorkanäle)&lt;br /&gt;
&lt;br /&gt;
Der Schaltkanal kann angeschlossene Verbraucher oder angelernte HomeMatic Aktoren ein- bzw. ausschalten.&lt;br /&gt;
Der Messkanal verfügt über eine Messfunktion und Empfangs- sowie Übertragungsmöglichkeit von Messdaten (z.B. Spannung, Strom, Wirkleistung, Frequenz und Energieverbrauch bis 3680 Watt/16 A). Die Messdaten werden je nach Verbraucherverhalten in Abständen von einigen Sekunden bis mehreren Minuten übertragen, der Sendezyklus kann durch verschiedene Register konfiguriert werden (Änderungsschwellwerte). Des weiteren kann er - in Abhängigkeit von definierbaren Schwellwerten (Über- / Unterschreitung) - andere Aktoren schalten.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Technische Daten:&#039;&#039;&#039;&lt;br /&gt;
* Spannungsversorgung: 230 V/50 Hz&lt;br /&gt;
* Stromaufnahme: 16 A max.&lt;br /&gt;
* Leistungsaufnahme Ruhebetrieb: &amp;lt; 0,6 W&lt;br /&gt;
* Max. Schaltleistung: 3680 W (ohmsche Last)&lt;br /&gt;
* Schutzart: IP 20&lt;br /&gt;
* Relais: Schließer&lt;br /&gt;
* Schaltzyklen: 50.000 bei cosφ=1&lt;br /&gt;
* Abmessungen (B x H x T): 59 x 123 x 40 mm&lt;br /&gt;
* Gewicht: 165 g (ohne Netzstecker)&lt;br /&gt;
* Messauflösung Leistung: 0,01 W&lt;br /&gt;
* Messbereich Leistung: 0–3.680 W&lt;br /&gt;
* Messgenauigkeit Leistung: 1 % ±0,03 W&lt;br /&gt;
* Messauflösung Strom: 1 mA&lt;br /&gt;
* Messbereich Strom: 0–16 A&lt;br /&gt;
* Messgenauigkeit Strom: 1 % ±1 mA&lt;br /&gt;
* Messauflösung Spannung: 0,1 V&lt;br /&gt;
* Messbereich Spannung: 200–255 V&lt;br /&gt;
* Messgenauigkeit Spannung: 0,5 % ±0,1 V&lt;br /&gt;
* Messauflösung Frequenz: 0,01 Hz&lt;br /&gt;
* Messbereich Frequenz: 48,72–51,27 Hz&lt;br /&gt;
* Messgenauigkeit Frequenz: 0,1 % ±0,01 Hz&lt;br /&gt;
&lt;br /&gt;
(Angaben ohne Gewähr)&lt;br /&gt;
&lt;br /&gt;
== Hinweise zur Inbetriebnahme und Installation ==&lt;br /&gt;
Der PMSw1 funktioniert &amp;quot;out-of-the-box&amp;quot;, nachdem er an FHEM angelernt (gepairt) worden ist.&lt;br /&gt;
&lt;br /&gt;
Das [[Pairing (HomeMatic)|Pairing]] sollte wie in [[HomeMatic Devices pairen]] beschrieben durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit FHEM ==&lt;br /&gt;
Der PMSw1 verfügt über insgesamt 6 Kanäle (HM-Jargon: channels), von denen der Schaltkanal (Kanal 1) und der Messkanal (Kanal 2) in FHEM primär genutzt werden. Die Kanäle 3 - 6 sind zur Konfiguration der Schaltvorgänge [[Peering (HomeMatic)|gepeerter]] Aktoren bei Änderungen des Leistungsverbrauchs (Kanal 3), des Stromverbrauchs (Kanal 4), der elektrischen Spannung (Kanal 5) oder der Frequenz (Kanal 6). Diese Kanäle können ausschließlich über Register konfiguriert werden. &lt;br /&gt;
&lt;br /&gt;
=== Channels (Kanäle) 01 bis 06 ===&lt;br /&gt;
==== Channel 01 (_Sw) ====&lt;br /&gt;
Der eigentliche Schaltkanal, über den die am PMSw1 eingesteckten Verbraucher ein- und ausgeschaltet werden können.&lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw set_on&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw level: 100 %&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw pct: 100&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw deviceMsg: on (to HMLAN1)&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw timedOn: off&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw set_off&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw level: 0 %&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw pct: 0&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw deviceMsg: off (to HMLAN1)&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Sw timedOn: off&lt;br /&gt;
&lt;br /&gt;
==== Channel 02 (_Pwr) ====&lt;br /&gt;
&lt;br /&gt;
Der Messkanal des PMSw1, über den die momentane Netzspannung, die Frequenz (in Hz), die aktuellen Verbrauchswerte (Last, Watt) sowie die seit Inbetriebnahme umgewandelte Leistung (&amp;quot;Verbrauch&amp;quot;, Wh) usw. an die Zentrale (hier FHEM) übermittelt werden.&lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr energy: 153.2&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr power: 90.92&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr current: 427&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr voltage: 233.4&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr 50: -&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr boot: on&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr energy: 153.8&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr power: 80.85&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr current: 384&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr voltage: 232.2&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr 50: -&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr boot: on&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr energy: 157.5&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr power: 86.41&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr current: 409&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr voltage: 232.6&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr 50: -&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_Pwr boot: on&lt;br /&gt;
&lt;br /&gt;
==== Channel 03 (_SenPwr) ====&lt;br /&gt;
&lt;br /&gt;
Dieser Sensorkanal beinhaltet die Logik für eine automatische Schaltung aller angelernten Aktoren auf Basis des &#039;&#039;&#039;momentanen Leistungsverbrauchs&#039;&#039;&#039; (Überschreitung oder Unterschreitung) der angeschlossenen Verbraucher. Mittels der verfügbaren Register kann man genau einstellen, nach welchen Bedingungen aufgrund des &#039;&#039;&#039;momentanen Leistungsverbrauches&#039;&#039;&#039; ein Schaltbefehl gesendet werden soll.&lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals (verfügbaren Register):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-cndTxCycBelow: 0 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-txThrLoPwr: 200 W&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-transmitTryMax: 6 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-cndTxCycAbove: 200 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-cndTxFalling: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-txThrHiPwr: 100 W&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-cndTxRising: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenPwr R-ledOnTime: 0.5 s&lt;br /&gt;
&lt;br /&gt;
Dieser Kanal dient nur zum Auslesen und Setzen der Register für die Schaltautomaik und stellt daher keine Readings oder speziellen Kommandos zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==== Channel 04 (_SenI) ====&lt;br /&gt;
Dieser Sensorkanal beinhaltet die Logik für eine automatische Schaltung aller angelernten Aktoren auf Basis des &#039;&#039;&#039;momentanen Stromverbrauchs&#039;&#039;&#039; (Überschreitung oder Unterschreitung) der angeschlossenen Verbraucher. Mittels der verfügbaren Register kann man genau einstellen, nach welchen Bedingungen aufgrund des &#039;&#039;&#039;momentanen Stromverbrauchs&#039;&#039;&#039; ein Schaltbefehl gesendet werden soll.&lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals (verfügbaren Register):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-cndTxCycBelow: 0 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-txThrLoCur: 20 mA&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-transmitTryMax: 6 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-cndTxCycAbove: 200 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-cndTxFalling: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-txThrHiCur: 10 mA&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-cndTxRising: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenI R-ledOnTime: 0.5 s&lt;br /&gt;
&lt;br /&gt;
Dieser Kanal dient nur zum Auslesen und Setzen der Register für die Abschaltautomatik und stellt daher keine Readings oder speziellen Kommandos zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==== Channel 05 (_SenU) ====&lt;br /&gt;
Dieser Sensorkanal beinhaltet die Logik für eine automatische Schaltung aller angelernten Aktoren auf Basis der aktuell anliegenden &#039;&#039;&#039;elektrischen Spannung&#039;&#039;&#039; (Überschreitung oder Unterschreitung). Mittels der verfügbaren Register kann man genau einstellen, nach welchen Bedingungen auf Basis der &#039;&#039;&#039;elektrischen Spannung&#039;&#039;&#039; ein Schaltbefehl durchgeführt werden soll.&lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals (verfügbaren Register):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-cndTxCycBelow: 0 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-transmitTryMax: 6 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-txThrLoVlt: 24 V&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-cndTxCycAbove: 200 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-cndTxFalling: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-txThrHiVlt: 22 V&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-cndTxRising: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenU R-ledOnTime: 0.5 s&lt;br /&gt;
&lt;br /&gt;
==== Channel 06 (_SenF) ====&lt;br /&gt;
Dieser Sensorkanal beinhaltet die Logik für eine automatische Schaltung aller angelernten Aktoren auf Basis der &#039;&#039;&#039;Frequenz&#039;&#039;&#039; (Überschreitung oder Unterschreitung) der anliegenden Spannung. Mittels der verfügbaren Register kann man genau einstellen, nach welchen Bedingungen auf Basis der &#039;&#039;&#039;Frequenz&#039;&#039;&#039; ein Schaltbefehl durchgeführt werden soll.&lt;br /&gt;
&lt;br /&gt;
Die Abschaltung erfolgt dann selbstständig durch den Aktor. &lt;br /&gt;
&lt;br /&gt;
Log-Datei des Kanals (verfügbaren Register):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-cndTxCycBelow: 0 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-txThrHiFrq: 49.8 Hz&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-txThrLoFrq: 50.2 Hz&lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-transmitTryMax: 6 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-cndTxCycAbove: 200 &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-cndTxFalling: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-cndTxRising: off &lt;br /&gt;
 &amp;lt;Datum&amp;gt;_&amp;lt;Zeit&amp;gt; HMPMSW_01_SenF R-ledOnTime: 0.5 s&lt;br /&gt;
&lt;br /&gt;
Dieser Kanal dient nur zum Auslesen und Setzen der Register für die Abschaltautomatik und stellt daher keine Readings oder speziellen Kommandos zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
=== Beispielkonfiguration ===&lt;br /&gt;
Ein Master-Slave-Beispiel aus dem {{Link2Forum|Topic=32840|Message=253040|LinkText=Forum}} um einen HM-ES-PMSw1-Pl mit einem HM Aktor zu [[Peering (HomeMatic)|peeren]]:&lt;br /&gt;
&lt;br /&gt;
Es gibt vier Sensorkanäle: Leistung (03), Strom (04), Spannung (05) und Frequenz (06). Wenn in Abhängigkeit vom Strom geschaltet werden soll, wird der  Strom-Komparator-Channel mit einem Aktor gepeert.&lt;br /&gt;
&lt;br /&gt;
 set HM-ES-PMSw1-Pl_Senl peerChan 0 hm_aktor set&lt;br /&gt;
&lt;br /&gt;
Dann wird der Komparator eingestellt. Hier werden die Events konfiguriert die der Komparator an den Aktor senden soll. Eine Übersicht gibt es mit &amp;lt;code&amp;gt;get regList&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 list:         register | range              | peer     | description &lt;br /&gt;
    1: cndTxCycAbove    |     literal        |          | cyclic trigger if level is above cndTxDecAbove options:on,off &lt;br /&gt;
    1: cndTxCycBelow    |     literal        |          | cyclic trigger if level is below cndTxCycBelow options:on,off &lt;br /&gt;
    1: cndTxDecAbove    |   0 to 255         |          | level for cndTxCycAbove &lt;br /&gt;
    1: cndTxDecBelow    |   0 to 255         |          | level for cndTxCycBelow &lt;br /&gt;
    1: cndTxFalling     |     literal        |          | trigger if falling options:on,off &lt;br /&gt;
    1: cndTxRising      |     literal        |          | trigger if rising options:on,off &lt;br /&gt;
    1: ledOnTime        |   0 to 1.275s      |          | LED ontime &lt;br /&gt;
    1: sign             |     literal        |          | signature (AES) options:on,off &lt;br /&gt;
    1: transmitTryMax   |   1 to 10          |          | max message re-transmit &lt;br /&gt;
    1: txThrHiCur       |   0 to 16000mA     |          | threshold low current &lt;br /&gt;
    1: txThrLoCur       |   0 to 16000mA     |          | threshold high current &lt;br /&gt;
    4: expectAES        |     literal        | required | expect AES options:on,off &lt;br /&gt;
    4: peerNeedsBurst   |     literal        | required | peer expects burst options:on,off &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst musst entschieden werden, was wie geschaltet werden soll: bei welchem Strom soll ein-/ausgeschaltet werden. Bei positiver oder negativer Flanke. Sollen die Schaltbefehle permanent wiederholt werden, oder nur bei Änderung kommen und welche Schaltwerte sollen bei den Ereignissen gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Beispiel, 2 Events erzeugen:&lt;br /&gt;
#wenn i von unter 10mA nach über 100mA wechselt, wird ein Event mit dem Wert 200 gesendet (daraus machen wir später im Aktor ein on).&lt;br /&gt;
#wenn i von über 100mA nach unter 10mA wechselt, wird ein Event mit dem Wert 0 gesendet (daraus machen wir später im Aktor ein off).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Schaltschwellen definieren:&lt;br /&gt;
&lt;br /&gt;
 txThrHiCur       100&lt;br /&gt;
 txThrLoCur       10&lt;br /&gt;
&lt;br /&gt;
Cyclisches Senden abschalten:&lt;br /&gt;
&lt;br /&gt;
 cndTxCycAbove    off&lt;br /&gt;
 cndTxCycBelow    off&lt;br /&gt;
&lt;br /&gt;
Beide Schaltflanken auswerten, positiv soll anschalten, negativ soll ausschalten:&lt;br /&gt;
&lt;br /&gt;
 cndTxFalling     on&lt;br /&gt;
 cndTxRising      on&lt;br /&gt;
&lt;br /&gt;
und zum Schluss die Werte setzen, die der Messsensor bei den Events übermitteln soll. Zur Erinnerung: positive Flanke =&amp;gt; 200 und negative Flanke =&amp;gt; 0:&lt;br /&gt;
&lt;br /&gt;
 cndTxDecAbove    200&lt;br /&gt;
 cndTxDecBelow    0&lt;br /&gt;
&lt;br /&gt;
Danach wird im Aktor festgelegt, was beim Eintreffen von den Werten 0,200 geschehen soll.&lt;br /&gt;
&lt;br /&gt;
=== event Monitor ===&lt;br /&gt;
&amp;lt;Bitte ergänzen&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== fhem.log Auszug ===&lt;br /&gt;
&lt;br /&gt;
 2013.12.29 19:06:11.957 3: CUL_HM Unknown device CUL_HM_HM_ES_PMSw1_Pl_24A920, please define it&lt;br /&gt;
 2013.12.29 19:06:11.976 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920 CUL_HM 24A920 A1A5B840024A9200000001400AC4B455130393635383038513F0100&lt;br /&gt;
 2013.12.29 19:06:11.994 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920 FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920&lt;br /&gt;
 2013.12.29 19:06:16.879 3: Device CUL_HM_HM_ES_PMSw1_Pl_24A920 added to ActionDetector with 000:10 time&lt;br /&gt;
 2013.12.29 19:06:16.889 3: CUL_HM pair: CUL_HM_HM_ES_PMSw1_Pl_24A920 powerMeter, model HM-ES-PMSw1-Pl serialNr KEQ0965808&lt;br /&gt;
 2013.12.29 19:06:16.998 3: Device CUL_HM_HM_ES_PMSw1_Pl_24A920 added to ActionDetector with 000:10 time&lt;br /&gt;
 2013.12.29 19:06:17.905 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw CUL_HM 24A92001&lt;br /&gt;
 2013.12.29 19:06:17.909 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw&lt;br /&gt;
 2013.12.29 19:06:18.906 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr CUL_HM 24A92002&lt;br /&gt;
 2013.12.29 19:06:18.909 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr&lt;br /&gt;
 2013.12.29 19:06:19.906 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr CUL_HM 24A92003&lt;br /&gt;
 2013.12.29 19:06:19.909 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr&lt;br /&gt;
 2013.12.29 19:06:20.906 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI CUL_HM 24A92004&lt;br /&gt;
 2013.12.29 19:06:20.910 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI&lt;br /&gt;
 2013.12.29 19:06:21.907 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU CUL_HM 24A92005&lt;br /&gt;
 2013.12.29 19:06:21.974 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU&lt;br /&gt;
 2013.12.29 19:06:22.096 2: CUL_HM set CUL_HM_HM_ES_PMSw1_Pl_24A920 getConfig&lt;br /&gt;
 2013.12.29 19:06:22.917 2: autocreate: define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF CUL_HM 24A92006&lt;br /&gt;
 2013.12.29 19:06:22.921 2: autocreate: define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF&lt;br /&gt;
 2013.12.29 19:06:28.968 2: CUL_HM set CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw statusRequest&lt;br /&gt;
 2013.12.29 19:06:29.980 2: CUL_HM set CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU getConfig&lt;br /&gt;
 2013.12.29 19:06:33.990 2: CUL_HM set CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF getConfig&lt;br /&gt;
&lt;br /&gt;
=== fhem.cfg ===&lt;br /&gt;
&amp;lt;pre&amp;gt;define CUL_HM_HM_ES_PMSw1_Pl_24A920 CUL_HM 24A920&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 .devInfo 3F0100&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 .stc 51&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 IODev LANCUL&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 actCycle 000:10&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 actStatus alive&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 autoReadReg 4_reqStatus&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 expert 2_full&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 firmware 1.4&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 peerIDs &lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 room CUL_HM&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 serialNr KEQ0965808&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 subType powerMeter&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920 webCmd getConfig&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920 FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920 logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920 room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw CUL_HM 24A92001&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw peerIDs 00000000,&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Sw room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr CUL_HM 24A92002&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr peerIDs &lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_Pwr room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr CUL_HM 24A92003&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr peerIDs 00000000,&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenPwr room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI CUL_HM 24A92004&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI peerIDs 00000000,&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenI room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU CUL_HM 24A92005&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU peerIDs 00000000,&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenU room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF CUL_HM 24A92006&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF expert 1&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF model HM-ES-PMSw1-Pl&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF peerIDs 00000000,&lt;br /&gt;
 attr CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF room CUL_HM&lt;br /&gt;
&lt;br /&gt;
 define FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF FileLog /usr/local/FHEM/var/log/CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF-%Y.log CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF logtype text&lt;br /&gt;
 attr FileLog_CUL_HM_HM_ES_PMSw1_Pl_24A920_SenF room CUL_HM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Loggen von Werten ===&lt;br /&gt;
Leider werden die Verbauchswerte nicht automatisch geloggt, das von FHEM angelegte Log sammelt nur Informationen des Haupt-Devices.&lt;br /&gt;
&lt;br /&gt;
Damit hier auch die Verbrauchs- und Stromwerte mitgeloggt werden, muss man dies dem Log des Haupt-Device (bevorzugt per WebInterface) hinzufügen.&lt;br /&gt;
&lt;br /&gt;
Am Ende sollte die entsprechende Definition wie folgt aussehen:&lt;br /&gt;
:&amp;lt;code&amp;gt;define FileLog_Keller.Waeschetrockner FileLog ./log/Keller.Waeschetrockner-%Y.log Keller.Waeschetrockner|Keller.Waeschetrockner_Pwr:.*&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Die Devicenamen sind natürlich an die vorliegenden Gegebenheiten anzupassen.&lt;br /&gt;
&lt;br /&gt;
=== Plots/Grafiken ===&lt;br /&gt;
Hier ein Beispielplot für den Channel 02 (Pwr):&lt;br /&gt;
&lt;br /&gt;
[[Datei:HM-ES-PMSw1-PI cut.jpg|Plot des HM-ES-PMSw1-PI (Channel 02)]]&lt;br /&gt;
&lt;br /&gt;
Inhalt der zugehörigen gplot-Datei (SVG_FileLog_HMPMSW_01_Pwr_1.gplot):&lt;br /&gt;
&lt;br /&gt;
 set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
 set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
 set xdata time&lt;br /&gt;
 set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
 set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
 set title &#039;&amp;lt;TL&amp;gt;&#039;&lt;br /&gt;
 set ytics &lt;br /&gt;
 set y2tics &lt;br /&gt;
 set grid&lt;br /&gt;
 set ylabel &amp;quot;Energie&amp;quot;&lt;br /&gt;
 set y2label &amp;quot;Power&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 #FileLog 4:HMPMSW_01_Pwr.energy\x3a::&lt;br /&gt;
 #FileLog 4:HMPMSW_01_Pwr.power\x3a::&lt;br /&gt;
 &lt;br /&gt;
 plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y1 title &#039;Energie&#039; ls l0 lw 1 with lines,\&lt;br /&gt;
      &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Power&#039; ls l1 lw 1 with lines&lt;br /&gt;
&lt;br /&gt;
und die Definitionen dafür beim Device (fhem.cfg):&lt;br /&gt;
&lt;br /&gt;
 define SVG_FileLog_HMPMSW_01_Pwr_1 SVG FileLog_HMPMSW_01_Pwr:SVG_FileLog_HMPMSW_01_Pwr_1:CURRENT&lt;br /&gt;
&lt;br /&gt;
== Tipps ==&lt;br /&gt;
Um dafür zu sorgen, dass nach einem Stromausfall der Aktor den Schaltausgang von sich aus auf &amp;quot;An&amp;quot; stellt (Default ist &amp;quot;Aus&amp;quot;), kann man seit Firmware Version 2.5 wie folgt vorgehen:&lt;br /&gt;
&lt;br /&gt;
Im Kanal 1 des devices (_sw) das Register R-powerUpAction auf on setzen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device_channel01&amp;gt; regSet powerUpAction on&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die folgende Variante ist für ältere Firmware-Versionen möglich:&lt;br /&gt;
&lt;br /&gt;
# Device auf übliche Weise mit FHEM pairen&lt;br /&gt;
# Interne Peers/Register für FHEM aktivieren &amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;set &amp;lt;deviceName&amp;gt; regSet intKeyVisib visib&amp;lt;/code&amp;gt;&lt;br /&gt;
# Erneutes getConfig auf das Device durchführen &amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;set &amp;lt;deviceName&amp;gt; getConfig&amp;lt;/code&amp;gt;&lt;br /&gt;
# Ch01 (Sw) mit Ch05 (SenU) peeren &amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;set &amp;lt;deviceName&amp;gt;_SenU peerChan 0 &amp;lt;deviceName&amp;gt;_Sw single set&amp;lt;/code&amp;gt;&lt;br /&gt;
# Erneutes getConfig auf das Device durchführen &amp;lt;br /&amp;gt;&amp;lt;code&amp;gt;set &amp;lt;deviceName&amp;gt; getConfig&amp;lt;/code&amp;gt;&lt;br /&gt;
# Register auf Ch01 (Sw) setzen &amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet lgSwJtDlyOff on self01 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet lgSwJtOn on self01 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet shSwJtDlyOff on self01 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet shSwJtOn on self01 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet lgSwJtDlyOff on self05 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet lgSwJtOn on self05 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet shSwJtDlyOff on self05 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_Sw regSet shSwJtOn on self05 &amp;lt;/code&amp;gt;&lt;br /&gt;
# Register auf Ch05 (SenU) setzen &amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_SenU regSet cndTxRising on &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!-- &lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_SenU regSet txThrHiVlt 200 &amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;code&amp;gt; set &amp;lt;deviceName&amp;gt;_SenU regSet txThrLoVlt 180 &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
* Sobald der PMSw1 selbst von der Spannungsversorgung getrennt worden ist, verliert er die bisherigen Verbrauchswerte.&lt;br /&gt;
* Nach einem Stromausfall steht der Schalter auf &amp;quot;Aus&amp;quot;, das angeschlossene Gerät ist also ebenfalls aus. Dies kann - falls man den Aktor nur zur reinen Verbrauchsmessung verwendet - bei der Messung von z.B. Kühlschrank, Kühltruhe oder Heizung zu unerfreulichen Auswirkungen führen. Eine Abhilfe schaffen die unter [[#Tipps|Tipps]] aufgeführten Register-Einstellungen.&lt;br /&gt;
: Mit der Firmware 2.5 wurde am 16.3.2015 im Switch-Channel das Register powerUpAction eingeführt.&lt;br /&gt;
&lt;br /&gt;
== Firmware Update ==&lt;br /&gt;
Empfohlene und erprobte Vorgehensweise beim [[HomeMatic Firmware Update|Update der Firmware]] wie {{Link2Forum|Topic=59000|Message=503989|LinkText=hier im Forum}} beschrieben. Besonders zu beachten:&lt;br /&gt;
* IO Device verwenden, das für Updates geeignet ist (Attribute IODev und IOgrp), ggf. andere IO Devices vorübergehend auf inaktiv setzen&lt;br /&gt;
* Aktor in Steckdose stecken und einschalten&lt;br /&gt;
* fwUpdate Kommando aus FHEM heraus absetzen&lt;br /&gt;
* Update kann zwei bis drei Minuten dauern (schnelles Blinken der LED (rot) am Aktor)&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://files.elv.de/Assets/Produkte/13/1302/130248/Downloads/130248_schaltaktor_messen_um.pdf Manual]&lt;br /&gt;
* [http://files.elv.de/Assets/Produkte/13/1302/130248/Downloads/130248_schaltaktor_messfunktion_data.pdf Datenblatt]&lt;br /&gt;
* [http://www.eq-3.de/produkte/homematic/licht/homematic-funk-schaltaktor-1-fach-mit-leistungsmessung-typ-f.html Produktinfo]&lt;br /&gt;
* [http://www.meintechblog.de/2014/01/homematic-funk-steckdose-mit-leistungsmessung-deine-waschmaschine-ist-fertig/ Beispiel-Anwendung]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;br /&gt;
[[Kategorie:Schalter (Empfänger)]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Dimmer&amp;diff=22062</id>
		<title>FTUI Widget Dimmer</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Dimmer&amp;diff=22062"/>
		<updated>2017-08-04T20:45:35Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* Homematic-Dimmer */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Dimmer Widget]] ist ein Widget für [[FHEM Tablet UI]], das einen Ein-/Aus-Button mit inkludiertem Schieberegler erstellt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:FTUI_Widget_Dimmer_01.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get&#039;&#039;&#039;||Device-Reading, welches den Status-Wert enthält||STATE||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-on&#039;&#039;&#039;||Wert für EIN||on||data-get-on=&amp;quot;An&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-off&#039;&#039;&#039;||Wert für AUS||off||data-get-off=&amp;quot;Aus&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-value&#039;&#039;&#039;||[[Regulärer Ausdruck|RegEx]] oder Position in einer leerzeichen-getrennten Auflistung, die den Wert repräsentiert||-1 (alles anzeigen)||data-get-value=&amp;quot;2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set&#039;&#039;&#039;||Reading, welches geändert werden soll||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-on&#039;&#039;&#039;||Wert für EIN, der gesetzt werden soll||data-get-on||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-off&#039;&#039;&#039;||Wert für AUS, der gesetzt werden soll||data-get-off||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-value&#039;&#039;&#039;||Wert für EIN, der gesetzt werden soll||$v - nur der Wert||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-cmd&#039;&#039;&#039;||Name des Befehls zum Ändern des EIN-/AUS-Wertes, der mittels Schieberegler geändert wird||set||data-set-cmd=&amp;quot;setreading&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-cmd-value&#039;&#039;&#039;||Name des Befehls zum Ändern des Wertes, der mittels Schieberegler geändert wird||set||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-dim&#039;&#039;&#039;||Name des Readings, das für den DIM-Wert zuständig ist||||data-dim=&amp;quot;dim&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-icon&#039;&#039;&#039;||Name des Icons für den Schieberegler||fa-lightbulb-o||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-max&#039;&#039;&#039;||Maximalwert, der gesetzt werden kann||100||data-max=&amp;quot;25&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-min&#039;&#039;&#039;||Minimalwert, der gesetzt werden kann||0||data-min=&amp;quot;10&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-step&#039;&#039;&#039;||Größe der Änderungsschritte||1||data-step=&amp;quot;5&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-lock&#039;&#039;&#039;||Name des Readings, welches durch einen Boolean-Wert definiert, ob das Widget gesperrt (readonly) ist||||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
{{FTUI Klasse|FS20}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
* Um den Dim-Wert zu ändern, muss der Button gedrückt und nach unten oder oben verschoben werden.&lt;br /&gt;
* Im einfachen Modus (ohne &#039;&#039;data-dim&#039;&#039;-Parameter) schaltet das Widget zwischen OFF und dem DIM-Wert.&lt;br /&gt;
* Im erweiterten Modus (mit &#039;&#039;data-dim&#039;&#039;-Parameter) wird der DIM-Wert vom definierten Reading empfangen bzw. gesendet und der Button wird nur für EIN/AUS verwendet.&lt;br /&gt;
* &#039;&#039;$v&#039;&#039; ist ein Platzhalter für den numerischen Wert. Er wird zur Laufzeit durch den richtigen Wert ersetzt.&lt;br /&gt;
* data-lock: Das Widget wird gesperrt (readonly), wenn das definierte Reading den Wert &#039;&#039;1&#039;&#039;, &#039;&#039;on&#039;&#039; oder &#039;&#039;true&#039;&#039; hat.&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===HUEDevice===&lt;br /&gt;
Einfaches Beispiel:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&#039;HUEDevice1&#039;&lt;br /&gt;
     data-set=&amp;quot;pct&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;!off&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Dimmer_01.png]]&lt;br /&gt;
&lt;br /&gt;
Nun ein Beispiel mit einem eigenen Reading für den DIM-Wert. Es ist dasselbe HUEDevice wie oben, nur wird diesmal der pct-Wert getrennt von EIN/AUS geregelt:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;HUEDevice1&amp;quot;&lt;br /&gt;
     data-get=&amp;quot;onoff&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;1&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;0&amp;quot;&lt;br /&gt;
     data-set=&amp;quot;&amp;quot;&lt;br /&gt;
     data-set-on=&amp;quot;on&amp;quot;&lt;br /&gt;
     data-set-off=&amp;quot;off&amp;quot;&lt;br /&gt;
     data-dim=&amp;quot;pct&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Homematic-Dimmer===&lt;br /&gt;
So wird ein Homematic-Dimmer im erweiterten Modus eingebunden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot; &lt;br /&gt;
     data-device=&amp;quot;HomematicDevice1&amp;quot; &lt;br /&gt;
     data-get-on=&amp;quot;on|^[1-9][0-9]?(?:\.5)?$&amp;quot; &lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot; &lt;br /&gt;
     data-set-on=&amp;quot;on&amp;quot; &lt;br /&gt;
     data-dim=&amp;quot;pct&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===RegEx für On-Werte===&lt;br /&gt;
Dieses Beispiel verwendet einen RegEx-Ausdruck, um alle möglichen Werte für &amp;quot;EIN&amp;quot; abzudecken.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&#039;Dimmer1&#039;&lt;br /&gt;
     data-set=&amp;quot;pct&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;[0-9]{1,3}|on&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Dimmer&amp;diff=21776</id>
		<title>FTUI Widget Dimmer</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Dimmer&amp;diff=21776"/>
		<updated>2017-06-30T20:30:21Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Änderung 21775 von All-Ex (Diskussion) rückgängig gemacht.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Dimmer Widget]] ist ein Widget für [[FHEM Tablet UI]], das einen Ein-/Aus-Button mit inkludiertem Schieberegler erstellt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:FTUI_Widget_Dimmer_01.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get&#039;&#039;&#039;||Device-Reading, welches den Status-Wert enthält||STATE||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-on&#039;&#039;&#039;||Wert für EIN||on||data-get-on=&amp;quot;An&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-off&#039;&#039;&#039;||Wert für AUS||off||data-get-off=&amp;quot;Aus&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-value&#039;&#039;&#039;||[[Regulärer Ausdruck|RegEx]] oder Position in einer leerzeichen-getrennten Auflistung, die den Wert repräsentiert||-1 (alles anzeigen)||data-get-value=&amp;quot;2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set&#039;&#039;&#039;||Reading, welches geändert werden soll||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-on&#039;&#039;&#039;||Wert für EIN, der gesetzt werden soll||data-get-on||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-off&#039;&#039;&#039;||Wert für AUS, der gesetzt werden soll||data-get-off||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-value&#039;&#039;&#039;||Wert für EIN, der gesetzt werden soll||$v - nur der Wert||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-cmd&#039;&#039;&#039;||Name des Befehls zum Ändern des EIN-/AUS-Wertes, der mittels Schieberegler geändert wird||set||data-set-cmd=&amp;quot;setreading&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-cmd-value&#039;&#039;&#039;||Name des Befehls zum Ändern des Wertes, der mittels Schieberegler geändert wird||set||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-dim&#039;&#039;&#039;||Name des Readings, das für den DIM-Wert zuständig ist||||data-dim=&amp;quot;dim&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-icon&#039;&#039;&#039;||Name des Icons für den Schieberegler||fa-lightbulb-o||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-max&#039;&#039;&#039;||Maximalwert, der gesetzt werden kann||100||data-max=&amp;quot;25&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-min&#039;&#039;&#039;||Minimalwert, der gesetzt werden kann||0||data-min=&amp;quot;10&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-step&#039;&#039;&#039;||Größe der Änderungsschritte||1||data-step=&amp;quot;5&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-lock&#039;&#039;&#039;||Name des Readings, welches durch einen Boolean-Wert definiert, ob das Widget gesperrt (readonly) ist||||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
{{FTUI Klasse|FS20}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
* Um den Dim-Wert zu ändern, muss der Button gedrückt und nach unten oder oben verschoben werden.&lt;br /&gt;
* Im einfachen Modus (ohne &#039;&#039;data-dim&#039;&#039;-Parameter) schaltet das Widget zwischen OFF und dem DIM-Wert.&lt;br /&gt;
* Im erweiterten Modus (mit &#039;&#039;data-dim&#039;&#039;-Parameter) wird der DIM-Wert vom definierten Reading empfangen bzw. gesendet und der Button wird nur für EIN/AUS verwendet.&lt;br /&gt;
* &#039;&#039;$v&#039;&#039; ist ein Platzhalter für den numerischen Wert. Er wird zur Laufzeit durch den richtigen Wert ersetzt.&lt;br /&gt;
* data-lock: Das Widget wird gesperrt (readonly), wenn das definierte Reading den Wert &#039;&#039;1&#039;&#039;, &#039;&#039;on&#039;&#039; oder &#039;&#039;true&#039;&#039; hat.&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===HUEDevice===&lt;br /&gt;
Einfaches Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&#039;HUEDevice1&#039;&lt;br /&gt;
     data-set=&amp;quot;pct&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;!off&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Dimmer_01.png]]&lt;br /&gt;
&lt;br /&gt;
Nun ein Beispiel mit einem eigenen Reading für den DIM-Wert. Es ist dasselbe HUEDevice wie oben, nur wird diesmal der pct-Wert getrennt von EIN/AUS geregelt:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;HUEDevice1&amp;quot;&lt;br /&gt;
     data-get=&amp;quot;onoff&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;1&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;0&amp;quot;&lt;br /&gt;
     data-set=&amp;quot;&amp;quot;&lt;br /&gt;
     data-set-on=&amp;quot;on&amp;quot;&lt;br /&gt;
     data-set-off=&amp;quot;off&amp;quot;&lt;br /&gt;
     data-dim=&amp;quot;pct&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Homematic-Dimmer===&lt;br /&gt;
So wird ein Homematic-Dimmer im erweiterten Modus eingebunden:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot; &lt;br /&gt;
     data-device=&amp;quot;HomematicDevice1&amp;quot; &lt;br /&gt;
     data-get-on=&amp;quot;on|^[1-9][0-9]?$&amp;quot; &lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot; &lt;br /&gt;
     data-set-on=&amp;quot;on&amp;quot; &lt;br /&gt;
     data-dim=&amp;quot;pct&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===RegEx für On-Werte===&lt;br /&gt;
Dieses Beispiel verwendet einen RegEx-Ausdruck, um alle möglichen Werte für &amp;quot;EIN&amp;quot; abzudecken.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&#039;Dimmer1&#039;&lt;br /&gt;
     data-set=&amp;quot;pct&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;[0-9]{1,3}|on&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Dimmer&amp;diff=21775</id>
		<title>FTUI Widget Dimmer</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Dimmer&amp;diff=21775"/>
		<updated>2017-06-30T19:58:34Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* Homematic-Dimmer */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Dimmer Widget]] ist ein Widget für [[FHEM Tablet UI]], das einen Ein-/Aus-Button mit inkludiertem Schieberegler erstellt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:FTUI_Widget_Dimmer_01.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get&#039;&#039;&#039;||Device-Reading, welches den Status-Wert enthält||STATE||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-on&#039;&#039;&#039;||Wert für EIN||on||data-get-on=&amp;quot;An&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-off&#039;&#039;&#039;||Wert für AUS||off||data-get-off=&amp;quot;Aus&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-value&#039;&#039;&#039;||[[Regulärer Ausdruck|RegEx]] oder Position in einer leerzeichen-getrennten Auflistung, die den Wert repräsentiert||-1 (alles anzeigen)||data-get-value=&amp;quot;2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set&#039;&#039;&#039;||Reading, welches geändert werden soll||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-on&#039;&#039;&#039;||Wert für EIN, der gesetzt werden soll||data-get-on||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-off&#039;&#039;&#039;||Wert für AUS, der gesetzt werden soll||data-get-off||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-value&#039;&#039;&#039;||Wert für EIN, der gesetzt werden soll||$v - nur der Wert||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-cmd&#039;&#039;&#039;||Name des Befehls zum Ändern des EIN-/AUS-Wertes, der mittels Schieberegler geändert wird||set||data-set-cmd=&amp;quot;setreading&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-cmd-value&#039;&#039;&#039;||Name des Befehls zum Ändern des Wertes, der mittels Schieberegler geändert wird||set||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-dim&#039;&#039;&#039;||Name des Readings, das für den DIM-Wert zuständig ist||||data-dim=&amp;quot;dim&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-icon&#039;&#039;&#039;||Name des Icons für den Schieberegler||fa-lightbulb-o||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-max&#039;&#039;&#039;||Maximalwert, der gesetzt werden kann||100||data-max=&amp;quot;25&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-min&#039;&#039;&#039;||Minimalwert, der gesetzt werden kann||0||data-min=&amp;quot;10&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-step&#039;&#039;&#039;||Größe der Änderungsschritte||1||data-step=&amp;quot;5&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-lock&#039;&#039;&#039;||Name des Readings, welches durch einen Boolean-Wert definiert, ob das Widget gesperrt (readonly) ist||||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
{{FTUI Klasse|FS20}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
* Um den Dim-Wert zu ändern, muss der Button gedrückt und nach unten oder oben verschoben werden.&lt;br /&gt;
* Im einfachen Modus (ohne &#039;&#039;data-dim&#039;&#039;-Parameter) schaltet das Widget zwischen OFF und dem DIM-Wert.&lt;br /&gt;
* Im erweiterten Modus (mit &#039;&#039;data-dim&#039;&#039;-Parameter) wird der DIM-Wert vom definierten Reading empfangen bzw. gesendet und der Button wird nur für EIN/AUS verwendet.&lt;br /&gt;
* &#039;&#039;$v&#039;&#039; ist ein Platzhalter für den numerischen Wert. Er wird zur Laufzeit durch den richtigen Wert ersetzt.&lt;br /&gt;
* data-lock: Das Widget wird gesperrt (readonly), wenn das definierte Reading den Wert &#039;&#039;1&#039;&#039;, &#039;&#039;on&#039;&#039; oder &#039;&#039;true&#039;&#039; hat.&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===HUEDevice===&lt;br /&gt;
Einfaches Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&#039;HUEDevice1&#039;&lt;br /&gt;
     data-set=&amp;quot;pct&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;!off&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Dimmer_01.png]]&lt;br /&gt;
&lt;br /&gt;
Nun ein Beispiel mit einem eigenen Reading für den DIM-Wert. Es ist dasselbe HUEDevice wie oben, nur wird diesmal der pct-Wert getrennt von EIN/AUS geregelt:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;HUEDevice1&amp;quot;&lt;br /&gt;
     data-get=&amp;quot;onoff&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;1&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;0&amp;quot;&lt;br /&gt;
     data-set=&amp;quot;&amp;quot;&lt;br /&gt;
     data-set-on=&amp;quot;on&amp;quot;&lt;br /&gt;
     data-set-off=&amp;quot;off&amp;quot;&lt;br /&gt;
     data-dim=&amp;quot;pct&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Homematic-Dimmer===&lt;br /&gt;
So wird ein Homematic-Dimmer im erweiterten Modus eingebunden:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot; &lt;br /&gt;
     data-device=&amp;quot;HomematicDevice1&amp;quot;&lt;br /&gt;
     data-get=&amp;quot;pct&amp;quot;  &lt;br /&gt;
     data-get-on=&amp;quot;on|^[1-9][0-9]?$&amp;quot; &lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot; &lt;br /&gt;
     data-set-on=&amp;quot;on&amp;quot; &lt;br /&gt;
     data-dim=&amp;quot;pct&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===RegEx für On-Werte===&lt;br /&gt;
Dieses Beispiel verwendet einen RegEx-Ausdruck, um alle möglichen Werte für &amp;quot;EIN&amp;quot; abzudecken.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&#039;Dimmer1&#039;&lt;br /&gt;
     data-set=&amp;quot;pct&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;[0-9]{1,3}|on&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Dimmer&amp;diff=21769</id>
		<title>FTUI Widget Dimmer</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Dimmer&amp;diff=21769"/>
		<updated>2017-06-29T20:59:05Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: data-get-on verbessert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Dimmer Widget]] ist ein Widget für [[FHEM Tablet UI]], das einen Ein-/Aus-Button mit inkludiertem Schieberegler erstellt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:FTUI_Widget_Dimmer_01.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get&#039;&#039;&#039;||Device-Reading, welches den Status-Wert enthält||STATE||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-on&#039;&#039;&#039;||Wert für EIN||on||data-get-on=&amp;quot;An&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-off&#039;&#039;&#039;||Wert für AUS||off||data-get-off=&amp;quot;Aus&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-value&#039;&#039;&#039;||[[Regulärer Ausdruck|RegEx]] oder Position in einer leerzeichen-getrennten Auflistung, die den Wert repräsentiert||-1 (alles anzeigen)||data-get-value=&amp;quot;2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set&#039;&#039;&#039;||Reading, welches geändert werden soll||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-on&#039;&#039;&#039;||Wert für EIN, der gesetzt werden soll||data-get-on||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-off&#039;&#039;&#039;||Wert für AUS, der gesetzt werden soll||data-get-off||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-value&#039;&#039;&#039;||Wert für EIN, der gesetzt werden soll||$v - nur der Wert||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-cmd&#039;&#039;&#039;||Name des Befehls zum Ändern des EIN-/AUS-Wertes, der mittels Schieberegler geändert wird||set||data-set-cmd=&amp;quot;setreading&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-cmd-value&#039;&#039;&#039;||Name des Befehls zum Ändern des Wertes, der mittels Schieberegler geändert wird||set||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-dim&#039;&#039;&#039;||Name des Readings, das für den DIM-Wert zuständig ist||||data-dim=&amp;quot;dim&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-icon&#039;&#039;&#039;||Name des Icons für den Schieberegler||fa-lightbulb-o||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-max&#039;&#039;&#039;||Maximalwert, der gesetzt werden kann||100||data-max=&amp;quot;25&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-min&#039;&#039;&#039;||Minimalwert, der gesetzt werden kann||0||data-min=&amp;quot;10&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-step&#039;&#039;&#039;||Größe der Änderungsschritte||1||data-step=&amp;quot;5&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-lock&#039;&#039;&#039;||Name des Readings, welches durch einen Boolean-Wert definiert, ob das Widget gesperrt (readonly) ist||||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
{{FTUI Klasse|FS20}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
* Um den Dim-Wert zu ändern, muss der Button gedrückt und nach unten oder oben verschoben werden.&lt;br /&gt;
* Im einfachen Modus (ohne &#039;&#039;data-dim&#039;&#039;-Parameter) schaltet das Widget zwischen OFF und dem DIM-Wert.&lt;br /&gt;
* Im erweiterten Modus (mit &#039;&#039;data-dim&#039;&#039;-Parameter) wird der DIM-Wert vom definierten Reading empfangen bzw. gesendet und der Button wird nur für EIN/AUS verwendet.&lt;br /&gt;
* &#039;&#039;$v&#039;&#039; ist ein Platzhalter für den numerischen Wert. Er wird zur Laufzeit durch den richtigen Wert ersetzt.&lt;br /&gt;
* data-lock: Das Widget wird gesperrt (readonly), wenn das definierte Reading den Wert &#039;&#039;1&#039;&#039;, &#039;&#039;on&#039;&#039; oder &#039;&#039;true&#039;&#039; hat.&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===HUEDevice===&lt;br /&gt;
Einfaches Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&#039;HUEDevice1&#039;&lt;br /&gt;
     data-set=&amp;quot;pct&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;!off&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Dimmer_01.png]]&lt;br /&gt;
&lt;br /&gt;
Nun ein Beispiel mit einem eigenen Reading für den DIM-Wert. Es ist dasselbe HUEDevice wie oben, nur wird diesmal der pct-Wert getrennt von EIN/AUS geregelt:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;HUEDevice1&amp;quot;&lt;br /&gt;
     data-get=&amp;quot;onoff&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;1&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;0&amp;quot;&lt;br /&gt;
     data-set=&amp;quot;&amp;quot;&lt;br /&gt;
     data-set-on=&amp;quot;on&amp;quot;&lt;br /&gt;
     data-set-off=&amp;quot;off&amp;quot;&lt;br /&gt;
     data-dim=&amp;quot;pct&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Homematic-Dimmer===&lt;br /&gt;
So wird ein Homematic-Dimmer im erweiterten Modus eingebunden:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot; &lt;br /&gt;
     data-device=&amp;quot;HomematicDevice1&amp;quot; &lt;br /&gt;
     data-get-on=&amp;quot;on|^[1-9][0-9]?$&amp;quot; &lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot; &lt;br /&gt;
     data-set-on=&amp;quot;on&amp;quot; &lt;br /&gt;
     data-dim=&amp;quot;pct&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===RegEx für On-Werte===&lt;br /&gt;
Dieses Beispiel verwendet einen RegEx-Ausdruck, um alle möglichen Werte für &amp;quot;EIN&amp;quot; abzudecken.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&#039;Dimmer1&#039;&lt;br /&gt;
     data-set=&amp;quot;pct&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;[0-9]{1,3}|on&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEM_Tablet_UI_FAQ&amp;diff=21115</id>
		<title>FHEM Tablet UI FAQ</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEM_Tablet_UI_FAQ&amp;diff=21115"/>
		<updated>2017-04-01T22:18:14Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* Nachbearbeitung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Auf dieser Seite sind einige häufige Fragen zu [[FHEM Tablet UI]] beantwortet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Das UI zeigt Statusänderungen erst nach 30s==&lt;br /&gt;
&lt;br /&gt;
Sehr wahrscheinlich hast du die Aktualisierungsmethode &#039;&#039;&#039;longPoll&#039;&#039;&#039; deaktiviert. Es gibt zwei Aktualisierungsmethoden: shortPoll und longPoll. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;shortPoll&#039;&#039;&#039; aktualisiert den Status aller Widgets auf einmal. Bei aktivem longPoll ist das shortPoll-Interval mit 15 Minuten festgelegt, ansonsten mit 30 Sekunden. shortPoll kann nicht deaktiviert werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;longPoll&#039;&#039;&#039; benutzt den eventgesteuerten Benachrichtigungsdienst von fhem um Statusänderungen direkt zu aktualisieren. Das heisst, fhem sendet eine Nachricht per longPoll sobald sich ein Status ändert und das UI aktualisiert daraufhin automatisch nur die betroffenen Widgets. longPoll ist in fhem standardmäßig aktiv, kann aber deaktiviert werden. Im Zweifel bitte prüfen ob an der verwendeten [[FHEMWEB]]-Instanz das Attribut &amp;quot;longpoll 1&amp;quot; gesetzt ist (`list WEB`). Falls nicht, bitte `attr WEB longpoll 1` in fhem ausführen (&amp;quot;WEB&amp;quot; ist ggf. durch den Namen der verwendeten [[FHEMWEB]]-Instanz zu ersetzen). Im UI ist longPoll ebenfalls standardmäßig aktiv, kann aber ebenfalls deaktiviert werden. Bitte prüfen, ob der HTML-Code den Meta-Tag `&amp;lt;meta name=&amp;quot;longpoll&amp;quot; content=&amp;quot;1&amp;quot;&amp;gt;` enthält. Falls nicht, bitte so übernehmen.&lt;br /&gt;
&lt;br /&gt;
==Das UI zeigt Statusänderungen erst nach Neuladen der Seite im Browser==&lt;br /&gt;
&lt;br /&gt;
Das kann durch einen zwischengeschalteten Proxy bzw. Reverse-Proxy passieren. Wenn nginx als Reverse-Proxy benutzt wird, kann das Problem mit der folgenden Konfiguration in nginx behoben werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
location /fhem {&lt;br /&gt;
	proxy_pass http://meinfhemserver:8083/fhem;&lt;br /&gt;
	proxy_http_version 1.1;&lt;br /&gt;
	proxy_set_header Upgrade $http_upgrade;&lt;br /&gt;
	proxy_buffering off;&lt;br /&gt;
	proxy_ignore_client_abort off;&lt;br /&gt;
	break;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Das UI zeigt Statusänderungen gar nicht an==&lt;br /&gt;
&lt;br /&gt;
Prüfe zunächst, ob die Statusänderungen nicht vielleicht nur verspätet kommen (siehe FAQ [[#Das UI zeigt Statusänderungen erst nach 30s|Das UI zeigt Statusänderungen erst nach 30s]]). Wenn tatsächlich keine Statusänderungen im UI ankommen, sind die Werte der data-get-on/off Attribute vermutlich falsch gesetzt. Prüfe im [[Event_monitor]] welche Werte die Events, die bei Statusänderungen erzeugt werden, genau haben und passe deine Attribute entsprechend an. Manchmal weichen die erzeugten Events von den Namen der zugehörigen Readings ab. Sollten allerdings gar keine Events erzeugt werden (manche Module erzeugen nicht für jede Readingsänderung ein Event), dann kann die longPoll-Aktualisierung für diese Statusänderung nicht funktionieren.&lt;br /&gt;
&lt;br /&gt;
==Wie öffne ich die Javascript-Konsole?==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;FHEM Tablet UI&amp;quot; benutzt Javascript und um Fehlermeldungen nachvollziehen zu können ist es oft erforderlich Informationen aus der &amp;quot;Javascript Konsole&amp;quot; des Browsers zu posten. Je nach Browser wird die Konsole mit einer anderen Tastenkombination geöffnet:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Browser&lt;br /&gt;
! Tastenkombination&lt;br /&gt;
|-&lt;br /&gt;
|Chrome: &lt;br /&gt;
|{{Taste|Ctrl}} + {{Taste|Shift}} + {{Taste|J}}&lt;br /&gt;
|-&lt;br /&gt;
|Edge: &lt;br /&gt;
|{{Taste|F12}}&lt;br /&gt;
|-&lt;br /&gt;
|Firefox: &lt;br /&gt;
|{{Taste|Ctrl}} + {{Taste|Shift}} + {{Taste|K}}&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer: &lt;br /&gt;
|{{Taste|F12}}&lt;br /&gt;
|-&lt;br /&gt;
|Opera:  &lt;br /&gt;
|{{Taste|Ctrl}} + {{Taste|Shift}} + {{Taste|I}} &lt;br /&gt;
|-&lt;br /&gt;
|Safari: &lt;br /&gt;
|{{Taste|Cmd}} + {{Taste|Opt}} + {{Taste|C}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Wie kann ich eigene Icons verwenden?==&lt;br /&gt;
&lt;br /&gt;
Die Button-ähnlichen Widgets (switch, push, symbol etc.) verwenden Fonts um Icons anzuzeigen. Standardmässig wird der Font [http://fortawesome.github.io/Font-Awesome/ Font-Awesome] mitgeliefert, der mehr als [http://fortawesome.github.io/Font-Awesome/icons/ 500 Icons] mitbringt. Wenn diese Auswahl nicht ausreichend ist, kann ein eigener Iconfont eingebunden werden. Am einfachsten kann ein solcher Font mit Hilfe der [https://icomoon.io/app IcoMoon App] erstellt werden.&lt;br /&gt;
&lt;br /&gt;
===IcoMoon App===&lt;br /&gt;
IcoMoon bietet verschiedene Icon-Libraries aus denen gewählt werden kann. Viele davon sind unter kostenlosen Lizenzen verfügbar, die App weist transparent darauf hin, wenn man eine (bzw. aus einer) nicht kostenfreien Library auswählt. Standardmässig wird die Library &amp;quot;IcoMoon Free&amp;quot; angeboten, weitere können über den Button &amp;quot;Add Icons From Library&amp;quot; ausgewählt werden. Zielführender ist das &amp;quot;search&amp;quot; Feld oben zu verwenden. Die Icons aller Libraries sind verschlagwortet und über das Suchfeld findbar. Darüber hinaus können eigene Grafiken hochgeladen werden (&amp;quot;Import Icons&amp;quot;), diese müssen im SVG-Format vorliegen.&lt;br /&gt;
&lt;br /&gt;
Nach abgeschlossener Icon-Auswahl wird über den großen Button &amp;quot;Generate Font&amp;quot; (unten) ein Font erstellt. Dazu sollte zunächst oben unter &amp;quot;Preferences&amp;quot; ein Font Name (z.B. &amp;quot;Font 1&amp;quot;) und ein eindeutiger Class-Prefix (zB &amp;quot;font1-&amp;quot;) gewählt werden. Insbesondere der Class-Prefix ist wichtig und sollte nicht zu lang ausfallen. Er wird bei der Benutzung der Icons dem Icon-Namen vorangestellt. Das Class-Prefix des mitgelieferten Font-Awesome lautet &amp;quot;fa-&amp;quot;. Danach kann der Font über den Button &amp;quot;Download&amp;quot; herunter geladen werden.&lt;br /&gt;
&lt;br /&gt;
===Nachbearbeitung===&lt;br /&gt;
In der Datei style.css im heruntergeladenen Zip-File müssen einige Punkte verändert werden:&lt;br /&gt;
&lt;br /&gt;
Am Anfang wo die Font-Dateinamen stehen, müssen die Fragezeichen hinter der Dateiendung und die dahinter angehängten Buchstaben entfernt werden.&lt;br /&gt;
&lt;br /&gt;
Die Zeile &lt;br /&gt;
&amp;lt;code&amp;gt;line-height: 1;&amp;lt;/code&amp;gt;&lt;br /&gt;
auskommentieren oder löschen, da die Anzeige in den Buttons ansonsten &amp;quot;verschoben&amp;quot; wirkt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;.icon {&amp;lt;/code&amp;gt;&lt;br /&gt;
ersetzen durch&lt;br /&gt;
&amp;lt;code&amp;gt;[class^=&amp;quot;xxx-&amp;quot;], [class*=&amp;quot; xxx-&amp;quot;] {&amp;lt;/code&amp;gt;&lt;br /&gt;
(xxx ist der gewählte Class-Prefix)&lt;br /&gt;
&lt;br /&gt;
===In FTUI einbinden===&lt;br /&gt;
Der gesamte Inhalt des Ziparchivs kann jetzt in ein eigenes Verzeichnis innerhalb der FHEM Tablet UI Installation kopiert werden, zB nach &amp;quot;customfonts/font1&amp;quot;. Es sollte nicht in eines der Standardverzeichnisse kopiert werden, da dort die Gefahr besteht, dass die Dateien vom Updatemechanismus überschrieben werden. In der/den HTML-File(s) ist jetzt im &amp;lt;head&amp;gt;-Bereich noch der Pfad zur style.css aus dem Archiv anzugeben:&lt;br /&gt;
:&amp;lt;source lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;customfonts/font1/style.css&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Verwenden ===&lt;br /&gt;
Jetzt können die eigenen Icons in den Widgets verwendet werden, indem sie im Attribut data-icon (bzw. data-icons, data-background-icon..) eingetragen werden; zB:&lt;br /&gt;
:&amp;lt;source lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;WECKER&amp;quot; data-icon=&amp;quot;font1-alarmclock&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Wichtig: Daran denken, vor dem Namen des Icons das selbst gewählte Class-Prefix (hier &amp;quot;font1-&amp;quot;) zu notieren.&lt;br /&gt;
&lt;br /&gt;
==Warum führen mich Links auf andere Seiten zurück zu FHEMWEB?==&lt;br /&gt;
Zur Auslieferung des FTUI an den Browser wird das Modul [http://fhem.de/commandref.html#HTTPSRV HTTPSRV] verwendet. Leider zeigt es ein seltsames Verhalten, wenn man ausgehend von einer Adresse ohne abschliessenden Slash oder Dateinamen auf einen Link mit relativem URL (also zB nur ein Dateiname) klickt. Der relative Pfad wird in so einem Fall ab dem letzten Slash der Adresse der Ausgangsseite ermittelt. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel: Wir starten bei &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/tablet&amp;lt;/nowiki&amp;gt;&#039;&#039; und klicken auf einen Link zur Datei &#039;&#039;wohnzimmer.html&#039;&#039;. Dieser Klick wird &#039;&#039;&#039;nicht&#039;&#039;&#039; auf &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/tablet/wohnzimmer.html&amp;lt;/nowiki&amp;gt;&#039;&#039; geleitet, sondern zu &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/wohnzimmer.html&amp;lt;/nowiki&amp;gt;&#039;&#039;. Da es &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/wohnzimmer.html&amp;lt;/nowiki&amp;gt;&#039;&#039; nicht gibt, wird man darauf postwendend zu &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem&amp;lt;/nowiki&amp;gt;&#039;&#039; gebracht. Startet man den gleichen Vorgang ausgehend von &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/tablet/&amp;lt;/nowiki&amp;gt;&#039;&#039; (mit Slash am Ende), wird man wie erwartet nach &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/tablet/wohnzimmer.html&amp;lt;/nowiki&amp;gt;&#039;&#039; gebracht.&lt;br /&gt;
&lt;br /&gt;
Darüber hinaus kann die Startseite  - typischerweise index.html - nicht gefunden werden, wenn ein abschliessender Slash, aber kein Dateiname notiert wird.&lt;br /&gt;
&lt;br /&gt;
Es sollte also insbesondere in der Definition des Links für FHEMWEB darauf geachtet werden, den vollen Pfad zur Startseite zu notieren (&amp;lt;code&amp;gt;define tablet_ui HTTPSRV tablet/index.html ./www/tablet Tablet Frontend&amp;lt;/code&amp;gt;). Das gleiche beim Anlegen von Lesezeichen.&lt;br /&gt;
&lt;br /&gt;
== Wie kann ich ein eigenes Hintergrundbild einbinden, anstatt des einfachen schwarz? ==&lt;br /&gt;
* Bild besorgen : &amp;quot;Einfach mal Tante Google&#039;s Fotoalbum befragen.  ;)&amp;quot;&lt;br /&gt;
* In /opt/fhem/www/tablet den Ordner /images angelegen und Bild dort ablegen und in die **-custom.css eintragen.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt; body {&lt;br /&gt;
	background:#000000 url(../images/orange_blue_bg.jpg) 0 0 no-repeat&lt;br /&gt;
 }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:So wird der Hintergrund aus der originalen CSS überschrieben. &lt;br /&gt;
* Wenn nicht schon geschehen, die CSS in den HTMLs verlinken/deklarieren:&lt;br /&gt;
:&amp;lt;source lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/css/fhem-tablet-ui-custom.css&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Kleiner Tipp: Das Bild in genau der Auflösung suchen/herunterladen, in der die Seite später im FTUI dargestellt werden soll.&lt;br /&gt;
&lt;br /&gt;
Das UI mit Hintergrundbild sieht besser aus, wenn der Vordergrund transparent erscheint. &lt;br /&gt;
Dazu muss noch folgendes in die fhem-tablet-ui-custom.css eingefügt werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
.semitransparent {&lt;br /&gt;
    background: rgba(0, 0, 0, 0.7) !important;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Klasse benutzt dann man bei den Gridster Elementen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot; data-sizey=&amp;quot;5&amp;quot; data-template=&amp;quot;menu.html&amp;quot; class=&amp;quot;semitransparent&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wie baue ich ein Menü mit dem Pagetab Widget auf?==&lt;br /&gt;
&lt;br /&gt;
Grundsätzliche Struktur:&lt;br /&gt;
&lt;br /&gt;
index.html -&amp;gt; Header-Files (css/js), Nur ein Gridster-Element zum Import des Templates &amp;quot;menu.html&amp;quot;&lt;br /&gt;
&lt;br /&gt;
menu.html -&amp;gt;  eine Liste von Pagetab Widgets mit Links zu den Unterseiten&lt;br /&gt;
&lt;br /&gt;
sub*.html -&amp;gt; Unterseiten mit den eigentlichen Widgets, keine Header-Files (css/js), ein Gridster-Element für menu.html &lt;br /&gt;
&lt;br /&gt;
- Die index.html (Startseite) ist minimal und beinhaltet nur das Menu mit den 1-n Pagetabs und alle Links zu CSS und Scripts&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;widget_base_width&amp;quot; content=&amp;quot;74&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;widget_base_height&amp;quot; content=&amp;quot;71&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;mobile-web-app-capable&amp;quot; content=&amp;quot;yes&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;apple-mobile-web-app-capable&amp;quot; content=&amp;quot;yes&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;meta http-equiv=&amp;quot;X-UA-Compatible&amp;quot; content=&amp;quot;IE=edge&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;longpoll&amp;quot; content=&amp;quot;1&amp;quot;&amp;gt; &amp;lt;!-- 1=longpoll;0=shortpoll every 30sec --&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;debug&amp;quot; content=&amp;quot;1&amp;quot;&amp;gt; &amp;lt;!-- 1=output to console;0=not output --&amp;gt;&lt;br /&gt;
    &amp;lt;meta http-equiv=&amp;quot;Cache-Control&amp;quot; content=&amp;quot;no-store&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/lib/jquery.gridster.min.css&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/css/fhem-tablet-ui.css&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/lib/font-awesome.min.css&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/lib/jquery.toast.min.css&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- define your personal style here, it wont be overwritten  --&amp;gt;&lt;br /&gt;
    &amp;lt;!-- link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/css/fhem-green-ui.css&amp;quot; / --&amp;gt;&lt;br /&gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/css/fhem-tablet-ui-user.css&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/pgm2/jquery.min.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/tablet/lib/jquery.toast.min.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/tablet/lib/jquery.gridster.min.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/tablet/js/fhem-tablet-ui.min.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Remove this line to enable for usage with WebViewControl&lt;br /&gt;
    &amp;lt;script defer&amp;gt;var wvcDevices = {&#039;12345&#039;: &#039;Tablet&#039;}; var wvcUserCssFile=&amp;quot;webviewcontrol.css&amp;quot;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/pgm2/cordova-2.3.0.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/pgm2/webviewcontrol.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;!-- End for WebViewControl --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;title&amp;gt;FHEM-Tablet-UI&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;gridster&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;ul&amp;gt;&lt;br /&gt;
            &amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot; data-sizey=&amp;quot;9&amp;quot; data-template=&amp;quot;menu.html&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
        &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
- die per Template eingebundene menu.html enthält die Pagetabs mit den Links zu den Unterseiten&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;header&amp;gt;MENU&amp;lt;/header&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;cell&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;sub1.html&amp;quot;  data-icon=&amp;quot;fa-home&amp;quot; class=&amp;quot;top-space&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;sub2.html&amp;quot;  data-icon=&amp;quot;fa-music&amp;quot; class=&amp;quot;top-space&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;sub3.html&amp;quot;  data-icon=&amp;quot;fa-sliders&amp;quot; class=&amp;quot;top-space&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;sub4.html&amp;quot;  data-icon=&amp;quot;fa-lightbulb-o&amp;quot; class=&amp;quot;top-space&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;sub5.html&amp;quot;  data-icon=&amp;quot;fa-line-chart&amp;quot; class=&amp;quot;top-space&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;bottom bottom-space-2x&amp;quot;&amp;gt;&lt;br /&gt;
           &amp;lt;div data-type=&amp;quot;clock&amp;quot; data-format=&amp;quot;H:i&amp;quot; class=&amp;quot;large&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
           &amp;lt;div data-type=&amp;quot;clock&amp;quot; data-format=&amp;quot;d.n.Y&amp;quot; class=&amp;quot;small&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
- Ganz oben im Menu ist die sub1.html, die zuerst angezeigt wird und die eigentlichen Haupt-Widgets hat&lt;br /&gt;
&lt;br /&gt;
- Jede Unterseite sub*.html hat auch wieder die gleiche Menü-Leiste dabei, die wieder per Template eingebunden wird. Die Unterseiten haben keine Scripts oder CSS Links, da nur der Gridster Teil in die index.html importiert wird&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;FHEM Sub1&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;gridster&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot; data-sizey=&amp;quot;7&amp;quot; data-template=&amp;quot;menu.html&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;2&amp;quot; data-sizex=&amp;quot;3&amp;quot; data-sizey=&amp;quot;4&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;header&amp;gt;EXAMPLE1&amp;lt;/header&amp;gt;&lt;br /&gt;
  &amp;lt;!-- place your widget here --&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;4&amp;quot; data-sizex=&amp;quot;6&amp;quot; data-sizey=&amp;quot;4&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;header&amp;gt;EXAMPLE2&amp;lt;/header&amp;gt;&lt;br /&gt;
   &amp;lt;!-- place your widget here --&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;10&amp;quot; data-sizex=&amp;quot;2&amp;quot; data-sizey=&amp;quot;4&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;header&amp;gt;EXAMPLE3&amp;lt;/header&amp;gt;&lt;br /&gt;
    &amp;lt;!-- place your widget here --&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;5&amp;quot; data-col=&amp;quot;2&amp;quot; data-sizex=&amp;quot;6&amp;quot; data-sizey=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;header&amp;gt;EXAMPLE4&amp;lt;/header&amp;gt;&lt;br /&gt;
  &amp;lt;!-- place your widget here --&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;5&amp;quot; data-col=&amp;quot;8&amp;quot; data-sizex=&amp;quot;5&amp;quot; data-sizey=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;header&amp;gt;EXAMPLE5&amp;lt;/header&amp;gt;&lt;br /&gt;
  &amp;lt;!-- place your widget here --&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wie bekommt man Elemente nebeneinander und übereinander?==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nebeneinder&#039;&#039;&#039; klappt mit der CSS Klasse &#039;&#039;inline&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;übereinander&#039;&#039;&#039; ist das Standardverhalten von div Elementen. Man steckt einfach alle Elemente, die untereinander angeordnet werden sollen, in einen gemeinsamen übergeordneten div Container.&lt;br /&gt;
&lt;br /&gt;
Beispiel: Zwei Blöcken nebeneinander mit jeweils einem Switch und Label übereinander&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;top-space inline&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;switch&amp;quot; data-device=&amp;quot;GalerieLicht&amp;quot; class=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;Galerie&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;top-space inline&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;switch&amp;quot; data-device=&amp;quot;GartenLicht&amp;quot; class=&amp;quot;&amp;quot; &amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;Garten&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Warum erscheint bei mir die index.html aus dem Example völlig verschoben?==&lt;br /&gt;
&lt;br /&gt;
Dann passt die widget_base_width und widget_base_height bei dir nicht und muss angepasst werden.&lt;br /&gt;
Dazu in der index.html im Header folgendes ändern:&lt;br /&gt;
&lt;br /&gt;
vorher&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;meta name=&amp;quot;widget_base_width&amp;quot; content=&amp;quot;77&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;meta name=&amp;quot;widget_base_height&amp;quot; content=&amp;quot;71&amp;quot;&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
nachher&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;meta name=&amp;quot;widget_base_width&amp;quot; content=&amp;quot;154&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;meta name=&amp;quot;widget_base_height&amp;quot; content=&amp;quot;142&amp;quot;&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wie kann ich das Zoomen auf mobilen Geräten verhindern?==&lt;br /&gt;
Um zu Verhindern, dass auf mobilen Geräten eine automatische oder manuelle Größenanpassung möglich ist, kann dieser META-Tag im &amp;lt;nowiki&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/nowiki&amp;gt;-Abschnitt der Seite verwendet werden:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wie kann ich auf iOS-Geräten FTUI im Vollbildmodus starten?==&lt;br /&gt;
Um FTUI auf iOS-Geräten vom Home-Screen im Vollbildmodus starten zu können, sind folgende Einträge im &amp;lt;nowiki&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/nowiki&amp;gt;-Bereich der Seite zu setzen.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;meta name=&amp;quot;apple-mobile-web-app-capable&amp;quot; content=&amp;quot;yes&amp;quot; /&amp;gt;&lt;br /&gt;
 &amp;lt;meta name=&amp;quot;apple-mobile-web-app-status-bar-style&amp;quot; content=&amp;quot;black&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie: FAQ]]&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEM_Tablet_UI_FAQ&amp;diff=21114</id>
		<title>FHEM Tablet UI FAQ</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEM_Tablet_UI_FAQ&amp;diff=21114"/>
		<updated>2017-04-01T22:17:50Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* Nachbearbeitung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Auf dieser Seite sind einige häufige Fragen zu [[FHEM Tablet UI]] beantwortet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Das UI zeigt Statusänderungen erst nach 30s==&lt;br /&gt;
&lt;br /&gt;
Sehr wahrscheinlich hast du die Aktualisierungsmethode &#039;&#039;&#039;longPoll&#039;&#039;&#039; deaktiviert. Es gibt zwei Aktualisierungsmethoden: shortPoll und longPoll. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;shortPoll&#039;&#039;&#039; aktualisiert den Status aller Widgets auf einmal. Bei aktivem longPoll ist das shortPoll-Interval mit 15 Minuten festgelegt, ansonsten mit 30 Sekunden. shortPoll kann nicht deaktiviert werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;longPoll&#039;&#039;&#039; benutzt den eventgesteuerten Benachrichtigungsdienst von fhem um Statusänderungen direkt zu aktualisieren. Das heisst, fhem sendet eine Nachricht per longPoll sobald sich ein Status ändert und das UI aktualisiert daraufhin automatisch nur die betroffenen Widgets. longPoll ist in fhem standardmäßig aktiv, kann aber deaktiviert werden. Im Zweifel bitte prüfen ob an der verwendeten [[FHEMWEB]]-Instanz das Attribut &amp;quot;longpoll 1&amp;quot; gesetzt ist (`list WEB`). Falls nicht, bitte `attr WEB longpoll 1` in fhem ausführen (&amp;quot;WEB&amp;quot; ist ggf. durch den Namen der verwendeten [[FHEMWEB]]-Instanz zu ersetzen). Im UI ist longPoll ebenfalls standardmäßig aktiv, kann aber ebenfalls deaktiviert werden. Bitte prüfen, ob der HTML-Code den Meta-Tag `&amp;lt;meta name=&amp;quot;longpoll&amp;quot; content=&amp;quot;1&amp;quot;&amp;gt;` enthält. Falls nicht, bitte so übernehmen.&lt;br /&gt;
&lt;br /&gt;
==Das UI zeigt Statusänderungen erst nach Neuladen der Seite im Browser==&lt;br /&gt;
&lt;br /&gt;
Das kann durch einen zwischengeschalteten Proxy bzw. Reverse-Proxy passieren. Wenn nginx als Reverse-Proxy benutzt wird, kann das Problem mit der folgenden Konfiguration in nginx behoben werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
location /fhem {&lt;br /&gt;
	proxy_pass http://meinfhemserver:8083/fhem;&lt;br /&gt;
	proxy_http_version 1.1;&lt;br /&gt;
	proxy_set_header Upgrade $http_upgrade;&lt;br /&gt;
	proxy_buffering off;&lt;br /&gt;
	proxy_ignore_client_abort off;&lt;br /&gt;
	break;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Das UI zeigt Statusänderungen gar nicht an==&lt;br /&gt;
&lt;br /&gt;
Prüfe zunächst, ob die Statusänderungen nicht vielleicht nur verspätet kommen (siehe FAQ [[#Das UI zeigt Statusänderungen erst nach 30s|Das UI zeigt Statusänderungen erst nach 30s]]). Wenn tatsächlich keine Statusänderungen im UI ankommen, sind die Werte der data-get-on/off Attribute vermutlich falsch gesetzt. Prüfe im [[Event_monitor]] welche Werte die Events, die bei Statusänderungen erzeugt werden, genau haben und passe deine Attribute entsprechend an. Manchmal weichen die erzeugten Events von den Namen der zugehörigen Readings ab. Sollten allerdings gar keine Events erzeugt werden (manche Module erzeugen nicht für jede Readingsänderung ein Event), dann kann die longPoll-Aktualisierung für diese Statusänderung nicht funktionieren.&lt;br /&gt;
&lt;br /&gt;
==Wie öffne ich die Javascript-Konsole?==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;FHEM Tablet UI&amp;quot; benutzt Javascript und um Fehlermeldungen nachvollziehen zu können ist es oft erforderlich Informationen aus der &amp;quot;Javascript Konsole&amp;quot; des Browsers zu posten. Je nach Browser wird die Konsole mit einer anderen Tastenkombination geöffnet:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Browser&lt;br /&gt;
! Tastenkombination&lt;br /&gt;
|-&lt;br /&gt;
|Chrome: &lt;br /&gt;
|{{Taste|Ctrl}} + {{Taste|Shift}} + {{Taste|J}}&lt;br /&gt;
|-&lt;br /&gt;
|Edge: &lt;br /&gt;
|{{Taste|F12}}&lt;br /&gt;
|-&lt;br /&gt;
|Firefox: &lt;br /&gt;
|{{Taste|Ctrl}} + {{Taste|Shift}} + {{Taste|K}}&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer: &lt;br /&gt;
|{{Taste|F12}}&lt;br /&gt;
|-&lt;br /&gt;
|Opera:  &lt;br /&gt;
|{{Taste|Ctrl}} + {{Taste|Shift}} + {{Taste|I}} &lt;br /&gt;
|-&lt;br /&gt;
|Safari: &lt;br /&gt;
|{{Taste|Cmd}} + {{Taste|Opt}} + {{Taste|C}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Wie kann ich eigene Icons verwenden?==&lt;br /&gt;
&lt;br /&gt;
Die Button-ähnlichen Widgets (switch, push, symbol etc.) verwenden Fonts um Icons anzuzeigen. Standardmässig wird der Font [http://fortawesome.github.io/Font-Awesome/ Font-Awesome] mitgeliefert, der mehr als [http://fortawesome.github.io/Font-Awesome/icons/ 500 Icons] mitbringt. Wenn diese Auswahl nicht ausreichend ist, kann ein eigener Iconfont eingebunden werden. Am einfachsten kann ein solcher Font mit Hilfe der [https://icomoon.io/app IcoMoon App] erstellt werden.&lt;br /&gt;
&lt;br /&gt;
===IcoMoon App===&lt;br /&gt;
IcoMoon bietet verschiedene Icon-Libraries aus denen gewählt werden kann. Viele davon sind unter kostenlosen Lizenzen verfügbar, die App weist transparent darauf hin, wenn man eine (bzw. aus einer) nicht kostenfreien Library auswählt. Standardmässig wird die Library &amp;quot;IcoMoon Free&amp;quot; angeboten, weitere können über den Button &amp;quot;Add Icons From Library&amp;quot; ausgewählt werden. Zielführender ist das &amp;quot;search&amp;quot; Feld oben zu verwenden. Die Icons aller Libraries sind verschlagwortet und über das Suchfeld findbar. Darüber hinaus können eigene Grafiken hochgeladen werden (&amp;quot;Import Icons&amp;quot;), diese müssen im SVG-Format vorliegen.&lt;br /&gt;
&lt;br /&gt;
Nach abgeschlossener Icon-Auswahl wird über den großen Button &amp;quot;Generate Font&amp;quot; (unten) ein Font erstellt. Dazu sollte zunächst oben unter &amp;quot;Preferences&amp;quot; ein Font Name (z.B. &amp;quot;Font 1&amp;quot;) und ein eindeutiger Class-Prefix (zB &amp;quot;font1-&amp;quot;) gewählt werden. Insbesondere der Class-Prefix ist wichtig und sollte nicht zu lang ausfallen. Er wird bei der Benutzung der Icons dem Icon-Namen vorangestellt. Das Class-Prefix des mitgelieferten Font-Awesome lautet &amp;quot;fa-&amp;quot;. Danach kann der Font über den Button &amp;quot;Download&amp;quot; herunter geladen werden.&lt;br /&gt;
&lt;br /&gt;
===Nachbearbeitung===&lt;br /&gt;
Im der Datei style.css im heruntergeladenen Zip-File müssen einige Punkte verändert werden:&lt;br /&gt;
&lt;br /&gt;
Am Anfang wo die Font-Dateinamen stehen müssen die Fragezeichen hinter der Dateiendung und die dahinter angehängten Buchstaben entfernt werden.&lt;br /&gt;
&lt;br /&gt;
Die Zeile &lt;br /&gt;
&amp;lt;code&amp;gt;line-height: 1;&amp;lt;/code&amp;gt;&lt;br /&gt;
auskommentieren oder löschen, da die Anzeige in den Buttons ansonsten &amp;quot;verschoben&amp;quot; wirkt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;.icon {&amp;lt;/code&amp;gt;&lt;br /&gt;
ersetzen durch&lt;br /&gt;
&amp;lt;code&amp;gt;[class^=&amp;quot;xxx-&amp;quot;], [class*=&amp;quot; xxx-&amp;quot;] {&amp;lt;/code&amp;gt;&lt;br /&gt;
(xxx ist der gewählte Class-Prefix)&lt;br /&gt;
&lt;br /&gt;
===In FTUI einbinden===&lt;br /&gt;
Der gesamte Inhalt des Ziparchivs kann jetzt in ein eigenes Verzeichnis innerhalb der FHEM Tablet UI Installation kopiert werden, zB nach &amp;quot;customfonts/font1&amp;quot;. Es sollte nicht in eines der Standardverzeichnisse kopiert werden, da dort die Gefahr besteht, dass die Dateien vom Updatemechanismus überschrieben werden. In der/den HTML-File(s) ist jetzt im &amp;lt;head&amp;gt;-Bereich noch der Pfad zur style.css aus dem Archiv anzugeben:&lt;br /&gt;
:&amp;lt;source lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;customfonts/font1/style.css&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Verwenden ===&lt;br /&gt;
Jetzt können die eigenen Icons in den Widgets verwendet werden, indem sie im Attribut data-icon (bzw. data-icons, data-background-icon..) eingetragen werden; zB:&lt;br /&gt;
:&amp;lt;source lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;WECKER&amp;quot; data-icon=&amp;quot;font1-alarmclock&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Wichtig: Daran denken, vor dem Namen des Icons das selbst gewählte Class-Prefix (hier &amp;quot;font1-&amp;quot;) zu notieren.&lt;br /&gt;
&lt;br /&gt;
==Warum führen mich Links auf andere Seiten zurück zu FHEMWEB?==&lt;br /&gt;
Zur Auslieferung des FTUI an den Browser wird das Modul [http://fhem.de/commandref.html#HTTPSRV HTTPSRV] verwendet. Leider zeigt es ein seltsames Verhalten, wenn man ausgehend von einer Adresse ohne abschliessenden Slash oder Dateinamen auf einen Link mit relativem URL (also zB nur ein Dateiname) klickt. Der relative Pfad wird in so einem Fall ab dem letzten Slash der Adresse der Ausgangsseite ermittelt. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel: Wir starten bei &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/tablet&amp;lt;/nowiki&amp;gt;&#039;&#039; und klicken auf einen Link zur Datei &#039;&#039;wohnzimmer.html&#039;&#039;. Dieser Klick wird &#039;&#039;&#039;nicht&#039;&#039;&#039; auf &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/tablet/wohnzimmer.html&amp;lt;/nowiki&amp;gt;&#039;&#039; geleitet, sondern zu &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/wohnzimmer.html&amp;lt;/nowiki&amp;gt;&#039;&#039;. Da es &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/wohnzimmer.html&amp;lt;/nowiki&amp;gt;&#039;&#039; nicht gibt, wird man darauf postwendend zu &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem&amp;lt;/nowiki&amp;gt;&#039;&#039; gebracht. Startet man den gleichen Vorgang ausgehend von &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/tablet/&amp;lt;/nowiki&amp;gt;&#039;&#039; (mit Slash am Ende), wird man wie erwartet nach &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/tablet/wohnzimmer.html&amp;lt;/nowiki&amp;gt;&#039;&#039; gebracht.&lt;br /&gt;
&lt;br /&gt;
Darüber hinaus kann die Startseite  - typischerweise index.html - nicht gefunden werden, wenn ein abschliessender Slash, aber kein Dateiname notiert wird.&lt;br /&gt;
&lt;br /&gt;
Es sollte also insbesondere in der Definition des Links für FHEMWEB darauf geachtet werden, den vollen Pfad zur Startseite zu notieren (&amp;lt;code&amp;gt;define tablet_ui HTTPSRV tablet/index.html ./www/tablet Tablet Frontend&amp;lt;/code&amp;gt;). Das gleiche beim Anlegen von Lesezeichen.&lt;br /&gt;
&lt;br /&gt;
== Wie kann ich ein eigenes Hintergrundbild einbinden, anstatt des einfachen schwarz? ==&lt;br /&gt;
* Bild besorgen : &amp;quot;Einfach mal Tante Google&#039;s Fotoalbum befragen.  ;)&amp;quot;&lt;br /&gt;
* In /opt/fhem/www/tablet den Ordner /images angelegen und Bild dort ablegen und in die **-custom.css eintragen.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt; body {&lt;br /&gt;
	background:#000000 url(../images/orange_blue_bg.jpg) 0 0 no-repeat&lt;br /&gt;
 }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:So wird der Hintergrund aus der originalen CSS überschrieben. &lt;br /&gt;
* Wenn nicht schon geschehen, die CSS in den HTMLs verlinken/deklarieren:&lt;br /&gt;
:&amp;lt;source lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/css/fhem-tablet-ui-custom.css&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Kleiner Tipp: Das Bild in genau der Auflösung suchen/herunterladen, in der die Seite später im FTUI dargestellt werden soll.&lt;br /&gt;
&lt;br /&gt;
Das UI mit Hintergrundbild sieht besser aus, wenn der Vordergrund transparent erscheint. &lt;br /&gt;
Dazu muss noch folgendes in die fhem-tablet-ui-custom.css eingefügt werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
.semitransparent {&lt;br /&gt;
    background: rgba(0, 0, 0, 0.7) !important;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Klasse benutzt dann man bei den Gridster Elementen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot; data-sizey=&amp;quot;5&amp;quot; data-template=&amp;quot;menu.html&amp;quot; class=&amp;quot;semitransparent&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wie baue ich ein Menü mit dem Pagetab Widget auf?==&lt;br /&gt;
&lt;br /&gt;
Grundsätzliche Struktur:&lt;br /&gt;
&lt;br /&gt;
index.html -&amp;gt; Header-Files (css/js), Nur ein Gridster-Element zum Import des Templates &amp;quot;menu.html&amp;quot;&lt;br /&gt;
&lt;br /&gt;
menu.html -&amp;gt;  eine Liste von Pagetab Widgets mit Links zu den Unterseiten&lt;br /&gt;
&lt;br /&gt;
sub*.html -&amp;gt; Unterseiten mit den eigentlichen Widgets, keine Header-Files (css/js), ein Gridster-Element für menu.html &lt;br /&gt;
&lt;br /&gt;
- Die index.html (Startseite) ist minimal und beinhaltet nur das Menu mit den 1-n Pagetabs und alle Links zu CSS und Scripts&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;widget_base_width&amp;quot; content=&amp;quot;74&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;widget_base_height&amp;quot; content=&amp;quot;71&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;mobile-web-app-capable&amp;quot; content=&amp;quot;yes&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;apple-mobile-web-app-capable&amp;quot; content=&amp;quot;yes&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;meta http-equiv=&amp;quot;X-UA-Compatible&amp;quot; content=&amp;quot;IE=edge&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;longpoll&amp;quot; content=&amp;quot;1&amp;quot;&amp;gt; &amp;lt;!-- 1=longpoll;0=shortpoll every 30sec --&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;debug&amp;quot; content=&amp;quot;1&amp;quot;&amp;gt; &amp;lt;!-- 1=output to console;0=not output --&amp;gt;&lt;br /&gt;
    &amp;lt;meta http-equiv=&amp;quot;Cache-Control&amp;quot; content=&amp;quot;no-store&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/lib/jquery.gridster.min.css&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/css/fhem-tablet-ui.css&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/lib/font-awesome.min.css&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/lib/jquery.toast.min.css&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- define your personal style here, it wont be overwritten  --&amp;gt;&lt;br /&gt;
    &amp;lt;!-- link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/css/fhem-green-ui.css&amp;quot; / --&amp;gt;&lt;br /&gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/css/fhem-tablet-ui-user.css&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/pgm2/jquery.min.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/tablet/lib/jquery.toast.min.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/tablet/lib/jquery.gridster.min.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/tablet/js/fhem-tablet-ui.min.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Remove this line to enable for usage with WebViewControl&lt;br /&gt;
    &amp;lt;script defer&amp;gt;var wvcDevices = {&#039;12345&#039;: &#039;Tablet&#039;}; var wvcUserCssFile=&amp;quot;webviewcontrol.css&amp;quot;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/pgm2/cordova-2.3.0.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/pgm2/webviewcontrol.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;!-- End for WebViewControl --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;title&amp;gt;FHEM-Tablet-UI&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;gridster&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;ul&amp;gt;&lt;br /&gt;
            &amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot; data-sizey=&amp;quot;9&amp;quot; data-template=&amp;quot;menu.html&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
        &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
- die per Template eingebundene menu.html enthält die Pagetabs mit den Links zu den Unterseiten&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;header&amp;gt;MENU&amp;lt;/header&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;cell&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;sub1.html&amp;quot;  data-icon=&amp;quot;fa-home&amp;quot; class=&amp;quot;top-space&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;sub2.html&amp;quot;  data-icon=&amp;quot;fa-music&amp;quot; class=&amp;quot;top-space&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;sub3.html&amp;quot;  data-icon=&amp;quot;fa-sliders&amp;quot; class=&amp;quot;top-space&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;sub4.html&amp;quot;  data-icon=&amp;quot;fa-lightbulb-o&amp;quot; class=&amp;quot;top-space&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;sub5.html&amp;quot;  data-icon=&amp;quot;fa-line-chart&amp;quot; class=&amp;quot;top-space&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;bottom bottom-space-2x&amp;quot;&amp;gt;&lt;br /&gt;
           &amp;lt;div data-type=&amp;quot;clock&amp;quot; data-format=&amp;quot;H:i&amp;quot; class=&amp;quot;large&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
           &amp;lt;div data-type=&amp;quot;clock&amp;quot; data-format=&amp;quot;d.n.Y&amp;quot; class=&amp;quot;small&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
- Ganz oben im Menu ist die sub1.html, die zuerst angezeigt wird und die eigentlichen Haupt-Widgets hat&lt;br /&gt;
&lt;br /&gt;
- Jede Unterseite sub*.html hat auch wieder die gleiche Menü-Leiste dabei, die wieder per Template eingebunden wird. Die Unterseiten haben keine Scripts oder CSS Links, da nur der Gridster Teil in die index.html importiert wird&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;FHEM Sub1&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;gridster&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot; data-sizey=&amp;quot;7&amp;quot; data-template=&amp;quot;menu.html&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;2&amp;quot; data-sizex=&amp;quot;3&amp;quot; data-sizey=&amp;quot;4&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;header&amp;gt;EXAMPLE1&amp;lt;/header&amp;gt;&lt;br /&gt;
  &amp;lt;!-- place your widget here --&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;4&amp;quot; data-sizex=&amp;quot;6&amp;quot; data-sizey=&amp;quot;4&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;header&amp;gt;EXAMPLE2&amp;lt;/header&amp;gt;&lt;br /&gt;
   &amp;lt;!-- place your widget here --&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;10&amp;quot; data-sizex=&amp;quot;2&amp;quot; data-sizey=&amp;quot;4&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;header&amp;gt;EXAMPLE3&amp;lt;/header&amp;gt;&lt;br /&gt;
    &amp;lt;!-- place your widget here --&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;5&amp;quot; data-col=&amp;quot;2&amp;quot; data-sizex=&amp;quot;6&amp;quot; data-sizey=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;header&amp;gt;EXAMPLE4&amp;lt;/header&amp;gt;&lt;br /&gt;
  &amp;lt;!-- place your widget here --&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;5&amp;quot; data-col=&amp;quot;8&amp;quot; data-sizex=&amp;quot;5&amp;quot; data-sizey=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;header&amp;gt;EXAMPLE5&amp;lt;/header&amp;gt;&lt;br /&gt;
  &amp;lt;!-- place your widget here --&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wie bekommt man Elemente nebeneinander und übereinander?==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nebeneinder&#039;&#039;&#039; klappt mit der CSS Klasse &#039;&#039;inline&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;übereinander&#039;&#039;&#039; ist das Standardverhalten von div Elementen. Man steckt einfach alle Elemente, die untereinander angeordnet werden sollen, in einen gemeinsamen übergeordneten div Container.&lt;br /&gt;
&lt;br /&gt;
Beispiel: Zwei Blöcken nebeneinander mit jeweils einem Switch und Label übereinander&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;top-space inline&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;switch&amp;quot; data-device=&amp;quot;GalerieLicht&amp;quot; class=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;Galerie&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;top-space inline&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;switch&amp;quot; data-device=&amp;quot;GartenLicht&amp;quot; class=&amp;quot;&amp;quot; &amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;Garten&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Warum erscheint bei mir die index.html aus dem Example völlig verschoben?==&lt;br /&gt;
&lt;br /&gt;
Dann passt die widget_base_width und widget_base_height bei dir nicht und muss angepasst werden.&lt;br /&gt;
Dazu in der index.html im Header folgendes ändern:&lt;br /&gt;
&lt;br /&gt;
vorher&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;meta name=&amp;quot;widget_base_width&amp;quot; content=&amp;quot;77&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;meta name=&amp;quot;widget_base_height&amp;quot; content=&amp;quot;71&amp;quot;&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
nachher&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;meta name=&amp;quot;widget_base_width&amp;quot; content=&amp;quot;154&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;meta name=&amp;quot;widget_base_height&amp;quot; content=&amp;quot;142&amp;quot;&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wie kann ich das Zoomen auf mobilen Geräten verhindern?==&lt;br /&gt;
Um zu Verhindern, dass auf mobilen Geräten eine automatische oder manuelle Größenanpassung möglich ist, kann dieser META-Tag im &amp;lt;nowiki&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/nowiki&amp;gt;-Abschnitt der Seite verwendet werden:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wie kann ich auf iOS-Geräten FTUI im Vollbildmodus starten?==&lt;br /&gt;
Um FTUI auf iOS-Geräten vom Home-Screen im Vollbildmodus starten zu können, sind folgende Einträge im &amp;lt;nowiki&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/nowiki&amp;gt;-Bereich der Seite zu setzen.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;meta name=&amp;quot;apple-mobile-web-app-capable&amp;quot; content=&amp;quot;yes&amp;quot; /&amp;gt;&lt;br /&gt;
 &amp;lt;meta name=&amp;quot;apple-mobile-web-app-status-bar-style&amp;quot; content=&amp;quot;black&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie: FAQ]]&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Label&amp;diff=20477</id>
		<title>FTUI Widget Label</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Label&amp;diff=20477"/>
		<updated>2017-03-02T19:35:11Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Beispiel ergänzt bei ago()&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Label Widget]] ist ein Widget für [[FHEM Tablet UI]], mit dem ein Reading eines FHEM-Devices in Textform angezeigt werden kann.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:FTUI_Widget_Label_01.png&lt;br /&gt;
File:FTUI_Widget_Label_02.png&lt;br /&gt;
File:FTUI_Widget_Label_03.png&lt;br /&gt;
File:FTUI_Widget_Label_04.png&lt;br /&gt;
File:FTUI_Widget_Label_05.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get&#039;&#039;&#039;||Name des Readings, dessen Wert angezeigt werden soll||||data-get=&amp;quot;measured-temp&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-part&#039;&#039;&#039;||[[Regulärer Ausdruck|RegEx]] oder Nummer des Wortes, nach welcher der angezeigte Text gefiltert werden soll||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-fix&#039;&#039;&#039;||Angegebene Anzahl an Dezimalstellen einhalten||(-1 -&amp;gt; nicht numerisch)||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-color&#039;&#039;&#039;||Fester Wert oder Reading eines Devices für die Label-Farbe||||data-color=&amp;quot;red&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-colors&#039;&#039;&#039;||Ein Array von Farben. Welche Farbe für das Label verwendet wird, wird durch das &#039;&#039;data-limits&#039;&#039;-Attribut bestimmt||||data-colors=&#039;[&amp;quot;red&amp;quot;,&amp;quot;yellow&amp;quot;,&amp;quot;green&amp;quot;]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-classes&#039;&#039;&#039;||Ein Array von CSS-Klassen. Welche Klasse verwendet wird, hängt vom zutreffenden Wert im &#039;&#039;data-limits&#039;&#039;-Attribut ab||||data-classes=&#039;[&amp;quot;bg-red&amp;quot;,&amp;quot;bg-yellow&amp;quot;,&amp;quot;bg-green&amp;quot;]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-limits&#039;&#039;&#039;||Ein Array numerischer oder RegEx Werte für den Vergleich mit dem aktuellen Wert||||data-limits=&#039;[1,15,30]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-limits-get&#039;&#039;&#039;||Name des Readings, von dem die Werte für den Vergleich mit dem data-limits-Array geholt werden||data-get||data-limit-get=&amp;quot;Dummy01:Limits&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-limits-part&#039;&#039;&#039;||Filtern nach Wert, Position eines Wertes in einer Leerzeichen-getrennte Liste oder RegEx|&#039;-1&#039; -&amp;gt; alle||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-unit&#039;&#039;&#039;||Einheit nach Zahl hinzufügen||||data-unit=&amp;quot;%B0C%0A&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-substitution&#039;&#039;&#039;||Verschiedene Funktionen, um den empfangenen Wert durch etwas anderes zu ersetzen||||siehe [[#Hinweise]]&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-pre-text&#039;&#039;&#039;||Text, der vor dem empfangenen Wert stehen soll||||data-pre-text=&amp;quot;Es ist &amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-post-text&#039;&#039;&#039;||Text, der nach dem empfangenen Wert sehen soll||||data-post-text=&amp;quot; Grad warm&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-hide&#039;&#039;&#039;||Name des Readings, nach dessen Wert das Widget angezeigt werden soll oder nicht||STATE||data-hide=&amp;quot;power-on&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-hide-on&#039;&#039;&#039;||Wert, bei dem das Widget versteckt wird||true,1,on||data-hide-on=&amp;quot;on&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-hide-off&#039;&#039;&#039;||Wert, bei dem das Widget angezeigt wird||!on||data-hide-off=&amp;quot;!on&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-hideparents&#039;&#039;&#039;||jQuery-Selector, um auch die Eltern-Elemente zu verstecken||||data-hideparents=&amp;quot;#Name&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-refresh&#039;&#039;&#039;||Anzahl Sekunden, nach denen das Widget aktualisiert werden soll||0 -&amp;gt; kein Auto-Refresh||data-refresh=&amp;quot;10&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|small}}{{FTUI Klasse|large}}{{FTUI Klasse|big}}{{FTUI Klasse|bigger}}{{FTUI Klasse|thin}}{{FTUI Klasse|red}}{{FTUI Klasse|green}}{{FTUI Klasse|blue}}{{FTUI Klasse|orange}}{{FTUI Klasse|darker}}{{FTUI Klasse|timestamp}}{{FTUI Klasse|w1x}}{{FTUI Klasse|w2x}}{{FTUI Klasse|w3x}}{{FTUI Klasse|circleborder}}{{FTUI Klasse|squareborder}}{{FTUI Klasse|bg-limit}}{{FTUI Klasse|icon square}}{{FTUI Klasse|icon round}}{{FTUI Klasse|truncate}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
* Es kann nur entweder &#039;&#039;data-color&#039;&#039; verwendet werden, oder &#039;&#039;data-colors&#039;&#039; + &#039;&#039;data-limits&#039;&#039;, nicht beides gleichzeitig&lt;br /&gt;
* Mit der Klasse &#039;&#039;bg-limit&#039;&#039; wird die Hintergrund- statt der Vordergrundfarbe abhängig von den Werten in &#039;&#039;data-limits&#039;&#039; geändert&lt;br /&gt;
* Die Klassen &#039;&#039;icon square&#039;&#039; und &#039;&#039;icon round&#039;&#039; formatieren das Label mit einer fixen Breite und Höhe im Icon-Stil&lt;br /&gt;
* Wird die Klasse &#039;&#039;timestamp&#039;&#039; zusammen mit &#039;&#039;data-substitution=&amp;quot;toDate().ago()&amp;quot;&#039;&#039; verwendet, sollte eine automatische Aktualisierung (&#039;&#039;data-refresh=&amp;quot;xx&amp;quot;&#039;&#039;) eingestellt werden für den Fall, dass die Aktualisierungsrate des Readings zu gering ist.&lt;br /&gt;
* Ein benutzerdefiniertes Layout kann durch Hinzufügen der folgenden Klassen in die fhem-tablet-ui-user.css erreicht werden:&lt;br /&gt;
** .label-precomma&lt;br /&gt;
** .label-comma&lt;br /&gt;
** .label-aftercomma&lt;br /&gt;
** .label-unit&lt;br /&gt;
** z.B.: &amp;lt;code&amp;gt;.label-aftercomma{ font-size:40%; left: 4px; top: -25px; position: relative; }&amp;lt;/code&amp;gt;&lt;br /&gt;
* Bis zur Version 2.6.2 wurde data-unit mit 50% Schriftgröße auf der Baseline des Wertes positioniert, danach wird die Unit auf superscript angehoben. Dies kann mit einem Eintrag in fhem-tablet-ui-user.css wieder überschrieben werden.&lt;br /&gt;
** &amp;lt;Code&amp;gt;.label-unit{ font-size: 50%; vertical-align: baseline; }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Funktionsweise(n) von &#039;&#039;data-substitution&#039;&#039;:&lt;br /&gt;
* Ein Array an Ersetzungen: &amp;lt;code&amp;gt;data-substitution=&#039;[&amp;quot;on&amp;quot;,&amp;quot;Lampe ist an&amp;quot;,&amp;quot;off&amp;quot;,&amp;quot;Lampe ist aus&amp;quot;]&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* [[Regulärer Ausdruck|RegEx]], die auf dem Wert angewandt werden soll. Standard RegEx-Schreibweise wird erwartet (s/regex/subst/modifier): &amp;lt;code&amp;gt;data-substitution=&amp;quot;s/no soundplayer active//g&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;data-substitution=&amp;quot;weekdayshort&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Mit JavaScript- und RegEx-Funktionen den Wert umwandeln in:&lt;br /&gt;
** Tag:Monat: &amp;lt;code&amp;gt;data-substitution=&amp;quot;toDate().ddmm()&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
** Stunden:Minuten: &amp;lt;code&amp;gt;data-substitution=&amp;quot;toDate().hhmm()&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
** Stunden:Minuten:Sekunden: &amp;lt;code&amp;gt;data-substitution=&amp;quot;toDate().hhmmss()&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
** den Namen des Wochentages: &amp;lt;code&amp;gt;data-substitution=&amp;quot;toDate().eeee()&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
** einen Zeitraum (langes Format): &amp;lt;code&amp;gt;data-substitution=&amp;quot;toDate().ago()&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
** einen Zeitraum (kurzes Format):&amp;lt;code&amp;gt;data-substitution=&amp;quot;toDate().ago(&#039;hh:mm:ss&#039;)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
** einen Zeitraum (Minuten ohne führende Nullen):&amp;lt;code&amp;gt;data-substitution=&amp;quot;toDate().ago(&#039;m&#039;)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
** 20:15 statt 20:15:00: &amp;lt;code&amp;gt;data-substitution=&amp;quot;s/(:00)$//g&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===Einfaches Auslesen des STATE eines Devices===&lt;br /&gt;
Ein ganz einfaches Beispiel, welches den &#039;&#039;STATE&#039;&#039; eines FHEM-Devices (in diesem Fall ein Heizkörperthermostat) ausliest und anzeigt.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;HM_367B39_Climate&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Label_01.png]]&lt;br /&gt;
&lt;br /&gt;
===Anzeige bestimmter Werte eines Devices===&lt;br /&gt;
In diesem Beispiel werden Temperatur und Luftfeuchtigkeit eines Heizkörperthermostates ausgelesen und untereinander angezeigt.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;Temperatur&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;HM_367B21_Climate&amp;quot; &lt;br /&gt;
     data-get=&amp;quot;measured-temp&amp;quot;&lt;br /&gt;
     data-unit=&amp;quot;&amp;amp;deg;C&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div&amp;gt;Luftfeuchte&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;HM_367B21_Climate&amp;quot; &lt;br /&gt;
     data-get=&amp;quot;humidity&amp;quot;&lt;br /&gt;
     data-unit=&amp;quot;%&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Label_02.png]]&lt;br /&gt;
&lt;br /&gt;
===Textfarbe bei bestimmten Grenzwerten ändern===&lt;br /&gt;
Mit dem Label-Widget kann die Textfarbe je nach bestimmten Grenzwerten geändert werden. In diesem Beispiel ist die Farbe blau, sobald die Temperatur gleich oder kleiner 18° ist, grün ab 20° und rot ab 23°.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; &lt;br /&gt;
     data-device=&amp;quot;dDummy&amp;quot;&lt;br /&gt;
     data-limits=&#039;[18,20,23]&#039; &lt;br /&gt;
     data-colors=&#039;[&amp;quot;blue&amp;quot;,&amp;quot;green&amp;quot;,&amp;quot;#FF0000&amp;quot;]&#039; &lt;br /&gt;
     data-unit=&amp;quot;&amp;amp;deg;C&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Label_03.png]]&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;br /&gt;
&lt;br /&gt;
===Zwei Labels in einer Textzeile===&lt;br /&gt;
Mit der Klasse &#039;&#039;inline&#039;&#039; (kein Zeilenumbruch) können mehrere Label-Widgets in der selben Textzeile platziert werden.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;dDummy&amp;quot; class=&amp;quot;inline&amp;quot;&amp;gt;&amp;lt;/div&amp;gt; bis&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;dDummy2&amp;quot; class=&amp;quot;inline&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Label_04.png]]&lt;br /&gt;
&lt;br /&gt;
===Kombination von Label- mit anderen Widgets===&lt;br /&gt;
Das Label-Widget kann sehr gut verwendet werden, um einen Beschreibungstext für andere Widgets bereitzustellen.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;switch&amp;quot; data-device=&amp;quot;EnO_0193F070&amp;quot; data-icon=&amp;quot;mi-power_settings_new&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot;&amp;gt;Nexus7&amp;lt;/div&amp;gt;&lt;br /&gt;
(&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;Nexus7&amp;quot; data-get=&amp;quot;powerLevel&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;%)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Label_05.png]]&lt;br /&gt;
&lt;br /&gt;
===Statisches Label mit Symbol===&lt;br /&gt;
Möchte man einen statischen Text darstellen, muss hierfür nicht unbedingt das Label-Widget verwendet werden. Das nachfolgende Beispiel zeigt genau dies und fügt links noch ein Symbol ein. Der Teil für das Symbol kann auch für richtige Labels verwendet werden.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;i class=&amp;quot;fa fa-cloud fa-2x inline&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;div class=&amp;quot;inline big&amp;quot;&amp;gt;WETTER&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_label_symbol.png]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Pagetab&amp;diff=20476</id>
		<title>FTUI Widget Pagetab</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Pagetab&amp;diff=20476"/>
		<updated>2017-03-02T19:32:28Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Pagetab Widget]] ist ein Widget für [[FHEM Tablet UI]], welches es erlaubt, den Inhalt einer Seite durch den einer anderen zu ersetzen. Es kann zum Beispiel für ein Menü verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:FTUI_Widget_Pagetab_03.png&lt;br /&gt;
File:FTUI_Widget_Pagetab_04.png&lt;br /&gt;
File:FTUI_Widget_Pagetab_01.png&lt;br /&gt;
File:FTUI_Widget_Pagetab_02.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-device&#039;&#039;&#039;||FHEM Device, dessen Status das Aussehen des Widgets bestimmt||||data-device=&amp;quot;dummy1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-url&#039;&#039;&#039;||URL der neuen Seite, die angezeigt werden soll||||data-url=&amp;quot;content_main.html&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-icon&#039;&#039;&#039;||Vordergrund-Icon des Widgets||fa-power-off||data-icon=&amp;quot;mi-home&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-background-icon&#039;&#039;&#039;||Hintergrund-Icon des Widgets||fa-circle||data-background-icon=&amp;quot;fa-square&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-on-background-color&#039;&#039;&#039;||Farbe des Hintergrund-Icons, wenn der gewünschte Inhalt angezeigt wird||#606060||data-on-background-color=&amp;quot;gray&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-off-background-color&#039;&#039;&#039;||Farbe des Vordergrund-Icons, wenn der gewünschte Inhalt nicht angezeigt wird||transparent||data-off-background-color=&amp;quot;#cccccc&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-on-color&#039;&#039;&#039;||Farbe des Vordergrund-Icons, wenn der gewünschte Inhalt angezeigt wird||#222222||data-on-color=&amp;quot;yellow&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-off-color&#039;&#039;&#039;||Farbe des Vordergrund-Icons, wenn der gewünschte Inhalt nicht angezeigt wird||#505050||data-off-color=&amp;quot;#000000&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-on&#039;&#039;&#039;||Ein Array an Stati eines Devices. Je nach Status wird ein anderes Icon aus &#039;&#039;data-icons&#039;&#039; angezeigt.||||data-get-on=&#039;[&amp;quot;Ein&amp;quot;,&amp;quot;Pause&amp;quot;,&amp;quot;Aus&amp;quot;]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-icons&#039;&#039;&#039;||Ein Array an Icons, die in Abhängigkeit von &#039;&#039;data-get-on&#039;&#039; angezeigt werden||||data-icons=&#039;[&amp;quot;mi-play_arrow&amp;quot;,&amp;quot;mi-pause&amp;quot;,&amp;quot;mi-stop&amp;quot;]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-return-time&#039;&#039;&#039;||Kehrt nach der angegebenen Zeit in Sekunden wieder zur &amp;quot;Startseite&amp;quot; zurück. Muss auf dem ersten Pagetab gesetzt werden||0 (endlos)||data-return-time=&amp;quot;5&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-text&#039;&#039;&#039;||Text für die Beschreibung||||data-text=&amp;quot;Home&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
{{FTUI Klasse|warn}}{{FTUI Klasse|activate}}{{FTUI Klasse|labelright}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
* Das Attribut &#039;&#039;&#039;data-return-time&#039;&#039;&#039; muss auf dem &amp;quot;Haupt-Pagetab&amp;quot; (dem ersten; index 0) platziert werden&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===Einfacher Link===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;pagetab&amp;quot;&lt;br /&gt;
     data-url=&amp;quot;index.html&amp;quot;&lt;br /&gt;
     data-icon=&amp;quot;mi-home&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Pagetab_03.png]]&lt;br /&gt;
&lt;br /&gt;
===Einfacher Link mit Beschreibungstext===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;pagetab&amp;quot;&lt;br /&gt;
     data-url=&amp;quot;index.html&amp;quot;&lt;br /&gt;
     data-icon=&amp;quot;mi-home&amp;quot;&lt;br /&gt;
     data-text=&amp;quot;home&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Pagetab_04.png]]&lt;br /&gt;
&lt;br /&gt;
===Navigationsleiste===&lt;br /&gt;
Ein guter Anwendungszweck für das Pagetab-Widget ist eine Navigationsleiste. Dazu braucht es allerdings mehrere Seiten:&lt;br /&gt;
*Eine mit der Navigations selbst. Die wird später als Template auf den Zielseiten eingebunden&lt;br /&gt;
*Eine Startseite&lt;br /&gt;
*Eine oder mehrere Zielseiten, auf die navigiert werden kann&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Menü-Seite (menu.html)&lt;br /&gt;
Eine Menü-Seite könnte z.B. wie folgt aussehen. Auf dieser Seite sind drei Pagetab-Widgets platziert.&lt;br /&gt;
*Das erste ist ein ganz einfacher Link mit einem Beschreibungstext. Die Seite unter &#039;&#039;data-url&#039;&#039; wird beim Aufruf der Startseite automatisch geladen.&lt;br /&gt;
*Das zweite Widget ändert sein Icon je nach Status-Wert des Dummies &#039;&#039;dummy1&#039;&#039;. Ist der Status 0, wird nur das Icon &#039;&#039;fa-fax&#039;&#039; angezeigt. Ist der Status größer 0, erscheint rechts über dem Icon noch ein &amp;quot;Warnhinweis&amp;quot; mit dem Status-Wert des Dummies. Außerdem ist der Beschreibungstext nach rechts gerückt.&lt;br /&gt;
*Das dritte Widget funktioniert im Prinzip wie das zweite. Außer der Status-Wert des Dummies ist &#039;&#039;on&#039;&#039;. Dann wird die im Widget verlinkte Seite automatisch geöffnet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;sheet&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;&lt;br /&gt;
		&amp;lt;div data-type=&amp;quot;pagetab&amp;quot;&lt;br /&gt;
			 data-url=&amp;quot;pagetab01.html&amp;quot;&lt;br /&gt;
			 data-icon=&amp;quot;fa-home&amp;quot;&lt;br /&gt;
			 data-text=&amp;quot;home&amp;quot;&lt;br /&gt;
			 class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
	&amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;&lt;br /&gt;
		&amp;lt;div data-type=&amp;quot;pagetab&amp;quot;&lt;br /&gt;
			 data-device=&amp;quot;dummy1&amp;quot;&lt;br /&gt;
			 data-get-on=&#039;[&amp;quot;0&amp;quot;,&amp;quot;1&amp;quot;]&#039;&lt;br /&gt;
			 data-icons=&#039;[&amp;quot;fa-fax&amp;quot;,&amp;quot;fa-fax warn&amp;quot;]&#039;&lt;br /&gt;
			 data-url=&amp;quot;pagetab02.html&amp;quot;	&lt;br /&gt;
			 data-text=&amp;quot;anrufe&amp;quot;&lt;br /&gt;
			 class=&amp;quot;cell labelright&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
	&amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;&lt;br /&gt;
		&amp;lt;div data-type=&amp;quot;pagetab&amp;quot;&lt;br /&gt;
			 data-device=&amp;quot;dummy2&amp;quot;&lt;br /&gt;
			 data-get-on=&#039;[&amp;quot;0&amp;quot;,&amp;quot;(?:[1-9][0-9]*)&amp;quot;,&amp;quot;on&amp;quot;]&#039;&lt;br /&gt;
			 data-icons=&#039;[&amp;quot;fa-fax&amp;quot;,&amp;quot;fa-fax warn&amp;quot;,&amp;quot;fa-fax warn activate&amp;quot;]&#039;&lt;br /&gt;
			 data-url=&amp;quot;pagetab03.html&amp;quot;&lt;br /&gt;
			 class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Startseite (index.html)&lt;br /&gt;
Auf der Startseite müssen keine Inhalte sein. Durch das erste Pagetab-Widget wird dessen URL automatisch geladen. Allerdings ist das Menü-Template einzubinden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;js/fhem-tablet-ui.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;title&amp;gt;FHEM-Tablet-UI&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;gridster&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;ul&amp;gt;&lt;br /&gt;
		&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot; data-sizey=&amp;quot;4&amp;quot; data-template=&amp;quot;menu.html&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;2&amp;quot; data-sizex=&amp;quot;4&amp;quot; data-sizey=&amp;quot;4&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
	&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Zielseiten (pagetab01.html, pagetab02.html, pagetab03.html)&lt;br /&gt;
Die Zielseiten können ganz normal gestaltet werden. Es ist nur darauf zu achten, dass auf jeder Zielseite auch das Menü-Template eingebunden wird. Eine Zielseite könnte so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;gridster&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;ul&amp;gt;&lt;br /&gt;
		&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot; data-sizey=&amp;quot;4&amp;quot; data-template=&amp;quot;menu.html&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;2&amp;quot; data-sizex=&amp;quot;4&amp;quot; data-sizey=&amp;quot;4&amp;quot; class=&amp;quot;left-align&amp;quot;&amp;gt;Pagetab02.html&amp;lt;/li&amp;gt;&lt;br /&gt;
	&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wird nun auf eines der Icons geklickt, blendet die aktuelle Seite aus und die Zielseite wird eingeblendet.&lt;br /&gt;
&lt;br /&gt;
[[File:FTUI_Widget_Pagetab_02.png]]&lt;br /&gt;
&lt;br /&gt;
==Weblinks==&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Link&amp;diff=20475</id>
		<title>FTUI Widget Link</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Link&amp;diff=20475"/>
		<updated>2017-03-02T19:26:46Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: class=&amp;quot;default&amp;quot; ergänzt (vgl. https://forum.fhem.de/index.php/topic,57569.msg492679.html#msg492679)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Link Widget]] ist ein Widget für [[FHEM Tablet UI]] mit dem ein Text-Link oder Button erstellt werden kann um Befehle an FHEM zu senden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:FTUI_Widget_Link_01.png&lt;br /&gt;
File:FTUI_Widget_Link_02.png&lt;br /&gt;
File:FTUI_Widget_Link_03.png&lt;br /&gt;
File:FTUI_Widget_Link_04.png&lt;br /&gt;
File:FTUI_Widget_Link_05.png&lt;br /&gt;
File:FTUI_Widget_Link_06.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-color&#039;&#039;&#039;||Farbe für Text oder Icon (RGB-Angabe oder Farbname)||orange||data-color=&amp;quot;#c0c0c0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-background-color&#039;&#039;&#039;||Hintergrundfarbe des Links oder Icons (RGB-Angabe oder Farbname)||||data-background-color=&amp;quot;blue&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-border-color&#039;&#039;&#039;||Farbe des Rahmens (RGB-Angabe oder Farbname)||||data-border-color=&amp;quot;#ff0000&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-icon-left&#039;&#039;&#039;||Name des linken Icons||||data-icon-left=&amp;quot;mi-stop&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-icon-right&#039;&#039;&#039;||Name des rechten Icons||||data-icon-right=&amp;quot;mi-play_circle_outline&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-width&#039;&#039;&#039;||Breite des Links oder Icons||auto||data-width=&amp;quot;50px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-height&#039;&#039;&#039;||Höhe des Links oder Icons||auto||data-height=&amp;quot;3em&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-url&#039;&#039;&#039;||URL zu der verlinkt wird||||data-url=&amp;quot;content-1.html&amp;quot;&amp;lt;br&amp;gt;data-url=&amp;quot;&amp;lt;nowiki&amp;gt;https://fhem.de&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get&#039;&#039;&#039;||Name des Readings von dem die URL gelesen werden soll||||data-get=&amp;quot;URL&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-url-xhr&#039;&#039;&#039;||URL, mit der der Verweis im Hintergrund aufgerufen werden kann||||data-url-xhr=&amp;quot;&amp;lt;nowiki&amp;gt;http://webaradio/control?next&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-fhem-cmd&#039;&#039;&#039;||FHEM Befehl, der ausgeführt werden soll||||data-fhem-cmd=&amp;quot;SET Lampe ON&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-load&#039;&#039;&#039;||Lädt den Inhalt einer mit &#039;&#039;data-url&#039;&#039; angegebenen Webseite in ein &#039;&#039;&amp;lt;div&amp;gt;&#039;&#039; Element und ermöglicht so z.B. eine Navigation ähnlich zum [[FTUI Widget Pagetab|Pagetab-Widget]]||||data-load=&amp;quot;#content-1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-text-align&#039;&#039;&#039;||Ausrichtung des Textes &#039;left&#039;,&#039;center&#039;,&#039;right&#039;||||data-text-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-active-pattern&#039;&#039;&#039;||[[Regulärer Ausdruck|RegEx]] mit der der ermittelt wird, ob der Link aktiv ist. Der Check wird gegen die aktuelle &amp;quot;document location&amp;quot; durchgeführt||||data-active-pattern=&amp;quot;.*page1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-active-color&#039;&#039;&#039;||Farbe des Textes oder Icons wenn das &amp;quot;active-pattern&amp;quot; zutrifft||wie data-color||data-active-color=&amp;quot;#123456&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-active-background-color&#039;&#039;&#039;||Hintergrundfarbe des Textes oder Icons wenn das &amp;quot;active-pattern&amp;quot; zutrifft||same as data-background-color||data-active-background-color=&amp;quot;yellow&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-active-border-color&#039;&#039;&#039;||Farbe des Rahmens wenn das &amp;quot;active-pattern&amp;quot; zutrifft||wie data-border-color||data-active-border-color=&amp;quot;grey&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-fade-duration&#039;&#039;&#039;||Fade-Dauer beim Umschalten zur nächsten Seite (X ms/slow/fast)||slow||data-fade-duration=&amp;quot;100ms&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|round}}{{FTUI Klasse|square}}{{FTUI Klasse|blank}}{{FTUI Klasse|nocache}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===Link ohne Icon===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;link&amp;quot;&lt;br /&gt;
     data-color=&amp;quot;blue&amp;quot;&lt;br /&gt;
     data-url=&amp;quot;#link.html&amp;quot;&amp;gt;LINK&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Link_04.png]]&lt;br /&gt;
&lt;br /&gt;
===Button-ähnlicher Link===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;link&amp;quot;&lt;br /&gt;
     class=&amp;quot;round&amp;quot;&lt;br /&gt;
     data-color=&amp;quot;grey&amp;quot;&lt;br /&gt;
     data-border-color=&amp;quot;grey&amp;quot;&lt;br /&gt;
     data-icon=&amp;quot;fa-server&amp;quot;&amp;gt;Details&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Link_01.png]]&lt;br /&gt;
&lt;br /&gt;
===Großer Button-ähnlicher Link zum Absenden eines FHEM-Befehls===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;link&amp;quot;&lt;br /&gt;
     class=&amp;quot;round&amp;quot;&lt;br /&gt;
     data-width=&amp;quot;130&amp;quot; data-height=&amp;quot;50&amp;quot;&lt;br /&gt;
     data-color=&amp;quot;white&amp;quot;&lt;br /&gt;
     data-background-color=&amp;quot;red&amp;quot;&lt;br /&gt;
     data-icon=&amp;quot;fa-lock&amp;quot;&lt;br /&gt;
     data-fhem-cmd=&amp;quot;set AllDoors locked&amp;quot;&amp;gt;Lock Doors&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Link_02.png]]&lt;br /&gt;
&lt;br /&gt;
===Button-ähnlicher Link zum Aufrufen einer URL===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;link&amp;quot;&lt;br /&gt;
     data-width=&amp;quot;150&amp;quot;&lt;br /&gt;
     data-icon-left=&amp;quot;fa-video-camera&amp;quot;&lt;br /&gt;
     data-color=&amp;quot;green&amp;quot;&lt;br /&gt;
     data-url=&amp;quot;#cam.html&amp;quot;&amp;gt;View cam&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Link_03.png]]&lt;br /&gt;
&lt;br /&gt;
===Rechteckiger Button===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;link&amp;quot;&lt;br /&gt;
     data-width=&amp;quot;130&amp;quot; data-height=&amp;quot;50&amp;quot;&lt;br /&gt;
     data-color=&amp;quot;white&amp;quot;&lt;br /&gt;
     data-background-color=&amp;quot;green&amp;quot;&lt;br /&gt;
     data-icon=&amp;quot;fa-refresh&amp;quot;&lt;br /&gt;
     data-fhem-cmd=&amp;quot;update all https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;quot;&amp;gt;Update FTUI&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Link_05.png]]&lt;br /&gt;
&lt;br /&gt;
===Button mit mehrzeiligem Text===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;link&amp;quot; class=&amp;quot;round medium&amp;quot;&lt;br /&gt;
     data-width=&amp;quot;230&amp;quot;&lt;br /&gt;
     data-color=&amp;quot;white&amp;quot;&lt;br /&gt;
     data-background-color=&amp;quot;#717453&amp;quot;&lt;br /&gt;
     data-icon-left=&amp;quot;fa-coffee&amp;quot;&lt;br /&gt;
     data-icon-right=&amp;quot;fa-angle-right&amp;quot;&lt;br /&gt;
     data-text-align=&amp;quot;left&amp;quot;&lt;br /&gt;
     data-url=&amp;quot;#break.html&amp;quot;&amp;gt;This Text is medium&amp;lt;br/&amp;gt;and contains line&amp;lt;br/&amp;gt;breaks&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Link_06.png]]&lt;br /&gt;
&lt;br /&gt;
===Navigationsmenü mit Link-Buttons===&lt;br /&gt;
Dafür werden mehrere HTML-Seiten benötigt. Zum einen eine &amp;quot;Haupt&amp;quot;-Seite, auf der die Links dargestellt werden. Zum anderen die jeweiligen Unterseiten, die auf der Haupt-Seite angezeigt werden sollen. Die Unterseite, die beim ersten Aufruf der Hauptseite geladen werden soll, kann mit &#039;&#039;class=&amp;quot;default&amp;quot;&#039;&#039; markiert werden (im Beispiel ist das &#039;&#039;schlafzimmer.html&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Die Hauptseite könnte wie folgt aussehen:&lt;br /&gt;
{| class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%&amp;quot;&lt;br /&gt;
!style=&amp;quot;text-align: left;&amp;quot;|index.html&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;mw-collapsible-content&amp;quot; |&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
   [...]&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;panel&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;page&amp;quot; id=&amp;quot;schlafzimmer&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;page&amp;quot; id=&amp;quot;badezimmer&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;div id=&amp;quot;menu&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;default&amp;quot;&lt;br /&gt;
         data-type=&amp;quot;link&amp;quot;&lt;br /&gt;
         data-load=&amp;quot;#schlafzimmer&amp;quot;&lt;br /&gt;
         data-url=&amp;quot;#schlafzimmer.html&amp;quot;&lt;br /&gt;
         data-active-color=&amp;quot;#419aff&amp;quot;&lt;br /&gt;
         data-active-pattern=&amp;quot;.*#schlafzimmer.html&amp;quot;&amp;gt;Schlafzimmer&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;link&amp;quot;&lt;br /&gt;
         data-load=&amp;quot;#badezimmer&amp;quot;&lt;br /&gt;
         data-url=&amp;quot;#badezimmer.html&amp;quot;&lt;br /&gt;
         data-active-color=&amp;quot;#419aff&amp;quot;&lt;br /&gt;
         data-active-pattern=&amp;quot;.*#badezimmer.html&amp;quot;&amp;gt;Badezimmer&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
In den jeweiligen Unterseiten finden sich dann die Inhalte und Widgets, die für den jeweiligen Raum angezeigt werden sollen.&lt;br /&gt;
Hier ein Beispiel für eine Unterseite. Wichtig ist die richtige Benennung der ersten &#039;&#039;&amp;lt;nowiki&amp;gt;&amp;lt;div&amp;gt;&amp;lt;/nowiki&amp;gt;&#039;&#039;-Elements (&#039;&#039;id=&amp;quot;...&amp;quot;&#039;&#039;) analog zum Attribut &#039;&#039;data-load&#039;&#039; der Hauptseite ohne der Raute (#):&lt;br /&gt;
{| class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%&amp;quot;&lt;br /&gt;
!style=&amp;quot;text-align: left;&amp;quot;|schlafzimmer.html&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;mw-collapsible-content&amp;quot; |&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
  &amp;lt;div class=&amp;quot;page&amp;quot; id=&amp;quot;schlafzimmer&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;panel&amp;quot;&amp;gt;&lt;br /&gt;
      [...]&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[File:FTUI_Widget_Link_07.png|thumb|none|left|200px|Beispiel für eine Navigation mit dem Link-Widget]]&lt;br /&gt;
&lt;br /&gt;
==Weblinks==&lt;br /&gt;
*[https://knowthelist.github.io/fhem/tablet/demo_link.html Weitere Beispiele]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEM_Tablet_UI&amp;diff=20438</id>
		<title>FHEM Tablet UI</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEM_Tablet_UI&amp;diff=20438"/>
		<updated>2017-03-01T18:38:17Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Oberfläche für FHEM&lt;br /&gt;
|ModType=x&lt;br /&gt;
|ModFTopic=34233&lt;br /&gt;
|ModForumArea=Frontends&lt;br /&gt;
|ModTechName=n.a.&lt;br /&gt;
|ModOwner=setstate ({{Link2FU|7023|Forum}})&lt;br /&gt;
}}&lt;br /&gt;
[[FHEM Tablet UI]] (FTUI) ist ein leichtgewichtiges aber funktionsreiches Frontend-Framework zum Steuern und Überwachen von in FHEM integrierten Geräten. Es basiert auf HTML/CSS/JavaScript und stellt somit keine zusätzlichen Anforderungen an den FHEM-Server.&lt;br /&gt;
&lt;br /&gt;
Mit Hilfe zahlreicher Widgets, die sehr leicht mit HTML Code konfiguriert werden können, ist es möglich, innerhalb kurzer Zeit ein den eigenen Wünschen entsprechendes User-Interface aufzubauen.&lt;br /&gt;
&lt;br /&gt;
Für den Betrieb ist nur eine FHEM-Installation mit [[HTTPSRV|HTTPSRV-Modul]] sowie ein gängiger Webbrowser notwendig.&lt;br /&gt;
&lt;br /&gt;
Mit wenigen Anpassungen ist es auch möglich das UI auf anderen Webservern (Apache, u.a.) zu betreiben. Somit können FHEM und FHEM Tablet UI auch auf getrennten Systemen ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
[[File:tablet_ui.png|thumb|500px|center|Beispiel für ein mit [[FHEM Tablet UI]] erstelltes User-Interface]]&lt;br /&gt;
&lt;br /&gt;
{{Todo|Design-Möglichkeiten erklären, Navigationsmethoden ausformulieren}} &lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
Die Installation von FHEM Tablet UI erzeugt keinen großen Aufwand und besteht im Großen und Ganzen aus drei Schritten:&lt;br /&gt;
*Dateien aus dem GitHub-Repository herunterladen&lt;br /&gt;
*FHEM konfigurieren ([[HTTPSRV]]-Device erstellen, [[FHEMWEB]]-Attribut longpoll einstellen)&lt;br /&gt;
*Eine Beispieldatei anlegen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Diese Anleitung geht davon aus, dass FHEM unter Debian nach der Anleitung [https://debian.fhem.de Stable build using apt] installiert wurde.&lt;br /&gt;
Ist dies nicht der Fall, muss der Pfad &#039;&#039;&#039;/opt/fhem&#039;&#039;&#039; dementsprechend angepasst werden.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Zuerst müssen alle Dateien von FHEM Tablet UI in das FHEM-Verzeichnis &#039;&#039;&#039;/opt/fhem/www&#039;&#039;&#039; kopiert werden. Das geht mit folgendem &#039;&#039;&#039;update&#039;&#039;&#039;-Befehl über die FHEM-Befehlszeile.&lt;br /&gt;
:&amp;lt;code&amp;gt;update all https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[[Datei:FTUI_Installation_01.png|thumb|none|Schritt 1: Dateien kopieren]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; Anschließend ist ein neues [[HTTPSRV]]-Device in FHEM anzulegen, welches auf den Ordner mit den gerade heruntergeladenen Dateien verweist.&lt;br /&gt;
:&amp;lt;code&amp;gt;define TABLETUI HTTPSRV ftui/ ./www/tablet/ Tablet-UI&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[[Datei:FTUI_Installation_02.png|thumb|none|Schritt 2: HTTPSRV-Device anlegen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; Damit FHEM Tablet UI mit FHEM kommunizieren kann, ist noch die &#039;&#039;&#039;longpoll&#039;&#039;&#039;-Einstellung im [[FHEMWEB]] Device festzulegen.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;attr WEB longpoll websocket&amp;lt;/code&amp;gt;&lt;br /&gt;
:bzw. bei Problemen mit &#039;&#039;websocket&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr WEB longpoll 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[[Datei:FTUI_Installation_03.png|thumb|none|Schritt 3: longpoll einstellen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; Weil FTUI noch nichts anzuzeigen hat, wird die Datei &#039;&#039;&#039;/opt/fhem/www/tablet/index-example.html&#039;&#039;&#039; nach &#039;&#039;&#039;/opt/fhem/www/tablet/index.html&#039;&#039;&#039; kopiert.&lt;br /&gt;
:&amp;lt;code&amp;gt;sudo cp -a /opt/fhem/www/tablet/index-example.html /opt/fhem/www/tablet/index.html&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[[Datei:FTUI_Installation_04.png|thumb|none|Schritt 4: index.html erstellen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Abschließend muss FHEM noch &#039;&#039;&#039;neu gestartet&#039;&#039;&#039; werden (&#039;&#039;shutdown restart&#039;&#039;) da das Attribut &#039;&#039;&#039;longpoll&#039;&#039;&#039; geändert wurde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Somit ist FHEM Tablet UI bereit zur Verwendung und kann durch Aufruf der URL &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;http://&amp;lt;fhem-server&amp;gt;:8083/fhem/ftui&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039; oder den Link im FHEM-Menü geöffnet werden&lt;br /&gt;
&lt;br /&gt;
== Update ==&lt;br /&gt;
Ein Update von FTUI kann ebenfalls über die FHEM-Kommandozeile erfolgen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Prüfen der Änderungen seit dem letzten Download/Update durch Eingabe von:&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;update check https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; Update der geänderten Dateien durch Eingabe von:&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;update all https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine weitere Option ist das Hinzufügen des FTUI-Git-Repositories zum allgemeinem Update-Vorgang von FHEM. Dabei wird dann bei einem FHEM-Update auch gleich FHEM Tablet UI aktualisiert, bzw. die Änderungen angezeigt.&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;update add https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Konfiguration ==&lt;br /&gt;
Das Tablet UI lässt sich über die META-Parameter konfigurieren. Diese Parameter sind in jeder &#039;&#039;&#039;.html&#039;&#039;&#039; Datei (z.B. index.html) im Abschnitt &#039;&#039;&#039;&amp;lt;head&amp;gt;&#039;&#039;&#039; einzutragen. Ausgenommen davon sind Dateien, die als Template, Pagebutton-Zielseiten oder ähnliches eingebunden werden.&lt;br /&gt;
&lt;br /&gt;
Die Parameter sind immer nach diesem Schema aufgebaut:&lt;br /&gt;
 &amp;lt;meta name=&amp;quot;[Parameter-Name]&amp;quot; content=&amp;quot;[Parameter-Wert]&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Verbindung zu FHEM===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Parameter-Name!!Standard-Wert!!Mögliche Werte!!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|web_device||WEB||String||FHEM-Device, welches für das Polling verwendet wird&lt;br /&gt;
|-&lt;br /&gt;
|longpoll||1||0, 1||&lt;br /&gt;
&#039;&#039;&#039;0&#039;&#039;&#039;: Longpoll deaktiviert; alle 30s ein Shortpoll (Neuladen der gesamten Statusänderungen)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1&#039;&#039;&#039;: Longpoll aktiv; geänderte Stati werden sofort aktualisiert, zusätzlich werden alle 15min die gesamten Statusänderungen geladen.&lt;br /&gt;
|-&lt;br /&gt;
|longpoll_type||websocket||websocket, ajax, 0||&lt;br /&gt;
&#039;&#039;&#039;websocket&#039;&#039;&#039;: Für die Aktualisierung der Daten wird das Websocket-Protokoll verwendet. Werden vom Browser keine Websockets unterstützt, gibt es einen automatischen Fallback auf Ajax.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ajax&#039;&#039;&#039;: Ajax wird für die Aktualisierung verwendet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0&#039;&#039;&#039;: Longpoll deaktiviert, Shortpoll wird verwendet.&lt;br /&gt;
|-&lt;br /&gt;
|longpoll_filter||.*||RegEx||Event-Filter. Kann verwendet werden, wenn z.B. Devices, die in FTUI angezeigt werden, in einem eigenen FHEM-Room sind.&lt;br /&gt;
|-&lt;br /&gt;
|longpoll_maxage||240||Integer||Kommen in diesem Zeitraum (Sekunden) keine Longpoll-Events bei FTUI an, wird die Verbindung als &amp;quot;disconnected&amp;quot; angesehen und ein neuer Verbindungsversuch wird gestartet.&lt;br /&gt;
|-&lt;br /&gt;
|shortpoll_interval||900||Integer||Zeitraum in Sekunden, nach dem ein vollständiger Refresh stattfindet&lt;br /&gt;
|-&lt;br /&gt;
|shortpoll_only_interval||30||Integer||Zeitraum in Sekunden, nach dem ein vollständiger Refresh stattfindet, sollte Longpoll deaktiviert sein&lt;br /&gt;
|-&lt;br /&gt;
|fhemweb_url||/fhem/||Integer||URL zu FHEM. Wird benötigt wenn FTUI auf einem anderen als dem FHEM Server läuft oder nicht im Standard-Pfad installiert ist.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Funktionalität===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Parameter-Name!!Standard-Wert!!Mögliche Werte!!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|debug||0||0 - 5||Log-Level&lt;br /&gt;
|-&lt;br /&gt;
|toast||5||Integer||Anzahl an gleichzeitig angezeigten Toast-Nachrichten. Um keine anzuzeigen, ist der Wert auf 0 zu setzen.&lt;br /&gt;
|-&lt;br /&gt;
|lang||de||de||Sprache der Oberfläche (für z.B. Datums-/Zeitfunktionen)&lt;br /&gt;
|-&lt;br /&gt;
|username||||String||Benutzername für eine Basic-Authentifierung *&lt;br /&gt;
|-&lt;br /&gt;
|password||||String||Passwort für eine Basic-Authentifizierung *&lt;br /&gt;
|}&lt;br /&gt;
&#039;&#039;&#039;*&#039;&#039;&#039; Derzeit wird die Basic-Authentifizierung in Kombination mit WebSockets nicht unterstützt. Die Verwendung von &#039;&#039;&#039;longpoll=1&#039;&#039;&#039; (ajax) ist daher notwendig.&lt;br /&gt;
&lt;br /&gt;
===Layout===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Parameter-Name!!Standard-Wert!!Mögliche Werte!!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|gridster_disable||0||0, 1||Verschieben der Gridster-Elemente deaktivieren.&lt;br /&gt;
|-&lt;br /&gt;
| widget_margin||||Integer||Abstand der Gridsterelemente zueinander&lt;br /&gt;
|-&lt;br /&gt;
| widget_base_width||||Integer||Fixe Breite des Basis-Rasters (data-sizex=1)&lt;br /&gt;
|-&lt;br /&gt;
| widget_base_heigth||||Integer||Fixe Höhe des Basis-Rasters (data-sizey=1).&lt;br /&gt;
|-&lt;br /&gt;
| gridster_cols||||Integer||Fixe Anzahl an Spalten (Spaltengröße wird automatisch an Bildschirmauflösung angepasst)&lt;br /&gt;
|-&lt;br /&gt;
| gridster_rows||||Integer||Fixe Anzahl der Reihen (Reihengröße wird automatisch an Bildschirmauflösung angepasst)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Navigationsmethoden==&lt;br /&gt;
{{Todo|Dieser Abschnitt dient derzeit lediglich als Sammlung von Stichpunkten und muss vollständig überarbeitet werden.}} &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unterschied zwischen Pagetab und Pagebutton:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pagetab:&#039;&#039;&#039; Ganze Seite austauschen -&amp;gt; Menü muss auf jede Seite&lt;br /&gt;
[[FTUI_Widget_Pagetab]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pagebutton:&#039;&#039;&#039; Teil der Seite austauschen -&amp;gt; Menü nur in erster Seite&lt;br /&gt;
[[FTUI_Widget_Pagebutton]]&lt;br /&gt;
&lt;br /&gt;
==Styling==&lt;br /&gt;
=== Farben ===&lt;br /&gt;
Es besteht die Möglichkeit, die Farbwerte in hexadezimaler Form, als RGB-Wert oder mit dem Farbnamen anzugeben. Zum Beispiel: &lt;br /&gt;
&lt;br /&gt;
*HEX: #ADD8E6&lt;br /&gt;
*RBG: rgb(173, 216, 230)&lt;br /&gt;
*Namen: lightblue&lt;br /&gt;
&lt;br /&gt;
Knallige Farben wie &#039;&#039;&#039;&amp;lt;span style=&amp;quot;color: #ff0000;&amp;quot;&amp;gt;#ff0000&amp;lt;/span&amp;gt;&#039;&#039;&#039; für Rot oder &#039;&#039;&#039;&amp;lt;span style=&amp;quot;color: #00ff00;&amp;quot;&amp;gt;#00ff00&amp;lt;/span&amp;gt;&#039;&#039;&#039; für Grün sollten vermieden werden.&lt;br /&gt;
Es ist besser unterhalb von #D0 (208) für die Grundfarben zu bleiben.&lt;br /&gt;
&lt;br /&gt;
Empfohlene Farben sind z.B.:&lt;br /&gt;
&lt;br /&gt;
*Orange: &amp;lt;span style=&amp;quot;color: #aa6900;&amp;quot;&amp;gt;#aa6900&amp;lt;/span&amp;gt;&lt;br /&gt;
*Rot: &amp;lt;span style=&amp;quot;color: #ad3333;&amp;quot;&amp;gt;#ad3333&amp;lt;/span&amp;gt;&lt;br /&gt;
*Grün: &amp;lt;span style=&amp;quot;color: #32a054;&amp;quot;&amp;gt;#32a054&amp;lt;/span&amp;gt;&lt;br /&gt;
*Blau: &amp;lt;span style=&amp;quot;color: #6699FF;&amp;quot;&amp;gt;#6699FF&amp;lt;/span&amp;gt;&lt;br /&gt;
*Grau: &amp;lt;span style=&amp;quot;color: #8C8C8C;&amp;quot;&amp;gt;#8C8C8C&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hilfreich bei der Suche nach den Farbwerten ist zum Beispiel der Color-Picker auf dieser Seite: http://www.colorpicker.com. Für die Suche nach Farben, die einen guten Kontrast bilden, diese Webseite: http://vanisoft.pl/~lopuszanski/public/colors/&lt;br /&gt;
&lt;br /&gt;
Im Ordner &#039;&#039;css&#039;&#039; der FTUI Installation finden sich einige vorbereitete Farbschemas. Diese können mit einem zusätzlichen Eintrag im &amp;lt;nowiki&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/nowiki&amp;gt;-Bereich der FTUI-Seite(n) aktiviert werden.&lt;br /&gt;
&lt;br /&gt;
Hier am Beispiel eines blauen Farbschemas:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
   [...]&lt;br /&gt;
   &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/css/fhem-blue-ui.css&amp;quot; /&amp;gt;&lt;br /&gt;
   [...]&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Schema-Dateien ändern alle Widgets. Einzelne Widgets können durch Hinzufügen der jeweiligen [[#CSS-Klassen|CSS-Klasse]] geändert werden.&lt;br /&gt;
&lt;br /&gt;
===CSS-Styles===&lt;br /&gt;
Das Layout und das Aussehen des UI kann durch diverse vorgegebene CSS-Klassen beeinflusst werden. Die verfügbaren Klassen sind im Abschnitt [[#CSS-Klassen|CSS-Klassen]] aufgeführt.&lt;br /&gt;
&lt;br /&gt;
Soll das Aussehen des UI durch eigene CSS-Klassen oder durch Überschreiben der vorhandenen verändert werden, kann eine eigene CSS-Datei erstellt werden, die dann bei einem eventuellen Update von FTUI nicht überschrieben wird. Diese Datei muss den Dateinamen &#039;&#039;&#039;fhem-tablet-ui-user.css&#039;&#039;&#039; haben und im Ordner &#039;&#039;&#039;/fhem/tablet/css&#039;&#039;&#039; abgelegt werden. Sie wird dann beim Aufruf von FTUI automatisch mitgeladen.&lt;br /&gt;
&lt;br /&gt;
=== CSS-Klassen ===&lt;br /&gt;
Nicht alle Widgets unterstützen alle hier angegebenen Klassen. Welche genau unterstützt werden, kann auf der jeweiligen Widget-Seite nachgelesen werden.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|sheet/row/cell-Layout&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|sheet}}{{FTUI Klasse|row}}{{FTUI Klasse|cell}}{{FTUI Klasse|cell-1-x}}{{FTUI Klasse|cell-x}}{{FTUI Klasse|left-align}}{{FTUI Klasse|right-align}}{{FTUI Klasse|bottom-align}}{{FTUI Klasse|top-align}}{{FTUI Klasse|center-align}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|row/col-Layout&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|col}}{{FTUI Klasse|col-1-x}}{{FTUI Klasse|col-x}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|hbox/vbox-Layout&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|vbox}}{{FTUI Klasse|hbox}}{{FTUI Klasse|card}}{{FTUI Klasse|phone-width}}{{FTUI Klasse|full-height}}{{FTUI Klasse|full-width}}{{FTUI Klasse|grow-0}}{{FTUI Klasse|grow-1}}{{FTUI Klasse|grow-2}}{{FTUI Klasse|grow-x}}{{FTUI Klasse|items-top}}{{FTUI Klasse|items-center}}{{FTUI Klasse|items-bottom}}{{FTUI Klasse|items-space-between}}{{FTUI Klasse|items-space-around}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Generelle Klassen für die Positionierung&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|inline}}{{FTUI Klasse|newline}}{{FTUI Klasse|top-space}}{{FTUI Klasse|top-space-2x}}{{FTUI Klasse|top-space-3x}}{{FTUI Klasse|left-space}}{{FTUI Klasse|left-space-2x}}{{FTUI Klasse|left-space-3x}}{{FTUI Klasse|right-space}}{{FTUI Klasse|right-space-2x}}{{FTUI Klasse|right-space-3x}}{{FTUI Klasse|top-narrow}}{{FTUI Klasse|top-narrow-2x}}{{FTUI Klasse|top-narrow-10}}{{FTUI Klasse|left-narrow}}{{FTUI Klasse|left-narrow-2x}}{{FTUI Klasse|left-narrow-3x}}{{FTUI Klasse|right-narrow}}{{FTUI Klasse|right-narrow-2x}}{{FTUI Klasse|right-narrow-3x}}{{FTUI Klasse|centered}}{{FTUI Klasse|wider}}{{FTUI Klasse|narrow}}{{FTUI Klasse|fullsize}}{{FTUI Klasse|compressed}}{{FTUI Klasse|height-narrow}}{{FTUI Klasse|w1x}}{{FTUI Klasse|w2x}}{{FTUI Klasse|w3x}}{{FTUI Klasse|maxw40}}{{FTUI Klasse|doublebox-v}}{{FTUI Klasse|doublebox-h}}{{FTUI Klasse|triplebox-v}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Vordergrundfarben&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|red}}{{FTUI Klasse|green}}{{FTUI Klasse|blue}}{{FTUI Klasse|lightblue}}{{FTUI Klasse|orange}}{{FTUI Klasse|gray}}{{FTUI Klasse|lightgray}}{{FTUI Klasse|white}}{{FTUI Klasse|black}}{{FTUI Klasse|mint}}{{FTUI Klasse|yellow}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Hintergrundfarben&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|bg-red}}{{FTUI Klasse|bg-green}}{{FTUI Klasse|bg-blue}}{{FTUI Klasse|bg-lightblue}}{{FTUI Klasse|bg-orange}}{{FTUI Klasse|bg-gray}}{{FTUI Klasse|bg-lightgray}}{{FTUI Klasse|bg-white}}{{FTUI Klasse|bg-black}}{{FTUI Klasse|bg-mint}}{{FTUI Klasse|bg-yellow}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Rahmen&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|verticalLine}}{{FTUI Klasse|border-black}}{{FTUI Klasse|border-white}}{{FTUI Klasse|border-orange}}{{FTUI Klasse|border-red}}{{FTUI Klasse|border-green}}{{FTUI Klasse|border-mint}}{{FTUI Klasse|border-lightblue}}{{FTUI Klasse|border-blue}}{{FTUI Klasse|border-gray}}{{FTUI Klasse|border-yellow}}{{FTUI Klasse|border-lightgray}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Größen&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|mini}}{{FTUI Klasse|tiny}}{{FTUI Klasse|small}}{{FTUI Klasse|normal}}{{FTUI Klasse|large}}{{FTUI Klasse|big}}{{FTUI Klasse|bigger}}{{FTUI Klasse|tall}}{{FTUI Klasse|great}}{{FTUI Klasse|grande}}{{FTUI Klasse|gigantic}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Schriftstil&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|thin}}{{FTUI Klasse|bold}}{{FTUI Klasse|darker}}{{FTUI Klasse|truncate}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Sonstiges&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|blank}}{{FTUI Klasse|transparent}}{{FTUI Klasse|half-transparent}}{{FTUI Klasse|blurry}}{{FTUI Klasse|shake}}{{FTUI Klasse|fail-shake}}{{FTUI Klasse|marquee}}{{FTUI Klasse|icon round}}{{FTUI Klasse|icon square}}{{FTUI Klasse|readonly}}{{FTUI Klasse|blink}}{{FTUI Klasse|rotate-90}}{{FTUI Klasse|horizontal}}{{FTUI Klasse|circleborder}}{{FTUI Klasse|autohide}}{{FTUI Klasse|notransmit}}{{FTUI Klasse|tab}}{{FTUI Klasse|FS20}}{{FTUI Klasse|value}}{{FTUI Klasse|novalue}}{{FTUI Klasse|timestamp}}{{FTUI Klasse|percent}}{{FTUI Klasse|nocache}}{{FTUI Klasse|fade}}{{FTUI Klasse|rotate}}{{FTUI Klasse|nolabels}}{{FTUI Klasse|default}}{{FTUI Klasse|prefetch}}{{FTUI Klasse|circulate}}{{FTUI Klasse|valueonly}}{{FTUI Klasse|positiononly}}{{FTUI Klasse|lineIndicator}}{{FTUI Klasse|barIndicator}}{{FTUI Klasse|roundIndicator}}{{FTUI Klasse|dim-tick}}{{FTUI Klasse|dim-front}}{{FTUI Klasse|dim-back}}{{FTUI Klasse|hue-tick}}{{FTUI Klasse|hue-front}}{{FTUI Klasse|hue-back}}{{FTUI Klasse|warn}}{{FTUI Klasse|activate}}{{FTUI Klasse|labelright}}{{FTUI Klasse|interlock}}{{FTUI Klasse|keepopen}}{{FTUI Klasse|noshade}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Icons ===&lt;br /&gt;
FTUI bringt einige Icons-&amp;quot;Schriftarten&amp;quot; mit, die für die Darstellung genützt werden können. Diese werden automatisch beim Start des UI eingebunden, sobald ein entsprechendes Icon-Präfix im Code der Seite vorkommt.&lt;br /&gt;
&lt;br /&gt;
Verfügbare Icon-Schriftarten sind:&lt;br /&gt;
* Eingebaute Icons &#039;&#039;ftui-windows&#039;&#039; und &#039;&#039;ftui-door&#039;&#039;. Präfix &#039;&#039;&#039;ftui-&#039;&#039;&#039;. Beispiel: &amp;lt;code&amp;gt;data-icon=&amp;quot;ftui-door&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
* [http://fontawesome.io/icons/ Font-Awesome]: Mehr als 500 Icons zur Auswahl. Präfix &#039;&#039;&#039;fa-&#039;&#039;&#039;. Beispiel: &amp;lt;code&amp;gt;data-icon=&amp;quot;fa-volume-up&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
* [https://material.io/icons/ Material Icons]: Mehr als 900 Icons zur Auswahl. Präfix &#039;&#039;&#039;mi-&#039;&#039;&#039;. Beispiel: &amp;lt;code&amp;gt;data-icon=&amp;quot;mi-local_gas_station&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
* FHEM und OpenAutomation Icons: Präfix &#039;&#039;&#039;fs-&#039;&#039;&#039; und &#039;&#039;&#039;oa-&#039;&#039;&#039;. Beispiel: &amp;lt;code&amp;gt;data-icon=&amp;quot;oa-secur_locked&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
* [https://erikflowers.github.io/weather-icons/ Weather-Icons]: Präfix &#039;&#039;&#039;wi-&#039;&#039;&#039;. Beispiel: &amp;lt;code&amp;gt;data-icon=&amp;quot;wi-day-rain-mix&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Widgets ==&lt;br /&gt;
===Allgemeine Attribute===&lt;br /&gt;
Jedes Widget kann über verschiedene Attribute konfiguriert werden. Folgende Attribute gelten für alle Widgets:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+allgemeine Attribute&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-type&lt;br /&gt;
|Widget-Typ&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-device&lt;br /&gt;
|FHEM-Name des Gerätes (mit dem Befehl &#039;list&#039; bekommt man im FHEM die kpl. Liste)&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |class&lt;br /&gt;
|CSS-Klassen für Aussehen und Formatierung des Widgets&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Daten Empfangen&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get&lt;br /&gt;
|Reading Name&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-on&lt;br /&gt;
|Wert für den Status on&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-off&lt;br /&gt;
|Wert für den Status off&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Daten Senden&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set&lt;br /&gt;
|Reading Name&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set-on&lt;br /&gt;
|Wert für den Status on&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set-off&lt;br /&gt;
|Wert für den Status off&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Widget-spezifische Attribute können auf der jeweiligen Widget-Seite nachgelesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Integrierte Widgets ===&lt;br /&gt;
Folgende Widgets sind direkt in FHEM Tablet UI integriert und können &amp;quot;out of the box&amp;quot; verwendet werden.&lt;br /&gt;
&lt;br /&gt;
* [[FTUI Widget Agenda|agenda]]: Zeigt Kalendereinträge in einer Listenform an&lt;br /&gt;
* [[FTUI Widget Button|button]]: Variante der push und switch Widgets, die entweder einen URL ansteuern oder einen FHEM-Befehl absetzen kann.&lt;br /&gt;
* [[FTUI Widget Calview|calview]]: Zeigt Einträge aus einem [[CALVIEW]]-Device an&lt;br /&gt;
* [[FTUI Widget Chart|chart]]: Diagramm mit ähnlichen Möglichkeiten wie die FHEM-Plots&lt;br /&gt;
* [[FTUI Widget Checkbox|checkbox]]: Umschalter zwischen zwei definierten Zuständen&lt;br /&gt;
* [[FTUI Widget Circlemenu|circlemenu]]: Mehrere Widgets hinter einem Widget verborgen, trotz des &#039;circle&#039; im Namen kann das Menue jetzt auch horizontal oder vertikal ausgeklappt werden &lt;br /&gt;
* [[FTUI Widget Classchanger|classchanger]]: Ändert seine CSS-Klassen je nach Status eines Devices&lt;br /&gt;
* [[FTUI Widget Clock|clock]]: Stellt eine einfach Uhr zur Verfügung.&lt;br /&gt;
* [[FTUI Widget Colorwheel|colorwheel]]: Farbpalette zur Auswahl von Farben&lt;br /&gt;
* [[FTUI Widget Datetimepicker|datetimepicker]]: Erstellt eine Auswahl für Datum/Uhrzeit&lt;br /&gt;
* [[FTUI Widget Departure|departure]]: Abfahrtszeiten öffentlicher Verkehrsmittel&lt;br /&gt;
* [[FTUI Widget Dimmer|dimmer]]: Ein-/Aus-Button mit integriertem Schieberegler für z.B. einen Dim-Wert&lt;br /&gt;
* [[FTUI Widget Eventmonitor|eventmonitor]]:&lt;br /&gt;
* [[FTUI Widget Filelog|filelog]]:&lt;br /&gt;
* [[FTUI Widget Fullcalview|fullcalview]]:&lt;br /&gt;
* [[FTUI Widget Gds|gds]]:&lt;br /&gt;
* [[FTUI Widget Highchart|highchart]]:&lt;br /&gt;
* [[FTUI Widget Highchart3d|highchart3d]]:&lt;br /&gt;
* [[FTUI Widget Homestatus|homestatus]]: Auswahl für vier oder fünf definierte Stati eines Objects (z.B.: FHEM Residents)&lt;br /&gt;
* [[FTUI Widget Html|html]]:&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/iframe iframe]: Widget zum Einbinden externer Inhalte in einem Iframe. &lt;br /&gt;
* [[FTUI Widget Image|image]]: Zeigt ein Bild, dessen URL fest vorgegeben oder aus einem Device-Reading gelesen werden kann.&lt;br /&gt;
* [[FTUI Widget Input|input]]: Erstellen eines Texteingabefeldes&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/itunes_artwork itunes_artwork]: itunes_artwork durchsucht die iTunes-Datenbank anhand eines Arrays von beliebigen Suchworten nach einem Cover-Artwork und zeigt dieses an. &lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/joinedlabel joinedlabel]: verbindet mehrere Readings zu einem Feld&lt;br /&gt;
* [[FTUI Widget Klimatrend|klimatrend]]: wandelt Daten aus dem statistics-Modul in einen Pfeil um, der den aktuellen Trend anzeigt. &lt;br /&gt;
* [[FTUI Widget Knob|knob]]: Erstellt einen Statusbalken auf einer Kreisbahn&lt;br /&gt;
* [[FTUI Widget Label|label]]: Reading als Text anzeigen&lt;br /&gt;
* [[FTUI Widget Level|level]]: Vertikale oder horizontale Leiste zur Anzeige von Werten zwischen einem Minimal- und einem Maximalwert&lt;br /&gt;
* [[FTUI Widget Link|link]]: Erstellt einen Link oder Button zum Aufrufen von URLs oder Senden von Befehlen an FHEM&lt;br /&gt;
* [[FTUI Widget Loading|loading]]:&lt;br /&gt;
* [[FTUI Widget Medialist|medialist]]:&lt;br /&gt;
* [[FTUI Widget Meteogram|meteogram]]:&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/mpdnowplaying mpdnowplaying]: Zeigt Titelinformationen eines per MPD-Modul angebundenen Music Player Daemon an. &lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/multistatebutton multistatebutton]: Variante des push-Widgets das den set-Befehl abhängig vom gelesenen Status ändert.&lt;br /&gt;
* [[FTUI Widget Notify|notify]]: Blendet ein Hinweisfenster im Browser ein&lt;br /&gt;
* [[FTUI Widget Pagebutton|pagebutton]]: Button, mit dem auf andere Seiten gesprungen werden kann. Eignet sich gut für eine Navigation&lt;br /&gt;
* [[FTUI Widget Pagetab|pagetab]]: Tauscht den Inhalt einer Seite durch den einer anderen. Eignet sich gut für ein Navigationsmenü.&lt;br /&gt;
* [[FTUI Widget Playstream|playstream]]: Abspielen eines Webradio-Streams per Button&lt;br /&gt;
* [[FTUI Widget Popup|popup]]: Öffnet ein Popup nach einem Klick auf ein Widget oder HTML-Element &lt;br /&gt;
* [[FTUI Widget Progress|progress]]: Zeigt einen Prozentwert in Form einer runden Fortschrittsleiste&lt;br /&gt;
* [[FTUI_Widget_Push|push]]: Button, mir dem ein Befehl an FHEM gesendet werden kann.&lt;br /&gt;
* [[FTUI Widget Range|range]]: Erstellt vertikale Balken, die einen Wertebereich in unterschiedlichen Farben darstellen&lt;br /&gt;
* [[FTUI Widget Readingsgroup|readingsgroup]]: Zeigt eine Readingsgroup an, wie sie in FHEM definiert wurde&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/reload reload]: auslösen eine Pagereloads&lt;br /&gt;
* [[FTUI Widget Rotor|rotor]]: Animiertes Umschalten von zwei oder mehr Widgets an einer Position&lt;br /&gt;
* [[FTUI_Widget_Select|select]]: Combobox, die eine Liste an Werten zur Auswahl anzeigt&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/settimer settimer]: Zum Anzeigen und Einstellen einer Uhrzeit.&lt;br /&gt;
* [[FTUI Widget Simplechart|simplechart]]: Einfaches XY-Diagramm zur Anzeige eines Wertes, der direkt aus einem FHEM-Logfile gelesen wird&lt;br /&gt;
* [[FTUI Widget Slideout|slideout]]:&lt;br /&gt;
* [[FTUI Widget Slider|slider]]: Vertikaler Schieberegler um einen Wert einzustellen&lt;br /&gt;
* [[FTUI Widget Spinner|spinner]]: Element um Werte durch Drücken auf Plus- und Minus- oder Höher-/Tiefer-Icons zu ändern&lt;br /&gt;
* [[FTUI Widget Svgplot|svgplot]]:&lt;br /&gt;
* [[FTUI Widget Swiper|swiper]]: Bietet die Möglichkeit, durch Wischen, zwischen verschiedenen Widgets zu wechseln&lt;br /&gt;
* [[FTUI Widget Switch|switch]]: Button um zwischen zwei Zuständen zu schalten (z.B. on / off)&lt;br /&gt;
* [[FTUI Widget Symbol|symbol]]: Status eines Devices als Symbol darstellen (z.B. Fenster offen)&lt;br /&gt;
* [[FTUI Widget Thermostat|thermostat]]: Anzeige für Heizungsthermostate, mit der die gewünschte Temperatur eingestellt werden kann&lt;br /&gt;
* [[FTUI Widget Tts|tts]]:&lt;br /&gt;
* [[FTUI Widget Uwz|uwz]]:&lt;br /&gt;
* [[FTUI Widget Volume|volume]]: Einstellscheibe zur Änderung eines einzelnen Wertes&lt;br /&gt;
* [[FTUI Widget Wakeup|wakeup]]:&lt;br /&gt;
* [https://github.com/svenson08/ftui-weekdaytimer-widget wdtimer]: Visualisierung des [[WeekdayTimer]] Modul&lt;br /&gt;
* [[FTUI Widget Weather|weather]]: Wettersymbol anzeigen&lt;br /&gt;
* [[FTUI Widget Weekprofile|weekprofile]]:&lt;br /&gt;
* [[FTUI Widget Wind_direction|Wind_direction]]: Anzeige der Windrichtung auf einer Windrose&lt;br /&gt;
&lt;br /&gt;
===3rd Party Widgets===&lt;br /&gt;
Für diese Widgets kann nicht sichergestellt werden, dass sie mit der jeweils aktuellen Version von FTUI funktionieren.&lt;br /&gt;
* [[FTUI Widget Clicksound|clicksound]]: Mit dem Widget &amp;quot;clicksound&amp;quot; können Sounds an Click-Events von Elementen gebunden werden.&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/javascript javascript]: Ermöglicht die Ausführung beliebigen Javascript-Codes aus einem Reading.&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/kodinowplaying kodinowplaying]: zeigt Informationen zu grade in KODI gespielten Medien in Form eines Labels an.&lt;br /&gt;
* [[FTUI Widget Screensaver|screensaver]]:&lt;br /&gt;
&lt;br /&gt;
==Templates==&lt;br /&gt;
Kommt ein bestimmtes &amp;quot;Code-Fragment&amp;quot; auf mehreren Seiten oder öfter pro Seite vor, bietet FTUI die Option, Templates zu erstellen. Diese werden einmal gebaut und können dann mit dem Attribut &#039;&#039;&#039;data-template&#039;&#039;&#039; nach Belieben in eine Seite eingefügt werden. Dabei besteht auch die Möglichkeit, Parameter zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Im Folgenden ein paar Beispiele, wie Templates verwendet werden können.&lt;br /&gt;
&lt;br /&gt;
===Einzelnes Widget===&lt;br /&gt;
Soll ein Widget an mehreren Stellen in exakt der selben Ausführung eingebunden werden, kann diese Widget in einer eigenen Datei erstellt und diese dann auf den Zielseiten automatisch mitgeladen werden.&lt;br /&gt;
&lt;br /&gt;
;Template-Seite&lt;br /&gt;
Die Template-Seite soll in diesem Beispiel &#039;&#039;template_symbol.html&#039;&#039; genannt werden. Diese wird daher zuerst im FTUI-Verzeichnis erstellt.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;symbol&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;dummy1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Haupt-Seite&lt;br /&gt;
Die oben erstellte Template-Seite kann nun in jeder gewünschten Seite eingebunden werden.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot; highlight=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;gridster&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;ul&amp;gt;&lt;br /&gt;
      &amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizey=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
         &amp;lt;div data-template=&amp;quot;template_symbol.html&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
      &amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Gridster-Element===&lt;br /&gt;
Natürlich kann auch ein ganzes Gridster-Element - in diesem Fall ein Menü - als Template eingebunden werden.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot; data-sizey=&amp;quot;4&amp;quot; data-template=&amp;quot;menu.html&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Widget-Gruppen ===&lt;br /&gt;
Die Template-Datei des [[#Einzelnes Widget|ersten Beispiels]] kann natürlich auch mehrere Widgets auf einmal enthalten.&lt;br /&gt;
&lt;br /&gt;
=== Verwendung von Parametern ===&lt;br /&gt;
==== Einfaches Beispiel ====&lt;br /&gt;
Oft wird ein und dasselbe, liebevoll gestaltete, Widget für verschiedenen Devices verwendet. Um nicht für jedes Device das Widget neu kopieren zu müssen (bzw. bei Änderungen alle Seiten ausbessern zu müssen), kann ein Template verwendet werden, dem einfach per Parameter mitgeteilt wird, von welchem Device es gerade die Daten empfangen soll.&lt;br /&gt;
&lt;br /&gt;
In diesem Beispiel wird ein Template erzeugt, dass nur die Temperatur verschiedenen Thermostate mittels eines [[FTUI Widget Label|Label-Widgets]] anzeigt.&lt;br /&gt;
&lt;br /&gt;
;Template-Seite&lt;br /&gt;
Die Template-Seite enthält nur ein einfaches Label-Widget und wird in diesem Beispiel &#039;&#039;template_label.html&#039;&#039; genannt. Um sie für mehrere Devices verwenden zu können, wird im Attribut &#039;&#039;&#039;data-device&#039;&#039;&#039; der Name des eigentlichen Devices durch den Parameter &#039;&#039;&#039;par01&#039;&#039;&#039; ersetzt.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot; highlight=&amp;quot;2&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;par01&amp;quot;&lt;br /&gt;
     data-get=&amp;quot;measured-temp&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Haupt-Seite&lt;br /&gt;
Auf der Haupt-Seite wird die Template-Seite mit dem Attribut &#039;&#039;&#039;data-template&#039;&#039;&#039; eingebunden und ihr via Attribut &#039;&#039;&#039;data-parameter&#039;&#039;&#039; das jeweils gewünschte Device übergeben.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;div data-template=&amp;quot;template_label.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;Thermostat1&amp;quot;}&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-template=&amp;quot;template_label.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;Thermostat2&amp;quot;}&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-template=&amp;quot;template_label.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;Thermostat3&amp;quot;}&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wetter-Slider mit Template ====&lt;br /&gt;
In diesem Beispiel wird ein [[FTUI Widget Slider|Slider-Widget]] erstellt, welches die verschiedenen Tage eines Wetterberichtes anzeigt. Dabei wird für den Wetterbericht des jeweiligen Tages immer dasselbe Template verwendet um nicht für jeden Tag ein eigenes Widget schreiben zu müssen.&lt;br /&gt;
&lt;br /&gt;
;Template-Seite&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par01&amp;quot; data-unit=&amp;quot;&amp;amp;deg;C&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
   &amp;lt;div class=&amp;quot;inline&amp;quot;&amp;gt;&lt;br /&gt;
       &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par02&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
       &amp;lt;div data-type=&amp;quot;weather&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par02&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
       min:&amp;amp;nbsp;&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par03&amp;quot; data-unit=&amp;quot;&amp;amp;deg;C&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
   &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par04&amp;quot; data-substitution=&amp;quot;toDate().eeee()+&#039;,&#039;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
   &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par04&amp;quot; data-substitution=&amp;quot;toDate().ddmm()&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Haupt-Seite&lt;br /&gt;
In der Haupt-Seite wird das Template dann für jede Slider-Seite eingebunden und das Reading für den jeweiligen Tag via Parameter übergeben.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;swiper&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
   &amp;lt;li data-template=&amp;quot;templates/wetter.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;fc0_tempMax&amp;quot;,&amp;quot;par02&amp;quot;:&amp;quot;fc0_weatherDay&amp;quot;,&amp;quot;par03&amp;quot;:&amp;quot;fc0_tempMin&amp;quot;,&amp;quot;par04&amp;quot;:&amp;quot;fc0_date&amp;quot;}&#039;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li data-template=&amp;quot;templates/wetter.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;fc1_tempMax&amp;quot;,&amp;quot;par02&amp;quot;:&amp;quot;fc1_weatherDay&amp;quot;,&amp;quot;par03&amp;quot;:&amp;quot;fc1_tempMin&amp;quot;,&amp;quot;par04&amp;quot;:&amp;quot;fc1_date&amp;quot;}&#039;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li data-template=&amp;quot;templates/wetter.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;fc2_tempMax&amp;quot;,&amp;quot;par02&amp;quot;:&amp;quot;fc2_weatherDay&amp;quot;,&amp;quot;par03&amp;quot;:&amp;quot;fc2_tempMin&amp;quot;,&amp;quot;par04&amp;quot;:&amp;quot;fc2_date&amp;quot;}&#039;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li data-template=&amp;quot;templates/wetter.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;fc3_tempMax&amp;quot;,&amp;quot;par02&amp;quot;:&amp;quot;fc3_weatherDay&amp;quot;,&amp;quot;par03&amp;quot;:&amp;quot;fc3_tempMin&amp;quot;,&amp;quot;par04&amp;quot;:&amp;quot;fc3_date&amp;quot;}&#039;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== JavaScript-Funktionen ==&lt;br /&gt;
Neben den Widgets können auch einige JavaScript-Funktionen verwendet werden, um Befehle an FHEM zu senden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Folgende Zeile setzt einen direkten Befehl an FHEM ab (&amp;lt;code&amp;gt;set dummy1 off&amp;lt;/code&amp;gt;):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;div onclick=&amp;quot;ftui.setFhemStatus(&#039;set dummy1 off&#039;)&amp;quot;&amp;gt;Dummy1 aus&amp;lt;/div&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese Zeile veranlasst FHEM dazu, eine Funktion aus der 99_myUtils.pm auszuführen (&amp;lt;code&amp;gt;myUtils_HeizungUpDown(&amp;quot;WZ.Thermostat_Climate&amp;quot;,&amp;quot;up&amp;quot;)&amp;lt;/code&amp;gt;):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;div onclick=&amp;quot;ftui.setFhemStatus(&#039;{myUtils_HeizungUpDown(&amp;amp;quot;WZ.Thermostat_Climate&amp;amp;quot;,&amp;amp;quot;up&amp;amp;quot;)}&#039;)&amp;quot;&amp;gt;+&amp;lt;/div&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel, wie ein Kommando an FHEM gesendet wird und gleichzeitig der Wert eines bereits in FTUI angezeigten Readings verwendet werden kann:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;dummy1&amp;quot; data-get=&amp;quot;temperature&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div onClick=&amp;quot;ftui.setFhemStatus(&#039;set dummy2 &#039;+ftui.getDeviceParameter(&#039;dummy1&#039;,&#039;temperature&#039;).val);&amp;quot;&amp;gt;Senden&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
Häufig gestellte Fragen zum FHEM Tablet UI sind in der [[FHEM Tablet UI FAQ]] zusammengestellt.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/knowthelist/fhem-tablet-ui Projekt auf Github]&lt;br /&gt;
* [http://forum.fhem.de/index.php/topic,34233.0.html Forums-Beitrag]&lt;br /&gt;
* [[FTUI_Snippets|Snippets]]&lt;br /&gt;
* [http://knowthelist.github.io/fhem/tablet/demo_widgets.html Live-Demos]&lt;br /&gt;
* [http://forum.fhem.de/index.php/topic,37378.0.html User-Demos]&lt;br /&gt;
* [https://github.com/ovibox/fhem-ftui-user-demos Download der User-Demo-Dateien]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEM_Tablet_UI_FAQ&amp;diff=20437</id>
		<title>FHEM Tablet UI FAQ</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEM_Tablet_UI_FAQ&amp;diff=20437"/>
		<updated>2017-03-01T18:36:03Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Edge Browser ergänzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Auf dieser Seite sind einige häufige Fragen zu [[FHEM Tablet UI]] beantwortet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Das UI zeigt Statusänderungen erst nach 30s==&lt;br /&gt;
&lt;br /&gt;
Sehr wahrscheinlich hast du die Aktualisierungsmethode &#039;&#039;&#039;longPoll&#039;&#039;&#039; deaktiviert. Es gibt zwei Aktualisierungsmethoden: shortPoll und longPoll. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;shortPoll&#039;&#039;&#039; aktualisiert den Status aller Widgets auf einmal. Bei aktivem longPoll ist das shortPoll-Interval mit 15 Minuten festgelegt, ansonsten mit 30 Sekunden. shortPoll kann nicht deaktiviert werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;longPoll&#039;&#039;&#039; benutzt den eventgesteuerten Benachrichtigungsdienst von fhem um Statusänderungen direkt zu aktualisieren. Das heisst, fhem sendet eine Nachricht per longPoll sobald sich ein Status ändert und das UI aktualisiert daraufhin automatisch nur die betroffenen Widgets. longPoll ist in fhem standardmäßig aktiv, kann aber deaktiviert werden. Im Zweifel bitte prüfen ob an der verwendeten [[FHEMWEB]]-Instanz das Attribut &amp;quot;longpoll 1&amp;quot; gesetzt ist (`list WEB`). Falls nicht, bitte `attr WEB longpoll 1` in fhem ausführen (&amp;quot;WEB&amp;quot; ist ggf. durch den Namen der verwendeten [[FHEMWEB]]-Instanz zu ersetzen). Im UI ist longPoll ebenfalls standardmäßig aktiv, kann aber ebenfalls deaktiviert werden. Bitte prüfen, ob der HTML-Code den Meta-Tag `&amp;lt;meta name=&amp;quot;longpoll&amp;quot; content=&amp;quot;1&amp;quot;&amp;gt;` enthält. Falls nicht, bitte so übernehmen.&lt;br /&gt;
&lt;br /&gt;
==Das UI zeigt Statusänderungen erst nach Neuladen der Seite im Browser==&lt;br /&gt;
&lt;br /&gt;
Das kann durch einen zwischengeschalteten Proxy bzw. Reverse-Proxy passieren. Wenn nginx als Reverse-Proxy benutzt wird, kann das Problem mit der folgenden Konfiguration in nginx behoben werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
location /fhem {&lt;br /&gt;
	proxy_pass http://meinfhemserver:8083/fhem;&lt;br /&gt;
	proxy_http_version 1.1;&lt;br /&gt;
	proxy_set_header Upgrade $http_upgrade;&lt;br /&gt;
	proxy_buffering off;&lt;br /&gt;
	proxy_ignore_client_abort off;&lt;br /&gt;
	break;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Das UI zeigt Statusänderungen gar nicht an==&lt;br /&gt;
&lt;br /&gt;
Prüfe zunächst, ob die Statusänderungen nicht vielleicht nur verspätet kommen (siehe FAQ [[#Das UI zeigt Statusänderungen erst nach 30s|Das UI zeigt Statusänderungen erst nach 30s]]). Wenn tatsächlich keine Statusänderungen im UI ankommen, sind die Werte der data-get-on/off Attribute vermutlich falsch gesetzt. Prüfe im [[Event_monitor]] welche Werte die Events, die bei Statusänderungen erzeugt werden, genau haben und passe deine Attribute entsprechend an. Manchmal weichen die erzeugten Events von den Namen der zugehörigen Readings ab. Sollten allerdings gar keine Events erzeugt werden (manche Module erzeugen nicht für jede Readingsänderung ein Event), dann kann die longPoll-Aktualisierung für diese Statusänderung nicht funktionieren.&lt;br /&gt;
&lt;br /&gt;
==Wie öffne ich die Javascript-Konsole?==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;FHEM Tablet UI&amp;quot; benutzt Javascript und um Fehlermeldungen nachvollziehen zu können ist es oft erforderlich Informationen aus der &amp;quot;Javascript Konsole&amp;quot; des Browsers zu posten. Je nach Browser wird die Konsole mit einer anderen Tastenkombination geöffnet:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Browser&lt;br /&gt;
! Tastenkombination&lt;br /&gt;
|-&lt;br /&gt;
|Chrome: &lt;br /&gt;
|{{Taste|Ctrl}} + {{Taste|Shift}} + {{Taste|J}}&lt;br /&gt;
|-&lt;br /&gt;
|Edge: &lt;br /&gt;
|{{Taste|F12}}&lt;br /&gt;
|-&lt;br /&gt;
|Firefox: &lt;br /&gt;
|{{Taste|Ctrl}} + {{Taste|Shift}} + {{Taste|K}}&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer: &lt;br /&gt;
|{{Taste|F12}}&lt;br /&gt;
|-&lt;br /&gt;
|Opera:  &lt;br /&gt;
|{{Taste|Ctrl}} + {{Taste|Shift}} + {{Taste|I}} &lt;br /&gt;
|-&lt;br /&gt;
|Safari: &lt;br /&gt;
|{{Taste|Cmd}} + {{Taste|Opt}} + {{Taste|C}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Wie kann ich eigene Icons verwenden?==&lt;br /&gt;
&lt;br /&gt;
Die Button-ähnlichen Widgets (switch, push, symbol etc.) verwenden Fonts um Icons anzuzeigen. Standardmässig wird der Font [http://fortawesome.github.io/Font-Awesome/ Font-Awesome] mitgeliefert, der mehr als [http://fortawesome.github.io/Font-Awesome/icons/ 500 Icons] mitbringt. Wenn diese Auswahl nicht ausreichend ist, kann ein eigener Iconfont eingebunden werden. Am einfachsten kann ein solcher Font mit Hilfe der [https://icomoon.io/app IcoMoon App] erstellt werden.&lt;br /&gt;
&lt;br /&gt;
===IcoMoon App===&lt;br /&gt;
IcoMoon bietet verschiedene Icon-Libraries aus denen gewählt werden kann. Viele davon sind unter kostenlosen Lizenzen verfügbar, die App weist transparent darauf hin, wenn man eine (bzw. aus einer) nicht kostenfreien Library auswählt. Standardmässig wird die Library &amp;quot;IcoMoon Free&amp;quot; angeboten, weitere können über den Button &amp;quot;Add Icons From Library&amp;quot; ausgewählt werden. Zielführender ist das &amp;quot;search&amp;quot; Feld oben zu verwenden. Die Icons aller Libraries sind verschlagwortet und über das Suchfeld findbar. Darüber hinaus können eigene Grafiken hochgeladen werden (&amp;quot;Import Icons&amp;quot;), diese müssen im SVG-Format vorliegen.&lt;br /&gt;
&lt;br /&gt;
Nach abgeschlossener Icon-Auswahl wird über den großen Button &amp;quot;Generate Font&amp;quot; (unten) ein Font erstellt. Dazu sollte zunächst oben unter &amp;quot;Preferences&amp;quot; ein Font Name (z.B. &amp;quot;Font 1&amp;quot;) und ein eindeutiger Class-Prefix (zB &amp;quot;font1-&amp;quot;) gewählt werden. Insbesondere der Class-Prefix ist wichtig und sollte nicht zu lang ausfallen. Er wird bei der Benutzung der Icons dem Icon-Namen vorangestellt. Das Class-Prefix des mitgelieferten Font-Awesome lautet &amp;quot;fa-&amp;quot;. Danach kann der Font über den Button &amp;quot;Download&amp;quot; herunter geladen werden.&lt;br /&gt;
&lt;br /&gt;
===Nachbearbeitung===&lt;br /&gt;
Im heruntergeladenen Zip-file aus der IcoMoon App muss die Zeile &lt;br /&gt;
:&amp;lt;code&amp;gt;line-height: 1;&amp;lt;/code&amp;gt;&lt;br /&gt;
auskommentiert oder gelöscht werden, da die Anzeige in den Buttons ansonsten &amp;quot;verschoben&amp;quot; wirkt.&lt;br /&gt;
&lt;br /&gt;
===In FTUI einbinden===&lt;br /&gt;
Der gesamte Inhalt des Ziparchivs kann jetzt in ein eigenes Verzeichnis innerhalb der FHEM Tablet UI Installation kopiert werden, zB nach &amp;quot;customfonts/font1&amp;quot;. Es sollte nicht in eines der Standardverzeichnisse kopiert werden, da dort die Gefahr besteht, dass die Dateien vom Updatemechanismus überschrieben werden. In der/den HTML-File(s) ist jetzt im &amp;lt;head&amp;gt;-Bereich noch der Pfad zur style.css aus dem Archiv anzugeben:&lt;br /&gt;
:&amp;lt;source lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;customfonts/font1/style.css&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Verwenden ===&lt;br /&gt;
Jetzt können die eigenen Icons in den Widgets verwendet werden, indem sie im Attribut data-icon (bzw. data-icons, data-background-icon..) eingetragen werden; zB:&lt;br /&gt;
:&amp;lt;source lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;WECKER&amp;quot; data-icon=&amp;quot;font1-alarmclock&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Wichtig: Daran denken, vor dem Namen des Icons das selbst gewählte Class-Prefix (hier &amp;quot;font1-&amp;quot;) zu notieren.&lt;br /&gt;
&lt;br /&gt;
==Warum führen mich Links auf andere Seiten zurück zu FHEMWEB?==&lt;br /&gt;
Zur Auslieferung des FTUI an den Browser wird das Modul [http://fhem.de/commandref.html#HTTPSRV HTTPSRV] verwendet. Leider zeigt es ein seltsames Verhalten, wenn man ausgehend von einer Adresse ohne abschliessenden Slash oder Dateinamen auf einen Link mit relativem URL (also zB nur ein Dateiname) klickt. Der relative Pfad wird in so einem Fall ab dem letzten Slash der Adresse der Ausgangsseite ermittelt. &lt;br /&gt;
&lt;br /&gt;
Ein Beispiel: Wir starten bei &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/tablet&amp;lt;/nowiki&amp;gt;&#039;&#039; und klicken auf einen Link zur Datei &#039;&#039;wohnzimmer.html&#039;&#039;. Dieser Klick wird &#039;&#039;&#039;nicht&#039;&#039;&#039; auf &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/tablet/wohnzimmer.html&amp;lt;/nowiki&amp;gt;&#039;&#039; geleitet, sondern zu &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/wohnzimmer.html&amp;lt;/nowiki&amp;gt;&#039;&#039;. Da es &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/wohnzimmer.html&amp;lt;/nowiki&amp;gt;&#039;&#039; nicht gibt, wird man darauf postwendend zu &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem&amp;lt;/nowiki&amp;gt;&#039;&#039; gebracht. Startet man den gleichen Vorgang ausgehend von &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/tablet/&amp;lt;/nowiki&amp;gt;&#039;&#039; (mit Slash am Ende), wird man wie erwartet nach &#039;&#039;&amp;lt;nowiki&amp;gt;http://host:8083/fhem/tablet/wohnzimmer.html&amp;lt;/nowiki&amp;gt;&#039;&#039; gebracht.&lt;br /&gt;
&lt;br /&gt;
Darüber hinaus kann die Startseite  - typischerweise index.html - nicht gefunden werden, wenn ein abschliessender Slash, aber kein Dateiname notiert wird.&lt;br /&gt;
&lt;br /&gt;
Es sollte also insbesondere in der Definition des Links für FHEMWEB darauf geachtet werden, den vollen Pfad zur Startseite zu notieren (&amp;lt;code&amp;gt;define tablet_ui HTTPSRV tablet/index.html ./www/tablet Tablet Frontend&amp;lt;/code&amp;gt;). Das gleiche beim Anlegen von Lesezeichen.&lt;br /&gt;
&lt;br /&gt;
== Wie kann ich ein eigenes Hintergrundbild einbinden, anstatt des einfachen schwarz? ==&lt;br /&gt;
* Bild besorgen : &amp;quot;Einfach mal Tante Google&#039;s Fotoalbum befragen.  ;)&amp;quot;&lt;br /&gt;
* In /opt/fhem/www/tablet den Ordner /images angelegen und Bild dort ablegen und in die **-custom.css eintragen.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt; body {&lt;br /&gt;
	background:#000000 url(../images/orange_blue_bg.jpg) 0 0 no-repeat&lt;br /&gt;
 }&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:So wird der Hintergrund aus der originalen CSS überschrieben. &lt;br /&gt;
* Wenn nicht schon geschehen, die CSS in den HTMLs verlinken/deklarieren:&lt;br /&gt;
:&amp;lt;source lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/css/fhem-tablet-ui-custom.css&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Kleiner Tipp: Das Bild in genau der Auflösung suchen/herunterladen, in der die Seite später im FTUI dargestellt werden soll.&lt;br /&gt;
&lt;br /&gt;
Das UI mit Hintergrundbild sieht besser aus, wenn der Vordergrund transparent erscheint. &lt;br /&gt;
Dazu muss noch folgendes in die fhem-tablet-ui-custom.css eingefügt werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
.semitransparent {&lt;br /&gt;
    background: rgba(0, 0, 0, 0.7) !important;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Klasse benutzt dann man bei den Gridster Elementen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot; data-sizey=&amp;quot;5&amp;quot; data-template=&amp;quot;menu.html&amp;quot; class=&amp;quot;semitransparent&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wie baue ich ein Menü mit dem Pagetab Widget auf?==&lt;br /&gt;
&lt;br /&gt;
Grundsätzliche Struktur:&lt;br /&gt;
&lt;br /&gt;
index.html -&amp;gt; Header-Files (css/js), Nur ein Gridster-Element zum Import des Templates &amp;quot;menu.html&amp;quot;&lt;br /&gt;
&lt;br /&gt;
menu.html -&amp;gt;  eine Liste von Pagetab Widgets mit Links zu den Unterseiten&lt;br /&gt;
&lt;br /&gt;
sub*.html -&amp;gt; Unterseiten mit den eigentlichen Widgets, keine Header-Files (css/js), ein Gridster-Element für menu.html &lt;br /&gt;
&lt;br /&gt;
- Die index.html (Startseite) ist minimal und beinhaltet nur das Menu mit den 1-n Pagetabs und alle Links zu CSS und Scripts&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;widget_base_width&amp;quot; content=&amp;quot;74&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;widget_base_height&amp;quot; content=&amp;quot;71&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;mobile-web-app-capable&amp;quot; content=&amp;quot;yes&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;apple-mobile-web-app-capable&amp;quot; content=&amp;quot;yes&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;meta http-equiv=&amp;quot;X-UA-Compatible&amp;quot; content=&amp;quot;IE=edge&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;longpoll&amp;quot; content=&amp;quot;1&amp;quot;&amp;gt; &amp;lt;!-- 1=longpoll;0=shortpoll every 30sec --&amp;gt;&lt;br /&gt;
    &amp;lt;meta name=&amp;quot;debug&amp;quot; content=&amp;quot;1&amp;quot;&amp;gt; &amp;lt;!-- 1=output to console;0=not output --&amp;gt;&lt;br /&gt;
    &amp;lt;meta http-equiv=&amp;quot;Cache-Control&amp;quot; content=&amp;quot;no-store&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/lib/jquery.gridster.min.css&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/css/fhem-tablet-ui.css&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/lib/font-awesome.min.css&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/lib/jquery.toast.min.css&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- define your personal style here, it wont be overwritten  --&amp;gt;&lt;br /&gt;
    &amp;lt;!-- link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/css/fhem-green-ui.css&amp;quot; / --&amp;gt;&lt;br /&gt;
    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/css/fhem-tablet-ui-user.css&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/pgm2/jquery.min.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/tablet/lib/jquery.toast.min.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/tablet/lib/jquery.gridster.min.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/tablet/js/fhem-tablet-ui.min.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Remove this line to enable for usage with WebViewControl&lt;br /&gt;
    &amp;lt;script defer&amp;gt;var wvcDevices = {&#039;12345&#039;: &#039;Tablet&#039;}; var wvcUserCssFile=&amp;quot;webviewcontrol.css&amp;quot;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/pgm2/cordova-2.3.0.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;/fhem/pgm2/webviewcontrol.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;!-- End for WebViewControl --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;title&amp;gt;FHEM-Tablet-UI&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;gridster&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;ul&amp;gt;&lt;br /&gt;
            &amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot; data-sizey=&amp;quot;9&amp;quot; data-template=&amp;quot;menu.html&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
        &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
- die per Template eingebundene menu.html enthält die Pagetabs mit den Links zu den Unterseiten&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;header&amp;gt;MENU&amp;lt;/header&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;cell&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;sub1.html&amp;quot;  data-icon=&amp;quot;fa-home&amp;quot; class=&amp;quot;top-space&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;sub2.html&amp;quot;  data-icon=&amp;quot;fa-music&amp;quot; class=&amp;quot;top-space&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;sub3.html&amp;quot;  data-icon=&amp;quot;fa-sliders&amp;quot; class=&amp;quot;top-space&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;sub4.html&amp;quot;  data-icon=&amp;quot;fa-lightbulb-o&amp;quot; class=&amp;quot;top-space&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;sub5.html&amp;quot;  data-icon=&amp;quot;fa-line-chart&amp;quot; class=&amp;quot;top-space&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;bottom bottom-space-2x&amp;quot;&amp;gt;&lt;br /&gt;
           &amp;lt;div data-type=&amp;quot;clock&amp;quot; data-format=&amp;quot;H:i&amp;quot; class=&amp;quot;large&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
           &amp;lt;div data-type=&amp;quot;clock&amp;quot; data-format=&amp;quot;d.n.Y&amp;quot; class=&amp;quot;small&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
- Ganz oben im Menu ist die sub1.html, die zuerst angezeigt wird und die eigentlichen Haupt-Widgets hat&lt;br /&gt;
&lt;br /&gt;
- Jede Unterseite sub*.html hat auch wieder die gleiche Menü-Leiste dabei, die wieder per Template eingebunden wird. Die Unterseiten haben keine Scripts oder CSS Links, da nur der Gridster Teil in die index.html importiert wird&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;FHEM Sub1&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;gridster&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot; data-sizey=&amp;quot;7&amp;quot; data-template=&amp;quot;menu.html&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;2&amp;quot; data-sizex=&amp;quot;3&amp;quot; data-sizey=&amp;quot;4&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;header&amp;gt;EXAMPLE1&amp;lt;/header&amp;gt;&lt;br /&gt;
  &amp;lt;!-- place your widget here --&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;4&amp;quot; data-sizex=&amp;quot;6&amp;quot; data-sizey=&amp;quot;4&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;header&amp;gt;EXAMPLE2&amp;lt;/header&amp;gt;&lt;br /&gt;
   &amp;lt;!-- place your widget here --&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;10&amp;quot; data-sizex=&amp;quot;2&amp;quot; data-sizey=&amp;quot;4&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;header&amp;gt;EXAMPLE3&amp;lt;/header&amp;gt;&lt;br /&gt;
    &amp;lt;!-- place your widget here --&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;5&amp;quot; data-col=&amp;quot;2&amp;quot; data-sizex=&amp;quot;6&amp;quot; data-sizey=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;header&amp;gt;EXAMPLE4&amp;lt;/header&amp;gt;&lt;br /&gt;
  &amp;lt;!-- place your widget here --&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;5&amp;quot; data-col=&amp;quot;8&amp;quot; data-sizex=&amp;quot;5&amp;quot; data-sizey=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;header&amp;gt;EXAMPLE5&amp;lt;/header&amp;gt;&lt;br /&gt;
  &amp;lt;!-- place your widget here --&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wie bekommt man Elemente nebeneinander und übereinander?==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nebeneinder&#039;&#039;&#039; klappt mit der CSS Klasse &#039;&#039;inline&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;übereinander&#039;&#039;&#039; ist das Standardverhalten von div Elementen. Man steckt einfach alle Elemente, die untereinander angeordnet werden sollen, in einen gemeinsamen übergeordneten div Container.&lt;br /&gt;
&lt;br /&gt;
Beispiel: Zwei Blöcken nebeneinander mit jeweils einem Switch und Label übereinander&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;top-space inline&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;switch&amp;quot; data-device=&amp;quot;GalerieLicht&amp;quot; class=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;Galerie&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;top-space inline&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;switch&amp;quot; data-device=&amp;quot;GartenLicht&amp;quot; class=&amp;quot;&amp;quot; &amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;Garten&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Warum erscheint bei mir die index.html aus dem Example völlig verschoben?==&lt;br /&gt;
&lt;br /&gt;
Dann passt die widget_base_width und widget_base_height bei dir nicht und muss angepasst werden.&lt;br /&gt;
Dazu in der index.html im Header folgendes ändern:&lt;br /&gt;
&lt;br /&gt;
vorher&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;meta name=&amp;quot;widget_base_width&amp;quot; content=&amp;quot;77&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;meta name=&amp;quot;widget_base_height&amp;quot; content=&amp;quot;71&amp;quot;&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
nachher&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;meta name=&amp;quot;widget_base_width&amp;quot; content=&amp;quot;154&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;meta name=&amp;quot;widget_base_height&amp;quot; content=&amp;quot;142&amp;quot;&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wie kann ich das Zoomen auf mobilen Geräten verhindern?==&lt;br /&gt;
Um zu Verhindern, dass auf mobilen Geräten eine automatische oder manuelle Größenanpassung möglich ist, kann dieser META-Tag im &amp;lt;nowiki&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/nowiki&amp;gt;-Abschnitt der Seite verwendet werden:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wie kann ich auf iOS-Geräten FTUI im Vollbildmodus starten?==&lt;br /&gt;
Um FTUI auf iOS-Geräten vom Home-Screen im Vollbildmodus starten zu können, sind folgende Einträge im &amp;lt;nowiki&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/nowiki&amp;gt;-Bereich der Seite zu setzen.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;meta name=&amp;quot;apple-mobile-web-app-capable&amp;quot; content=&amp;quot;yes&amp;quot; /&amp;gt;&lt;br /&gt;
 &amp;lt;meta name=&amp;quot;apple-mobile-web-app-status-bar-style&amp;quot; content=&amp;quot;black&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie: FAQ]]&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Dimmer&amp;diff=20431</id>
		<title>FTUI Widget Dimmer</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Dimmer&amp;diff=20431"/>
		<updated>2017-03-01T16:39:52Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Dimmer Widget]] ist ein Widget für [[FHEM Tablet UI]], das einen Ein-/Aus-Button mit inkludiertem Schieberegler erstellt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:FTUI_Widget_Dimmer_01.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get&#039;&#039;&#039;||Device-Reading, welches den Status-Wert enthält||STATE||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-on&#039;&#039;&#039;||Wert für EIN||on||data-get-on=&amp;quot;An&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-off&#039;&#039;&#039;||Wert für AUS||off||data-get-off=&amp;quot;Aus&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-value&#039;&#039;&#039;||[[Regulärer Ausdruck|RegEx]] oder Position in einer leerzeichen-getrennten Auflistung, die den Wert repräsentiert||-1 (alles anzeigen)||data-get-value=&amp;quot;2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set&#039;&#039;&#039;||Reading, welches geändert werden soll||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-on&#039;&#039;&#039;||Wert für EIN, der gesetzt werden soll||data-get-on||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-off&#039;&#039;&#039;||Wert für AUS, der gesetzt werden soll||data-get-off||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-value&#039;&#039;&#039;||Wert für EIN, der gesetzt werden soll||$v - nur der Wert||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-cmd&#039;&#039;&#039;||Name des Befehls zum Ändern des EIN-/AUS-Wertes, der mittels Schieberegler geändert wird||set||data-set-cmd=&amp;quot;setreading&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-cmd-value&#039;&#039;&#039;||Name des Befehls zum Ändern des Wertes, der mittels Schieberegler geändert wird||set||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-dim&#039;&#039;&#039;||Name des Readings, das für den DIM-Wert zuständig ist||||data-dim=&amp;quot;dim&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-icon&#039;&#039;&#039;||Name des Icons für den Schieberegler||fa-lightbulb-o||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-max&#039;&#039;&#039;||Maximalwert, der gesetzt werden kann||100||data-max=&amp;quot;25&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-min&#039;&#039;&#039;||Minimalwert, der gesetzt werden kann||0||data-min=&amp;quot;10&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-step&#039;&#039;&#039;||Größe der Änderungsschritte||1||data-step=&amp;quot;5&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-lock&#039;&#039;&#039;||Name des Readings, welches durch einen Boolean-Wert definiert, ob das Widget gesperrt (readonly) ist||||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
{{FTUI Klasse|FS20}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
* Um den Dim-Wert zu ändern, muss der Button gedrückt und nach unten oder oben verschoben werden.&lt;br /&gt;
* Im einfachen Modus (ohne &#039;&#039;data-dim&#039;&#039;-Parameter) schaltet das Widget zwischen OFF und dem DIM-Wert.&lt;br /&gt;
* Im erweiterten Modus (mit &#039;&#039;data-dim&#039;&#039;-Parameter) wird der DIM-Wert vom definierten Reading empfangen bzw. gesendet und der Button wird nur für EIN/AUS verwendet.&lt;br /&gt;
* &#039;&#039;$v&#039;&#039; ist ein Platzhalter für den numerischen Wert. Er wird zur Laufzeit durch den richtigen Wert ersetzt.&lt;br /&gt;
* data-lock: Das Widget wird gesperrt (readonly), wenn das definierte Reading den Wert &#039;&#039;1&#039;&#039;, &#039;&#039;on&#039;&#039; oder &#039;&#039;true&#039;&#039; hat.&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===HUEDevice===&lt;br /&gt;
Einfaches Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&#039;HUEDevice1&#039;&lt;br /&gt;
     data-set=&amp;quot;pct&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;!off&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Dimmer_01.png]]&lt;br /&gt;
&lt;br /&gt;
Nun ein Beispiel mit einem eigenen Reading für den DIM-Wert. Es ist dasselbe HUEDevice wie oben, nur wird diesmal der pct-Wert getrennt von EIN/AUS geregelt:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;HUEDevice1&amp;quot;&lt;br /&gt;
     data-get=&amp;quot;onoff&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;1&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;0&amp;quot;&lt;br /&gt;
     data-set=&amp;quot;&amp;quot;&lt;br /&gt;
     data-set-on=&amp;quot;on&amp;quot;&lt;br /&gt;
     data-set-off=&amp;quot;off&amp;quot;&lt;br /&gt;
     data-dim=&amp;quot;pct&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Homematic-Dimmer===&lt;br /&gt;
So wird ein Homematic-Dimmer im erweiterten Modus eingebunden:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot; &lt;br /&gt;
     data-device=&amp;quot;HomematicDevice1&amp;quot; &lt;br /&gt;
     data-get-on=&amp;quot;!off&amp;quot; &lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot; &lt;br /&gt;
     data-set-on=&amp;quot;on&amp;quot;&lt;br /&gt;
     data-dim=&amp;quot;pct&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===RegEx für On-Werte===&lt;br /&gt;
Dieses Beispiel verwendet einen RegEx-Ausdruck, um alle möglichen Werte für &amp;quot;EIN&amp;quot; abzudecken.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&#039;Dimmer1&#039;&lt;br /&gt;
     data-set=&amp;quot;pct&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;[0-9]{1,3}|on&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Dimmer&amp;diff=19960</id>
		<title>FTUI Widget Dimmer</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Dimmer&amp;diff=19960"/>
		<updated>2017-02-14T21:37:02Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Formatierung&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Dimmer Widget]] ist ein Widget für [[FHEM Tablet UI]], das einen Ein-/Aus-Button mit inkludiertem Schieberegler erstellt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:FTUI_Widget_Dimmer_01.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get&#039;&#039;&#039;||Device-Reading, welches den Status-Wert enthält||STATE||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-on&#039;&#039;&#039;||Wert für EIN||on||data-get-on=&amp;quot;An&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-off&#039;&#039;&#039;||Wert für AUS||off||data-get-off=&amp;quot;Aus&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-value&#039;&#039;&#039;||[[Regulärer Ausdruck|RegEx]] oder Position in einer leerzeichen-getrennten Auflistung, die den Wert repräsentiert||-1 (alles anzeigen)||data-get-value=&amp;quot;2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set&#039;&#039;&#039;||Reading, welches geändert werden soll||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-on&#039;&#039;&#039;||Wert für EIN, der gesetzt werden soll||data-get-on||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-off&#039;&#039;&#039;||Wert für AUS, der gesetzt werden soll||data-get-off||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-value&#039;&#039;&#039;||Wert für EIN, der gesetzt werden soll||$v - nur der Wert||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-cmd&#039;&#039;&#039;||Name des Befehls zum Ändern des EIN-/AUS-Wertes, der mittels Schieberegler geändert wird||set||data-set-cmd=&amp;quot;setreading&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-cmd-value&#039;&#039;&#039;||Name des Befehls zum Ändern des Wertes, der mittels Schieberegler geändert wird||set||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-dim&#039;&#039;&#039;||Name des Readings, das für den DIM-Wert zuständig ist||||data-dim=&amp;quot;dim&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-icon&#039;&#039;&#039;||Name des Icons für den Schieberegler||fa-lightbulb-o||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-max&#039;&#039;&#039;||Maximalwert, der gesetzt werden kann||100||data-max=&amp;quot;25&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-min&#039;&#039;&#039;||Minimalwert, der gesetzt werden kann||0||data-min=&amp;quot;10&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-step&#039;&#039;&#039;||Größe der Änderungsschritte||1||data-step=&amp;quot;5&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-lock&#039;&#039;&#039;||Name des Readings, welches durch einen Boolean-Wert definiert, ob das Widget gesperrt (readonly) ist||||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
{{FTUI Klasse|FS20}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
* Um den Dim-Wert zu ändern, muss der Button gedrückt und nach unten oder oben verschoben werden.&lt;br /&gt;
* Im einfache Modus (ohne &#039;&#039;data-dim&#039;&#039;-Parameter) schaltet das Widget zwischen OFF und dem DIM-Wert.&lt;br /&gt;
* Im erweiterten Modus (mit &#039;&#039;data-dim&#039;&#039;-Parameter) wird der DIM-Wert vom definierten Reading empfangen bzw. gesendet und der Button wird nur für EIN/AUS verwendet.&lt;br /&gt;
* &#039;&#039;$v&#039;&#039; ist ein Platzhalter für den numerischen Wert. Er wird zur Laufzeit durch den richtigen Wert ersetzt.&lt;br /&gt;
* data-lock: Das Widget wird gesperrt (readonly), wenn das definierte Reading den Wert &#039;&#039;1&#039;&#039;, &#039;&#039;on&#039;&#039; oder &#039;&#039;true&#039;&#039; hat.&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===HUEDevice===&lt;br /&gt;
Einfaches Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&#039;HUEDevice1&#039;&lt;br /&gt;
     data-set=&amp;quot;pct&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;!off&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Dimmer_01.png]]&lt;br /&gt;
&lt;br /&gt;
Nun ein Beispiel mit einem eigenen Reading für den DIM-Wert. Es ist dasselbe HUEDevice wie oben, nur wird diesmal der pct-Wert getrennt von EIN/AUS geregelt:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;HUEDevice1&amp;quot;&lt;br /&gt;
     data-get=&amp;quot;onoff&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;1&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;0&amp;quot;&lt;br /&gt;
     data-set=&amp;quot;&amp;quot;&lt;br /&gt;
     data-set-on=&amp;quot;on&amp;quot;&lt;br /&gt;
     data-set-off=&amp;quot;off&amp;quot;&lt;br /&gt;
     data-dim=&amp;quot;pct&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Homematic-Dimmer===&lt;br /&gt;
So wird ein Homematic-Dimmer eingebunden:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot; &lt;br /&gt;
     data-device=&amp;quot;HomematicDevice1&amp;quot; &lt;br /&gt;
     data-get-on=&amp;quot;!off&amp;quot; &lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot; &lt;br /&gt;
     data-set-on=&amp;quot;on&amp;quot;&lt;br /&gt;
     data-dim=&amp;quot;pct&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===RegEx für On-Werte===&lt;br /&gt;
Dieses Beispiel verwendet einen RegEx-Ausdruck, um alle möglichen Werte für &amp;quot;EIN&amp;quot; abzudecken.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&#039;Dimmer1&#039;&lt;br /&gt;
     data-set=&amp;quot;pct&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;[0-9]{1,3}|on&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Dimmer&amp;diff=19959</id>
		<title>FTUI Widget Dimmer</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Dimmer&amp;diff=19959"/>
		<updated>2017-02-14T21:26:59Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Homematic-Beispiel ergänzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Dimmer Widget]] ist ein Widget für [[FHEM Tablet UI]], das einen Ein-/Aus-Button mit inkludiertem Schieberegler erstellt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:FTUI_Widget_Dimmer_01.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get&#039;&#039;&#039;||Device-Reading, welches den Status-Wert enthält||STATE||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-on&#039;&#039;&#039;||Wert für EIN||on||data-get-on=&amp;quot;An&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-off&#039;&#039;&#039;||Wert für AUS||off||data-get-off=&amp;quot;Aus&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-value&#039;&#039;&#039;||[[Regulärer Ausdruck|RegEx]] oder Position in einer leerzeichen-getrennten Auflistung, die den Wert repräsentiert||-1 (alles anzeigen)||data-get-value=&amp;quot;2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set&#039;&#039;&#039;||Reading, welches geändert werden soll||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-on&#039;&#039;&#039;||Wert für EIN, der gesetzt werden soll||data-get-on||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-off&#039;&#039;&#039;||Wert für AUS, der gesetzt werden soll||data-get-off||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-value&#039;&#039;&#039;||Wert für EIN, der gesetzt werden soll||$v - nur der Wert||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-cmd&#039;&#039;&#039;||Name des Befehls zum Ändern des EIN-/AUS-Wertes, der mittels Schieberegler geändert wird||set||data-set-cmd=&amp;quot;setreading&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-cmd-value&#039;&#039;&#039;||Name des Befehls zum Ändern des Wertes, der mittels Schieberegler geändert wird||set||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-dim&#039;&#039;&#039;||Name des Readings, das für den DIM-Wert zuständig ist||||data-dim=&amp;quot;dim&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-icon&#039;&#039;&#039;||Name des Icons für den Schieberegler||fa-lightbulb-o||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-max&#039;&#039;&#039;||Maximalwert, der gesetzt werden kann||100||data-max=&amp;quot;25&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-min&#039;&#039;&#039;||Minimalwert, der gesetzt werden kann||0||data-min=&amp;quot;10&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-step&#039;&#039;&#039;||Größe der Änderungsschritte||1||data-step=&amp;quot;5&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-lock&#039;&#039;&#039;||Name des Readings, welches durch einen Boolean-Wert definiert, ob das Widget gesperrt (readonly) ist||||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
{{FTUI Klasse|FS20}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
* Um den Dim-Wert zu ändern, muss der Button gedrückt und nach unten oder oben verschoben werden.&lt;br /&gt;
* Im einfache Modus (ohne &#039;&#039;data-dim&#039;&#039;-Parameter) schaltet das Widget zwischen OFF und dem DIM-Wert.&lt;br /&gt;
* Im erweiterten Modus (mit &#039;&#039;data-dim&#039;&#039;-Parameter) wird der DIM-Wert vom definierten Reading empfangen bzw. gesendet und der Button wird nur für EIN/AUS verwendet.&lt;br /&gt;
* &#039;&#039;$v&#039;&#039; ist ein Platzhalter für den numerischen Wert. Er wird zur Laufzeit durch den richtigen Wert ersetzt.&lt;br /&gt;
* data-lock: Das Widget wird gesperrt (readonly), wenn das definierte Reading den Wert &#039;&#039;1&#039;&#039;, &#039;&#039;on&#039;&#039; oder &#039;&#039;true&#039;&#039; hat.&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===HUEDevice: Einfaches Beispiel===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&#039;HUEDevice1&#039;&lt;br /&gt;
     data-set=&amp;quot;pct&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;!off&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Dimmer_01.png]]&lt;br /&gt;
&lt;br /&gt;
===HUEDevice: Eigenes Reading für DIM-Wert===&lt;br /&gt;
Das selbe HUEDevice wie oben, nur wird diesmal der pct-Wert getrennt von EIN/AUS geregelt.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;HUEDevice1&amp;quot;&lt;br /&gt;
     data-get=&amp;quot;onoff&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;1&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;0&amp;quot;&lt;br /&gt;
     data-set=&amp;quot;&amp;quot;&lt;br /&gt;
     data-set-on=&amp;quot;on&amp;quot;&lt;br /&gt;
     data-set-off=&amp;quot;off&amp;quot;&lt;br /&gt;
     data-dim=&amp;quot;pct&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Homematic-Dimmer===&lt;br /&gt;
So wird ein Homematic-Dimmer eingebunden:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot; &lt;br /&gt;
     data-device=&amp;quot;HomematicDevice1&amp;quot; &lt;br /&gt;
     data-get-on=&amp;quot;!off&amp;quot; &lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot; &lt;br /&gt;
     data-set-on=&amp;quot;on&amp;quot;&lt;br /&gt;
     data-dim=&amp;quot;pct&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===RegEx für On-Werte===&lt;br /&gt;
Dieses Beispiel verwendet einen RegEx-Ausdruck, um alle möglichen Werte für &amp;quot;EIN&amp;quot; abzudecken.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
     data-device=&#039;Dimmer1&#039;&lt;br /&gt;
     data-set=&amp;quot;pct&amp;quot;&lt;br /&gt;
     data-get-on=&amp;quot;[0-9]{1,3}|on&amp;quot;&lt;br /&gt;
     data-get-off=&amp;quot;off&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Rotor&amp;diff=19860</id>
		<title>FTUI Widget Rotor</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Rotor&amp;diff=19860"/>
		<updated>2017-02-13T20:59:17Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Rotor Widget]] ist ein Widget für [[FHEM Tablet UI]], welches mehrere Widgets an derselben Stelle nacheinander anzeigen kann. Der Wechsel vom einen zum anderen Widget erfolgt durch konfigurierbare Effekte (z.B. Überblendung).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:FTUI_Widget_Rotor_01.gif&lt;br /&gt;
File:FTUI_Widget_Rotor_02.gif&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-delay&#039;&#039;&#039;||Zeit - in Millisekunden - bis das nächste Element in der Liste angezeigt wird||3500||data-delay=&amp;quot;1000&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
*Wird keine Klasse angegeben, die den Animationseffekt beschreibt (&amp;lt;code&amp;gt;class=&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;), wird auch keine Animation verwendet&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|rotate}}{{FTUI Klasse|fade}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===Wechsel zwischen zwei verschiedenen Labels===&lt;br /&gt;
In diesem Beispiel wird einfach zwischen zwei verschiedenen Labels mit einem Überblendungseffekt umgeschaltet.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;rotor&amp;quot; class=&amp;quot;fade&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;ul&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;&lt;br /&gt;
      &amp;lt;div data-type=&amp;quot;label&amp;quot;&amp;gt;Label 1&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;&lt;br /&gt;
      &amp;lt;div data-type=&amp;quot;label&amp;quot;&amp;gt;Label 2&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Rotor_01.gif]]&lt;br /&gt;
&lt;br /&gt;
===Umschalten zwischen Tagen eines Wetterberichts===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;rotor&amp;quot; class=&amp;quot;fade&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;ul&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;&lt;br /&gt;
      &amp;lt;div data-type=&amp;quot;label&amp;quot;&amp;gt;Heute&amp;lt;/div&amp;gt;&lt;br /&gt;
      &amp;lt;div data-type=&amp;quot;weather&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;fc0_weatherDay&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
      &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;fc0_weatherDay&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
      &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;fc0_tempMax&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;&lt;br /&gt;
      &amp;lt;div data-type=&amp;quot;label&amp;quot;&amp;gt;Morgen&amp;lt;/div&amp;gt;&lt;br /&gt;
      &amp;lt;div data-type=&amp;quot;weather&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;fc1_weatherDay&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
      &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;fc1_weatherDay&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
      &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;fc1_tempMax&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Rotor_02.gif]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Chart&amp;diff=19859</id>
		<title>FTUI Widget Chart</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Chart&amp;diff=19859"/>
		<updated>2017-02-13T20:56:05Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Chart Widget]] ist ein Widget für [[FHEM Tablet UI]], mit dem sich verschiedenste Diagramme darstellen lassen. Die Aneinanderreihung mehrerer Werte eines Device-Readings zu einem zeitlichen Verlauf wird dabei als Graph bezeichnet.&lt;br /&gt;
&lt;br /&gt;
Es können beliebige Werte dargestellt und entsprechend der Sinnhaftigkeit, oder persönlichem Geschmack, formatiert werden. Farbe und Form der Linien sind je Graph einstellbar, auch wenn mehrere gleichzeitig in einem Diagramm angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
Jedes Diagramm kann zwei Y-Achsen besitzen. Die primäre Y-Achse (primary) wird auf der linken Seite angezeigt, die sekundäre Y-Achse (secondary) auf der rechten Seite. Beide Achsen können unterschiedlich formatiert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Chart_tabletUI.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-logdevice&#039;&#039;&#039;||Name des Log-Device, das dargestellt werden soll, oder ein Array, um mehrere Werte in einem Diagramm darzustellen||||data-logdevice=&amp;quot;FileLog_WohnzimmerHeizung&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-logfile&#039;&#039;&#039;|| Name des Log-Files, aus dem die Daten entnommen werden sollen (oder Array)||&#039;-&#039; = aktuelle Datei||data-logfine=&amp;quot;WohnzimmerHeizung-2015.log&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-columnspec&#039;&#039;&#039;||Ermittelt den Wert aus dem Log-File, der angezeigt werden soll (oder Array)||||data-columnspec=&amp;quot;4:meas.*&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-style&#039;&#039;&#039;||Stil, wie die Graphen dargestellt werden sollen (z.B. &#039;SVGplot l0&#039; oder &#039;ftui l0dash&#039;), oder ein Array, wenn mehrere Linien unterschiedlich dargestellt werden sollen||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-ptype&#039;&#039;&#039;||Form, wie die Graphen dargestellt werden sollen (z.B. &#039;lines&#039;, &#039;cubic&#039; oder &#039;fa-cog&#039;), oder ein Array||&#039;lines&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-uaxis&#039;&#039;&#039;||Name der Achse, die verwendet werden soll (&#039;primary&#039; = links, oder &#039;secondary&#039; = rechts), oder ein Array||&#039;primary&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-legend&#039;&#039;&#039;||Bezeichnung des Graphen (wird in Legende und am Cursor angezeigt), oder ein Array||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-minvalue&#039;&#039;&#039;||Minimaler Wert, der auf der linken Y-Achse (&#039;primary&#039;) angezeigt werden soll. &#039;auto&#039; = automatische Berechnung||&#039;10&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-maxvalue&#039;&#039;&#039;||Maximaler Wert, der auf der linken Y-Achse (&#039;primary&#039;) angezeigt werden soll. &#039;auto&#039; = automatische Berechnung||&#039;30&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-minvalue_sec&#039;&#039;&#039;||Minimaler Wert, der auf der rechten Y-Achse (&#039;secondary&#039;) angezeigt werden soll. &#039;auto&#039; = automatische Berechnung||&#039;auto&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-maxvalue_sec&#039;&#039;&#039;||Maximaler Wert, der auf der rechten Y-Achse (&#039;secondary&#039;) angezeigt werden soll. &#039;auto&#039; = automatische Berechnung||&#039;auto&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yticks&#039;&#039;&#039;||Abstand zwischen den horizontalen Hilfslinien (bezogen auf die linke Y-Achse). Kann auch ein Array mit Werte-Paaren enthalten, um die Linien mit Text zu beschriften.||&#039;auto&#039;||data-yticks=&#039;[[0,&amp;quot;open&amp;quot;],[1,&amp;quot;closed&amp;quot;]]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yticks_sec&#039;&#039;&#039;||Abstand zwischen den horizontalen Hilfslinien (bezogen auf die rechte Y-Achse). Kann auch ein Array mit Werte-Paaren enthalten, um die Linien mit Text zu beschriften.||&#039;auto&#039;||data-yticks=&#039;[[0,&amp;quot;open&amp;quot;],[1,&amp;quot;closed&amp;quot;]]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-xticks&#039;&#039;&#039;||Abstand zwischen den vertikalen Hilfslinien (bezogen auf die X-Achse) in Minuten. &#039;auto&#039; = automatische Berechnung||&#039;auto&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-daysago_start&#039;&#039;&#039;||Anzahl der vergangenen Tage, wo das Diagramm beginnen soll. &#039;0&#039; = Beginn heute 0:00 Uhr. Es kann auch ein fixes Datum (z.B. &#039;2013-10-23&#039;) angegeben werden. Uhrzeitangaben werden nur berücksichtigt, wenn &#039;&#039;&#039;data-nofulldays=&#039;true&#039; &#039;&#039;&#039; verwendet wird.||&#039;0&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-daysago_end&#039;&#039;&#039;||Anzahl der vergangenen Tage, wo das Diagramm enden soll. &#039;-1&#039; = Ende heute 24:00 Uhr. Es kann auch ein fixes Datum (z.B. &#039;2013-10-24&#039;) angegeben werden. Uhrzeitangaben werden nur berücksichtigt, wenn &#039;&#039;&#039;data-nofulldays=&#039;true&#039; &#039;&#039;&#039; verwendet wird.||&#039;-1&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-nofulldays&#039;&#039;&#039;||Aktiviert/deaktiviert die Rundung der X-Achse auf ganze Tage. Binärwert (&#039;true&#039; oder &#039;false&#039;)||&#039;false&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-timeformat&#039;&#039;&#039;||Zeitformat für die Anzeige an der X-Achse (siehe Hinweise)||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-ytext&#039;&#039;&#039;||Text, der neben der linken Y-Achse angezeigt wird||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-ytext_sec&#039;&#039;&#039;||Text, der neben der rechten Y-Achse angezeigt wird||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yunit&#039;&#039;&#039;||Einheit, die an der linken Y-Achse angezeigt wird||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-yunit_sec&#039;&#039;&#039;||Einheit, die an der rechten Y-Achse angezeigt wird||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-crosshair&#039;&#039;&#039;||Aktiviert/deaktiviert den Fadenkreuz-Cursor. Binärwert (&#039;true&#039; oder &#039;false&#039;)||&#039;false&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-cursorgroup&#039;&#039;&#039;||Zahl zur Gruppierung der Werte am Fadenkreuz-Cursor (siehe Hinweise)||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-scrollgroup&#039;&#039;&#039;||Zahl zur Gruppierung der Graphen beim Bewegen und Zoomen. Alle Linien mit der selben Zahl werden miteinander gekoppelt und bewegen sich gemeinsam.||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-showlegend&#039;&#039;&#039;||Aktiviert/deaktiviert die Anzeige der Legene. Binärwert (&#039;true&#039; oder &#039;false&#039;)||&#039;false&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-legendpos&#039;&#039;&#039;||Array von zwei Werten, die die horizontale und vertikale Position der Legende festlegen (siehe Hinweise)||&#039;[&amp;quot;top&amp;quot;,&amp;quot;right&amp;quot;]&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-width&#039;&#039;&#039;||Breite des Diagramms (in % oder px)||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-height&#039;&#039;&#039;||Höhe des Diagramms (in % oder px)||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-graphsshown&#039;&#039;&#039;||Aktiviert/deaktiviert die initiale Anzeige von Graphen. Binärwert (&#039;true&#039; oder &#039;false&#039;). Array, wenn mehrere Linien angezeigt werden sollen.||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-ddd&#039;&#039;&#039;||Einstellung für die 3D-Drehung (siehe Hinweise)||||data-ddd=&#039;[&amp;quot;40&amp;quot;,&amp;quot;60&amp;quot;,&amp;quot;0&amp;quot;]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-dddspace&#039;&#039;&#039;||Abstand zwischen zwei Graphen, wenn die 3D-Anzeige aktiviert wurde (px)||&#039;15&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-dddwidth&#039;&#039;&#039;||Breite, bzw. Tiefe der Graphen, wenn diese 3-dimensional angezeigt werden (px)||&#039;10&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-title&#039;&#039;&#039;||Titel, der über dem Diagramm angezeigt werden soll. Der Inhalt kann auch dynamisch erzeugt werden (siehe Hinweise)||||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Datenquellen==&lt;br /&gt;
In einem Diagramm werden zumeist Daten zur Anzeige gebracht, die in der Vergangenheit genau zu diesem Zweck gespeichert wurden. FHEM bietet für die Speicherung zwei Möglichkeiten:&lt;br /&gt;
# [[FileLog]]: Daten werden in einer Textdatei gespeichert&lt;br /&gt;
# [[DbLog]]: Daten werden in einer Datenbank gespeichert.&lt;br /&gt;
&lt;br /&gt;
Beide Arten der Datenhaltung werden unterstützt und bieten in Bezug auf das Widget weder Vor-, noch Nachteile. Einzig die Definition des Widgets sieht etwas anders aus.&lt;br /&gt;
&lt;br /&gt;
===FileLog===&lt;br /&gt;
Um [[FileLog]] zu nutzen, wird als &#039;&#039;&#039;data-logdevice&#039;&#039;&#039; das FHEM-Device für das FileLog angegeben. In der Regel entstehen hier im Laufe der Zeit mehrere Log-Dateien. Name und Anzahl sind von der Definition abhängig - meist wird jeden Monat oder jedes Jahr eine neue Datei angelegt. Die gewünschte Datei kann mit &#039;&#039;&#039;data-logfile&#039;&#039;&#039; ausgewählt werden. Möchte man stets die aktuelle Datei verwenden (macht vor allem dann Sinn, wenn man die neusten Daten anzeigen will), kann das Attribut weggelassen, oder explizit &amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt; eingetragen werden. Zuletzt wird &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; benötigt, um die gewünschten Daten zu in der Logdatei zu identifizieren. Hier wird die Spalte, in der die Daten stehen, gefolgt von Doppelpunkt und Readingname angegeben.&lt;br /&gt;
&lt;br /&gt;
Für ein Heizungsthermostat von Homematic mit dem Namen &#039;&#039;DG.wz.HZ.Heizungsventil&#039;&#039; ergibt sich somit beispielhaft folgende Definition, um gemessene Temperatur, Sollwert und Ventilstellung im Diagramm darzustellen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-logdevice=&amp;quot;FileLog_DG.wz.HZ.Heizungsventil&amp;quot;&lt;br /&gt;
	 data-logfile=&amp;quot;-&amp;quot;&lt;br /&gt;
	 data-columnspec=&#039;[&amp;quot;4:measured-temp&amp;quot;,&amp;quot;4:desired-temp&amp;quot;,&amp;quot;4:actuator&amp;quot;]&#039;&lt;br /&gt;
	 ...&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollen Daten von unterschiedlichen Geräten in einem Diagramm angezeigt werden, muss &#039;&#039;&#039;data-logdevice&#039;&#039;&#039; als Array nach dem Schema &amp;lt;code&amp;gt;data-logdevice=&#039;[&amp;quot;&amp;lt;Logdatei_1&amp;gt;&amp;quot;,&amp;quot;&amp;lt;Logdatei_2&amp;gt;&amp;quot;,&amp;quot;&amp;lt;Logdatei_3&amp;gt;&amp;quot;]&#039;&amp;lt;/code&amp;gt; definiert werden. Für jeden Eintrag in &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; muss es auch den passenden Eintrag in &#039;&#039;&#039;data-logdevice&#039;&#039;&#039; geben (auch die Reihenfolge ist relevant).&lt;br /&gt;
&lt;br /&gt;
===DbLog===&lt;br /&gt;
Um die Daten aus [[DbLog]] anzeigen zu können, werden die gleichen Attribute verwendet und mit für die Datenbank angepassten Werten beschrieben. Bei &#039;&#039;&#039;data-logdevice&#039;&#039;&#039; das FHEM-Device für die Datenbank angegeben. Im nachfolgenden Beispiel heißt diese &amp;lt;code&amp;gt;logdb&amp;lt;/code&amp;gt; und besitzt wie üblich zwei Tabellen: &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;history&amp;lt;/code&amp;gt; (der zeitliche Verlauf liegt in letzterer). Der Tabellenname wird bei &#039;&#039;&#039;data-logfile&#039;&#039;&#039; eingetragen. Da die Daten in der Datenbank etwas anders abgelegt werden, muss auch &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; entsprechend angepasst werden. Statt der Spalte wird hier das FHEM-Device, gefolgt von Doppelpunkt und Readingname angegeben.&lt;br /&gt;
&lt;br /&gt;
Für das oben beschriebene Homematic-Heizungsthermostat ergibt sich dann folgende Definition, um die gleichen Daten aus einer Datenbank, statt einem LogFile zu lesen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-logdevice=&amp;quot;logdb&amp;quot;&lt;br /&gt;
	 data-logfile=&amp;quot;HISTORY&amp;quot;&lt;br /&gt;
	 data-columnspec=&#039;[&amp;quot;DG.wz.HZ.Heizungsventil:measured-temp&amp;quot;,&amp;quot;DG.wz.HZ.Heizungsventil:desired-temp&amp;quot;,&amp;quot;DG.wz.HZ.Heizungsventil:actuator&amp;quot;]&#039;&lt;br /&gt;
	 ...&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für die Anzeige von unterschiedlichen Geräten in einem Diagramm, muss nur &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; entsprechend angepasst werden, solange sich alle Daten in der Datenbank befinden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|fullsize}}{{FTUI Klasse|noticks}}{{FTUI Klasse|nobuttons}}{{FTUI Klasse|small}}{{FTUI Klasse|normal}}{{FTUI Klasse|big}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Folgende Widget-spezifsche Klassen können zusätzlich in einer eigenen CSS-Datei definiert werden:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Klasse&lt;br /&gt;
!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;chart-background&#039;&#039;&#039;||Hintergrundfarbe des Diagramms&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;buttons&#039;&#039;&#039;||Größe und Farbe der Buttons&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;text.axes&#039;&#039;&#039;||Generelle Schriftart und Farbe der Achsen&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;gridlines&#039;&#039;&#039;||Generelle Farbe und Größe der Gitternetzlinien&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;xaxis&#039;&#039;&#039;||Schriftart, Größe und Farbe der X-Achse&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;yaxis&#039;&#039;&#039;||Schriftart, Größe und Farbe der Y-Achse&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;xticks&#039;&#039;&#039;||Schriftart, Größe und Farbe der X-Achse (Zwischenlinien)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;yticks&#039;&#039;&#039;||Schriftart, Größe und Farbe der Y-Achse (Zwischenlinien)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;crosshair&#039;&#039;&#039;||Schriftart, Größe und Vordergrund/Hintergrundfarbe der Momentanwerte am Fadenkreuzcursor&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;caption&#039;&#039;&#039;||Schriftart, Größe und Farbe der Text-Buttons für Legende und Cursor&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;legend&#039;&#039;&#039;||Schriftart, Größe und Farbe der Legende&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
===Aussehen der Linien===&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;data-style&#039;&#039;&#039; kann das Aussehen der Linien des jeweiligen Graphen verändert werden. Hierfür können die Standard-FHEM-Styles verwendet werden. Es existieren jedoch auch noch weitere, zu finden in der CSS-Datei &amp;lt;code&amp;gt;css/ftui_chart.css&amp;lt;/code&amp;gt;. Eigene Styles können zum Beispiel in der Datei &amp;lt;code&amp;gt;css/fhem-table-ui-user.css&amp;lt;/code&amp;gt; definiert werden.&lt;br /&gt;
&lt;br /&gt;
===Form der Linien===&lt;br /&gt;
Das Attribut &#039;&#039;&#039;data-ptype&#039;&#039;&#039; beeinflusst die Form der Linien. Alle FHEM-Plot-Stile werden unterstützt. Zusätzlich ist es möglich, Symbole anzeigen zu lassen. Unterstützt werden Font-Awesome (&#039;fa-...&#039;), Open Automation (&#039;oa-...&#039;) und FHEM-Symbole (&#039;fs-...&#039;)).&lt;br /&gt;
&lt;br /&gt;
Es kann auch Inhalt im Format &amp;lt;code&amp;gt;&#039;icon:1&#039;&amp;lt;/code&amp;gt; verarbeitet werden. In diesem Fall muss der zugehörige Wert in &#039;&#039;&#039;data-columnspec&#039;&#039;&#039; den Pfad zu einem Icon (z.B. für Wettervorhersagen) beinhalten. Der Y-Wert wird dann vom ersten Graphen übernommen.&lt;br /&gt;
&lt;br /&gt;
===Zeitformat der X-Achse===&lt;br /&gt;
Die Zeitanzeige auf der X-Achse kann sehr flexibel eingestellt werden. Dafür stehen verschiedene Platzhalter zur Verfügung, die durch spezielle Zeichen (&amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt; &amp;lt;/code&amp;gt; (Leerzeichen), &amp;lt;code&amp;gt;:&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;,&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt;) getrennt werden. Alle Zeichen werden trotz Escape-Zeichen (&amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt;) in der Ausgabe angezeigt.&lt;br /&gt;
&lt;br /&gt;
Folgende Platzhalter werden unterstützt:&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;mm&#039;&amp;lt;/code&amp;gt;: Minuten als zweistellige Zahl&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;hh&#039;&amp;lt;/code&amp;gt;: Stunden als zweistellige Zahl&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;dd&#039;&amp;lt;/code&amp;gt;: Tag als zweistellige Zahl (Kalenderdatum)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;MM&#039;&amp;lt;/code&amp;gt;: Monat als zweistellige Zahl (z.B. 02 für Februar)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;MMM&#039;&amp;lt;/code&amp;gt;: Monat als dreistellige Abkürzung (z.B. Dec für Dezember)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;MMMM&#039;&amp;lt;/code&amp;gt;: Langname des Monats (z.B. March)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;ee&#039;&amp;lt;/code&amp;gt;: Wochentag als zweistellige Zahl (z.B. 00 für Sonntag)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;eee&#039;&amp;lt;/code&amp;gt;: Wochentag als dreistellige Abkürzung (z.B. Mon für Montag)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;eeee&#039;&amp;lt;/code&amp;gt;: Langname des Wochentags (z.B. Tuesday)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;yy&#039;&amp;lt;/code&amp;gt;: Jahr als zweistellige Zahl (z.B. 16 für 2016)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;yyyy&#039;&amp;lt;/code&amp;gt;: Jahr als vierstellige Zahl (z.B. 2016)&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;LF&#039;&amp;lt;/code&amp;gt;: Fügt einen Zeilenumbruch hinzu&lt;br /&gt;
&lt;br /&gt;
Beispiel: Der String &amp;lt;code&amp;gt;&#039;MMM\LF\yyyy&#039;&amp;lt;/code&amp;gt; zeigt &amp;lt;code&amp;gt;&#039;Jan&#039;&amp;lt;/code&amp;gt; in der ersten, und &amp;lt;code&amp;gt;&#039;2016&#039;&amp;lt;/code&amp;gt; in der zweiten Zeile. &amp;lt;code&amp;gt;&#039;MM.dd 2016&#039;&amp;lt;/code&amp;gt; wird zu &amp;lt;code&amp;gt;&#039;03.05 2016&#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Fadenkreuz-Cursor===&lt;br /&gt;
Der Fadenkreuz-Cursor zeigt die Momentanwerte, indem man ihn über die Graphen bewegt. In Desktop-Browsern reicht einfaches Bewegen des Maus. Unter iOS und Android kann der Cursor wird der Cursor durch einfaches Tippen auf die neue Position bewegt.&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;data-cursorgroup&#039;&#039;&#039; können Graphen gruppiert werden. Am Cursor werden dann die Momentanwerte aller Graphen gleichzeitig angezeigt, die die selbe Zahl besitzen, sobald man die Maus über einen aus der Gruppe bewegt.&lt;br /&gt;
&lt;br /&gt;
===Legende===&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;data-legendpos&#039;&#039;&#039; kann die Position der Legende innerhalb des Diagramms festgelegt werden. Die Position wird mit einem Array, bestehend aus zwei Werten im Format &amp;lt;code&amp;gt;&#039;[&amp;quot;&amp;lt;horizontal&amp;gt;&amp;quot;,&amp;quot;&amp;lt;vertikal&amp;gt;&amp;quot;]&#039;&amp;lt;/code&amp;gt; angegeben. Für die horizontale Positionierung sind &amp;lt;code&amp;gt;&#039;left&#039;&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;&#039;right&#039;&amp;lt;/code&amp;gt;, die vertikale Positionierung &amp;lt;code&amp;gt;&#039;top&#039;&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;&#039;bottom&#039;&amp;lt;/code&amp;gt; erlaubt. Alternativ können auch Zahlen verwendet werden, die die Position in Prozent angeben. In Desktop-Browsern kann die Legende auch an eine andere Position verschoben werden. Das funktioniert jedoch nicht unter iOS und Android.&lt;br /&gt;
&lt;br /&gt;
Wenn die Legende eingeblendet ist, kann mittels Klick auf einen Legendeneintrag der zugehörige Graph ein- und ausgeblendet werden.&lt;br /&gt;
&lt;br /&gt;
===3-dimensionale Drehung===&lt;br /&gt;
&#039;&#039;&#039;data-ddd&#039;&#039;&#039; ermöglicht, den Graphen 3-dimensional zu drehen. Als Wert wird ein Array mit den 3 Winkeln für x, y und z erwartet, wobei z selbst bisher nicht unterstützt wird.&lt;br /&gt;
&lt;br /&gt;
Beispiel: &amp;lt;code&amp;gt;data-ddd=&#039;[&amp;quot;40&amp;quot;,&amp;quot;60&amp;quot;,&amp;quot;0&amp;quot;]&#039;&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Wenn das Array angegeben wird, erscheinen zwei zusätzliche Buttons im Diagramm, mit denen die Drehung in X- und Y-Richtung verändert werden kann.&lt;br /&gt;
&lt;br /&gt;
===Diagrammtitel===&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;data-title&#039;&#039;&#039; kann dem Diagramm, ähnlich wie in FHEM-SVG-Plots, ein Titel hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
Folgende Platzhalter werden unterstützt:&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;min1&#039;&amp;lt;/code&amp;gt;: Minimaler Y-Wert des ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;max1&#039;&amp;lt;/code&amp;gt;: Maximaler Y-Wert des ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;avg1&#039;&amp;lt;/code&amp;gt;: Mittlerer Y-Wert des ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;cnt1&#039;&amp;lt;/code&amp;gt;: Anzahl der dargestellten Einzelwerte im ersten Graph&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;currval1&#039;&amp;lt;/code&amp;gt;: Letzter, bzw. aktuellster Y-Wert des ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;mindate1&#039;&amp;lt;/code&amp;gt;: Niedrigster Wert auf der X-Achse des ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;maxdate1&#039;&amp;lt;/code&amp;gt;: Höchster Wert auf der X-Achse vom ersten Graphs&lt;br /&gt;
*&amp;lt;code&amp;gt;&#039;currdate1&#039;&amp;lt;/code&amp;gt;: Letzter, bzw. aktuellster Wert auf der X-Achse des ersten Graphs&lt;br /&gt;
&lt;br /&gt;
Durch Einsetzen einer anderen Zahl statt &#039;1&#039; können auch die Werte der anderen Graphen angezeigt werden. Das Weglassen der Zahl bewirkt, dass der jeweils zutreffende Wert automatisch ermittelt wird. Bedeutet: &amp;lt;code&amp;gt;max&amp;lt;/code&amp;gt; führt dazu, dass der höchste Wert aller angezeigter Graphen verwendet wird.&lt;br /&gt;
&lt;br /&gt;
Beispiel: &amp;lt;code&amp;gt;data-title=&amp;quot;Min: $data{mindate4}, Max: $data{maxdate4}, Last: $data{currdate4}&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Buttons im Diagramm===&lt;br /&gt;
Es gibt mehrere Buttons, mit denen sich die Anzeige des Diagramms verändern lässt. &amp;lt;code&amp;gt;&amp;lt;-&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;-&amp;gt;&amp;lt;/code&amp;gt; bewegen die Graphen nach links und rechts. &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt; zoomen die Anzeige. &amp;lt;code&amp;gt;legend&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;cursor&amp;lt;/code&amp;gt; schalten die zugehörigen Anzeigen ein und aus.&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===Einfaches Diagramm===&lt;br /&gt;
Das Beispiel zeigt ein einfaches Diagramm mit 4 unterschiedlich formatierten Graphen, Legende und Momentanwerten am Fadenkreuz-Cursor.&lt;br /&gt;
&lt;br /&gt;
[[File:Chart_tabletUI.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	data-logdevice=&#039;[&amp;quot;Log.Garden&amp;quot;,&amp;quot;Log.Garden&amp;quot;,&amp;quot;Log.Garden&amp;quot;,&amp;quot;Log.Predicted&amp;quot;]&#039;&lt;br /&gt;
	data-columnspec=&#039;[&amp;quot;4:Garden.T:15:&amp;quot;,&amp;quot;10:Garden.T:0:delta-h&amp;quot;,&amp;quot;10:Garden.T:0:delta-d&amp;quot;,&amp;quot;4:predicted.*:15:&amp;quot;]&#039;&lt;br /&gt;
	data-style=&#039;[&amp;quot;ftui l0fill&amp;quot;,&amp;quot;ftui l1fill&amp;quot;,&amp;quot;ftui l2&amp;quot;,&amp;quot;ftui l3dot&amp;quot;]&#039;&lt;br /&gt;
	data-ptype=&#039;[&amp;quot;lines&amp;quot;,&amp;quot;histeps&amp;quot;,&amp;quot;histeps&amp;quot;,&amp;quot;cubic&amp;quot;]&#039;&lt;br /&gt;
	data-uaxis=&#039;[&amp;quot;primary&amp;quot;,&amp;quot;secondary&amp;quot;,&amp;quot;secondary&amp;quot;,&amp;quot;primary&amp;quot;]&#039;&lt;br /&gt;
	data-legend=&#039;[&amp;quot;Temperature&amp;quot;,&amp;quot;Rain/hour&amp;quot;,&amp;quot;Rain/day&amp;quot;,&amp;quot;Predicted Temp.&amp;quot;]&#039;&lt;br /&gt;
	data-yunit=&amp;quot;°C&amp;quot;&lt;br /&gt;
	data-ytext=&amp;quot;Temperature&amp;quot;&lt;br /&gt;
	data-minvalue=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-maxvalue=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-yunit_sec=&amp;quot;mm&amp;quot;&lt;br /&gt;
	data-ytext_sec=&amp;quot;Rain (mm)&amp;quot;&lt;br /&gt;
	data-height=&amp;quot;250&amp;quot;&lt;br /&gt;
	data-yticks=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-minvalue_sec=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-maxvalue_sec=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-nofulldays=&amp;quot;true&amp;quot;&lt;br /&gt;
	data-daysago_start=&amp;quot;2013-08-13T00:00:00&amp;quot;&lt;br /&gt;
	data-daysago_end=&amp;quot;2013-08-14T00:00:00&amp;quot;&lt;br /&gt;
	data-cursorgroup=&amp;quot;1&amp;quot;&lt;br /&gt;
	data-scrollgroup=&amp;quot;1&amp;quot;&lt;br /&gt;
	data-xticks=&amp;quot;auto&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Thermostat&amp;diff=19858</id>
		<title>FTUI Widget Thermostat</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Thermostat&amp;diff=19858"/>
		<updated>2017-02-13T20:49:56Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Formulierung&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Thermostat Widget]] ist ein Widget für [[FHEM Tablet UI]] welches ähnlich wie das [[FTUI Widget Knob|Knob-Widget]] ist, aber für Heizungsthermostate optimiert wurde. Es zeigt eine Skala, um die gewünschte Temperatur einzustellen, sowie die aktuelle Temperatur an.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:FTUI_Widget_Thermostat_01.png&lt;br /&gt;
File:FTUI_Widget_Thermostat_02.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
Für das Thermostat-Widget gelten dieselben Attribute, wie für das [[FTUI Widget Knob|Knob-Widget]]. Und zusätzlich noch die folgenden:&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get&#039;&#039;&#039;||Name des Readings, welches die gewünschte Temperatur enthält||desired-temp||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set&#039;&#039;&#039;||Name des Readings, mit dem die gewünschte Temperatur gesetzt wird||desired-temp||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-temp&#039;&#039;&#039;||Name des Readings, welches die aktuelle Temperatur enthält||measured-temp||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-valve&#039;&#039;&#039;||Name des Readings, das die Ventilstellung des Thermostates anzeigt||||data-valve=&amp;quot;ValvePosition&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-value&#039;&#039;&#039;||[[Regulärer Ausdruck|RegEx]] oder Stelle der Ventilposition in einer leerstellen-getrennten Zeile||-1 -&amp;gt; alles anzeigen||data-get-value=&amp;quot;2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-mode&#039;&#039;&#039;||Name des Readings für die Modi (auto, manual, etc.) des Thermostates||||data-mode=&amp;quot;controlMode&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-min&#039;&#039;&#039;||Mindesttemperatur, die gesetzt werden kann||10||data-min=&amp;quot;5&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-max&#039;&#039;&#039;||Höchsttemperatur, die gesetzt werden kann||30||data-max=&amp;quot;25&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-step&#039;&#039;&#039;||Abstufung, in der die Temperatur gesetzt werden kann||1||data-step=&amp;quot;0.5&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-off&#039;&#039;&#039;||Wert, der gesendet werden muss, um das Thermostat abzuschalten||||data-off=&amp;quot;5&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-boost&#039;&#039;&#039;||Wert, der gesendet werden muss, um das Thermostat in den Boost-Modus zu bringen||||data-boost=&amp;quot;30.5&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-height&#039;&#039;&#039;||Höhe des Widgets||100||data-height=&amp;quot;80&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-width&#039;&#039;&#039;||Breite des Widgets||100||data-width=&amp;quot;120&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-touch-height&#039;&#039;&#039;||Höhe des Widgets während Änderungen||data-height||data-touch-height=&amp;quot;200&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-touch-width&#039;&#039;&#039;||Breite des Widgets während Änderungen||data-width||data-touch-width=&amp;quot;200&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-touch-position&#039;&#039;&#039;||Position des Wertes während Änderungen||left||data-touch-position=&amp;quot;left&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
* Wenn beim MAX! Wand-Thermostat der Wert &#039;&#039;auto&#039;&#039; für &#039;&#039;data-mode&#039;&#039; empfangen wird, wird folgender Befehl generiert: &amp;lt;code&amp;gt;set wz_WandThermostat desiredTemperature auto&amp;lt;/code&amp;gt;. Andere Werte erzeugen Befehle wie &amp;lt;code&amp;gt;set wz_WandThermostat desiredTemperature&amp;lt;/code&amp;gt;&lt;br /&gt;
* Als &#039;&#039;data-device&#039;&#039; muss das Device angegeben werden, welches gewünschte und aktuelle Temperatur liefert. Bei HomeMatic Thermostaten ist das z.B. HM_XXXXXX_Clima&lt;br /&gt;
* Das Widget zeigt die Ventilposition nur an, wenn &#039;&#039;data-valve&#039;&#039; explizit definiert wurde.&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|mini}}{{FTUI Klasse|small}}{{FTUI Klasse|big}}{{FTUI Klasse|bigger}}{{FTUI Klasse|readonly}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===HomeMatic HM-CC-RT-DN===&lt;br /&gt;
Da die Standardwerte für &#039;&#039;data-get&#039;&#039;, &#039;&#039;data-temp&#039;&#039; und &#039;&#039;data-set&#039;&#039; schon den benötigten Werten für ein [[HM-CC-RT-DN Funk-Heizkörperthermostat]] entsprechen, reicht eine ganz einfache Code-Zeile.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;thermostat&amp;quot; data-device=&amp;quot;HM_302111_Clima&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das entspricht in diesem Fall der längeren Version:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;thermostat&amp;quot; &lt;br /&gt;
     data-device=&amp;quot;HM_302111_Clima&amp;quot; &lt;br /&gt;
     data-get=&amp;quot;desired-temp&amp;quot; &lt;br /&gt;
     data-temp=&amp;quot;measured-temp&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Thermostat_01.png]]&lt;br /&gt;
&lt;br /&gt;
===MAX! Thermostat===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;thermostat&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;HZ_Tuer&amp;quot; &lt;br /&gt;
     data-valve=&amp;quot;valveposition&amp;quot; &lt;br /&gt;
     data-get=&amp;quot;desiredTemperature&amp;quot; &lt;br /&gt;
     data-temp=&amp;quot;temperature&amp;quot; &lt;br /&gt;
     data-set=&amp;quot;desiredTemperature&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Thermostat_01.png]]&lt;br /&gt;
&lt;br /&gt;
===Mit Off- und Boost-Funktion===&lt;br /&gt;
Hier ein Beispiel, mit dem das Thermostat aus-, oder die Boost-Funktion eingeschaltet werden kann. Um Auszuschalten muss der Zeiger auf die Mindestposition gezogen werden. Um die Boost-Funktion zu aktivieren, auf die Maxmimalposition.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;thermostat&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;HM_302111_Clima&amp;quot;&lt;br /&gt;
     data-valve=&amp;quot;ValvePosition&amp;quot;&lt;br /&gt;
     data-min=&amp;quot;5&amp;quot;&lt;br /&gt;
     data-off=&amp;quot;off&amp;quot; &lt;br /&gt;
     data-max=&amp;quot;31&amp;quot;&lt;br /&gt;
     data-boost=&amp;quot;31&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Thermostat_02.png]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Push&amp;diff=19680</id>
		<title>FTUI Widget Push</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Push&amp;diff=19680"/>
		<updated>2017-02-10T21:36:44Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Push Widget]] ist ein Widget für [[FHEM Tablet UI]] in Form eines Button-förmigen Knopfes, der, ähnlich einem Taster, einen einfachen Befehl an FHEM sendet (zum Beispiel hoch/runter, Play/Pause, Nächster/vorheriger Titel, usw.). Der Befehl kann beim Drücken, beim Loslassen, oder beide male ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Ftui_widget_push.PNG&lt;br /&gt;
File:Push1.png&lt;br /&gt;
File:Push2.png&lt;br /&gt;
File:Ftui_widget_push_on-for-timer.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Steuer-Attribute==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-device&#039;&#039;&#039;||FHEM-Device, dessen Reading gesetzt werden soll (&amp;lt;command&amp;gt; &#039;&#039;&#039;&amp;lt;device&amp;gt;&#039;&#039;&#039; &amp;lt;reading&amp;gt; &amp;lt;value&amp;gt;)||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set&#039;&#039;&#039;||Reading, das gesetzt werden soll (&amp;lt;command&amp;gt; &amp;lt;device&amp;gt; &#039;&#039;&#039;&amp;lt;reading&amp;gt;&#039;&#039;&#039; &amp;lt;value&amp;gt;)||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-on&#039;&#039;&#039;||Wert, der beim Drücken gesendet werden soll. Kann auch ein Array sein, um verschiedene Werte abwechselnd zu schalten||on||data-set-on=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-off&#039;&#039;&#039;||Wert, der nach dem Loslassen gesendet werden soll||||data-set-off=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-cmd&#039;&#039;&#039;||Befehl, der gesendet werden soll (&#039;&#039;&#039;&amp;lt;command&amp;gt;&#039;&#039;&#039; &amp;lt;device&amp;gt; &amp;lt;reading&amp;gt; &amp;lt;value&amp;gt;) (z.B. setstate, set, setreading, trigger)||set||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-doubleclick&#039;&#039;&#039;||Zeit, die vergehen muss, bis das Element ein zweites mal betätigt werden kann. &#039;0&#039; schaltet dieses Verhalten ab.||0||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-countdown&#039;&#039;&#039;||Sekunden für Fortschrittsanzeige (progress control / &#039;on-for-timer&#039;)||Automatische Erkennung von &#039;on-for-timer&#039; bei &#039;&#039;&#039;data-set-on&#039;&#039;&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-warn&#039;&#039;&#039;||Reading, dessen Inhalt als rotes Kennzeichen angezeigt wird. Der Inhalt des Readings muss eine Ganzzahl (Integer) sein.||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get&#039;&#039;&#039;||Reading, dessen Inhalt zur Zustandsanzeige (ON/OFF) wird||keiner (muss explizit angegeben werden)||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-on&#039;&#039;&#039;||Zeichenkette, die als Zustand ON interpretiert wird||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-off&#039;&#039;&#039;||Zeichenkette, die als Zustand OFF interpretiert wird||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-hide&#039;&#039;&#039;||Reading zum Verstecken des Push-Elementes. Das Element verschwindet, wenn der Wert mit &#039;&#039;&#039;data-hide-on&#039;&#039;&#039; übereinstimmt.||&#039;STATE&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-hide-on&#039;&#039;&#039;||Zeichenkette, bei der das Element versteckt wird||&#039;true|1|on&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-hide-off&#039;&#039;&#039;||Zeichenkette, bei der das Element angezeigt wird||&#039;!on&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-hideparents&#039;&#039;&#039;||jQuery-Selector, um auch die Eltern-Elemente zu verstecken||||data-hideparents=&amp;quot;#Name&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-lock&#039;&#039;&#039;||Reading, mit dem das Element für eine Bedienung gesperrt wird. Gütige Werte sind &#039;true&#039;, &#039;1&#039; oder &#039;on&#039; ||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-reachable&#039;&#039;&#039;||Reading, dessen Inhalt angibt, ob das Device erreichbar ist, oder nicht. Der Inhalt des Readings muss eine Ganzzahl (Integer) sein.||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-icon&#039;&#039;&#039;||Name des Icons im Vordergrund||&#039;fa-power-off&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-background-icon&#039;&#039;&#039;||Name des Icons, das als Hintergrund verwendet werden soll||&#039;fa-circle&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-off-color&#039;&#039;&#039;||Feste Iconfarbe für den Zustand OFF, oder &#039;&#039;&#039;&amp;lt;device&amp;gt;:&amp;lt;reading&amp;gt;&#039;&#039;&#039;, um einen entsprechenden Wert dynamisch aus FHEM abzurufen.||&#039;#505050&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-off-background-color&#039;&#039;&#039;||Feste Hintergrundfarbe für den Zustand OFF, oder &#039;&#039;&#039;&amp;lt;device&amp;gt;:&amp;lt;reading&amp;gt;&#039;&#039;&#039;||&#039;#505050&#039;||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===Alle Lampen einschalten===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;push&amp;quot; &lt;br /&gt;
     data-device=&amp;quot;LightAll&amp;quot; &lt;br /&gt;
     data-cmd=&amp;quot;trigger&amp;quot; &lt;br /&gt;
     data-set-on=&amp;quot;on&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Steuerung hoch/runter (horizontal)===&lt;br /&gt;
[[File:Push1.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;doublebox-h&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;Rollo&amp;quot; &lt;br /&gt;
             data-icon=&amp;quot;fa-angle-up&amp;quot; data-background-icon=&amp;quot;fa-square-o&amp;quot; &lt;br /&gt;
             data-set-on=&amp;quot;up&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;Rollo&amp;quot; &lt;br /&gt;
             data-icon=&amp;quot;fa-angle-down&amp;quot; data-background-icon=&amp;quot;fa-square-o&amp;quot; &lt;br /&gt;
             data-set-on=&amp;quot;down&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Steuerung hoch/runter (vertikal)===&lt;br /&gt;
[[File:Push2.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;doublebox-v&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;Rollo&amp;quot; &lt;br /&gt;
             data-icon=&amp;quot;fa-chevron-up&amp;quot; data-background-icon=&amp;quot;fa-square-o&amp;quot; &lt;br /&gt;
             data-set-on=&amp;quot;up&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;Rollo&amp;quot; &lt;br /&gt;
            data-icon=&amp;quot;fa-chevron-down&amp;quot; data-background-icon=&amp;quot;fa-square-o&amp;quot; &lt;br /&gt;
            data-set-on=&amp;quot;down&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lampe für 5 Minuten einschalten===&lt;br /&gt;
Das Push-Widget zeigt einen einen abnehmenden Kreis, solange der Countdown läuft. Die Dauer wird automatisch aus dem &#039;&#039;&#039;on-for-timer&#039;&#039;&#039;-Befehel erkannt. Mit &#039;&#039;&#039;data-countdown&#039;&#039;&#039; kann jedoch auch auch ein eigener Wert angegeben werden.&lt;br /&gt;
&lt;br /&gt;
[[File:Ftui_widget_push_on-for-timer.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;MyLamp&amp;quot; data-set-on=&amp;quot;on-for-timer 300&amp;quot; &amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Push-Widget verstecken===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;hbox&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;div class=&amp;quot;vbox&amp;quot;&amp;gt;&lt;br /&gt;
		&amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;ftuitest&amp;quot; data-set-on=&amp;quot;1&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
		&amp;lt;div&amp;gt;on&amp;lt;/div&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
	&amp;lt;div class=&amp;quot;vbox&amp;quot;&amp;gt;&lt;br /&gt;
		&amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;ftuitest&amp;quot; data-set-on=&amp;quot;0&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
		&amp;lt;div&amp;gt;off&amp;lt;/div&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
	&amp;lt;div class=&amp;quot;vbox&amp;quot;&amp;gt;&lt;br /&gt;
		&amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;dummy1&amp;quot; data-get=&amp;quot;STATE&amp;quot; data-get-on=&amp;quot;on&amp;quot; data-hide=&amp;quot;ftuitest:STATE&amp;quot; data-hide-on=&amp;quot;1&amp;quot; class=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Weather&amp;diff=19651</id>
		<title>FTUI Widget Weather</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Weather&amp;diff=19651"/>
		<updated>2017-02-10T05:59:44Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Verweis auf FTUI ergänzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Todo|V1.0, Bitte prüfen}}&lt;br /&gt;
&lt;br /&gt;
Das [[{{PAGENAME}}|Widget Weather]] ist ein Widget für [[FHEM Tablet UI]], das Bezeichnungen von Wetterlagen in Icons umwandelt. Die Daten können durch FHEM-Module wie [[PROPLANTA]], [[OPENWEATHER]] und [[Weather]] bereitgestellt werden. Icon-Sets [http://www.alessioatzeni.com/meteocons/ meteocons] und [https://kleinklima.de/ kleinklima] werden mit FHEM geliefert.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:FTUI_Widget_Weather_01.png&lt;br /&gt;
File:FTUI_Widget_Weather_02.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-device&#039;&#039;&#039;||FHEM-Device, welches die Wetterdaten bereitstellt||||data-device=&amp;quot;Proplanta&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get&#039;&#039;&#039;||Reading, dessen Wettertext in ein Icon umgewandelt werden soll||||data-get=&amp;quot;fc0_weatherDay&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-imageset&#039;&#039;&#039;||Bildersammlung, mit der die Wetterlagen dargestellt werden. Derzeit: [http://http://www.alessioatzeni.com/meteocons/ meteocons] oder [https://kleinklima.de/ kleinklima]||[http://http://www.alessioatzeni.com/meteocons/ meteocons]||data-imageset=&amp;quot;kleinklima&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|mini}}{{FTUI Klasse|tiny}}{{FTUI Klasse|small}}{{FTUI Klasse|normal}}{{FTUI Klasse|large}}{{FTUI Klasse|big}}{{FTUI Klasse|bigger}}{{FTUI Klasse|tall}}{{FTUI Klasse|grande}}{{FTUI Klasse|gigantic}}{{FTUI Klasse|transparent}}{{FTUI Klasse|half-transparent}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
Die über die Devices verfügbaren umfangreichen Wetterdaten liefern eine wesentlich differenziertere Beschreibung der Wetterlage, als mit diesem Widget darstellbar ist. Sinnvoll ist deshalb eine Kombination des Weather-Widgets mit [[FTUI_Widget_Label]], ggf. auch wind_direction.&lt;br /&gt;
&lt;br /&gt;
Gelegentlich wird berichtet, dass einzelne Bilder nicht optimal auf die readings abgestimmt seien. In solchen Fällen bitte im Forum posten, damit die Zuordnungen verbessert werden können.&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===Einfaches Widget===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;weather&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc0_weatherDay&amp;quot; data-imageset=&amp;quot;meteocons&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc0_weatherDay&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc0_tempMin&amp;quot; data-unit=&amp;quot;%B0C%0A&amp;quot; class=&amp;quot;cell inline&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc0_tempMax&amp;quot; data-unit=&amp;quot;%B0C%0A&amp;quot; class=&amp;quot;cell inline&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:FTUI_Widget_Weather_03.png|100px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Komplexe Anwendung===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;4&amp;quot; data-sizey=&amp;quot;4&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;sheet&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;		&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-1-3&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell top-space narrow&amp;quot;&amp;gt;morgens&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;weather&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc0_weatherMorningIcon&amp;quot; data-imageset=&amp;quot;kleinklima&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc0_weatherMorning&amp;quot; class=&amp;quot;cell top-narrow&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc0_temp06&amp;quot; data-unit=&amp;quot;%B0C%0A&amp;quot; class=&amp;quot;cell bigger&amp;quot; data-limits=&#039;[-50,0]&#039; data-colors=&#039;[&amp;quot;#5858FA&amp;quot;,&amp;quot;white&amp;quot;]&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-1-3&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell top-space narrow&amp;quot;&amp;gt;mittags&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;weather&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc0_weatherDayIcon&amp;quot; data-imageset=&amp;quot;kleinklima&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc0_weatherDay&amp;quot; class=&amp;quot;cell top-narrow&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc0_temp12&amp;quot; data-unit=&amp;quot;%B0C%0A&amp;quot; class=&amp;quot;cell bigger&amp;quot; data-limits=&#039;[-50,0]&#039; data-colors=&#039;[&amp;quot;#5858FA&amp;quot;,&amp;quot;white&amp;quot;]&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-1-3&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell top-space narrow&amp;quot;&amp;gt;abends&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;weather&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc0_weatherEveningIcon&amp;quot; data-imageset=&amp;quot;kleinklima&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc0_weatherEvening&amp;quot; class=&amp;quot;cell top-narrow&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc0_temp18&amp;quot; data-unit=&amp;quot;%B0C%0A&amp;quot; class=&amp;quot;cell bigger&amp;quot; data-limits=&#039;[-50,0]&#039; data-colors=&#039;[&amp;quot;#5858FA&amp;quot;,&amp;quot;white&amp;quot;]&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;container top-space-3x&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell bigger darker&amp;quot;&amp;gt;Morgen&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sheet&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;		&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-1-3&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell top-space darker&amp;quot;&amp;gt;morgens&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;weather&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc1_weatherMorningIcon&amp;quot; data-imageset=&amp;quot;kleinklima&amp;quot; class=&amp;quot;cell half-transparent&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=”Proplanta&amp;quot; data-get=&amp;quot;fc1_weatherMorning&amp;quot; class=&amp;quot;cell top-narrow darker&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc1_temp06&amp;quot; data-unit=&amp;quot;%B0C%0A&amp;quot; class=&amp;quot;cell bigger&amp;quot; data-limits=&#039;[-50,0]&#039; data-colors=&#039;[&amp;quot;#a3a3fc&amp;quot;,&amp;quot;grey&amp;quot;]&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-1-3&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell top-space darker&amp;quot;&amp;gt;mittags&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;weather&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc1_weatherDayIcon&amp;quot; data-imageset=&amp;quot;kleinklima&amp;quot; class=&amp;quot;cell half-transparent&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc1_weatherDay&amp;quot; class=&amp;quot;cell top-narrow darker&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc1_temp12&amp;quot; data-unit=&amp;quot;%B0C%0A&amp;quot; class=&amp;quot;cell bigger&amp;quot; data-limits=&#039;[-50,0]&#039; data-colors=&#039;[&amp;quot;#a3a3fc&amp;quot;,&amp;quot;grey&amp;quot;]&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;col-1-3&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell top-space darker&amp;quot;&amp;gt;abends&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;weather&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc1_weatherEveningIcon&amp;quot; data-imageset=&amp;quot;kleinklima&amp;quot; class=&amp;quot;cell half-transparent&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc1_weatherEvening&amp;quot; class=&amp;quot;cell top-narrow darker&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;Proplanta&amp;quot; data-get=&amp;quot;fc1_temp18&amp;quot; data-unit=&amp;quot;%B0C%0A&amp;quot; class=&amp;quot;cell bigger&amp;quot; data-limits=&#039;[-50,0]&#039; data-colors=&#039;[&amp;quot;#a3a3fc&amp;quot;,&amp;quot;grey&amp;quot;]&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:FTUI_Widget_Weather_04.png|400px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEM_Tablet_UI&amp;diff=19583</id>
		<title>FHEM Tablet UI</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEM_Tablet_UI&amp;diff=19583"/>
		<updated>2017-02-08T20:18:23Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Schreibfehler korrigiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Oberfläche für FHEM&lt;br /&gt;
|ModType=x&lt;br /&gt;
|ModFTopic=34233&lt;br /&gt;
|ModForumArea=Frontends&lt;br /&gt;
|ModTechName=n.a.&lt;br /&gt;
|ModOwner=setstate ({{Link2FU|7023|Forum}})&lt;br /&gt;
}}&lt;br /&gt;
[[Datei:tablet_ui.png|200px|thumb|right|Fhem Tablet UI]]&lt;br /&gt;
FHEM Tablet UI ist ein leichtgewichtiges aber funktionsreiches Framework zum Steuern und Überwachen von in FHEM integrierten Geräten. Zahlreiche Widgets können sehr flexibel und leicht per HTML Code konfiguriert werden.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird die Installation und Konfiguration des FHEM Tablet UI beschrieben.&lt;br /&gt;
&lt;br /&gt;
{{Todo|alle Widgets hier übernehmen, Übersetzung, weitere Beispiele aus dem Forum einfügen (evtl. mit Link!?)}} &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
Das User Interface hat sehr wenige Anforderungen für den Betrieb. Es benötigt &amp;lt;u&amp;gt;keine&amp;lt;/u&amp;gt; zusätzliche Frameworks, wie z.B. PHP oder MySQL.&lt;br /&gt;
&lt;br /&gt;
Voraussetzung ist eine FHEM Installation mit HTTPSRV Modul. Das UI kann mit den gängigen Browsern Betriebssystem unabhängig genutzt werden oder mit dem Webviewcontrol.&lt;br /&gt;
Das Interface wird dabei in dem FHEM eigenen Webserver ausgeführt. Mit wenigen Anpassungen ist es auch möglich das UI auf anderen Webservern (Apache, u.a.) zu betreiben, dann kann FHEM und UI auch auf getrennten Systemen ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Im Befehls-Eingabefeld eingeben: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;update all https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Im Befehls-Eingabefeld eingeben: &amp;lt;code&amp;gt;define TABLETUI HTTPSRV ftui/ ./www/tablet Tablet-UI&amp;lt;/code&amp;gt;&lt;br /&gt;
* Im Verzeichnis ./fhem/www/tablet die Datei index-example.html in index.html umbenennen oder eine neue index.html erzeugen und diese index.html wie nachfolgend beschrieben editieren.&lt;br /&gt;
&lt;br /&gt;
Das UI ist über den Link &amp;quot;Tablet-UI&amp;quot; auf der FHEM-Hauptseite oder durch Direktaufruf der URL &amp;quot;&amp;lt;nowiki&amp;gt;http://&amp;lt;Fhem-url&amp;gt;:8083/fhem/tablet/index.html&amp;lt;/nowiki&amp;gt;&amp;quot; zu erreichen.&lt;br /&gt;
&lt;br /&gt;
Hinweise zu einer manuellen Installation und weitere Infos sind auf der Projektseite https://github.com/knowthelist/fhem-tablet-ui zu finden.&lt;br /&gt;
&lt;br /&gt;
== Update ==&lt;br /&gt;
* Prüfen der Änderungen seit dem letzten Download/Update durch Eingabe von: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;update check https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Update des UI durch Eingabe von: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;update all https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Über &lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;update add https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
kann seit dem 24.12.2015 die URL zum normalen Updatebefehl von FHEM hinzugefügt werden. Mit einen &amp;quot;update check&amp;quot; sieht man dann  gleich alle Updates aus beiden &amp;quot;Welten&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Konfiguration ==&lt;br /&gt;
&#039;&#039;&#039;META-Parameter&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Das Tablet UI lässt sich über die META-Parameter konfigurieren. Mit den meisten META-Parametern kann das verhalten des UI beeinflusst werden. Diese Parameter befinden sich in der jeweiligen &#039;&#039;&#039;.html&#039;&#039;&#039; Datei (z.B. index.html) im Abschnitt &#039;&#039;&#039;&amp;lt;head&amp;gt;&#039;&#039;&#039;. Nachfolgend sind die verschiedenen Konfigurationsparameter aufgeführt. Die Parameter sind immer gleich aufgebaut.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;meta name=&amp;quot;&amp;lt;META-Parameter&amp;gt;&amp;quot; content=&amp;quot;&amp;lt;Wert&amp;gt;&amp;quot;&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! META-Parameter                                !! Wert / Beispiel                       !! Erklärung&lt;br /&gt;
|-&lt;br /&gt;
| longpoll                     || 1 oder 0 || Refresh sofort, alle 15 Minuten ein voller Refresh (shortpoll) statt alle 30 Sekunden ein voller Refresh.&lt;br /&gt;
|-&lt;br /&gt;
| gridster_disable             || 1 oder 0 || Drag&amp;amp;Drop der Gridster-Elemente auf der Seite deaktivieren.&lt;br /&gt;
|-&lt;br /&gt;
| toast                        || 1 oder 0 || Toast messages deaktivieren&lt;br /&gt;
|-&lt;br /&gt;
| fhemweb_url       || http://meinFhemServer:8083/fhem || Wird benötigt wenn der Webserver des TabletUI nicht auf dem FHEM Server läuft.Default: &amp;quot;/fhem/&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| widget_margin                      || 1 bis 9999 || Abstände der Gridsterelemente verändern.&lt;br /&gt;
|-&lt;br /&gt;
| widget_base_width                      || 1 bis 9999 || Größe des Basis-Rasters (data-sizey=1/data-sizex=1) verändern.&lt;br /&gt;
|-&lt;br /&gt;
| widget_base_height                      || 1 bis 9999 || Größe des Basis-Rasters (data-sizey=1/data-sizex=1) verändern.&lt;br /&gt;
|-&lt;br /&gt;
| gridster_cols                      || 1 bis 9999 || Anzahl der Spalten.&lt;br /&gt;
|-&lt;br /&gt;
| gridster_rows                      || 1 bis 9999 || Anzahl der Reihen.&lt;br /&gt;
|-&lt;br /&gt;
| lang                      || de || Sprache der Visualisierung (derzeit nur DE vorhanden).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Layout&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Seit Version 2.5 werden die Gridster Kachel-Grössen, die Anzahl der Spalten und die Anzahl der Reihen dynamisch anhand der Bildschirmgrösse berechnet.&lt;br /&gt;
&lt;br /&gt;
Möchte man die Anzahl der Spalten und Reihen fest vorgeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;meta name=&amp;quot;gridster_cols&amp;quot; content=&amp;quot;12&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;meta name=&amp;quot;gridster_rows&amp;quot; content=&amp;quot;9&amp;quot;&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit folgendem Code kann man die Kachelgrössen fix definieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;meta name=&amp;quot;widget_base_width&amp;quot; content=&amp;quot;116&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;meta name=&amp;quot;widget_base_height&amp;quot; content=&amp;quot;131&amp;quot;&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;FHEM URL&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Werden die FTUI Seiten von einem anderen Server als FHEM-HTTPSRV bereitgestellt, muss man die URL, unter der FHEM angesprochen wird, anpassen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;meta name=&amp;quot;fhemweb_url&amp;quot; content=&amp;quot;/fhem/&amp;quot;&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CSS-Styles&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Das Layout und das Aussehen des UI kann durch diverse vorgegebene CSS-Klassen beeinflusst werden. Die verfügbaren Klassen sind im Abschnitt [[#CSS Class description|CSS Class description]] oder [[#Positioning|Positioning]] aufgeführt. Es besteht auch die Möglichkeit eine eigene CSS Datei zu erstellen und darüber Änderungen am Aussehen des UI vorzunehmen. Die eigene CSS Datei würde bei einem Update unverändert bleiben. Daher ist abzuraten eine CSS Datei, die mit dem UI Update verteilt wird zu modifizieren. Die eigene CSS Datei ist unter &#039;&#039;&#039;/fhem/tablet/css&#039;&#039;&#039; mit dem Namen &#039;&#039;&#039;fhem-tablet-ui-user.css&#039;&#039;&#039; zu finden. Sollte diese nicht vorhanden sein kann die Datei manuell erstellt werden.&lt;br /&gt;
Wird keine eigene CSS-Datei verwendet empfiehlt es sich den folgenden Eintrag im &amp;lt;head&amp;gt; der jeweiligen .html Datei zu entfernen, bzw. in Kommentar zu setzen um Probleme beim Laden der Seite zu verhindern.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/css/fhem-tablet-ui-user.css&amp;quot; /&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Farbe ==&lt;br /&gt;
Es besteht die Möglichkeit, die Farbwerte in hexadezimaler Form oder als RGB-Wert anzugeben. Zum Beispiel: Hex: #A3CFA3 RBG: rgb(163, 207, 163).&lt;br /&gt;
&lt;br /&gt;
Knallige Farben wie #ff0000 für Rot oder #00ff00 für Grün sollten vermieden werden. Es ist besser unterhalb von #D0 (208) für die Grundfarben zu bleiben.&lt;br /&gt;
&lt;br /&gt;
Hilfreich bei der Suche nach den Farbwerten ist der color picker: http://www.w3schools.com/tags/ref_colorpicker.asp oder diese Quelle: https://flatuicolors.com&lt;br /&gt;
&lt;br /&gt;
== CSS Klassen ==&lt;br /&gt;
&lt;br /&gt;
Nicht alle Widgets unterstützen alle hier angegebenen Klassen. Welche genau unterstützt werden, kann auf der jeweiligen Widget-Seite nachgelesen werden.&lt;br /&gt;
&lt;br /&gt;
===sheet/row/cell-Layout===&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
{{FTUI Klasse|sheet}}{{FTUI Klasse|row}}{{FTUI Klasse|cell}}{{FTUI Klasse|cell-1-x}}{{FTUI Klasse|cell-x}}{{FTUI Klasse|left-align}}{{FTUI Klasse|right-align}}{{FTUI Klasse|bottom-align}}{{FTUI Klasse|top-align}}{{FTUI Klasse|center-align}}&lt;br /&gt;
|}&lt;br /&gt;
===row/col-Layout===&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
{{FTUI Klasse|col}}{{FTUI Klasse|col-1-x}}{{FTUI Klasse|col-x}}&lt;br /&gt;
|}&lt;br /&gt;
===hbox/vbox-Layout===&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
{{FTUI Klasse|vbox}}{{FTUI Klasse|hbox}}{{FTUI Klasse|card}}{{FTUI Klasse|phone-width}}{{FTUI Klasse|full-height}}{{FTUI Klasse|full-width}}{{FTUI Klasse|grow-0}}{{FTUI Klasse|grow-1}}{{FTUI Klasse|grow-2}}{{FTUI Klasse|grow-x}}{{FTUI Klasse|items-top}}{{FTUI Klasse|items-center}}{{FTUI Klasse|items-bottom}}{{FTUI Klasse|items-space-between}}{{FTUI Klasse|items-space-around}}&lt;br /&gt;
|}&lt;br /&gt;
===Generelle Klassen für die Positionierung===&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
{{FTUI Klasse|inline}}{{FTUI Klasse|newline}}{{FTUI Klasse|top-space}}{{FTUI Klasse|top-space-2x}}{{FTUI Klasse|top-space-3x}}{{FTUI Klasse|left-space}}{{FTUI Klasse|left-space-2x}}{{FTUI Klasse|left-space-3x}}{{FTUI Klasse|right-space}}{{FTUI Klasse|right-space-2x}}{{FTUI Klasse|right-space-3x}}{{FTUI Klasse|top-narrow}}{{FTUI Klasse|top-narrow-2x}}{{FTUI Klasse|top-narrow-10}}{{FTUI Klasse|left-narrow}}{{FTUI Klasse|left-narrow-2x}}{{FTUI Klasse|left-narrow-3x}}{{FTUI Klasse|right-narrow}}{{FTUI Klasse|right-narrow-2x}}{{FTUI Klasse|right-narrow-3x}}{{FTUI Klasse|centered}}{{FTUI Klasse|wider}}{{FTUI Klasse|narrow}}{{FTUI Klasse|fullsize}}{{FTUI Klasse|compressed}}{{FTUI Klasse|w1x}}{{FTUI Klasse|w2x}}{{FTUI Klasse|w3x}}{{FTUI Klasse|maxw40}}{{FTUI Klasse|doublebox-v}}{{FTUI Klasse|doublebox-h}}{{FTUI Klasse|triplebox-v}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Vordergrundfarben===&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
{{FTUI Klasse|red}}{{FTUI Klasse|green}}{{FTUI Klasse|blue}}{{FTUI Klasse|lightblue}}{{FTUI Klasse|orange}}{{FTUI Klasse|gray}}{{FTUI Klasse|lightgray}}{{FTUI Klasse|white}}{{FTUI Klasse|black}}{{FTUI Klasse|mint}}{{FTUI Klasse|yellow}}&lt;br /&gt;
|}&lt;br /&gt;
===Hintergrundfarben===&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
{{FTUI Klasse|bg-red}}{{FTUI Klasse|bg-green}}{{FTUI Klasse|bg-blue}}{{FTUI Klasse|bg-lightblue}}{{FTUI Klasse|bg-orange}}{{FTUI Klasse|bg-gray}}{{FTUI Klasse|bg-lightgray}}{{FTUI Klasse|bg-white}}{{FTUI Klasse|bg-black}}{{FTUI Klasse|bg-mint}}{{FTUI Klasse|bg-yellow}}&lt;br /&gt;
|}&lt;br /&gt;
===Rahmen===&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
{{FTUI Klasse|verticalLine}}{{FTUI Klasse|border-black}}{{FTUI Klasse|border-white}}{{FTUI Klasse|border-orange}}{{FTUI Klasse|border-red}}{{FTUI Klasse|border-green}}{{FTUI Klasse|border-mint}}{{FTUI Klasse|border-lightblue}}{{FTUI Klasse|border-blue}}{{FTUI Klasse|border-gray}}{{FTUI Klasse|border-yellow}}{{FTUI Klasse|border-lightgray}}&lt;br /&gt;
|}&lt;br /&gt;
===Größen===&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
{{FTUI Klasse|mini}}{{FTUI Klasse|tiny}}{{FTUI Klasse|small}}{{FTUI Klasse|normal}}{{FTUI Klasse|large}}{{FTUI Klasse|big}}{{FTUI Klasse|bigger}}{{FTUI Klasse|tall}}{{FTUI Klasse|grande}}{{FTUI Klasse|gigantic}}&lt;br /&gt;
|}&lt;br /&gt;
===Schriftstil===&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
{{FTUI Klasse|thin}}{{FTUI Klasse|bold}}{{FTUI Klasse|darker}}{{FTUI Klasse|truncate}}&lt;br /&gt;
|}&lt;br /&gt;
===Sonstiges===&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
{{FTUI Klasse|blank}}{{FTUI Klasse|transparent}}{{FTUI Klasse|half-transparent}}{{FTUI Klasse|blurry}}{{FTUI Klasse|shake}}{{FTUI Klasse|fail-shake}}{{FTUI Klasse|marquee}}{{FTUI Klasse|round}}{{FTUI Klasse|square}}{{FTUI Klasse|readonly}}{{FTUI Klasse|blink}}{{FTUI Klasse|rotate-90}}{{FTUI Klasse|circleborder}}{{FTUI Klasse|autohide}}{{FTUI Klasse|notransmit}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Widgets ==&lt;br /&gt;
=== Integrierte Widgets ===&lt;br /&gt;
Folgende Widgets sind direkt in FHEM Tablet UI integriert und können &amp;quot;out of the box&amp;quot; verwendet werden.&lt;br /&gt;
&lt;br /&gt;
* [[FTUI Widget Agenda|agenda]]:&lt;br /&gt;
* [[FTUI Widget Button|button]]: Variante der push und switch Widgets, die entweder einen URL ansteuern oder einen FHEM-Befehl absetzen kann.&lt;br /&gt;
* [[FTUI Widget Calview|calview]]:&lt;br /&gt;
* [[#Chart|chart]]: chart with similar capabilities as the FHEM plots &lt;br /&gt;
* [[FTUI Widget Checkbox|checkbox]]:&lt;br /&gt;
* [[#Circlemenu|circlemenu]]: Mehrere Widgets hinter einem Widget verborgen, trotz des &#039;circle&#039; im Namen kann das Menue jetzt auch horizontal oder vertikal ausgeklappt werden &lt;br /&gt;
* [[FTUI Widget Classchanger|classchanger]]:&lt;br /&gt;
* [[FTUI Widget Clicksound|clicksound]]: Mit dem Widget &amp;quot;clicksound&amp;quot; können Sounds an Click-Events von Elementen gebunden werden. &lt;br /&gt;
* [[FTUI Widget Clock|clock]]: Stellt eine einfach Uhr zur Verfügung.&lt;br /&gt;
* [[FTUI Widget Colorwheel|colorwheel]]:&lt;br /&gt;
* [[FTUI Widget Datetimepicker|datetimepicker]]:&lt;br /&gt;
* [[#Departure|departure]]: show timetable of public transport provider&lt;br /&gt;
* [[#Dimmer|dimmer]]: toogle button with a setter for on value&lt;br /&gt;
* [[FTUI Widget Eventmonitor|eventmonitor]]:&lt;br /&gt;
* [[FTUI Widget Fullcalview|fullcalview]]:&lt;br /&gt;
* [[FTUI Widget Gds|gds]]:&lt;br /&gt;
* [[FTUI Widget Highchart|highchart]]:&lt;br /&gt;
* [[FTUI Widget Highchart3d|highchart3d]]:&lt;br /&gt;
* [[#Homestatus|homestatus]]: selector for 4 states (1=home, 2=night, 3=away, 4=holiday)&lt;br /&gt;
* [[FTUI Widget Html|html]]:&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/iframe iframe]: Widget zum Einbinden externer Inhalte in einem Iframe. &lt;br /&gt;
* [[#Image|image]]: insert an image, the URL is given by a reading&lt;br /&gt;
* [[FTUI Widget Input|input]]: Erstellen eines Texteingabefeldes&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/itunes_artwork itunes_artwork]: itunes_artwork durchsucht die iTunes-Datenbank anhand eines Arrays von beliebigen Suchworten nach einem Cover-Artwork und zeigt dieses an. &lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/javascript javascript]: Ermöglicht die Ausführung beliebigen Javascript-Codes aus einem Reading.&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/joinedlabel joinedlabel]: verbindet mehrere Readings zu einem Feld&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/klimatrend klimatrend]: wandelt Daten aus dem statistics-Modul in einen Pfeil um, der den aktuellen Trend anzeigt. &lt;br /&gt;
* [[FTUI Widget Knob|knob]]:&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/kodinowplaying kodinowplaying]: zeigt Informationen zu grade in KODI gespielten Medien in Form eines Labels an.&lt;br /&gt;
* [[#Label|label]]: Reading als Text anzeigen&lt;br /&gt;
* [[FTUI Widget Level|level]]: vertical/horizontal bar to show values between min/max value&lt;br /&gt;
* [[FTUI Widget Link|link]]: Erstellt einen Link oder Button zum Aufrufen von URLs oder Senden von Befehlen an FHEM&lt;br /&gt;
* [[FTUI Widget Loading|loading]]:&lt;br /&gt;
* [[FTUI Widget Medialist|medialist]]:&lt;br /&gt;
* [[FTUI Widget Meteogram|meteogram]]:&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/mpdnowplaying mpdnowplaying]: zeigt Titelinformationen eines per MPD-Modul angebundenen Music Player Daemon an. &lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/multistatebutton multistatebutton]: Variante des push-Widgets das den set-Befehl abhängig vom gelesenen Status ändert.&lt;br /&gt;
* [[FTUI Widget Notify|notify]]:&lt;br /&gt;
* [[FTUI Widget Pagebutton|pagebutton]]:&lt;br /&gt;
* [[#Pagetab|pagetab]]: Element to smoothly exchange the whole page with another page&lt;br /&gt;
* [[#Playstream|playstream]]: Abspielen eines Webradio-Streams per Button&lt;br /&gt;
* [[#Popup|popup]]: a popup dialog which open on click on another widget &lt;br /&gt;
* [[#Progress|progress]]: round symbolic display for percent values&lt;br /&gt;
* [[FTUI_Widget_Push|push]]: send any command to FHEM e.g. up / down&lt;br /&gt;
* [[FTUI Widget Range|range]]:&lt;br /&gt;
* [[FTUI Widget Readingsgroup|readingsgroup]]: Zeigt eine Readingsgroup an, wie sie in FHEM definiert wurde&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/reload reload]: auslösen eine Pagereloads&lt;br /&gt;
* [[#Rotor|rotor]]: Umschalten von zwei oder mehr Widgets an einer Position&lt;br /&gt;
* [[FTUI Widget Screensaver|screensaver]]:&lt;br /&gt;
* [[FTUI_Widget_Select|select]]: Combobox to provide a list for selection&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/settimer settimer]: zum anzeigen und einstellen einer Uhrzeit.&lt;br /&gt;
* [[#Simplechart|simplechart]]: simple XY line chart for one value (reads directly from FHEM log file)&lt;br /&gt;
* [[FTUI Widget Slideout|slideout]]:&lt;br /&gt;
* [[#Slider|slider]]: vertical slider to select between min/max value&lt;br /&gt;
* [[FTUI Widget Spinner|spinner]]:&lt;br /&gt;
* [[FTUI Widget Svgplot|svgplot]]:&lt;br /&gt;
* [[FTUI Widget Swiper|swiper]]:&lt;br /&gt;
* [[#Switch|switch]]: Toggle any command to FHEM (e.g. on / off)&lt;br /&gt;
* [[#Symbol|symbol]]: State als Symbol darstellen (z.B. Fenster offen)&lt;br /&gt;
* [[#Thermostat|thermostat]]: dial for heater thermostates to set desired value and show current value&lt;br /&gt;
* [[FTUI Widget Tts|tts]]:&lt;br /&gt;
* [[FTUI Widget Uwz|uwz]]:&lt;br /&gt;
* [[#Volume|volume]]: dial to set a single value (e.g. 0-60)&lt;br /&gt;
* [[FTUI Widget Wakeup|wakeup]]:&lt;br /&gt;
* [[FTUI Widget Wdtimer|wdtimer]]:&lt;br /&gt;
* [[#Weather|weather]]: insert an icon or image, represending a weather literal&lt;br /&gt;
* [[FTUI Widget Weekprofile|weekprofile]]:&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/wind_direction wind_direction]: Zeigt die Windrichtung auf einer Windrose an.&lt;br /&gt;
&lt;br /&gt;
===3rd Party Widgets===&lt;br /&gt;
* [https://github.com/svenson08/ftui-weekdaytimer-widget weekdaytimer]: Visualisierung des [[WeekdayTimer]] Modul&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
&lt;br /&gt;
Jedes Widget kann über verschiedene Attribute konfiguriert werden. Folgende Attribute gelten für alle Widgets:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+allgemeine Attribute&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-type&lt;br /&gt;
|Widget-Typ&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-device&lt;br /&gt;
|FHEM-Name des Gerätes (mit dem Befehl &#039;list&#039; bekommt man im FHEM die kpl. Liste)&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |class&lt;br /&gt;
|CSS-Klassen für Aussehen und Formatierung des Widgets&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Daten Empfangen&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get&lt;br /&gt;
|Reading Name&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-on&lt;br /&gt;
|Wert für den Status on&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-off&lt;br /&gt;
|Wert für den Status off&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Daten Senden&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set&lt;br /&gt;
|Reading Name&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set-on&lt;br /&gt;
|Wert für den Status on&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set-off&lt;br /&gt;
|Wert für den Status off&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Widget-spezifische Attribute können auf der jeweiligen Widget-Seite nachgelesen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Auflistung einiger Widgets==&lt;br /&gt;
===Chart===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-logdevice&lt;br /&gt;
|name of the logdevice (e.g. FileLog_WohnzimmerHeizung) or array of names if more than one graph shall be displayed&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-logfile&lt;br /&gt;
|name of the logfile (e.g. WohnzimmerHeizung-2015.log) or or array of names if more than one graph shall be displayed&lt;br /&gt;
|&#039;-&#039; or omitting this data means current logfile&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-columnspec&lt;br /&gt;
|definition for how to find the values (e.g. &amp;quot;4:meas.*:1:int&amp;quot;) or or array of columnspecs if more than one graph shall be displayed&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-style&lt;br /&gt;
|name of the graph style to be used (e.g. &#039;SVGplot l0&#039; or &#039;ftui l0dash&#039;) or or array of styles if more than one graph shall be displayed using different stlyes. The standard fhem plot styles can be used furthermore there are some more predefined styles existing (details see css file). Own styles can be specified e.g. in the fhem-table-ui-user.css file.&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-ptype&lt;br /&gt;
|name of the plot type (e.g. &#039;lines&#039; or &#039;fa-cog&#039;) or or array of plottypes if more than one graph shall be displayed. All fhem plot styles are supported. Additionally it is possible to specify symbols (currently supported are font awesome (&#039;fa-...&#039;), open automation (&#039;oa-...&#039;) and fhem symbols (&#039;fs-...&#039;)). Can also be something like &#039;icon:1&#039; in which case the respective columnspec should result in links to icons (e.g. for weather forecast) and the y-value is taken from the graph number 1 &lt;br /&gt;
|&#039;lines&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-uaxis&lt;br /&gt;
|name of the axis to be used (&#039;primary&#039; or &#039;secondary&#039;) or or array of axis&#039; to be used if more than one graph shall be displayed. The &#039;primary&#039; axis is labelled on the left side, the &#039;secondary&#039; axis is labelled on the right side&lt;br /&gt;
|&#039;primary&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-legend&lt;br /&gt;
|caption of the graph (used in the legend and at the cursor) or an array of legend texts if more than one graph shall be displayed.&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-minvalue&lt;br /&gt;
|min Y value to Show or an array of values for dynamic minY for primary axis. A value of &#039;auto&#039; means that the value is calculated from the data displayed dynamically&lt;br /&gt;
|10&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-minvalue_sec&lt;br /&gt;
|min Y value to Show or an array of values for dynamic minY for secondary axis. A value of &#039;auto&#039; means that the value is calculated from the data displayed dynamically&lt;br /&gt;
|&#039;auto&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-maxvalue&lt;br /&gt;
|max Y value to Show or an array of values for dynamic maxY for primary axis. A value of &#039;auto&#039; means that the value is calculated from the data displayed dynamically&lt;br /&gt;
|30&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-maxvalue_sec&lt;br /&gt;
|max Y value to Show or an array of values for dynamic maxY for secondary axis. A value of &#039;auto&#039; means that the value is calculated from the data displayed dynamically&lt;br /&gt;
|&#039;auto&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-yticks&lt;br /&gt;
|value distance between Y tick lines (related to primary axis). A value of &#039;auto&#039; means that the value is calculated from the data displayed dynamically. Can be an array containing value pairs in order to have arbitrary text for given values (e.g. data-yticks=&#039;[[0,&amp;quot;open&amp;quot;],[1,&amp;quot;closed&amp;quot;]]&#039;)&lt;br /&gt;
|&#039;auto&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-yticks_sec&lt;br /&gt;
|value distance between Y tick lines (related to secondary axis). A value of &#039;auto&#039; means that the value is calculated from the data displayed dynamically.Can be an array containing value pairs in order to have arbitrary text for given values (e.g. data-yticks_sec=&#039;[[0,&amp;quot;open&amp;quot;],[1,&amp;quot;closed&amp;quot;]]&#039;)&lt;br /&gt;
|&#039;auto&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-xticks&lt;br /&gt;
|time range between each X tick lines (in minutes). A value of &#039;auto&#039; means that the value is calculated from the data displayed dynamically&lt;br /&gt;
|&#039;auto&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-daysago_start&lt;br /&gt;
|number of days back from now for the start of the plot (0 means the plot starts from today 0:00). Additionally the x-axis start value can be set here unsing standard data formats like (&#039;2013-10-23&#039;), the time portion of the string is only used when &amp;lt;code&amp;gt;data-nofulldays&amp;lt;/code&amp;gt; is &#039;true&#039;. If the setting ends with &#039;w&#039;, &#039;W&#039;, &#039;m&#039;, &#039;M&#039;, &#039;y&#039;, &#039;Y&#039; the nuber given is interpreted as week, month or year respectively (capital letters mean rounding to full weeks, months years) (e.g. &#039;2Y&#039; means that, if current date is 3.6.2015, the graph will start 1.1.2013).&lt;br /&gt;
|0&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-daysago_end&lt;br /&gt;
|number of days back from now for the end of the plot (-1 means the plot ends today 24:00). Additionally the x-axis end value can be set here unsing standard data formats like (&#039;2013-10-23&#039;), the time portion of the string is only used when &amp;lt;code&amp;gt;data-nofulldays&amp;lt;/code&amp;gt; is &#039;true&#039;. If the setting ends with &#039;w&#039;, &#039;W&#039;, &#039;m&#039;, &#039;M&#039;, &#039;y&#039;, &#039;Y&#039; the nuber given is interpreted as week, month or year respectively (capital letters mean rounding to full weeks, months years) (e.g. &#039;2Y&#039; means that, if current date is 3.6.2015, the graph will end 31.12.2013).&lt;br /&gt;
|-1&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-timeformat&lt;br /&gt;
|setting for the formatting of the x-tick text. The format can be configured in a quite flexible way. Several format classifiers are supported which are separated by special characters (&#039;-&#039;, &#039;.&#039;, &#039;/&#039;, &#039; &#039;, &#039;:&#039;, &#039;,&#039;, &#039;\&#039;). All characters despite &#039;\&#039; will be displayed in the final output.&lt;br /&gt;
The following is a list of supported classifiers:&lt;br /&gt;
* &#039;LF&#039;enters a linefeed&lt;br /&gt;
* &#039;mm&#039;  - displays minutes as 2 digits&lt;br /&gt;
* &#039;hh&#039;  - displays hours as 2 digits&lt;br /&gt;
* &#039;dd&#039;  - displays day of the month as 2 digits&lt;br /&gt;
* &#039;MM&#039;  - displays months as 2 digits (e.g. 02 for February)&lt;br /&gt;
* &#039;MMM&#039; - displays months as 3 characters (e.g. Dec for December)&lt;br /&gt;
* &#039;MMMM&#039; - displays monhts as full names (e.g. March)&lt;br /&gt;
* &#039;ee&#039;   - displays weekdays as 2 digits (e.g. 00 for Sunday)&lt;br /&gt;
* &#039;eee&#039;  - displays weekdays as 3 characters (e.g. Mon for Monday)&lt;br /&gt;
* &#039;eeee&#039; - displays weekdays as full names (e.g. Tuesday)&lt;br /&gt;
* &#039;yy&#039;   - displays years as 2 digits (e.g. 16 as 2016)&lt;br /&gt;
* &#039;yyyy&#039; - displays years as 4 digits&lt;br /&gt;
For example a string given as &#039;MMM\LF\yyyy&#039; will display &#039;Jan&#039; in one line and &#039;2016&#039; in a second one. A string given as &#039;MM.dd 2016&#039; will display &#039;03.05 2016&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-nofulldays&lt;br /&gt;
|switch to activate/deactivate rounding of the xaxis start and end values to full days (&#039;true&#039; or &#039;false&#039;)&lt;br /&gt;
|&#039;false&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-ytext&lt;br /&gt;
|text to be shown besides the primary y axis.&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-ytext_sec&lt;br /&gt;
|text to be shown besides the secondary y axis.&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-yunit&lt;br /&gt;
|unit of the value to show beside of each Y ticks for primary y axis.&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-crosshair&lt;br /&gt;
|switch to activate/deactivate the crosshair cursor (&#039;true&#039; or &#039;false&#039;)&lt;br /&gt;
|&#039;false&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-cursorgroup&lt;br /&gt;
|number to define coupling of the crosshair cursor. The cursors of all charts having the same number are coupled and move together.&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-scrollgroup&lt;br /&gt;
|number to define coupling of the scrolling (shift and zoom). All charts having the same number are scrolled (shifted and zoomed) together.&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-showlegend&lt;br /&gt;
|switch to activate/deactivate the initial display of the legend window (&#039;true&#039; or &#039;false&#039;)&lt;br /&gt;
|&#039;false&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-legendpos&lt;br /&gt;
|array of two values (horizontal and vertical) to set the initial position of the legend window. Allowed values are &amp;quot;left&amp;quot;, &amp;quot;right&amp;quot; or a number giving the position in percent for the first parameter (horizontal position) and &#039;top&#039;, &#039;bottom&#039; or a number giving the position in percent for the second parameter (vertical position). &lt;br /&gt;
|&#039;[&amp;quot;top&amp;quot;,&amp;quot;right&amp;quot;]&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-yunit_sec&lt;br /&gt;
|unit of the value to show beside of each Y ticks for secondary y axis.&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-width&lt;br /&gt;
|fixed size for width (in&amp;amp;nbsp;% or px)&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-height&lt;br /&gt;
|fixed size for height (in&amp;amp;nbsp;% or px)&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-graphsshown&lt;br /&gt;
|boolean to define if graphs are activated (shown) initially or an array of booleans if more than one graph shall be displayed.&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-ddd&lt;br /&gt;
|setting for 3D display. Array with 3 angles for rotation of the 3D chart in x, y, z (z not yet supported) (e.g. &#039;[&amp;quot;40&amp;quot;,&amp;quot;60&amp;quot;,&amp;quot;0&amp;quot;]&#039;). If the array is existing, there will be 2 additional buttons on top for changing rotation in x and y.&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-dddspace&lt;br /&gt;
|setting for the space between different graphs in y direction if 3D is activated (space given in pixels).&lt;br /&gt;
|15&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-dddwidth&lt;br /&gt;
|setting for the width of the graphs if 3D is activated (width given in pixels).&lt;br /&gt;
|10&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-title&lt;br /&gt;
|setting for inclusion of chart title on top of the chart. Includes the possibility for calculation of values like in SVG Plots (e.g. data-title=&amp;quot;Min: $data{mindate4}, Max: $data{maxdate4}, Last: $data{currdate4}&amp;quot;). Supported are:&lt;br /&gt;
* min1: minimum value of graph 1 (first graph in the given list). Number can be any graph or omitted if calculation shall be done over all graphs.&lt;br /&gt;
* max1: maximum value of graph 1 (first graph in the given list)&lt;br /&gt;
* avg1: average value of graph 1 (first graph in the given list)&lt;br /&gt;
* cnt1: number of values of graph 1 (first graph in the given list)&lt;br /&gt;
* currval1: last (current) value of graph 1 (first graph in the given list)&lt;br /&gt;
* mindate1: minimum x value of graph 1 (first graph in the given list)&lt;br /&gt;
* maxdate1: maximum x value of graph 1 (first graph in the given list)&lt;br /&gt;
* currdate1: last (current) x value of graph 1 (first graph in the given list)&lt;br /&gt;
|&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |class&lt;br /&gt;
|fullsize, noticks, nobuttons, small, normal, big&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;data-logfile&amp;lt;/code&amp;gt; can be omitted in this case the default value &amp;quot;-&amp;quot; will be used. This means that the current logfile is going to be used.&lt;br /&gt;
&lt;br /&gt;
There are several buttons that control the dynamic behaviour of the chart. The &amp;lt;-, -&amp;gt;, + and - buttons shift and zoom the displayed data. The &amp;quot;legend&amp;quot; and &amp;quot;cursor&amp;quot; buttons are switching on and off the display of the legend window and the crosshair cursor respectively. If 3D display is activated (see above) 2 more buttons control the rotation in x and y.&lt;br /&gt;
&lt;br /&gt;
When the legend window is displayed, a click on the legend text shows/hides the respective graph. The legend window can be dragged to other positions on desktop browsers (currently not yet working for iOS and Android).&lt;br /&gt;
&lt;br /&gt;
The crosshair cursor currently only works dynamically on desktop browsers. On iOS and Android you have to tap on the screen to set the cursor to a new position.&lt;br /&gt;
&lt;br /&gt;
Three classes define default values for the texts (small, normal, big). Additionally there is a number of css styles that control the visible appearance of the chart. The following classes are supported:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!CSS class name&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
!.chart-background&lt;br /&gt;
|Color etc. for the chart background&lt;br /&gt;
|-&lt;br /&gt;
!.text.axes&lt;br /&gt;
|Font and color for the chart axes&lt;br /&gt;
|-&lt;br /&gt;
!.buttons&lt;br /&gt;
|Size and color for the buttons (shift etc.)&lt;br /&gt;
|-&lt;br /&gt;
!.gridlines&lt;br /&gt;
|Size and color for gridlines generally&lt;br /&gt;
|-&lt;br /&gt;
!.xaxis&lt;br /&gt;
|Font, size and color for xaxis&lt;br /&gt;
|-&lt;br /&gt;
!.yaxis&lt;br /&gt;
|Font, size and color for yaxis&lt;br /&gt;
|-&lt;br /&gt;
!.xticks&lt;br /&gt;
|Font, size and color for xticks&lt;br /&gt;
|-&lt;br /&gt;
!.yticks&lt;br /&gt;
|Font, size and color for yticks&lt;br /&gt;
|-&lt;br /&gt;
!.crosshair&lt;br /&gt;
|Font, size and color (foreground/background) for the crosshair cursor&lt;br /&gt;
|-&lt;br /&gt;
!.caption&lt;br /&gt;
|Font, size and color for text buttons for legend and cursor switching&lt;br /&gt;
|-&lt;br /&gt;
!.legend&lt;br /&gt;
|Font, size and background color for legend window&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_chart|Link zu einem Beispiel]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Circlemenu===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-item-diameter&lt;br /&gt;
|diameter of the circle&lt;br /&gt;
|52&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-circle-radius&lt;br /&gt;
|radius of each item, in pixel&lt;br /&gt;
|70&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-direction&lt;br /&gt;
|position of the items in relation to the center&lt;br /&gt;
|&#039;full&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-close-after&lt;br /&gt;
|closing time of the circle-menu&lt;br /&gt;
|(item-count + 1s) or a minimum of 4s&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |class&lt;br /&gt;
|keepopen&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Optionen für data-direction: top | right | bottom | left | top-right | top-left | bottom-right | bottom-left | top-half | right-half | bottom-half | left-half | full | vertical | horizontal&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_circlemenu|Link zu einem Beispiel]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Departure===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-type&lt;br /&gt;
|widget-type; must be departure&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-device&lt;br /&gt;
|name of the device to get data from&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get&lt;br /&gt;
|name of the reading of device to get data from&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-icon&lt;br /&gt;
|define icon for widget&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-interval&lt;br /&gt;
|interval to reload automatically&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |class&lt;br /&gt;
|choose style of widget; see example&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_departure|Link zu einem Beispiel]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Dimmer===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get&lt;br /&gt;
|name of the reading to get from FHEM&lt;br /&gt;
|&#039;STATE&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-on&lt;br /&gt;
|value for ON status to get&lt;br /&gt;
|&#039;on&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-off&lt;br /&gt;
|value for OFF status to get&lt;br /&gt;
|&#039;off&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set&lt;br /&gt;
|(&amp;lt;command&amp;gt; &amp;lt;device&amp;gt; &amp;lt;reading&amp;gt; &amp;lt;value&amp;gt;) &lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set-on&lt;br /&gt;
|value for ON status to set&lt;br /&gt;
|value of data-get-on&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set-off&lt;br /&gt;
|value for OFF status to set&lt;br /&gt;
|value of data-get-off&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-cmd&lt;br /&gt;
|name of the command (&amp;lt;command&amp;gt; &amp;lt;device&amp;gt; &amp;lt;value&amp;gt;) (e.g. setstate, set, setreading, trigger)&lt;br /&gt;
|&#039;set&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-dim&lt;br /&gt;
|name of the reading responsible for dim (&amp;lt;command&amp;gt; &amp;lt;device&amp;gt; &amp;lt;reading&amp;gt; &amp;lt;value&amp;gt;) &lt;br /&gt;
|value of data-get-on&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-icon&lt;br /&gt;
|name of the font-awesome icon&lt;br /&gt;
|fa-lightbulb-o&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_dimmer|Link zu einem Beispiel]]&lt;br /&gt;
&lt;br /&gt;
===Homestatus===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get&lt;br /&gt;
|name of the reading to get from FHEM&lt;br /&gt;
|&#039;STATE&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set&lt;br /&gt;
|command to send to FHEM (&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; &amp;lt;command&amp;gt; &amp;lt;value&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
|&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-on&lt;br /&gt;
|array of states using for get&lt;br /&gt;
|[&#039;1&#039;,&#039;2&#039;,&#039;3&#039;,&#039;4&#039;]&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set-on&lt;br /&gt;
|array of states using for set.&lt;br /&gt;
|value of data-get-on&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-alias&lt;br /&gt;
|array of fix names to show only in the UI as an alias to the real states&lt;br /&gt;
|&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-icons&lt;br /&gt;
|array of icons related to the data-get-on array&lt;br /&gt;
|&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-version&lt;br /&gt;
|name of the status model e.g. &#039;residents&#039;,&#039;roommate&#039;,&#039;guest&#039; &lt;br /&gt;
|(default NULL)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The default version has 4 states: &#039;1&#039;,&#039;2&#039;,&#039;3&#039;,&#039;4&#039; The default aliases are &#039;Home&#039;,&#039;Night&#039;,&#039;Away&#039;,&#039;Holiday&#039;; data-version=&#039;residents&#039; or &#039;roommate&#039; or &#039;guest&#039; has 5 states (&#039;home&#039;,&#039;asleep&#039;,&#039;absent&#039;,&#039;gone&#039;,&#039;gotosleep&#039;) They have these aliases &#039;Home&#039;,&#039;Night&#039;,&#039;Away&#039;,&#039;Holiday&#039;,&#039;Retire&#039;&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_homestatus|Link zu einem Beispiel]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Image===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get&lt;br /&gt;
|name of the reading to get an URL from FHEM&lt;br /&gt;
|&#039;STATE&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-size&lt;br /&gt;
|width of the image in px or %, the height scales proportionally&lt;br /&gt;
|50%&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-url&lt;br /&gt;
|URL of the image to show (use data-url or data-device + data-get, not both)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-refresh&lt;br /&gt;
|Interval in seconds for image refresh for usage together with data-url&lt;br /&gt;
|900&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_image|Link zu einem Beispiel]]&lt;br /&gt;
&lt;br /&gt;
===Label===&lt;br /&gt;
&lt;br /&gt;
Mit dem LABEL Widget kann der STATUS eines Device in Textform angezeigt werden. Dabei kann das die Farbe des Anzeigetext abhängig von dessen Wert festgelegt werden. &lt;br /&gt;
&lt;br /&gt;
Neben den &#039;&#039;&#039;allgemeine Attribute&#039;&#039;&#039; besitzt das LABEL-Widget die nachfolgenden Attribute.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get           &lt;br /&gt;
|Name des Readings in FHEM &lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-fix           &lt;br /&gt;
|Eine bestimmte Anzahl an Dezimalstellen &lt;br /&gt;
|&#039;-1&#039; -&amp;gt; non-numeric &lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-part          &lt;br /&gt;
|split position of the space separated value to show or an RegEx &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-color         &lt;br /&gt;
| fix color attribute or DEVICE:READING for dynamic setting of label color &lt;br /&gt;
| &#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-colors        &lt;br /&gt;
|a array of color values to affect the colour of the label according to the limit value &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-limits-get    &lt;br /&gt;
|name of the DEVICE:Reading to colorize the label  &lt;br /&gt;
|data-device:data-get &lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-limits        &lt;br /&gt;
|an array of numeric values to affect the colour of the Label &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-limits-part   &lt;br /&gt;
|part number of the space separated value to show or a RegEx &lt;br /&gt;
|&#039;-1&#039; -&amp;gt; all &lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-unit          &lt;br /&gt;
|add a unit after a numeric value. use encoded strings e.g. &amp;quot;%B0C%0A&amp;quot; &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-substitution  &lt;br /&gt;
|regex-substitution to apply on the value. Standard regex notation (s/regex/subst/modifier) is expected &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-hide          &lt;br /&gt;
|string to compare with current value. hide element when it&#039;s value equals data-hide &lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-hideparents   &lt;br /&gt;
|jquery selector to hide element&#039;s parents too &lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |class              &lt;br /&gt;
|small, large, big, bigger, thin, red, green, blue, darker, timestamp, w1x, w2x, w3x, fixedlabel, icon, bg-limit &lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Mit der Class &#039;fixedlabel&#039; kann man Label einbauen, die einen festen Text (direkt im HTML) haben, aber trotzdem die Farbe per Reading Value beeinflusst werden könnte.&amp;lt;br&amp;gt;&lt;br /&gt;
Mit der Class &#039;icon&#039; kann man Label einbauen, die wie Icons aussehen. Als Hintergrund gibt es &#039;icon round&#039; (rund), &#039;icon square&#039; (Rechteck mit abgerundeten Ecken) und &#039;icon squareborder&#039; (Rechteck mit abgerundeten Ecken und einem zusätzlichen Rand).&amp;lt;br&amp;gt;&lt;br /&gt;
Mit der Class &#039;bg-limit&#039; wird der Hintergrund des Icon auf grün oder rot gesetzt, passend zum on/off Status des data-limits.&lt;br /&gt;
Use data-color OR data-colors + data-limits, not both.&lt;br /&gt;
&lt;br /&gt;
With class=&amp;quot;bg-limit&amp;quot; it changes the background color not the forecolor according data-limits&lt;br /&gt;
&lt;br /&gt;
class=&amp;quot;icon square&amp;quot; or class=&amp;quot;icon round&amp;quot; forces the label to a fix width and height in icon style&lt;br /&gt;
&lt;br /&gt;
Special layout can be achieved by overwriting of following classes in the fhem-tablet-ui-user.css:&lt;br /&gt;
&lt;br /&gt;
.label-precomma .label-comma .label-aftercomma .label-unit&lt;br /&gt;
&lt;br /&gt;
e.g.: .label-aftercomma{ font-size:40%; left: 4px; top: -25px; position: relative; }&lt;br /&gt;
&lt;br /&gt;
Functions for data-substitution:&lt;br /&gt;
&lt;br /&gt;
Array of replacements&lt;br /&gt;
RegEx-substitution to apply on the value. Standard regex notation (s/regex/subst/modifier) is expected&lt;br /&gt;
data-substitution=&amp;quot;weekdayshort&amp;quot;&lt;br /&gt;
JS functions data-substitution=&amp;quot;toDate().ddmm()&amp;quot; - convert to day:month&lt;br /&gt;
data-substitution=&amp;quot;toDate().hhmm()&amp;quot; - convert to hour:minutes&lt;br /&gt;
&lt;br /&gt;
data-substitution=&amp;quot;toDate().hhmmss()&amp;quot; - convert to hour:minutes:secondes&lt;br /&gt;
&lt;br /&gt;
data-substitution=&amp;quot;toDate().eeee()&amp;quot; - convert to name of the week day&lt;br /&gt;
&lt;br /&gt;
data-substitution=&amp;quot;toDate().ago()&amp;quot; - convert to time span&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_label|Link zu einem Beispiel]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pagetab===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-url&lt;br /&gt;
|URL of the new page to show&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-icon&lt;br /&gt;
|name of the font-awesome icon&lt;br /&gt;
|&#039;fa-power-off&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-background-icon&lt;br /&gt;
|name of the font-awesome icon for background &lt;br /&gt;
|&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-on-background-color&lt;br /&gt;
|color of ON state&lt;br /&gt;
|&#039;#aa6900&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-off-background-color&lt;br /&gt;
|color of OFF state&lt;br /&gt;
|&#039;#505050&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-on-color&lt;br /&gt;
|color of ON state&lt;br /&gt;
|&#039;#aa6900&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-off-color&lt;br /&gt;
|color of Off state&lt;br /&gt;
|&#039;#505050&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-on&lt;br /&gt;
|array of status to assign a special icon-list from data-icons&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-icons&lt;br /&gt;
|array of icons related to the a data-get-on array&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |class&lt;br /&gt;
|warn, activate (as additionals for data-icons)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_pagetab|Link zu einem Beispiel]]&lt;br /&gt;
&lt;br /&gt;
===Playstream===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-url&lt;br /&gt;
|URL des Radio-Streams&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get&lt;br /&gt;
|name of the reading to get the control state from FHEM&lt;br /&gt;
|&#039;STATE&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-on&lt;br /&gt;
|value for PLAY status to get. &lt;br /&gt;
|&#039;on&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-off&lt;br /&gt;
|value for STOP status to get. &lt;br /&gt;
|&#039;off&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-volume&lt;br /&gt;
|name of the reading to get the volume value (0-100) &lt;br /&gt;
|volume&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_playstream|Link zu einem Beispiel]]&lt;br /&gt;
&lt;br /&gt;
===Popup===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get&lt;br /&gt;
|name of the reading where to get the alert value from&lt;br /&gt;
|&#039;STATE&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-on&lt;br /&gt;
|value which trigger to open the dialog&lt;br /&gt;
|&#039;on&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-off&lt;br /&gt;
|value which trigger to close the dialog &lt;br /&gt;
|&#039;off&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-width&lt;br /&gt;
|fixe size for width (in % or px)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-height&lt;br /&gt;
|fixe size for height (in % or px)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_popup|Link zu einem Beispiel]]&lt;br /&gt;
&lt;br /&gt;
===Progress===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get&lt;br /&gt;
|name of the reading to get from FHEM&lt;br /&gt;
|&#039;STATE&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-max&lt;br /&gt;
|maximal value to set or name of the reading which helds the max value&lt;br /&gt;
|100&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |class&lt;br /&gt;
|novalue, percent&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_progress|Link zu einem Beispiel]] (fehlt noch)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Rotor===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; | data-delay&lt;br /&gt;
|time in millisecondes to wait until next list item get shown&lt;br /&gt;
|3500&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |class&lt;br /&gt;
|fade, rotate&lt;br /&gt;
|&#039;&#039; &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
Ohne Angabe von class erfolgt keine Animation.&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_rotor|Link zu einem Beispiel]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Simplechart===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-logdevice&lt;br /&gt;
|name of the logdevice (e.g. FileLog_WohnzimmerHeizung)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-logfile&lt;br /&gt;
|name of the logfile (e.g. WohnzimmerHeizung-2015.log)&lt;br /&gt;
|&#039;-&#039; means current logfile&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-columnspec&lt;br /&gt;
|definition for how to find the values (e.g. &amp;quot;4:meas.*:1:int&amp;quot;)&lt;br /&gt;
|&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-minvalue&lt;br /&gt;
|min Y value to Show or an array of values for dynamic minY &lt;br /&gt;
|10&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-maxvalue&lt;br /&gt;
|max Y value to Show or an array of values for dynamic maxY &lt;br /&gt;
|30&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-yticks&lt;br /&gt;
|value distance between Y tick lines&lt;br /&gt;
|5&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-xticks&lt;br /&gt;
|time range between each X tick line (in Minuten)&lt;br /&gt;
|360 minutes&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-daysago&lt;br /&gt;
|number of days back from now &lt;br /&gt;
|0&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-caption&lt;br /&gt;
|name of the chart to show as text &lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-yunit&lt;br /&gt;
|unit of the value to show beside of each Y ticks&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-width&lt;br /&gt;
|fixe size for width (in % or px)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-height&lt;br /&gt;
|fixe size for height (in % or px)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |class&lt;br /&gt;
|fullsize, noticks&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|} &lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_simplechart|Link zu einem Beispiel]] (fehlt noch)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;data-logfile&amp;lt;/code&amp;gt; kann man auch weglassen, dann greift der Defaultwert &amp;quot;-&amp;quot;. Damit wird das neuste Logfile gelesen.&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
===Slider===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get&lt;br /&gt;
|name of the reading to get from FHEM&lt;br /&gt;
|&#039;STATE&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set&lt;br /&gt;
|command to send to FHEM (&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; &amp;lt;command&amp;gt; &amp;lt;value&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
|&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-cmd&lt;br /&gt;
|name of the command (&amp;lt;command&amp;gt; &amp;lt;device&amp;gt; &amp;lt;value&amp;gt;) (e.g. setstate, set, setreading, trigger)&lt;br /&gt;
|&#039;set&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-min&lt;br /&gt;
|minimal value to set&lt;br /&gt;
|0&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-max&lt;br /&gt;
|maximal value to set&lt;br /&gt;
|100&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-step&lt;br /&gt;
|step value&lt;br /&gt;
|1&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-on&lt;br /&gt;
|value where the slider moves to max&lt;br /&gt;
|&#039;on&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-off&lt;br /&gt;
|value where the slider moves to min&lt;br /&gt;
|&#039;off&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-value&lt;br /&gt;
|RegEx to retrieve the value or part number of the space separated input to get the value&lt;br /&gt;
|&#039;-1&#039;: all of the input&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set-value&lt;br /&gt;
|Format of the value to send to FHEM&lt;br /&gt;
|&#039;$v&#039;: the value only&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-width&lt;br /&gt;
|width for horizontal sliders&lt;br /&gt;
|&#039;120px&#039;, for mini &#039;60px&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-height&lt;br /&gt;
|height for vertical sliders &lt;br /&gt;
|&#039;120px&#039;, for mini &#039;60px&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-color&lt;br /&gt;
|color for quantity range&lt;br /&gt;
|&#039;#aa6900&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-background-color&lt;br /&gt;
|color for range bar&lt;br /&gt;
|#404040&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |class&lt;br /&gt;
|Aussehen/Ausrichtung&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Für class steht mini, horizontal und negated (0 liegt oben) zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_slider|Link zu einem Beispiel]]&lt;br /&gt;
&lt;br /&gt;
===Switch===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML-Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default-Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get&lt;br /&gt;
|Name des Reading, was gelesen werden soll&lt;br /&gt;
|&#039;STATE&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set&lt;br /&gt;
|Name des Reading, was gelesen werden soll&lt;br /&gt;
|&#039;STATE&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-cmd&lt;br /&gt;
|Kommando Name (&amp;lt;command&amp;gt; &amp;lt;device&amp;gt; &amp;lt;value&amp;gt;) &amp;lt;br /&amp;gt;(z.B setstate, set, setreading, trigger) &lt;br /&gt;
|&#039;set&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-doubleclick&lt;br /&gt;
|timeout to wait for x millisecondes click or touch. &#039;0&#039; disables the doubleclick feature.&lt;br /&gt;
|&#039;0&#039;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
Einstellung bei zwei Werten&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML-Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default-Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-on&lt;br /&gt;
|Wert, bei dem zum Status ON geschaltet werden soll. &lt;br /&gt;
|&#039;on&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-off&lt;br /&gt;
|Wert, bei dem zum Status OFF geschaltet werden soll. &lt;br /&gt;
|&#039;off&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set-on&lt;br /&gt;
|Wert, der zu FHEM gesendet werden soll, wenn das Widget auf ON geschaltet wurde  &lt;br /&gt;
|Wert von data-get-on&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set-off&lt;br /&gt;
|Wert, der zu FHEM gesendet werden soll, wenn das Widget auf OFF geschaltet wurde &lt;br /&gt;
|Wert von data-get-off&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-icon&lt;br /&gt;
|Name des Font-Awesome Icon. &lt;br /&gt;
|&#039;fa-lightbulb-o&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-background-icon&lt;br /&gt;
|Name des Font-Awesome Hintergrund Icon. &lt;br /&gt;
|&#039;fa-circle&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-on-background-color&lt;br /&gt;
|Hintergrundfarbe beim Status on oder DEVICE:Reading bei dynamischen Einstellungen&lt;br /&gt;
|&#039;#aa6900&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-off-background-color&lt;br /&gt;
|Hintergrundfarbe beim Status off oder DEVICE:Reading bei dynamischen Einstellungen&lt;br /&gt;
|&#039;#505050&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-on-color&lt;br /&gt;
|Widget Farbe beim Status ON &lt;br /&gt;
|&#039;#aa6900&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-off-color&lt;br /&gt;
|Widget Farbe beim Status OFF &lt;br /&gt;
|&#039;#505050&#039;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Einstellung bei mehreren Werten&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML-Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default-Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-states&lt;br /&gt;
|Array mit Status Angaben &lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set-states&lt;br /&gt;
|Array mit Status Angaben, die gesetzt werden sollen&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-icons&lt;br /&gt;
|Array Icons zum zuvor definierten Status&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-background-icons&lt;br /&gt;
|Array mit Hintergrund Icons zum zuvor definierten Status &lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-colors&lt;br /&gt;
|Array mit Farben zum zuvor definierten Status &lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-background-colors&lt;br /&gt;
|Array mit Hintergrund Farben zum zuvor definierten Status &lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |class : readonly&lt;br /&gt;
|Es wird nur der Status angezeigt und kann nicht geändert werden&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;data-get-on&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;data-get-off&amp;lt;/code&amp;gt; accept also RegEx values. e.g. data-get-on=&amp;quot;[0-9]{1,3}|on&amp;quot; means set switch on if STATE is a numeric value or &#039;on&#039;. data-get-off=&amp;quot;!on&amp;quot; means accept all but the data-get-on value (negation)&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_switch|Link zu einem Beispiel]]&lt;br /&gt;
&lt;br /&gt;
===Symbol===&lt;br /&gt;
&lt;br /&gt;
Mit dem SYMBOL Widget kann der STATUS eines Device dargestellt werden. Dabei kann das angezeigte Symbol und dessen Farbe bestimmt werden. Wie bei anderen Widgets kann das Symbol und die Farbe vom State abhängig konfiguriert werden. Das SYMBOL-Widget dient nur zur Anzeige eines STATUS, es besitzt kein Möglichkeit der Interaktion.&lt;br /&gt;
&lt;br /&gt;
Neben den &#039;&#039;&#039;allgemeine Attribute&#039;&#039;&#039; besitzt das SYMBOL-Widget die nachfolgenden Attribute.&lt;br /&gt;
&lt;br /&gt;
dual state notation&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! HTML Attribut !! Beschreibung !! Default Wert&lt;br /&gt;
|-&lt;br /&gt;
| data-get || Name des Reading, was gelesen werden soll || &#039;STATE&#039; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Einstellung bei zwei Werten&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML-Attribut !! Beschreibung !! Default-Wert&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-on&#039;&#039;&#039; ||Wert für on ||&#039;open&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-off&#039;&#039;&#039; ||Wert für off ||&#039;closed&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-warn&#039;&#039;&#039; ||?????? ||&#039;-1&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-icon&#039;&#039;&#039; ||Name des Symbols  ||&#039;ftui-window&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-background-icon&#039;&#039;&#039; ||Hintergrundsymbol ||&#039;&#039;&#039;leer&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-on-background-color&#039;&#039;&#039; ||Farbe für ON-Zustand. ||&#039;#aa6900&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-off-background-color&#039;&#039;&#039; ||Farbe für OFF-Zustand. ||&#039;#505050&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-on-color&#039;&#039;&#039; ||Farbe für ON-Zustand. ||&#039;#aa6900&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-off-color&#039;&#039;&#039; ||Farbe für OFF-Zustand. ||&#039;#505050&#039;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Einstellung bei mehreren Werten&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-states&lt;br /&gt;
|Array für states. &lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-icons&lt;br /&gt;
|Array mit Icons zu data-states Array&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-background-icons&lt;br /&gt;
|Array mit Icons zu data-states Array&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-colors&lt;br /&gt;
|Array mit Farben zu data-states aArray&lt;br /&gt;
|&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-background-colors&lt;br /&gt;
|Array mit Hintergrundfarben zu data-states array&lt;br /&gt;
|&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
data-get-on,data-get-off and data-states accept also RegEx values. The value for one icon can also contain an additional animatation CSS name, e.g. &amp;quot;fa-exclamation-triangle fa-blink&amp;quot; for a blinking Symbol&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_symbol|Link zu einem Beispiel]]&lt;br /&gt;
&lt;br /&gt;
===Thermostat===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get&lt;br /&gt;
|name of the reading to get from FHEM&lt;br /&gt;
|&#039;desired-temp&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-temp&lt;br /&gt;
|reading for measured temperature of thermostates&lt;br /&gt;
|&#039;measured-temp&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set&lt;br /&gt;
|command to send to FHEM (set &amp;lt;device&amp;gt; &amp;lt;command&amp;gt; &amp;lt;value&amp;gt;)&lt;br /&gt;
|&#039;desired-temp&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-valve&lt;br /&gt;
|reading for valve position of thermostates&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-min&lt;br /&gt;
|minimal value to set&lt;br /&gt;
| 10&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-max&lt;br /&gt;
|maximal value to set&lt;br /&gt;
| 30&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-minColor&lt;br /&gt;
|Farbe des Keises für Min&lt;br /&gt;
| #4477FF&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-maxColor&lt;br /&gt;
|Farbe des Kreises für Max, zwischen Min und Max wird linear interpoliert &lt;br /&gt;
| #FF0000&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-step&lt;br /&gt;
|step size for value adjustment e.g. 0.5 &lt;br /&gt;
|1&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-bgColor&lt;br /&gt;
|Die Farbe der Kreises zwischen den ticks&lt;br /&gt;
|&#039;transparent&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-fgColor&lt;br /&gt;
|Die Farbe der zahl im Kreismittelpunkt&lt;br /&gt;
|#bbbbbb&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-tkColor&lt;br /&gt;
|Die Farbe der ticks&lt;br /&gt;
|#696969&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-angleOffset&lt;br /&gt;
|Start der ticks im Kreis (in Winkelgraden, 0 = oben)&lt;br /&gt;
| -120&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-angleArc&lt;br /&gt;
|Bereich der ticks im Kreis (in Winkelgraden)&lt;br /&gt;
|240&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |class&lt;br /&gt;
|big, readonly&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_thermostat|Link zu einem Beispiel]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Volume===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get&lt;br /&gt;
|name of the reading to get from FHEM &lt;br /&gt;
|&#039;STATE&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set&lt;br /&gt;
|command to send to FHEM (set &amp;lt;device&amp;gt; &amp;lt;command&amp;gt; &amp;lt;value&amp;gt;)&lt;br /&gt;
|&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;rigth&amp;quot; |data-cmd&lt;br /&gt;
|name of the command (&amp;lt;command&amp;gt; &amp;lt;device&amp;gt; &amp;lt;value&amp;gt;) (e.g. setstate, set, setreading, trigger) &lt;br /&gt;
|&#039;set&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-min&lt;br /&gt;
|minimal value to set&lt;br /&gt;
|0&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-max&lt;br /&gt;
|maximal value to set&lt;br /&gt;
|70&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-value&lt;br /&gt;
|RegEx to retrieve the value or part number of the space separated input to get the value&lt;br /&gt;
|&#039;-1&#039;: all of the input&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set-value&lt;br /&gt;
|Format of the value to send to FHEM&lt;br /&gt;
|&#039;$v&#039;: the value only&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-tickstep&lt;br /&gt;
|distance between ticks&lt;br /&gt;
|4|20&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-unit&lt;br /&gt;
|add a unit after the desired value.&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |class&lt;br /&gt;
|mini, small, big, bigger, hue-tick, hue-front, hue-back, dim-tick ,dim-front, dim-back, readonly&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_volume|Link zu einem Beispiel]] (fehlt noch)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Weather===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!HTML Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Default Wert&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get&lt;br /&gt;
|name of the reading to get the weather literal from FHEM&lt;br /&gt;
|&#039;STATE&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-imageset&lt;br /&gt;
|collection of images to display current weather situation. Possible values: &#039;meteocons&#039;, &#039;kleinklima&#039;&lt;br /&gt;
|&#039;meteocons&#039;&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-image-path&lt;br /&gt;
|path to the images of the selected imageset&lt;br /&gt;
|/images/weather/&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[#Beispiel_weather|Link zu einem Beispiel]]&lt;br /&gt;
&lt;br /&gt;
== Widgets -- Beispiele ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;Beispiel_chart&amp;quot;&amp;gt;&#039;&#039;&#039;Chart&#039;&#039;&#039;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Display a chart with similar capabilities as the FHEM plots&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div    data-type=&amp;quot;chart&amp;quot;&lt;br /&gt;
	data-logdevice=&#039;[&amp;quot;Log.Garden&amp;quot;,&amp;quot;Log.Garden&amp;quot;,&amp;quot;Log.Garden&amp;quot;,&amp;quot;Log.Predicted&amp;quot;]&#039;&lt;br /&gt;
	data-columnspec=&#039;[&amp;quot;4:Garden.T:15:&amp;quot;,&amp;quot;10:Garden.T:0:delta-h&amp;quot;,&amp;quot;10:Garden.T:0:delta-d&amp;quot;,&amp;quot;4:predicted.*:15:&amp;quot;]&#039;&lt;br /&gt;
	data-style=&#039;[&amp;quot;ftui l0fill&amp;quot;,&amp;quot;ftui l1fill&amp;quot;,&amp;quot;ftui l2&amp;quot;,&amp;quot;ftui l3dot&amp;quot;]&#039;&lt;br /&gt;
	data-ptype=&#039;[&amp;quot;lines&amp;quot;,&amp;quot;histeps&amp;quot;,&amp;quot;histeps&amp;quot;,&amp;quot;cubic&amp;quot;]&#039;&lt;br /&gt;
	data-uaxis=&#039;[&amp;quot;primary&amp;quot;,&amp;quot;secondary&amp;quot;,&amp;quot;secondary&amp;quot;,&amp;quot;primary&amp;quot;]&#039;&lt;br /&gt;
	data-legend=&#039;[&amp;quot;Temperature&amp;quot;,&amp;quot;Rain/hour&amp;quot;,&amp;quot;Rain/day&amp;quot;,&amp;quot;Predicted Temp.&amp;quot;]&#039;&lt;br /&gt;
	data-yunit=&amp;quot;°C&amp;quot;&lt;br /&gt;
	data-ytext=&amp;quot;Temperature&amp;quot;&lt;br /&gt;
	data-minvalue=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-maxvalue=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-yunit_sec=&amp;quot;mm&amp;quot;&lt;br /&gt;
	data-ytext_sec=&amp;quot;Rain (mm)&amp;quot;&lt;br /&gt;
	data-height=&amp;quot;250&amp;quot;&lt;br /&gt;
	data-yticks=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-minvalue_sec=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-maxvalue_sec=&amp;quot;auto&amp;quot;&lt;br /&gt;
	data-nofulldays=&amp;quot;true&amp;quot;&lt;br /&gt;
	data-daysago_start=&amp;quot;2013-08-13T00:00:00&amp;quot;&lt;br /&gt;
	data-daysago_end=&amp;quot;2013-08-14T00:00:00&amp;quot;&lt;br /&gt;
	data-cursorgroup=&amp;quot;1&amp;quot;&lt;br /&gt;
	data-scrollgroup=&amp;quot;1&amp;quot;&lt;br /&gt;
	data-xticks=&amp;quot;auto&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:chart_tabletUI.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;Beispiel_circlemenu&amp;quot;&amp;gt;&#039;&#039;&#039;Circlemenu&#039;&#039;&#039;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cover a lot of other button behind one single button&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;circlemenu&amp;quot; class=&amp;quot;cell circlemenu&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;ul class=&amp;quot;menu&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;li&amp;gt;&amp;lt;div data-type=&amp;quot;push&amp;quot; data-icon=&amp;quot;fa-wrench&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
      &amp;lt;li&amp;gt;&amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;AvReceiver&amp;quot; &lt;br /&gt;
               data-set=&amp;quot;remoteControl subwoofer-temporary-level -6&amp;quot; &lt;br /&gt;
               data-icon=&amp;quot;&amp;quot;&amp;gt;-6&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
      &amp;lt;li&amp;gt;&amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;AvReceiver&amp;quot; &lt;br /&gt;
               data-set=&amp;quot;remoteControl subwoofer-temporary-level -2&amp;quot; &lt;br /&gt;
               data-icon=&amp;quot;&amp;quot;&amp;gt;-2&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
      &amp;lt;li&amp;gt;&amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;AvReceiver&amp;quot; &lt;br /&gt;
               data-set=&amp;quot;remoteControl subwoofer-temporary-level 0&amp;quot; &lt;br /&gt;
               data-icon=&amp;quot;&amp;quot;&amp;gt;0&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
      &amp;lt;li&amp;gt;&amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;AvReceiver&amp;quot; &lt;br /&gt;
               data-set=&amp;quot;remoteControl subwoofer-temporary-level +3&amp;quot; &lt;br /&gt;
               data-icon=&amp;quot;&amp;quot;&amp;gt;2&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
      &amp;lt;li&amp;gt;&amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;AvReceiver&amp;quot; &lt;br /&gt;
               data-set=&amp;quot;remoteControl subwoofer-temporary-level +9&amp;quot; &lt;br /&gt;
               data-icon=&amp;quot;&amp;quot;&amp;gt;9&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
      &amp;lt;li&amp;gt;&amp;lt;div data-type=&amp;quot;push&amp;quot; data-device=&amp;quot;AvReceiver&amp;quot; &lt;br /&gt;
               data-set=&amp;quot;remoteControl subwoofer-temporary-level +C&amp;quot; &lt;br /&gt;
               data-icon=&amp;quot;&amp;quot;&amp;gt;12&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;Woofer&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:circlemenu_tabletUI.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;Beispiel_departure&amp;quot;&amp;gt;&#039;&#039;&#039;Departure&#039;&#039;&#039;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Departure Widget Beispiel&lt;br /&gt;
&lt;br /&gt;
Minimalvariante&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
&amp;lt;div data-type=&amp;quot;departure&amp;quot;&lt;br /&gt;
	 data-device=&amp;quot;vvs&amp;quot;&lt;br /&gt;
	 data-get=&amp;quot;SSB-Zentrum&amp;quot;&lt;br /&gt;
	 data-icon=&amp;quot;fa-train&amp;quot;&lt;br /&gt;
	 data-interval=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionen für class&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class=&amp;quot;&amp;quot; : default Style (grau)&lt;br /&gt;
class=&amp;quot;DVB&amp;quot; anderer Style (gelb)&lt;br /&gt;
class=&amp;quot;VVO&amp;quot; : anderer Style (blau)&lt;br /&gt;
class=&amp;quot;alternate&amp;quot; : alternierender Hintergrund&lt;br /&gt;
class=&amp;quot;deptime&amp;quot; : Abfahrtszeit statt Minuten&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
weiteres Beispiel&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;departure&amp;quot;&lt;br /&gt;
	 data-device=&amp;quot;vvs&amp;quot;&lt;br /&gt;
	 data-get=&amp;quot;SSB-Zentrum&amp;quot;&lt;br /&gt;
	 data-icon=&amp;quot;fa-train&amp;quot;&lt;br /&gt;
	 data-interval=&amp;quot;0&amp;quot;&lt;br /&gt;
	 class=&amp;quot;DVB deptime alternate&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;Beispiel_dimmer&amp;quot;&amp;gt;&#039;&#039;&#039;Dimmer&#039;&#039;&#039;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dimmer Widget Beispiel für Philips Hue&lt;br /&gt;
&lt;br /&gt;
Minimalvariante&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot; data-device=&amp;quot;HUEDevice1&amp;quot;&lt;br /&gt;
        data-get-on=&amp;quot;!off&amp;quot; data-get-off=&amp;quot;off&amp;quot;&lt;br /&gt;
        data-set=&amp;quot;pct&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit Anzeige der Dimstufe&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot; data-device=&amp;quot;HUEDevice1&amp;quot;&lt;br /&gt;
       data-get=&amp;quot;onoff&amp;quot;&lt;br /&gt;
       data-get-on=&amp;quot;1&amp;quot; data-get-off=&amp;quot;0&amp;quot;&lt;br /&gt;
       data-set=&amp;quot;&amp;quot;&lt;br /&gt;
       data-set-on=&amp;quot;on&amp;quot; data-set-off=&amp;quot;off&amp;quot;&lt;br /&gt;
       data-dim=&amp;quot;pct&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dimmer Widget für MilightDevice&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;dimmer&amp;quot;&lt;br /&gt;
  data-device=&amp;quot;SonstWas&amp;quot;&lt;br /&gt;
  data-get=&amp;quot;brightness&amp;quot;&lt;br /&gt;
  data-get-off=&amp;quot;0&amp;quot;&lt;br /&gt;
  data-get-on=&amp;quot;[1-9][0-9]*&amp;quot;&lt;br /&gt;
  data-set-on=&amp;quot;on&amp;quot;&lt;br /&gt;
  data-set-off=&amp;quot;off&amp;quot;&lt;br /&gt;
  data-dim=&amp;quot;dim&amp;quot;&lt;br /&gt;
  data-min=&amp;quot;0&amp;quot;&lt;br /&gt;
  data-max=&amp;quot;100&amp;quot;&lt;br /&gt;
&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;Beispiel_homestatus&amp;quot;&amp;gt;&#039;&#039;&#039;Homestatus&#039;&#039;&#039;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiel rechts im Bild:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;homestatus&amp;quot; data-device=&#039;dummy1&#039;&lt;br /&gt;
       data-get-on=&#039;[&amp;quot;1&amp;quot;,&amp;quot;2&amp;quot;,&amp;quot;3&amp;quot;,&amp;quot;4&amp;quot;]&#039;&lt;br /&gt;
       data-alias=&#039;[&amp;quot;Home&amp;quot;,&amp;quot;Night&amp;quot;,&amp;quot;Away&amp;quot;,&amp;quot;Holiday&amp;quot;]&#039;&lt;br /&gt;
       data-icons=&#039;[&amp;quot;fa-home&amp;quot;,&amp;quot;fa-bed&amp;quot;,&amp;quot;fa-car&amp;quot;,&amp;quot;fa-suitcase&amp;quot;]&#039;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiel links im Bild:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;homestatus&amp;quot; data-device=&#039;dummy1&#039;&lt;br /&gt;
        data-get-on=&#039;[&amp;quot;home&amp;quot;,&amp;quot;asleep&amp;quot;,&amp;quot;absent&amp;quot;,&amp;quot;gone&amp;quot;,&amp;quot;gotosleep&amp;quot;]&#039;&lt;br /&gt;
        data-alias=&#039;[&amp;quot;Home&amp;quot;,&amp;quot;Night&amp;quot;,&amp;quot;Away&amp;quot;,&amp;quot;Holiday&amp;quot;,&amp;quot;Retire&amp;quot;]&#039;&lt;br /&gt;
        data-icons=&#039;[&amp;quot;fa-fire&amp;quot;,&amp;quot;fa-film&amp;quot;,&amp;quot;fa-plus&amp;quot;,&amp;quot;fa-car&amp;quot;,&amp;quot;fa-tint&amp;quot;]&#039;&lt;br /&gt;
        data-version=&#039;residents&#039;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:homestatus_tabletUI.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;Beispiel_image&amp;quot;&amp;gt;&#039;&#039;&#039;Image&#039;&#039;&#039;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Erzeugt ein Widget mit einem Bild aus dem www, das alle 5 Sekunden aktualisiert wird (hier eine Wetterkarte vom DWD).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;image&amp;quot;&lt;br /&gt;
     data-size=&amp;quot;80%&amp;quot;&lt;br /&gt;
     data-url=&amp;quot;http://www.dwd.de/wundk/wetter/de/Deutschland.jpg&amp;quot;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:image_tabletUI.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example for how to add an image to the dashboard which its URL is delivered by a FHEM module like PROPLANTA:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;image&amp;quot; data-device=&amp;quot;Wetter1&amp;quot; &lt;br /&gt;
     data-get=&amp;quot;fc0_weatherDayIcon&amp;quot; &lt;br /&gt;
     data-size=&amp;quot;40px&amp;quot; &lt;br /&gt;
     class=&amp;quot;cell&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;Beispiel_label&amp;quot;&amp;gt;&#039;&#039;&#039;Label&#039;&#039;&#039;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example for HM-WDS40-TH-I Funk-Temperatur-/Feuchtesensor innen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
STATE   T: 20.0 H: 61&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;THSensorWZ&amp;quot; &lt;br /&gt;
     data-part=&amp;quot;2&amp;quot; data-unit=&amp;quot;%B0C%0A&amp;quot; class=&amp;quot;cell big&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;Temperatur&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;THSensorWZ&amp;quot; data-part=&amp;quot;4&amp;quot; &lt;br /&gt;
     data-unit=&amp;quot;%&amp;quot; class=&amp;quot;cell big&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;Luftfeuchte&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But the same result can reached by getting single readings:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
humidity    58&lt;br /&gt;
temperature 20.1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;THSensorWZ&amp;quot; &lt;br /&gt;
     data-get=&amp;quot;temperature&amp;quot; data-unit=&amp;quot;%B0C%0A&amp;quot; class=&amp;quot;cell big&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;Temperatur&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;THSensorWZ&amp;quot; &lt;br /&gt;
     data-get=&amp;quot;humidity&amp;quot; data-unit=&amp;quot;%&amp;quot; class=&amp;quot;cell big&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;Luftfeuchte&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example for how to influence the color of the label according to value limits&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; &lt;br /&gt;
     data-device=&amp;quot;OutTemp&amp;quot; &lt;br /&gt;
     data-limits=&#039;[-73,10,23]&#039; &lt;br /&gt;
     data-colors=&#039;[&amp;quot;#6699FF&amp;quot;,&amp;quot;#AA6900&amp;quot;,&amp;quot;#FF0000&amp;quot;]&#039; &lt;br /&gt;
     data-unit=&amp;quot;%B0C%0A&amp;quot; &lt;br /&gt;
     class=&amp;quot;cell big&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example for how to create a widget for shutter via push: show state and set up/down&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;switch&amp;quot; &lt;br /&gt;
     data-device=&amp;quot;wzRollo&amp;quot; &lt;br /&gt;
     data-get-on=&amp;quot;up&amp;quot; &lt;br /&gt;
     data-get-off=&amp;quot;down&amp;quot; &lt;br /&gt;
     data-icon=&amp;quot;fa-bars&amp;quot; &lt;br /&gt;
     class=&amp;quot;cell&amp;quot; &amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; &lt;br /&gt;
     class=&amp;quot;cell&amp;quot;&amp;gt;Rollo&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example for how to create a label for a time value in short format with usage of RegEx.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; &lt;br /&gt;
     data-device=&amp;quot;dummy1&amp;quot; &lt;br /&gt;
     data-part=&amp;quot;(\d\d\.\d\d\.).*&amp;quot; &lt;br /&gt;
     class=&amp;quot;cell&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example for how to show two labels in one line.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;div type=&amp;quot;label&amp;quot; device=&amp;quot;OnSunrise&amp;quot; class=&amp;quot;inline&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;bis&lt;br /&gt;
   &amp;lt;div type=&amp;quot;label&amp;quot; device=&amp;quot;OnSunset&amp;quot; class=&amp;quot;inline&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiel für die Anzeige des UV-Indexes und der Abhängigkeit der anzuzeigenden Farbe.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;wider cell bigger&amp;quot; data-device=&amp;quot;ProVorhersage&amp;quot;&lt;br /&gt;
        data-get=&amp;quot;fc0_uv&amp;quot;&lt;br /&gt;
        data-limits=&amp;quot;[-2, 2, 5, 7, 10]&amp;quot; &lt;br /&gt;
	data-colors=&#039;[&amp;quot;#66FF33&amp;quot;,&amp;quot;#FFFF00&amp;quot;,&amp;quot;#FF6600&amp;quot;,&amp;quot;#FF0000&amp;quot;,&amp;quot;#993399&amp;quot;]&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
   &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot; data-device=&amp;quot;ProVorhersage&amp;quot; data-get=&amp;quot;fc0_date&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
   &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;wider cell bigger&amp;quot; data-device=&amp;quot;ProVorhersage&amp;quot;&lt;br /&gt;
        data-get=&amp;quot;fc1_uv&amp;quot;&lt;br /&gt;
	data-limits=&amp;quot;[-2, 2, 5, 7, 10]&amp;quot;&lt;br /&gt;
	data-colors=&#039;[&amp;quot;#66FF33&amp;quot;,&amp;quot;#FFFF00&amp;quot;,&amp;quot;#FF6600&amp;quot;,&amp;quot;#FF0000&amp;quot;,&amp;quot;#993399&amp;quot;]&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
   &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot; data-device=&amp;quot;ProVorhersage&amp;quot; data-get=&amp;quot;fc1_date&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:label_tabletUI.jpg]]&lt;br /&gt;
&lt;br /&gt;
Beispiel für die Anzeige des Labels als Icon.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;cell&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AvReceiver&amp;quot; data-get=&amp;quot;input&amp;quot; class=&amp;quot;icon round bg-red cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AvReceiver&amp;quot; data-get=&amp;quot;input&amp;quot; class=&amp;quot;icon square bg-blue cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AvReceiver&amp;quot; data-get=&amp;quot;input&amp;quot; class=&amp;quot;icon squareborder cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;PowerAV_Sw&amp;quot; data-colors=&#039;[&amp;quot;red&amp;quot;,&amp;quot;green&amp;quot;]&#039; data-limits=&#039;[&amp;quot;off&amp;quot;,&amp;quot;on&amp;quot;]&#039; class=&amp;quot;icon round bg-limit cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Label_tabletUI_icon.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;Beispiel_pagetab&amp;quot;&amp;gt;&#039;&#039;&#039;Pagetab&#039;&#039;&#039;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example for a tab menu to switch smoothly between multiple pages. Multiple pagetabs in a template file: menu.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;header&amp;gt;MENU&amp;lt;/header&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;cell&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;index.html&amp;quot;  data-icon=&amp;quot;fa-home&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;index_2.html&amp;quot; data-icon=&amp;quot;fa-sliders&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;index_3.html&amp;quot; data-icon=&amp;quot;fa-music&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;index_4.html&amp;quot; data-icon=&amp;quot;fa-hotel&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;index_5.html&amp;quot; data-icon=&amp;quot;fa-music&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;index_6.html&amp;quot; data-icon=&amp;quot;fa-database&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;pagetab&amp;quot; data-url=&amp;quot;index_7.html&amp;quot; data-icon=&amp;quot;fa-fax&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;Beispiel_playstream&amp;quot;&amp;gt;&#039;&#039;&#039;Playstream&#039;&#039;&#039;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Erzeugt einen Knopf zum direkten Abspielen eines Webradio-Streams.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     &amp;lt;div data-type=&amp;quot;playstream&amp;quot; data-url=&amp;quot;http://radioeins.de/stream&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
     &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;darker&amp;quot;&amp;gt;Radio eins&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;Beispiel_rotor&amp;quot;&amp;gt;&#039;&#039;&#039;Rotor&#039;&#039;&#039;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example for a rotor widget, which switches between to days of weather forecast&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;rotor&amp;quot; class=&amp;quot;fade&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;ul&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;darker&amp;quot;&amp;gt;Heute&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;weather&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;fc0_weatherDay&amp;quot; class=&amp;quot;big&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;fc0_weatherDay&amp;quot; class=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;fc0_tempMax&amp;quot; data-unit=&amp;quot;%B0C%0A&amp;quot; class=&amp;quot;large&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;darker&amp;quot;&amp;gt;Morgen&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;weather&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;fc1_weatherDay&amp;quot; class=&amp;quot;big&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;fc1_weatherDay&amp;quot; class=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;fc1_tempMax&amp;quot; data-unit=&amp;quot;%B0C%0A&amp;quot; class=&amp;quot;large&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;Beispiel_select&amp;quot;&amp;gt;&#039;&#039;&#039;Select&#039;&#039;&#039;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Erzeugt zwei Comboboxen zur Auswahl des Eingang eines 2-Zonen-AV-Receivers. Die Liste für Zone2 ist fest, die Liste für Zone1 wird von FHEM übergeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;cell wider&amp;quot;&amp;gt;&lt;br /&gt;
          &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;inline wider&amp;quot;&amp;gt;Zone2&amp;lt;/div&amp;gt;&lt;br /&gt;
          &amp;lt;div data-type=&amp;quot;select&amp;quot; data-device=&amp;quot;AvReceiverZ2&amp;quot; data-items=&#039;[&amp;quot;Airplay&amp;quot;,&amp;quot;Webradio&amp;quot;,&amp;quot;BD/DVD&amp;quot;,&amp;quot;PHONO&amp;quot;]&#039; data-get=&amp;quot;input&amp;quot; data-set=&amp;quot;input&amp;quot; class=&amp;quot;cell w2x&amp;quot; &amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
          &amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
          &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;inline&amp;quot;&amp;gt;Zone1&amp;lt;/div&amp;gt;&lt;br /&gt;
          &amp;lt;div data-type=&amp;quot;select&amp;quot; data-device=&amp;quot;AvReceiver&amp;quot; data-list=&amp;quot;inputs&amp;quot; data-get=&amp;quot;input&amp;quot; data-set=&amp;quot;input&amp;quot; class=&amp;quot;cell w2x&amp;quot; &amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:select_tabeltUI.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;Beispiel_slider&amp;quot;&amp;gt;&#039;&#039;&#039;Slider&#039;&#039;&#039;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Slider mit einstellbaren Werten von 10 bis 90:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;slider&amp;quot; &lt;br /&gt;
     data-device=&#039;Dummy1&#039; &lt;br /&gt;
     data-min=&amp;quot;10&amp;quot; &lt;br /&gt;
     data-max=&amp;quot;90&amp;quot; &lt;br /&gt;
     class=&amp;quot;cell&amp;quot; &amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;Light1&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:slider_tabletUI.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Horizontal angeordneter Slider:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;slider&amp;quot;&lt;br /&gt;
     data-device=&#039;Dummy1&#039; &lt;br /&gt;
     data-min=&amp;quot;0&amp;quot; &lt;br /&gt;
     data-max=&amp;quot;100&amp;quot; &lt;br /&gt;
     class=&amp;quot;horizontal&amp;quot; &lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:slider_tabletUI2.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;Beispiel_switch&amp;quot;&amp;gt;&#039;&#039;&#039;Switch&#039;&#039;&#039;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schalter. Usage of RegEx pattern for state request:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;switch&amp;quot; class=&amp;quot;cell&amp;quot; &lt;br /&gt;
            data-device=&amp;quot;MILIGHT_Zone1_Wohnzimmer&amp;quot; &lt;br /&gt;
            data-get-on=&amp;quot;on.*&amp;quot;&lt;br /&gt;
            data-get-off=&amp;quot;off&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:switch.png]]&lt;br /&gt;
&lt;br /&gt;
Beispiel für eine Gruppe von Schaltern, um zwischen vier verschiedenen Werten eines device umzuschalten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;cell left&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;div data-type=&amp;quot;switch&amp;quot; data-device=&amp;quot;dummy1&amp;quot; &lt;br /&gt;
      data-get-off=&amp;quot;((?!Wert1).)*&amp;quot; &lt;br /&gt;
      data-get-on=&amp;quot;Wert1&amp;quot; class=&amp;quot;cell&amp;quot; &amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;Wert1&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div data-type=&amp;quot;switch&amp;quot; data-device=&amp;quot;dummy1&amp;quot; &lt;br /&gt;
      data-get-off=&amp;quot;((?!Wert2).)*&amp;quot; &lt;br /&gt;
      data-get-on=&amp;quot;Wert2&amp;quot; class=&amp;quot;cell&amp;quot; &amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;Wert2&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div data-type=&amp;quot;switch&amp;quot; data-device=&amp;quot;dummy1&amp;quot; &lt;br /&gt;
      data-get-off=&amp;quot;((?!Wert3).)*&amp;quot; &lt;br /&gt;
      data-get-on=&amp;quot;Wert3&amp;quot; class=&amp;quot;cell&amp;quot; &amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;Wert3&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div data-type=&amp;quot;switch&amp;quot; data-device=&amp;quot;dummy1&amp;quot; &lt;br /&gt;
      data-get-off=&amp;quot;((?!Wert4).)*&amp;quot; &lt;br /&gt;
      data-get-on=&amp;quot;Wert4&amp;quot; class=&amp;quot;cell&amp;quot; &amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div data-type=&amp;quot;label&amp;quot; class=&amp;quot;cell&amp;quot;&amp;gt;Wert4&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:switch4.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;Beispiel_symbol&amp;quot;&amp;gt;&#039;&#039;&#039;Symbol&#039;&#039;&#039;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example for a tristate icon&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;symbol&amp;quot; data-device=&amp;quot;dummy1&amp;quot; &lt;br /&gt;
     data-get-on=&#039;[&amp;quot;wert1&amp;quot;,&amp;quot;wert2&amp;quot;,&amp;quot;wert3&amp;quot;]&#039; &lt;br /&gt;
     data-icons=&#039;[&amp;quot;fa-arrow-up&amp;quot;,&amp;quot;fa-user&amp;quot;,&amp;quot;fa-arrow-down&amp;quot;]&#039; &lt;br /&gt;
     data-on-colors=&#039;[&amp;quot;SeaGreen&amp;quot;,&amp;quot;SlateBlue&amp;quot;,&amp;quot;IndianRed&amp;quot;]&#039; &lt;br /&gt;
     class=&amp;quot;cell big&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example for a tristate icon with blink and spin animation&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;symbol&amp;quot; data-device=&amp;quot;dummy1&amp;quot; &lt;br /&gt;
     data-icons=&#039;[&amp;quot;fa-exclamation-triangle fa-blink&amp;quot;,&amp;quot;fa-exclamation-circle&amp;quot;,&amp;quot;fa-cog fa-spin&amp;quot;]&#039; &lt;br /&gt;
     data-on-colors=&#039;[&amp;quot;Crimson&amp;quot;,&amp;quot;GoldenRod&amp;quot;,&amp;quot;SeaGreen&amp;quot;]&#039; &lt;br /&gt;
     data-get-on=&#039;[&amp;quot;Wert1&amp;quot;,&amp;quot;Wert2&amp;quot;,&amp;quot;Wert3&amp;quot;]&#039; &amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example for a battery level control with RegEx&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;symbol&amp;quot; data-device=&amp;quot;BadHeizung&amp;quot; data-get=&amp;quot;batteryLevel&amp;quot;&lt;br /&gt;
     data-icons=&#039;[&amp;quot;oa-measure_battery_100&amp;quot;,&amp;quot;oa-measure_battery_75&amp;quot;,&amp;quot;oa-measure_battery_50&amp;quot;,&amp;quot;oa-measure_battery_25&amp;quot;,&amp;quot;oa-measure_battery_0&amp;quot;]&#039;&lt;br /&gt;
     data-get-on=&#039;[&amp;quot;3\\.[0-9]&amp;quot;,&amp;quot;2\\.[789]&amp;quot;,&amp;quot;2\\.[456]&amp;quot;,&amp;quot;2\\.[123]&amp;quot;,&amp;quot;((2\\.0)|([01]\\.[0-9]))&amp;quot;]&#039;&lt;br /&gt;
     data-on-colors=&#039;[&amp;quot;#505050&amp;quot;,&amp;quot;#505050&amp;quot;,&amp;quot;#505050&amp;quot;,&amp;quot;#ad3333&amp;quot;,&amp;quot;#ad3333&amp;quot;]&#039;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example for a battery level control with greater-equal compare and 90° rotated symbols&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;symbol&amp;quot; data-device=&amp;quot;BadHeizung&amp;quot; data-get=&amp;quot;batteryLevel&amp;quot;&lt;br /&gt;
    data-icons=&#039;[&amp;quot;oa-measure_battery_0 fa-rotate-90&amp;quot;,&amp;quot;oa-measure_battery_25 fa-rotate-90&amp;quot;,&amp;quot;oa-measure_battery_50 fa-rotate-90&amp;quot;,&amp;quot;oa-measure_battery_75 fa-rotate-90&amp;quot;,&amp;quot;oa-measure_battery_0 fa-rotate-90&amp;quot;]&#039;&lt;br /&gt;
    data-get-on=&#039;[&amp;quot;0&amp;quot;,&amp;quot;2&amp;quot;,&amp;quot;2.4&amp;quot;,&amp;quot;2.7&amp;quot;,&amp;quot;3.0&amp;quot;]&#039;&lt;br /&gt;
    data-on-colors=&#039;[&amp;quot;#ad3333&amp;quot;,&amp;quot;#ad3333&amp;quot;,&amp;quot;#505050&amp;quot;,&amp;quot;#505050&amp;quot;,&amp;quot;#505050&amp;quot;]&#039;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;Beispiel_thermostat&amp;quot;&amp;gt;&#039;&#039;&#039;Thermostat&#039;&#039;&#039;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Configure as data-device=&#039;...&#039; that item which delivers temp and desired-temp as reading.&lt;br /&gt;
&lt;br /&gt;
Default parameters are:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
data-get=&amp;quot;desired-temp&amp;quot; data-temp=&amp;quot;measured-temp&amp;quot; data-set=&amp;quot;desired-temp&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Therefor for HomaMatic HM-CC-RT-DN this is sufficient.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;thermostat&amp;quot; data-device=&#039;KH_Clima&#039; class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The long format looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;thermostat&amp;quot; &lt;br /&gt;
     data-device=&amp;quot;KH_Clima&amp;quot; &lt;br /&gt;
     data-valve=&amp;quot;ValvePosition&amp;quot;&lt;br /&gt;
     data-get=&amp;quot;desired-temp&amp;quot; &lt;br /&gt;
     data-temp=&amp;quot;measured-temp&amp;quot; &lt;br /&gt;
     class=&amp;quot;cell&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example for MAX!:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;thermostat&amp;quot; data-device=&amp;quot;HZ_Tuer&amp;quot; &lt;br /&gt;
    data-valve=&amp;quot;valveposition&amp;quot; &lt;br /&gt;
    data-get=&amp;quot;desiredTemperature&amp;quot; &lt;br /&gt;
    data-temp=&amp;quot;temperature&amp;quot; &lt;br /&gt;
    data-set=&amp;quot;desiredTemperature&amp;quot; &lt;br /&gt;
    class=&amp;quot;cell&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The wigets will show the valve value only in case of a valid data-valve attribute. The default for data-valve ist null. That means, a empty data-valve attribute hides the valve label for the widget.&lt;br /&gt;
&lt;br /&gt;
[[Datei:thermostat.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;Beispiel_weather&amp;quot;&amp;gt;&#039;&#039;&#039;Weather&#039;&#039;&#039;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Widget fügt ein dem Wetter entsprechendes Bild ein. Die Daten können durch FHEM-Module wie [[PROPLANTA]], [[OPENWEATHER]] und [[Weather]] bereitgestellt werden. &lt;br /&gt;
Add &#039;big&#039; or &#039;bigger&#039; to CSS class to get a bigger weather icon.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;weather&amp;quot; &lt;br /&gt;
     data-device=&amp;quot;Weather&amp;quot; &lt;br /&gt;
     data-get=&amp;quot;fc0_weatherDay&amp;quot; &lt;br /&gt;
     class=&amp;quot;cell big&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Datei:weather.png]]&lt;br /&gt;
&lt;br /&gt;
== Icon-Konfiguration ==&lt;br /&gt;
&lt;br /&gt;
* Eingebaute Icons: Diese haben das ftui-Präfix. Zurzeit sind folgende verfügbar: ftui-window, ftui-door&lt;br /&gt;
&lt;br /&gt;
* Mehr als 500 Icons von &amp;quot;http://fortawesome.github.io/Font-Awesome/icons&amp;quot; verfügbar. Einfach den Icon-Namen angeben (Präfix &amp;quot;fa-&amp;quot; nicht vergessen, Z.B. &amp;lt;code&amp;gt;data-icon=&amp;quot;fa-volume-up&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Es stehen auch Openautomation Font-Files zur Verfügung. Wer sie nutzen möchte, muss folgende Stylesheets in die index.html hinzufügen.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/lib/openautomation.css&amp;quot; /&amp;gt;&lt;br /&gt;
   &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/lib/fhemSVG.css&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese font icons haben das Präfix &#039;fs-&#039; bzw. &#039;oa-&#039;.&lt;br /&gt;
&lt;br /&gt;
Beispiel bei einem Schalter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;div data-type=&amp;quot;switch&amp;quot; data-device=&#039;dummy1&#039; data-icon=&amp;quot;oa-secur_locked&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Und so als großes Symbol:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;symbol&amp;quot; data-device=&#039;dummy1&#039;&lt;br /&gt;
        data-icon=&amp;quot;oa-status_frost&amp;quot;&lt;br /&gt;
        data-on-color=&amp;quot;#bb3232&amp;quot;&lt;br /&gt;
        data-get-on=&amp;quot;on&amp;quot;&lt;br /&gt;
        data-get-off=&amp;quot;!on&amp;quot;&lt;br /&gt;
        class=&amp;quot;bigger&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Icons kann man auch etwas dicker darstellen mit den Zusatz bold: &amp;lt;code&amp;gt;data-icon=&amp;quot;oa-secur_locked bold&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Namen der verfügbaren Icons findet man auch in den CSS Files (openautomation.css / fhemSVG.css)&lt;br /&gt;
&lt;br /&gt;
== Spezial ==&lt;br /&gt;
Folgender Befehl setzt einen direkten Befehl an FHEM ab (&amp;lt;code&amp;gt;set dummy1 off&amp;lt;/code&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     &amp;lt;div onclick=&amp;quot;ftui.setFhemStatus(&#039;set dummy1 off&#039;)&amp;quot;&amp;gt;All off!&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
Häufig gestellte Fragen zum FHEM Tablet UI sind in der [[FHEM_Tablet_UI/FAQ|FHEM Tablet UI FAQ]] zusammengestellt.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [http://forum.fhem.de/index.php/topic,34233.0.html Forums-Beitrag]&lt;br /&gt;
* [https://github.com/knowthelist/fhem-tablet-ui Projekt auf Github]&lt;br /&gt;
* [http://forum.fhem.de/index.php/topic,37378.0.html User-Demos]&lt;br /&gt;
* [https://github.com/ovibox/fhem-ftui-user-demos Download der User-Demo-Dateien]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Level&amp;diff=19582</id>
		<title>FTUI Widget Level</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Level&amp;diff=19582"/>
		<updated>2017-02-08T20:10:23Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: Schreibfehler korrigiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Level Widget]] ist ein Widget für [[FHEM Tablet UI]], mit dem eine horizontale oder vertikale Balkenanzeige erstellt werden kann.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Ftui_widget_level_2-fach.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-device&#039;&#039;&#039;||FHEM-Device, dessen Reading Reading angezeigt werden soll||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get&#039;&#039;&#039;||Name des Readings, das den Wert enthält||&#039;STATE&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-min&#039;&#039;&#039;||Minimaler Wert, der angezeigt werden soll||0||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-max&#039;&#039;&#039;||Maximaler Wert, der angezeigt werden soll, oder Name des Readings, das den Maximalwert enthält||100||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-on&#039;&#039;&#039;||Wert, bei dem der Balken maximalen Ausschlag zeigt||&#039;on&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-off&#039;&#039;&#039;||Wert, bei dem der Balken minimalen Ausschlag zeigt||&#039;off&#039;||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-part&#039;&#039;&#039;||Wählt bei Werten, die durch Leerzeichen getrennt sind, den Teil aus, der angezeigt werden soll. Der Teil kann auch mit RegEx ermittelt werden.||&#039;-1&#039;: alles Anzeigen||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-colors&#039;&#039;&#039;||Array von Farbwerten, die die Anzeige entsprechend der Grenzwerte von &#039;&#039;&#039;data-limits&#039;&#039;&#039; einfärben||||data-colors=&#039;[&amp;quot;#dd3366&amp;quot;,&amp;quot;#ffcc00&amp;quot;,&amp;quot;#55aa44&amp;quot;]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-limits&#039;&#039;&#039;||Array von Zahlen oder RegEx zur Einfärbung der Anzeige||||data-limits=&#039;[&amp;quot;20&amp;quot;,&amp;quot;70&amp;quot;,&amp;quot;95&amp;quot;]&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CSS-Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Klasse&lt;br /&gt;
!Beschreibung&lt;br /&gt;
{{FTUI Klasse|mini}}{{FTUI Klasse|big}}{{FTUI Klasse|bigger}}{{FTUI Klasse|large}}{{FTUI Klasse|horizontal}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===Zwei Level-Anzeigen mit Label===&lt;br /&gt;
Beide Level-Anzeigen besitzen ein Label auf gleicher Höhe, das den aktuellen Wert als Zahl mit Einheit anzeigt. Die Farbe der Level-Anzeigen wird beim Erreichen bestimmter Werte verändert.&lt;br /&gt;
&lt;br /&gt;
[[File:Ftui_widget_level_2-fach.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;level&amp;quot; data-device=&#039;Tablet&#039;  data-get=&#039;powerLevel&#039;&lt;br /&gt;
        data-limits=&#039;[&amp;quot;[12]*[0-9]&amp;quot;,&amp;quot;[3456][0-9]&amp;quot;,&amp;quot;([789][0-9]|100)&amp;quot;]&#039;&lt;br /&gt;
        data-colors=&#039;[&amp;quot;#dd3366&amp;quot;,&amp;quot;#ffcc00&amp;quot;,&amp;quot;#55aa44&amp;quot;]&#039;&lt;br /&gt;
        class=&amp;quot;horizontal left&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&#039;Tablet&#039;&lt;br /&gt;
         data-get=&#039;powerLevel&#039;&lt;br /&gt;
         data-unit=&amp;quot;%&amp;quot; class=&amp;quot;top-space left&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;level&amp;quot; data-device=&#039;dummy1&#039;&lt;br /&gt;
        data-limits=&#039;[&amp;quot;20&amp;quot;,&amp;quot;70&amp;quot;,&amp;quot;95&amp;quot;]&#039;&lt;br /&gt;
        data-colors=&#039;[&amp;quot;#dd3366&amp;quot;,&amp;quot;#ffcc00&amp;quot;,&amp;quot;#55aa44&amp;quot;]&#039;&lt;br /&gt;
        class=&amp;quot;horizontal left&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&#039;dummy1&#039; data-unit=&amp;quot;%&amp;quot; &lt;br /&gt;
         class=&amp;quot;top-space left&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=17656</id>
		<title>HM-LC-RGBW-WM Funk-RGBW-Controller</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=17656"/>
		<updated>2016-12-04T17:46:24Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{Todo|Dieses Device ist seit Anfang Oktober 2015 als Bausatz auf dem Markt - dieser Artikel ist noch im Aufbau - bitte Verständnis für Unvollständigkeiten und fehlende Bereiche}}&lt;br /&gt;
&lt;br /&gt;
{{Infobox Hardware&lt;br /&gt;
|Bild=HM-LC-RGBW-WM.jpg&lt;br /&gt;
|Bildbeschreibung=HomeMatic Funk-RGBW-Controller &lt;br /&gt;
|HWProtocol=HomeMatic&lt;br /&gt;
|HWType=Dimmer&lt;br /&gt;
|HWCategory=HomeMatic&lt;br /&gt;
|HWComm=868&amp;amp;nbsp;MHz&lt;br /&gt;
|HWChannels=3&lt;br /&gt;
|HWVoltage=12-24 V DC&lt;br /&gt;
|HWPowerConsumption=15 mA max. (LED&#039;s aus)&lt;br /&gt;
|HWPoweredBy=externe Stromversorgung&lt;br /&gt;
|HWSize=89x99x26mm&lt;br /&gt;
|HWDeviceFHEM=[http://fhem.de/commandref.html#CUL_HM CUL_HM]&lt;br /&gt;
|HWManufacturer=ELV / eQ-3 &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
Der Funk-RGBW-Controller erlaubt das Dimmen von 12/24 Volt Gleichstrom LED-Stripes mit gemeinsamer Anode (+). Es können max. 34W pro Kanal angesteuert werden.&lt;br /&gt;
&lt;br /&gt;
Im Oktober 2015 hat die Auslieferung der Geräte als (einfacher) Bausatz begonnen. Zusätzlich ist das Gerät als &amp;quot;fertig aufgebauter Bausatz&amp;quot; mit einem Aufpreis (derzeit 30 Euro) erhältlich.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Technische Daten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Gewicht: 90 g&lt;br /&gt;
&lt;br /&gt;
== Anwendungsszenarien ==&lt;br /&gt;
&lt;br /&gt;
Der Controller ist für die Montage an Ebenen Flächen gedacht. Es ist eine eigene vorhandene 12/24V Stromversorgung notwendig (nicht im Lieferumfang enthalten). Der Controller besitzt Schraubklemmen zum direkten Anschluss von LED-Stripes. Es ist dabei auf die max. zulässige Leistung pro Kanal zu achten. Diese kann je nach Stripe variieren.&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
 &lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
* Die Farbe weiß zusammen mit rot, grün oder blau zu mischen ist offenbar nicht möglich. &lt;br /&gt;
* Unklar ist, wie neue Programme erstellt und gespeichert werden können.&lt;br /&gt;
* Bei langsamen Farb- und Helligkeitsänderungen sind deutliche Farb- und Helligkeitssprünge wahrnehmbar, da die Änderung nicht kontinuierlich abläuft, sondern sprunghaft.&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit FHEM ==&lt;br /&gt;
&lt;br /&gt;
Der Controller hat drei Kanäle, die jeweils verschiedene Befehle ermöglichen:&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Dim Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe dauerhaft ein. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-for-timer &amp;lt;ontime&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe ein und nach &amp;lt;ontime&amp;gt; Sekunden wieder aus. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-till &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe ein und um &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; Uhr wieder aus. &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; hat das Format hh:mm:ss&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; off&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs dauerhaft aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; press&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sanft ausgeschaltet. Sind sie ausgeschaltet, werden sie mit der zuletzt eingestellten Farbe sanft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; toggle&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sofort ausgeschaltet. Sind sie ausgeschaltet, werden sie mit der zuletzt eingestellten Farbe sofort eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; pct&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die LEDs werden auf den angegebenen Helligkeitswert gesetzt. pct ist ein Wert von 0 bis 100 (Prozent).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; up&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die LEDs werden um 10% hoch gedimmt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; down&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die LEDs werden um 10% herunter gedimmt.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Color Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightCol &amp;lt;bright&amp;gt; &amp;lt;colVal&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. Die LED-Farbe ist in allen Phasen gleich.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; regelt die Helligkeit in der Duration-Phase und geht von 0 (=0%) bis 100 (=100%)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colVal&amp;gt;&#039;&#039;&#039; regelt die Farbe in der Ramp- und Duration-Phase und geht von 0 bis 100:&amp;lt;br&amp;gt;&lt;br /&gt;
0 = reines Rot, 33 = Grün, 66.5 = Blau, 99.5 = Rot mit minimalem Blauanteil, 100 = Weiß&amp;lt;br&amp;gt;&lt;br /&gt;
Werte dazwischen ergeben Mischfarben, z.B. 8 = Gelb, 75 = Lila. Weiß zusammen mit R, G oder B zu mischen ist offenbar nicht möglich. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. Ein Wert von 0 lässt die LEDs dauerhaft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; color &amp;lt;colVal&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stellt die Farbe &#039;&#039;&#039;&amp;lt;colVal&amp;gt;&#039;&#039;&#039; (siehe oben) in der aktuellen Helligkeit ein.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Auto Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightAuto &amp;lt;bright&amp;gt; &amp;lt;colProg&amp;gt; &amp;lt;min&amp;gt; &amp;lt;max&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analog zum brightCol-Befehl im Color-Kanal gibt es eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Grund-Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. In beiden Phasen wird ein vordefiniertes Programm abgespielt und während dessen blinkt die Automatiktaste regelmäßig 1x lang.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; steuert die Grund-Helligkeit analog zum brightCol-Befehl im Color-Kanal. Je nach Programm schwankt die Helligkeit während der Programmausführung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colProg&amp;gt;&#039;&#039;&#039; definiert welches Programm abgespielt wird. Im Auslieferungszustand sind folgende Programm-Nummern vorhanden:&lt;br /&gt;
&lt;br /&gt;
1: Farbverlauf langsam (Geschwindigkeit Farbwechsel: 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang, default: 20 Sekunden). &lt;br /&gt;
Der Farbverlauf geht von colVal &amp;lt;min&amp;gt; bis colVal &amp;lt;max&amp;gt;. colVal ist analog zum brightCol-Befehl im Color-Kanal. Nach der &amp;lt;max&amp;gt; Farbe geht es sofort bei der &amp;lt;min&amp;gt; Farbe weiter. Das kann zu Farbsprüngen führen. Die Geschwindigkeit des Farbwechsels kann mit dem Register colChangeSpeed geändert werden (default: colChangeSpeed = 10 Sekunden pro Durchgang). In Programm 1 dauert ein Durchgang von Farbe 0 (&amp;lt;min&amp;gt; = 0) bis Farbe 200 (&amp;lt;max&amp;gt; = 200) genau 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden (default also 20 Sekunden). Wenn weniger Farben durchlaufen werden, ist der Durchlauf entsprechend schneller.&amp;lt;br&amp;gt;&lt;br /&gt;
Beinhaltet der Farbbereich den Wert 200, so wird auch weiß angesteuert. Beim Einschalten der Automatikmodi über eine gepeerte Fernbedienung (oder bei der Bedienung über virtuelle Buttons) ist dies nicht der Fall, Weiß wird dann ausgespart.&lt;br /&gt;
&lt;br /&gt;
2: Farbverlauf normal (Geschwindigkeit Farbwechsel: &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit normaler Geschwindigkeit (default: 10 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
3: Farbverlauf schnell (Geschwindigkeit Farbwechsel: 0.5 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit doppelter Geschwindigkeit (default: 5 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
4: Kaminfeuer (rotes Licht, das ein Feuer simuliert). &amp;lt;min&amp;gt; und &amp;lt;max&amp;gt; haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
5: Wasserfall (blaues Licht, das die Helligkeit verändert). &amp;lt;min&amp;gt; und &amp;lt;max&amp;gt; haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
6: TV-Simulation (Farb- und Helligkeitsschwankungen simulieren ein eingeschaltetes TV-Gerät, dient zur Abwehr von Einbrechern). &amp;lt;min&amp;gt; und &amp;lt;max&amp;gt; haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;min&amp;gt;&#039;&#039;&#039; siehe Programme 1 bis 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;max&amp;gt;&#039;&#039;&#039; siehe Programme 1 bis 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. &amp;lt;br&amp;gt;&lt;br /&gt;
Eine Ansteuerung mit &amp;lt;duration&amp;gt; 0 als Dauerbetrieb ist im Automatikmodus offenbar nicht möglich. (?)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; colProgram &amp;lt;colProg&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es wird das Programm mit der Nummer &#039;&#039;&#039;&amp;lt;colProg&amp;gt;&#039;&#039;&#039; (siehe oben) in der aktuell gesetzten Helligkeit abgespielt. &lt;br /&gt;
&lt;br /&gt;
=== Peering ===&lt;br /&gt;
Die folgenden Befehle peeren alle Tasten eines HomeMatic 6-fach Tasters (HM-PB-6-WM55) mit den 3 Kanälen des RGBW-Controllers mit dem Namen &#039;&#039;&#039;rgbw&#039;&#039;&#039;. Die Bedienung ist dann wie auf S. 12+13 der Bedienungsanleitung beschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_01 peerChan 0 rgbw_Dim dual set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_03 peerChan 0 rgbw_Color dual set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_05 peerChan 0 rgbw_Auto dual set&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Taste 1: Kurzes Drücken schaltet das Licht aus, langes Drücken dimmt herunter&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 2: Kurzes Drücken schaltet das Licht ein, langes Drücken dimmt herauf&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 3: Kurzes Drücken springt um einen Schritt im Farbkreis nach unten, langes Drücken fährt im Farbkreis nach unten&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 4: Kurzes Drücken springt um einen Schritt im Farbkreis nach oben, langes Drücken fährt im Farbkreis nach oben&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 5: Kurzes Drücken schaltet den Automatikmodus aus, langes schaltet den nächstniedrigeren ein&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 6: Kurzes Drücken schaltet den Automatikmodus 1 ein, langes den nächsthöheren&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hinweise:&amp;lt;br&amp;gt;&lt;br /&gt;
Die Automatikmodi springen beim Durchschalten vom höchsten (TV) zum niedrigsten (Farbwechsel langsam) und umgekehrt.&amp;lt;br&amp;gt;&lt;br /&gt;
Das Durchfahren des Farbkreises hält immer bei Weiß an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die folgenden Befehle peeren die ersten 3 Tasten (=Kanäle) eines HomeMatic 6-fach Tasters (HM-PB-6-WM55) mit den 3 Kanälen des RGBW-Controllers.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Bedienung ist dadurch etwas anders.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_01 peerChan 0 rgbw_Dim single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_02 peerChan 0 rgbw_Color single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_03 peerChan 0 rgbw_Auto single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 1: Kurzes Drücken schaltet das Licht ein und aus, langes Drücken dimmt hoch bzw. herunter&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 2: Kurzes Drücken springt um einen Schritt im Farbkreis nach oben bzw unten, langes Drücken fährt im Farbkreis nach oben bzw unten&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 3: Kurzes Drücken schaltet den nächsthöheren Automatikmodus ein, langes den niedrigeren. &amp;lt;br&amp;gt;&lt;br /&gt;
Um die Automatik auszuschalten und den aktuellen Farbton einzufrieren, kurz auf Taste 2 (Farbe) drücken.&lt;br /&gt;
Auch hier springen die Automatikmodi weiter. Beim Durchfahren des Farbkreises nach unten oben wird aber (warum auch immer) über weiß hinweg nach rot gesprungen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ein HomeMatic 2-Kanal Funk-Sender (HM-RC-2-PBU-FM) kann wie folgt mit dem Dim-Kanal gepeert werden. Mit kurzem Druck nach oben/unten werden die LEDs ein-/ausgeschaltet und mit langem Druck hoch- und runtergedimmt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster2_Btn_01 peerChan 0 rgbw_Dim dual set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Readings im Dim Kanal ===&lt;br /&gt;
&lt;br /&gt;
Die Readings level, pct und state liefern den aktuellen Dim-Level (0 = aus, 100 = maximale Helligkeit) zurück.&lt;br /&gt;
&lt;br /&gt;
=== Readings im Color Kanal ===&lt;br /&gt;
&lt;br /&gt;
Die Readings color, level, pct und state liefern den aktuellen Farbwert zurück (0 = rot, 100 = weiß).&lt;br /&gt;
&lt;br /&gt;
=== Readings im Auto Kanal ===&lt;br /&gt;
&lt;br /&gt;
Die Readings colProgram, level, pct und state liefern das zuletzt gewählte Programm (0 = aus, 1 = Farbautomatik langsam, ..., 6 = TV-Simulation) zurück.&lt;br /&gt;
&lt;br /&gt;
=== Colorpicker in FHEM erzeugen ===&lt;br /&gt;
&lt;br /&gt;
1. Ein Dummy mit dem Namen RGB_Picker erzeugen, mit dem die Farbe ausgewählt wird. Außerdem wird ein Reading mit dem Namen rgb erzeugt, welches den Hex-Code der gewählten Farbe enthält:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define RGB_Picker dummy&lt;br /&gt;
&lt;br /&gt;
attr RGB_Picker devStateIcon {my $icon=Color_devStateIcon(ReadingsVal($name,&amp;quot;rgb&amp;quot;,&amp;quot;000000&amp;quot;));;$icon=~s/on/light_light_dim_100/;;$icon}&lt;br /&gt;
&lt;br /&gt;
attr RGB_Picker readingList hue&lt;br /&gt;
&lt;br /&gt;
attr RGB_Picker setList hue:colorpicker,HUE,0,0.5,100&lt;br /&gt;
&lt;br /&gt;
attr RGB_Picker stateFormat hue&lt;br /&gt;
&lt;br /&gt;
attr RGB_Picker userReadings rgb {my $hue=ReadingsVal($name,&amp;quot;hue&amp;quot;,&amp;quot;0&amp;quot;);;($hue eq &amp;quot;100&amp;quot;)?&amp;quot;FFFFFF&amp;quot;:Color::hsv2hex(($hue/100),1,1)}&lt;br /&gt;
&lt;br /&gt;
attr RGB_Picker webCmd hue&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Ein Notify definieren, welches bei jeder Änderung des Dummys (Schritt 1) den Color Befehl an den RGBW-Controller sendet. Statt rgbw_Color den Namen des Color Kanals des RGBW-Controllers eintragen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define RGB_Picker_notify notify RGB_Picker:hue.* { fhem &amp;quot;set rgbw_Color color &amp;quot; . ReadingsVal($NAME,&#039;hue&#039;,100) }&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
3. Jetzt noch die FHEM-Weboberfläche für die Dim und Auto Kanäle definieren (dabei rgbw_Dim und rgbw_Auto mit den Device Namen der entsprechenden Kanäle ersetzen):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
attr rgbw_Dim webCmd pct:on:off&lt;br /&gt;
&lt;br /&gt;
attr rgbw_Auto webCmd colProgram&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events Auszug === &lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
&lt;br /&gt;
== Logging/Graph. Darstellung ==&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Bedienungsanleitung: [http://files.elv.de/Assets/Produkte/14/1419/141952/Downloads/141952_rgbw_controller_um.pdf]&lt;br /&gt;
* Produktseite ELV: [http://www.elv.de/homematic-funk-rgbw-controller-bausatz.html] &lt;br /&gt;
* Diskussion im FHEM Forum: [http://forum.fhem.de/index.php/topic,39719.0.html]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Dimmer]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=17606</id>
		<title>HM-LC-RGBW-WM Funk-RGBW-Controller</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=17606"/>
		<updated>2016-11-29T18:46:00Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{Todo|Dieses Device ist seit Anfang Oktober 2015 als Bausatz auf dem Markt - dieser Artikel ist noch im Aufbau - bitte Verständnis für Unvollständigkeiten und fehlende Bereiche}}&lt;br /&gt;
&lt;br /&gt;
{{Infobox Hardware&lt;br /&gt;
|Bild=HM-LC-RGBW-WM.jpg&lt;br /&gt;
|Bildbeschreibung=HomeMatic Funk-RGBW-Controller &lt;br /&gt;
|HWProtocol=HomeMatic&lt;br /&gt;
|HWType=Dimmer&lt;br /&gt;
|HWCategory=HomeMatic&lt;br /&gt;
|HWComm=868&amp;amp;nbsp;MHz&lt;br /&gt;
|HWChannels=3&lt;br /&gt;
|HWVoltage=12-24 V DC&lt;br /&gt;
|HWPowerConsumption=15 mA max. (LED&#039;s aus)&lt;br /&gt;
|HWPoweredBy=externe Stromversorgung&lt;br /&gt;
|HWSize=89x99x26mm&lt;br /&gt;
|HWDeviceFHEM=[http://fhem.de/commandref.html#CUL_HM CUL_HM]&lt;br /&gt;
|HWManufacturer=ELV / eQ-3 &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
Der Funk-RGBW-Controller erlaubt das Dimmen von 12/24 Volt Gleichstrom LED-Stripes mit gemeinsamer Anode (+). Es können max. 34W pro Kanal angesteuert werden.&lt;br /&gt;
&lt;br /&gt;
Im Oktober 2015 hat die Auslieferung der Geräte als (einfacher) Bausatz begonnen. Zusätzlich ist das Gerät als &amp;quot;fertig aufgebauter Bausatz&amp;quot; mit einem Aufpreis (derzeit 30 Euro) erhältlich.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Technische Daten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Gewicht: 90 g&lt;br /&gt;
&lt;br /&gt;
== Anwendungsszenarien ==&lt;br /&gt;
&lt;br /&gt;
Der Controller ist für die Montage an Ebenen Flächen gedacht. Es ist eine eigene vorhandene 12/24V Stromversorgung notwendig (nicht im Lieferumfang enthalten). Der Controller besitzt Schraubklemmen zum direkten Anschluss von LED-Stripes. Es ist dabei auf die max. zulässige Leistung pro Kanal zu achten. Diese kann je nach Stripe variieren.&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
 &lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
* Die Farbe weiß zusammen mit rot, grün oder blau zu mischen ist offenbar nicht möglich. &lt;br /&gt;
* Unklar ist, wie neue Programme erstellt und gespeichert werden können.&lt;br /&gt;
* Bei langsamen Farb- und Helligkeitsänderungen sind deutliche Farb- und Helligkeitssprünge wahrnehmbar, da die Änderung nicht kontinuierlich abläuft, sondern sprunghaft.&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit FHEM ==&lt;br /&gt;
&lt;br /&gt;
Der Controller hat drei Kanäle, die jeweils verschiedene Befehle ermöglichen:&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Dim Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe dauerhaft ein. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-for-timer &amp;lt;ontime&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe ein und nach &amp;lt;ontime&amp;gt; Sekunden wieder aus. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-till &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe ein und um &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; Uhr wieder aus. &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; hat das Format hh:mm:ss&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; off&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs dauerhaft aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; press&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sanft ausgeschaltet. Sind sie ausgeschaltet, werden sie mit der zuletzt eingestellten Farbe sanft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; toggle&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sofort ausgeschaltet. Sind sie ausgeschaltet, werden sie mit der zuletzt eingestellten Farbe sofort eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; pct&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die LEDs werden auf den angegebenen Helligkeitswert gesetzt. pct ist ein Wert von 0 bis 100 (Prozent).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; up&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die LEDs werden um 10% hoch gedimmt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; down&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die LEDs werden um 10% herunter gedimmt.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Color Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightCol &amp;lt;bright&amp;gt; &amp;lt;colVal&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. Die LED-Farbe ist in allen Phasen gleich.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; regelt die Helligkeit in der Duration-Phase und geht von 0 (=0%) bis 100 (=100%)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colVal&amp;gt;&#039;&#039;&#039; regelt die Farbe in der Ramp- und Duration-Phase und geht von 0 bis 100:&amp;lt;br&amp;gt;&lt;br /&gt;
0 = reines Rot, 33 = Grün, 66.5 = Blau, 99.5 = Rot mit minimalem Blauanteil, 100 = Weiß&amp;lt;br&amp;gt;&lt;br /&gt;
Werte dazwischen ergeben Mischfarben, z.B. 8 = Gelb, 75 = Lila. Weiß zusammen mit R, G oder B zu mischen ist offenbar nicht möglich. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. Ein Wert von 0 lässt die LEDs dauerhaft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Auto Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightAuto &amp;lt;bright&amp;gt; &amp;lt;colProg&amp;gt; &amp;lt;min&amp;gt; &amp;lt;max&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analog zum brightCol-Befehl im Color-Kanal gibt es eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Grund-Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. In beiden Phasen wird ein vordefiniertes Programm abgespielt und während dessen blinkt die Automatiktaste regelmäßig 1x lang.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; steuert die Grund-Helligkeit analog zum brightCol-Befehl im Color-Kanal. Je nach Programm schwankt die Helligkeit während der Programmausführung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colProg&amp;gt;&#039;&#039;&#039; definiert welches Programm abgespielt wird. Im Auslieferungszustand sind folgende Programm-Nummern vorhanden:&lt;br /&gt;
&lt;br /&gt;
1: Farbverlauf langsam (Geschwindigkeit Farbwechsel: 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang, default: 20 Sekunden). &lt;br /&gt;
Der Farbverlauf geht von colVal &amp;lt;min&amp;gt; bis colVal &amp;lt;max&amp;gt;. colVal ist analog zum brightCol-Befehl im Color-Kanal. Nach der &amp;lt;max&amp;gt; Farbe geht es sofort bei der &amp;lt;min&amp;gt; Farbe weiter. Das kann zu Farbsprüngen führen. Die Geschwindigkeit des Farbwechsels kann mit dem Register colChangeSpeed geändert werden (default: colChangeSpeed = 10 Sekunden pro Durchgang). In Programm 1 dauert ein Durchgang von Farbe 0 (&amp;lt;min&amp;gt; = 0) bis Farbe 200 (&amp;lt;max&amp;gt; = 200) genau 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden (default also 20 Sekunden). Wenn weniger Farben durchlaufen werden, ist der Durchlauf entsprechend schneller.&amp;lt;br&amp;gt;&lt;br /&gt;
Beinhaltet der Farbbereich den Wert 200, so wird auch weiß angesteuert. Beim Einschalten der Automatikmodi über eine gepeerte Fernbedienung (oder bei der Bedienung über virtuelle Buttons) ist dies nicht der Fall, Weiß wird dann ausgespart.&lt;br /&gt;
&lt;br /&gt;
2: Farbverlauf normal (Geschwindigkeit Farbwechsel: &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit normaler Geschwindigkeit (default: 10 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
3: Farbverlauf schnell (Geschwindigkeit Farbwechsel: 0.5 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit doppelter Geschwindigkeit (default: 5 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
4: Kaminfeuer (rotes Licht, das ein Feuer simuliert). &amp;lt;min&amp;gt; und &amp;lt;max&amp;gt; haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
5: Wasserfall (blaues Licht, das die Helligkeit verändert). &amp;lt;min&amp;gt; und &amp;lt;max&amp;gt; haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
6: TV-Simulation (Farb- und Helligkeitsschwankungen simulieren ein eingeschaltetes TV-Gerät, dient zur Abwehr von Einbrechern). &amp;lt;min&amp;gt; und &amp;lt;max&amp;gt; haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;min&amp;gt;&#039;&#039;&#039; siehe Programme 1 bis 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;max&amp;gt;&#039;&#039;&#039; siehe Programme 1 bis 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. &amp;lt;br&amp;gt;&lt;br /&gt;
Eine Ansteuerung mit &amp;lt;duration&amp;gt; 0 als Dauerbetrieb ist im Automatikmodus offenbar nicht möglich. (?)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
=== Peering ===&lt;br /&gt;
Die folgenden Befehle peeren alle Tasten eines HomeMatic 6-fach Tasters (HM-PB-6-WM55) mit den 3 Kanälen des RGBW-Controllers mit dem Namen &#039;&#039;&#039;rgbw&#039;&#039;&#039;. Die Bedienung ist dann wie auf S. 12+13 der Bedienungsanleitung beschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_01 peerChan 0 rgbw_Dim dual set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_03 peerChan 0 rgbw_Color dual set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_05 peerChan 0 rgbw_Auto dual set&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Taste 1: Kurzes Drücken schaltet das Licht aus, langes Drücken dimmt herunter&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 2: Kurzes Drücken schaltet das Licht ein, langes Drücken dimmt herauf&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 3: Kurzes Drücken springt um einen Schritt im Farbkreis nach unten, langes Drücken fährt im Farbkreis nach unten&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 4: Kurzes Drücken springt um einen Schritt im Farbkreis nach oben, langes Drücken fährt im Farbkreis nach oben&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 5: Kurzes Drücken schaltet den Automatikmodus aus, langes schaltet den nächstniedrigeren ein&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 6: Kurzes Drücken schaltet den Automatikmodus 1 ein, langes den nächsthöheren&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hinweise:&amp;lt;br&amp;gt;&lt;br /&gt;
Die Automatikmodi springen beim Durchschalten vom höchsten (TV) zum niedrigsten (Farbwechsel langsam) und umgekehrt.&amp;lt;br&amp;gt;&lt;br /&gt;
Das Durchfahren des Farbkreises hält immer bei Weiß an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die folgenden Befehle peeren die ersten 3 Tasten (=Kanäle) eines HomeMatic 6-fach Tasters (HM-PB-6-WM55) mit den 3 Kanälen des RGBW-Controllers.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Bedienung ist dadurch etwas anders.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_01 peerChan 0 rgbw_Dim single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_02 peerChan 0 rgbw_Color single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_03 peerChan 0 rgbw_Auto single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 1: Kurzes Drücken schaltet das Licht ein und aus, langes Drücken dimmt hoch bzw. herunter&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 2: Kurzes Drücken springt um einen Schritt im Farbkreis nach oben bzw unten, langes Drücken fährt im Farbkreis nach oben bzw unten&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 3: Kurzes Drücken schaltet den nächsthöheren Automatikmodus ein, langes den niedrigeren. &amp;lt;br&amp;gt;&lt;br /&gt;
Um die Automatik auszuschalten und den aktuellen Farbton einzufrieren, kurz auf Taste 2 (Farbe) drücken.&lt;br /&gt;
Auch hier springen die Automatikmodi weiter. Beim Durchfahren des Farbkreises nach unten oben wird aber (warum auch immer) über weiß hinweg nach rot gesprungen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ein HomeMatic 2-Kanal Funk-Sender (HM-RC-2-PBU-FM) kann wie folgt mit dem Dim-Kanal gepeert werden. Mit kurzem Druck nach oben/unten werden die LEDs ein-/ausgeschaltet und mit langem Druck hoch- und runtergedimmt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster2_Btn_01 peerChan 0 rgbw_Dim dual set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Readings im Dim Kanal ===&lt;br /&gt;
&lt;br /&gt;
Die Readings level, pct und state liefern den aktuellen Dim-Level (0 = aus, 100 = maximale Helligkeit) zurück.&lt;br /&gt;
&lt;br /&gt;
=== Readings im Color Kanal ===&lt;br /&gt;
&lt;br /&gt;
Die Readings level, pct und state liefern (derzeit) den aktuellen Farbwert zurück (0 = rot, 100 = weiß).&lt;br /&gt;
&lt;br /&gt;
=== Readings im Auto Kanal ===&lt;br /&gt;
&lt;br /&gt;
Die Readings level, pct und state liefern (derzeit) den aktuellen Modus, geteilt durch 2 (0=aus, 0.5=Farbautomatik langsam, ..., 3=TV-Simulation) zurück.&lt;br /&gt;
&lt;br /&gt;
=== Events Auszug ===&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
&lt;br /&gt;
== Logging/Graph. Darstellung ==&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Bedienungsanleitung: [http://files.elv.de/Assets/Produkte/14/1419/141952/Downloads/141952_rgbw_controller_um.pdf]&lt;br /&gt;
* Produktseite ELV: [http://www.elv.de/homematic-funk-rgbw-controller-bausatz.html] &lt;br /&gt;
* Diskussion im FHEM Forum: [http://forum.fhem.de/index.php/topic,39719.0.html]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Dimmer]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=17605</id>
		<title>HM-LC-RGBW-WM Funk-RGBW-Controller</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=17605"/>
		<updated>2016-11-29T18:44:28Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{Todo|Dieses Device ist seit Anfang Oktober 2015 als Bausatz auf dem Markt - dieser Artikel ist noch im Aufbau - bitte Verständnis für Unvollständigkeiten und fehlende Bereiche}}&lt;br /&gt;
&lt;br /&gt;
{{Infobox Hardware&lt;br /&gt;
|Bild=HM-LC-RGBW-WM.jpg&lt;br /&gt;
|Bildbeschreibung=HomeMatic Funk-RGBW-Controller &lt;br /&gt;
|HWProtocol=HomeMatic&lt;br /&gt;
|HWType=Dimmer&lt;br /&gt;
|HWCategory=HomeMatic&lt;br /&gt;
|HWComm=868&amp;amp;nbsp;MHz&lt;br /&gt;
|HWChannels=3&lt;br /&gt;
|HWVoltage=12-24 V DC&lt;br /&gt;
|HWPowerConsumption=15 mA max. (LED&#039;s aus)&lt;br /&gt;
|HWPoweredBy=externe Stromversorgung&lt;br /&gt;
|HWSize=89x99x26mm&lt;br /&gt;
|HWDeviceFHEM=[http://fhem.de/commandref.html#CUL_HM CUL_HM]&lt;br /&gt;
|HWManufacturer=ELV / eQ-3 &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
Der Funk-RGBW-Controller erlaubt das Dimmen von 12/24 Volt Gleichstrom LED-Stripes mit gemeinsamer Anode (+). Es können max. 34W pro Kanal angesteuert werden.&lt;br /&gt;
&lt;br /&gt;
Im Oktober 2015 hat die Auslieferung der Geräte als (einfacher) Bausatz begonnen. Zusätzlich ist das Gerät als &amp;quot;fertig aufgebauter Bausatz&amp;quot; mit einem Aufpreis (derzeit 30 Euro) erhältlich.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Technische Daten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Gewicht: 90 g&lt;br /&gt;
&lt;br /&gt;
== Anwendungsszenarien ==&lt;br /&gt;
&lt;br /&gt;
Der Controller ist für die Montage an Ebenen Flächen gedacht. Es ist eine eigene vorhandene 12/24V Stromversorgung notwendig (nicht im Lieferumfang enthalten). Der Controller besitzt Schraubklemmen zum direkten Anschluss von LED-Stripes. Es ist dabei auf die max. zulässige Leistung pro Kanal zu achten. Diese kann je nach Stripe variieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
 &lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
* Die Farbe weiß zusammen mit rot, grün oder blau zu mischen ist offenbar nicht möglich. &lt;br /&gt;
* Unklar ist, wie neue Programme erstellt und gespeichert werden können.&lt;br /&gt;
* Bei langsamen Farb- und Helligkeitsänderungen sind deutliche Farb- und Helligkeitssprünge wahrnehmbar, da die Änderung nicht kontinuierlich abläuft, sondern sprunghaft.&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit FHEM ==&lt;br /&gt;
&lt;br /&gt;
Der Controller hat drei Kanäle, die jeweils verschiedene Befehle ermöglichen:&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Dim Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe dauerhaft ein. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-for-timer &amp;lt;ontime&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe ein und nach &amp;lt;ontime&amp;gt; Sekunden wieder aus. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-till &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe ein und um &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; Uhr wieder aus. &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; hat das Format hh:mm:ss&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; off&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs dauerhaft aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; press&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sanft ausgeschaltet. Sind sie ausgeschaltet, werden sie mit der zuletzt eingestellten Farbe sanft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; toggle&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sofort ausgeschaltet. Sind sie ausgeschaltet, werden sie mit der zuletzt eingestellten Farbe sofort eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; pct&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die LEDs werden auf den angegebenen Helligkeitswert gesetzt. pct ist ein Wert von 0-100 (Prozent).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; up&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die LEDs werden um 10% hoch gedimmt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; down&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die LEDs werden um 10% herunter gedimmt.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Color Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightCol &amp;lt;bright&amp;gt; &amp;lt;colVal&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. Die LED-Farbe ist in allen Phasen gleich.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; regelt die Helligkeit in der Duration-Phase und geht von 0 (=0%) bis 100 (=100%)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colVal&amp;gt;&#039;&#039;&#039; regelt die Farbe in der Ramp- und Duration-Phase und geht von 0 bis 100:&amp;lt;br&amp;gt;&lt;br /&gt;
0 = reines Rot, 33 = Grün, 66.5 = Blau, 99.5 = Rot mit minimalem Blauanteil, 100 = Weiß&amp;lt;br&amp;gt;&lt;br /&gt;
Werte dazwischen ergeben Mischfarben, z.B. 8 = Gelb, 75 = Lila. Weiß zusammen mit R, G oder B zu mischen ist offenbar nicht möglich. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. Ein Wert von 0 lässt die LEDs dauerhaft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Auto Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightAuto &amp;lt;bright&amp;gt; &amp;lt;colProg&amp;gt; &amp;lt;min&amp;gt; &amp;lt;max&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analog zum brightCol-Befehl im Color-Kanal gibt es eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Grund-Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. In beiden Phasen wird ein vordefiniertes Programm abgespielt und während dessen blinkt die Automatiktaste regelmäßig 1x lang.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; steuert die Grund-Helligkeit analog zum brightCol-Befehl im Color-Kanal. Je nach Programm schwankt die Helligkeit während der Programmausführung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colProg&amp;gt;&#039;&#039;&#039; definiert welches Programm abgespielt wird. Im Auslieferungszustand sind folgende Programm-Nummern vorhanden:&lt;br /&gt;
&lt;br /&gt;
1: Farbverlauf langsam (Geschwindigkeit Farbwechsel: 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang, default: 20 Sekunden). &lt;br /&gt;
Der Farbverlauf geht von colVal &amp;lt;min&amp;gt; bis colVal &amp;lt;max&amp;gt;. colVal ist analog zum brightCol-Befehl im Color-Kanal. Nach der &amp;lt;max&amp;gt; Farbe geht es sofort bei der &amp;lt;min&amp;gt; Farbe weiter. Das kann zu Farbsprüngen führen. Die Geschwindigkeit des Farbwechsels kann mit dem Register colChangeSpeed geändert werden (default: colChangeSpeed = 10 Sekunden pro Durchgang). In Programm 1 dauert ein Durchgang von Farbe 0 (&amp;lt;min&amp;gt; = 0) bis Farbe 200 (&amp;lt;max&amp;gt; = 200) genau 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden (default also 20 Sekunden). Wenn weniger Farben durchlaufen werden, ist der Durchlauf entsprechend schneller.&amp;lt;br&amp;gt;&lt;br /&gt;
Beinhaltet der Farbbereich den Wert 200, so wird auch weiß angesteuert. Beim Einschalten der Automatikmodi über eine gepeerte Fernbedienung (oder bei der Bedienung über virtuelle Buttons) ist dies nicht der Fall, Weiß wird dann ausgespart.&lt;br /&gt;
&lt;br /&gt;
2: Farbverlauf normal (Geschwindigkeit Farbwechsel: &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit normaler Geschwindigkeit (default: 10 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
3: Farbverlauf schnell (Geschwindigkeit Farbwechsel: 0.5 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit doppelter Geschwindigkeit (default: 5 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
4: Kaminfeuer (rotes Licht, das ein Feuer simuliert). &amp;lt;min&amp;gt; und &amp;lt;max&amp;gt; haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
5: Wasserfall (blaues Licht, das die Helligkeit verändert). &amp;lt;min&amp;gt; und &amp;lt;max&amp;gt; haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
6: TV-Simulation (Farb- und Helligkeitsschwankungen simulieren ein eingeschaltetes TV-Gerät, dient zur Abwehr von Einbrechern). &amp;lt;min&amp;gt; und &amp;lt;max&amp;gt; haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;min&amp;gt;&#039;&#039;&#039; siehe Programme 1 bis 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;max&amp;gt;&#039;&#039;&#039; siehe Programme 1 bis 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. &amp;lt;br&amp;gt;&lt;br /&gt;
Eine Ansteuerung mit &amp;lt;duration&amp;gt; 0 als Dauerbetrieb ist im Automatikmodus offenbar nicht möglich. (?)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
=== Peering ===&lt;br /&gt;
Die folgenden Befehle peeren alle Tasten eines HomeMatic 6-fach Tasters (HM-PB-6-WM55) mit den 3 Kanälen des RGBW-Controllers mit dem Namen &#039;&#039;&#039;rgbw&#039;&#039;&#039;. Die Bedienung ist dann wie auf S. 12+13 der Bedienungsanleitung beschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_01 peerChan 0 rgbw_Dim dual set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_03 peerChan 0 rgbw_Color dual set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_05 peerChan 0 rgbw_Auto dual set&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Taste 1: Kurzes Drücken schaltet das Licht aus, langes Drücken dimmt herunter&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 2: Kurzes Drücken schaltet das Licht ein, langes Drücken dimmt herauf&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 3: Kurzes Drücken springt um einen Schritt im Farbkreis nach unten, langes Drücken fährt im Farbkreis nach unten&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 4: Kurzes Drücken springt um einen Schritt im Farbkreis nach oben, langes Drücken fährt im Farbkreis nach oben&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 5: Kurzes Drücken schaltet den Automatikmodus aus, langes schaltet den nächstniedrigeren ein&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 6: Kurzes Drücken schaltet den Automatikmodus 1 ein, langes den nächsthöheren&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hinweise:&amp;lt;br&amp;gt;&lt;br /&gt;
Die Automatikmodi springen beim Durchschalten vom höchsten (TV) zum niedrigsten (Farbwechsel langsam) und umgekehrt.&amp;lt;br&amp;gt;&lt;br /&gt;
Das Durchfahren des Farbkreises hält immer bei Weiß an.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die folgenden Befehle peeren die ersten 3 Tasten (=Kanäle) eines HomeMatic 6-fach Tasters (HM-PB-6-WM55) mit den 3 Kanälen des RGBW-Controllers.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Bedienung ist dadurch etwas anders.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_01 peerChan 0 rgbw_Dim single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_02 peerChan 0 rgbw_Color single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_03 peerChan 0 rgbw_Auto single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 1: Kurzes Drücken schaltet das Licht ein und aus, langes Drücken dimmt hoch bzw. herunter&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 2: Kurzes Drücken springt um einen Schritt im Farbkreis nach oben bzw unten, langes Drücken fährt im Farbkreis nach oben bzw unten&amp;lt;br&amp;gt;&lt;br /&gt;
Taste 3: Kurzes Drücken schaltet den nächsthöheren Automatikmodus ein, langes den niedrigeren. &amp;lt;br&amp;gt;&lt;br /&gt;
Um die Automatik auszuschalten und den aktuellen Farbton einzufrieren, kurz auf Taste 2 (Farbe) drücken.&lt;br /&gt;
Auch hier springen die Automatikmodi weiter. Beim Durchfahren des Farbkreises nach unten oben wird aber (warum auch immer) über weiß hinweg nach rot gesprungen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ein HomeMatic 2-Kanal Funk-Sender (HM-RC-2-PBU-FM) kann wie folgt mit dem Dim-Kanal gepeert werden. Mit kurzem Druck nach oben/unten werden die LEDs ein-/ausgeschaltet und mit langem Druck hoch- und runtergedimmt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster2_Btn_01 peerChan 0 rgbw_Dim dual set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Readings im Dim Kanal ===&lt;br /&gt;
&lt;br /&gt;
Die Readings level, pct und state liefern den aktuellen Dim-Level (0 = aus, 100 = maximale Helligkeit) zurück.&lt;br /&gt;
&lt;br /&gt;
=== Readings im Color Kanal ===&lt;br /&gt;
&lt;br /&gt;
Die Readings level, pct und state liefern (derzeit) den aktuellen Farbwert zurück (0 = rot, 100 = weiß).&lt;br /&gt;
&lt;br /&gt;
=== Readings im Auto Kanal ===&lt;br /&gt;
&lt;br /&gt;
Die Readings level, pct und state liefern (derzeit) den aktuellen Modus, geteilt durch 2 (0=aus, 0.5=Farbautomatik langsam, ..., 3=TV-Simulation) zurück.&lt;br /&gt;
&lt;br /&gt;
=== Events Auszug ===&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
&lt;br /&gt;
== Logging/Graph. Darstellung ==&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Bedienungsanleitung: [http://files.elv.de/Assets/Produkte/14/1419/141952/Downloads/141952_rgbw_controller_um.pdf]&lt;br /&gt;
* Produktseite ELV: [http://www.elv.de/homematic-funk-rgbw-controller-bausatz.html] &lt;br /&gt;
* Diskussion im FHEM Forum: [http://forum.fhem.de/index.php/topic,39719.0.html]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Dimmer]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=14325</id>
		<title>HM-LC-RGBW-WM Funk-RGBW-Controller</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=14325"/>
		<updated>2016-02-21T19:16:08Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{Todo|Dieses Device ist seit Anfang Oktober 2015 als Bausatz auf dem Markt - dieser Artikel ist noch im Aufbau - bitte Verständnis für Unvollständigkeiten und fehlende Bereiche}}&lt;br /&gt;
&lt;br /&gt;
{{Infobox Hardware&lt;br /&gt;
|Bild=HM-LC-RGBW-WM.jpg&lt;br /&gt;
|Bildbeschreibung=HomeMatic Funk-RGBW-Controller &lt;br /&gt;
|HWProtocol=HomeMatic&lt;br /&gt;
|HWType=Dimmer&lt;br /&gt;
|HWCategory=HomeMatic&lt;br /&gt;
|HWComm=868&amp;amp;nbsp;MHz&lt;br /&gt;
|HWChannels=3&lt;br /&gt;
|HWVoltage=12-24 V DC&lt;br /&gt;
|HWPowerConsumption=15 mA max. (LED&#039;s aus)&lt;br /&gt;
|HWPoweredBy=externe Stromversorgung&lt;br /&gt;
|HWSize=89x99x26mm&lt;br /&gt;
|HWDeviceFHEM=[http://fhem.de/commandref.html#CUL_HM CUL_HM]&lt;br /&gt;
|HWManufacturer=ELV / eQ-3 &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
Der Funk-RGBW-Controller erlaubt das Dimmen von 12/24 Volt Gleichstrom LED-Stripes mit gemeinsamer Anode (+). Es können max. 34W pro Kanal angesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Technische Daten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Gewicht: 90 g&lt;br /&gt;
&lt;br /&gt;
== Anwendungsszenarien ==&lt;br /&gt;
&lt;br /&gt;
Der Controller ist für die Montage an Ebenen Flächen gedacht. Es ist eine eigene vorhandene 12/24V Stromversorgung notwendig (nicht im Lieferumfang enthalten). Direkt am Controller können dann LED-Stripes direkt angeklemmt werden. Es ist dabei auf die max. zulässige Leistung pro Kanal zu achten. Diese kann je nach Stripe variieren.&lt;br /&gt;
&lt;br /&gt;
Im Oktober 2015 hat die Auslieferung der Geräte als (einfacher) Bausatz begonnen.&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
 &lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
* Die Befehle im Dim Kanal sind noch nicht vollständig implementiert.&lt;br /&gt;
* Die Farbe weiß zusammen mit rot, grün oder blau zu mischen ist offenbar nicht möglich. &lt;br /&gt;
* Unklar ist, wie neue Programme erstellt und gespeichert werden können.&lt;br /&gt;
* Bei langsamen Farb- und Helligkeitsänderungen sind deutliche Farb- und Helligkeitssprünge wahrnehmbar, da die Änderung nicht kontinuierlich abläuft, sondern sprunghaft.&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit FHEM ==&lt;br /&gt;
&lt;br /&gt;
Der Controller hat drei Kanäle, die jeweils verschiedene Befehle ermöglichen:&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Dim Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe dauerhaft ein. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-for-timer &amp;lt;ontime&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe ein und nach &amp;lt;ontime&amp;gt; Sekunden wieder aus. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-till &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe ein und um &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; Uhr wieder aus. &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; hat das Format hh:mm:ss&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; off&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs dauerhaft aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; press&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sanft ausgeschaltet. Sind sie ausgeschaltet, werden sie mit der zuletzt eingestellten Farbe sanft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; toogle&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sofort ausgeschaltet. Sind sie ausgeschaltet, werden sie mit der zuletzt eingestellten Farbe sofort eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; pct&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; up&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; down&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Color Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightCol &amp;lt;bright&amp;gt; &amp;lt;colVal&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. Die LED-Farbe ist in allen Phasen gleich.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; regelt die Helligkeit in der Duration-Phase und geht von 0 (=0%) bis 200 (=100%)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colVal&amp;gt;&#039;&#039;&#039; regelt die Farbe in der Ramp- und Duration-Phase und geht von 0 bis 200:&amp;lt;br&amp;gt;&lt;br /&gt;
0 = Rot, 66 = Grün, 133 = Blau, 199 = Rot, 200 = Weiß&amp;lt;br&amp;gt;&lt;br /&gt;
Werte dazwischen ergeben Mischfarben, z.B. 15 = Gelb, 150 = Lila. Weiß zusammen mit R, G oder B zu mischen ist offenbar nicht möglich. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. Ein Wert von 0 lässt die LEDs dauerhaft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Auto Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightAuto &amp;lt;bright&amp;gt; &amp;lt;colProg&amp;gt; &amp;lt;min&amp;gt; &amp;lt;max&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analog zum brightCol-Befehl im Color-Kanal gibt es eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Grund-Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. In beiden Phasen wird ein vordefiniertes Programm abgespielt und während dessen blinkt die Automatiktaste regelmäßig 1x lang.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; steuert die Grund-Helligkeit analog zum brightCol-Befehl im Color-Kanal. Je nach Programm schwankt die Helligkeit während der Programmausführung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colProg&amp;gt;&#039;&#039;&#039; definiert welches Programm abgespielt wird. Im Auslieferungszustand sind folgende Programm-Nummern vorhanden:&lt;br /&gt;
&lt;br /&gt;
1: Farbverlauf langsam (Geschwindigkeit Farbwechsel: 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang, default: 20 Sekunden). &lt;br /&gt;
Der Farbverlauf geht von colVal &amp;lt;min&amp;gt; bis colVal &amp;lt;max&amp;gt;. colVal ist analog zum brightCol-Befehl im Color-Kanal. Nach der &amp;lt;max&amp;gt; Farbe geht es sofort bei der &amp;lt;min&amp;gt; Farbe weiter. Das kann zu Farbsprüngen führen. Die Geschwindigkeit des Farbwechsels kann mit dem Register colChangeSpeed geändert werden (default: colChangeSpeed = 10 Sekunden pro Durchgang). In Programm 1 dauert ein Durchgang von Farbe 0 (&amp;lt;min&amp;gt; = 0) bis Farbe 200 (&amp;lt;max&amp;gt; = 200) genau 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden (default also 20 Sekunden). Wenn weniger Farben durchlaufen werden, ist der Durchlauf entsprechend schneller.&lt;br /&gt;
&lt;br /&gt;
2: Farbverlauf normal (Geschwindigkeit Farbwechsel: &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit normaler Geschwindigkeit (default: 10 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
3: Farbverlauf schnell (Geschwindigkeit Farbwechsel: 0.5 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit doppelter Geschwindigkeit (default: 5 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
4: Kaminfeuer (rotes Licht, das ein Feuer simuliert). &amp;lt;min&amp;gt; und &amp;lt;max&amp;gt; haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
5: Wasserfall (blaues Licht, das die Helligkeit verändert). &amp;lt;min&amp;gt; und &amp;lt;max&amp;gt; haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
6: TV-Simulation (Farb- und Helligkeitsschwankungen simulieren ein eingeschaltetes TV-Gerät, dient zur Abwehr von Einbrechern). &amp;lt;min&amp;gt; und &amp;lt;max&amp;gt; haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;min&amp;gt;&#039;&#039;&#039; siehe Programme 1 bis 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;max&amp;gt;&#039;&#039;&#039; siehe Programme 1 bis 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
=== Peering ===&lt;br /&gt;
Die folgenden Befehle peeren die ersten 3 Tasten (=Kanäle) eines HomeMatic 6-fach Tasters (HM-PB-6-WM55) mit den 3 Kanälen des RGBW-Controllers. Die Bedienung ist dann in etwa wie auf S. 12+13 der Bedienungsanleitung beschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_01 peerChan 0 rgbw_Dim single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_02 peerChan 0 rgbw_Color single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_03 peerChan 0 rgbw_Auto single set&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein HomeMatic 2-Kanal Funk-Sender (HM-RC-2-PBU-FM) kann wie folgt mit dem Dim-Kanal gepeert werden. Mit kurzem Druck nach oben/unten werden die LEDs ein-/ausgeschaltet und mit langem Druck hoch- und runtergedimmt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster2_Btn_01 peerChan 0 rgbw_Dim dual set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Readings im Dim Kanal ===&lt;br /&gt;
&lt;br /&gt;
Die Readings level, pct und state liefern den aktuellen Dim-Level (0 = aus, 100 = maximale Helligkeit) zurück.&lt;br /&gt;
&lt;br /&gt;
=== Readings im Color Kanal ===&lt;br /&gt;
&lt;br /&gt;
=== Readings im Auto Kanal ===&lt;br /&gt;
&lt;br /&gt;
=== Events Auszug ===&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
&lt;br /&gt;
== Logging/Graph. Darstellung ==&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Bedienungsanleitung: [http://files.elv.de/Assets/Produkte/14/1419/141952/Downloads/141952_rgbw_controller_um.pdf]&lt;br /&gt;
* Produktseite ELV: [http://www.elv.de/homematic-funk-rgbw-controller-bausatz.html] &lt;br /&gt;
* Diskussion im FHEM Forum: [http://forum.fhem.de/index.php/topic,39719.0.html]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Dimmer]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=14310</id>
		<title>HM-LC-RGBW-WM Funk-RGBW-Controller</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=14310"/>
		<updated>2016-02-20T21:41:16Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* Befehle im Auto Kanal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{Todo|Dieses Device ist seit Anfang Oktober 2015 als Bausatz auf dem Markt - dieser Artikel ist noch im Aufbau - bitte Verständnis für Unvollständigkeiten und fehlende Bereiche}}&lt;br /&gt;
&lt;br /&gt;
{{Infobox Hardware&lt;br /&gt;
|Bild=HM-LC-RGBW-WM.jpg&lt;br /&gt;
|Bildbeschreibung=HomeMatic Funk-RGBW-Controller &lt;br /&gt;
|HWProtocol=HomeMatic&lt;br /&gt;
|HWType=Dimmer&lt;br /&gt;
|HWCategory=HomeMatic&lt;br /&gt;
|HWComm=868&amp;amp;nbsp;MHz&lt;br /&gt;
|HWChannels=3&lt;br /&gt;
|HWVoltage=12-24 V DC&lt;br /&gt;
|HWPowerConsumption=15 mA max. (LED&#039;s aus)&lt;br /&gt;
|HWPoweredBy=externe Stromversorgung&lt;br /&gt;
|HWSize=89x99x26mm&lt;br /&gt;
|HWDeviceFHEM=[http://fhem.de/commandref.html#CUL_HM CUL_HM]&lt;br /&gt;
|HWManufacturer=ELV / eQ-3 &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
Der Funk-RGBW-Controller erlaubt das Dimmen von 12/24 Volt Gleichstrom LED-Stripes mit gemeinsamer Anode (+). Es können max. 34W pro Kanal angesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Technische Daten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Gewicht: 90 g&lt;br /&gt;
&lt;br /&gt;
== Anwendungsszenarien ==&lt;br /&gt;
&lt;br /&gt;
Der Controller ist für die Montage an Ebenen Flächen gedacht. Es ist eine eigene vorhandene 12/24V Stromversorgung notwendig (nicht im Lieferumfang enthalten). Direkt am Controller können dann LED-Stripes direkt angeklemmt werden. Es ist dabei auf die max. zulässige Leistung pro Kanal zu achten. Diese kann je nach Stripe variieren.&lt;br /&gt;
&lt;br /&gt;
Im Oktober 2015 hat die Auslieferung der Geräte als (einfacher) Bausatz begonnen.&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
 &lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
* Die Befehle im Dim Kanal sind noch nicht vollständig implementiert.&lt;br /&gt;
* Die Farbe weiß zusammen mit rot, grün oder blau zu mischen ist offenbar nicht möglich. &lt;br /&gt;
* Unklar ist, wie neue Programme erstellt und gespeichert werden können.&lt;br /&gt;
* Bei langsamen Farb- und Helligkeitsänderungen sind deutliche Farb- und Helligkeitssprünge wahrnehmbar, da die Änderung nicht kontinuierlich abläuft, sondern sprunghaft.&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit FHEM ==&lt;br /&gt;
&lt;br /&gt;
Der Controller hat drei Kanäle, die jeweils verschiedene Befehle ermöglichen:&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Dim Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe dauerhaft ein. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-for-timer &amp;lt;ontime&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe ein und nach &amp;lt;ontime&amp;gt; Sekunden wieder aus. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-till &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe ein und um &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; Uhr wieder aus. &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; hat das Format hh:mm:ss&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; off&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs dauerhaft aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; press&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sanft ausgeschaltet. Sind sie ausgeschaltet, werden sie mit der zuletzt eingestellten Farbe sanft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; toogle&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sofort ausgeschaltet. Sind sie ausgeschaltet, werden sie mit der zuletzt eingestellten Farbe sofort eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; pct&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; up&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; down&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Color Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightCol &amp;lt;bright&amp;gt; &amp;lt;colVal&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. Die LED-Farbe ist in allen Phasen gleich.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; regelt die Helligkeit in der Duration-Phase und geht von 0 (=0%) bis 200 (=100%)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colVal&amp;gt;&#039;&#039;&#039; regelt die Farbe in der Ramp- und Duration-Phase und geht von 0 bis 200:&amp;lt;br&amp;gt;&lt;br /&gt;
0 = Rot, 66 = Grün, 133 = Blau, 199 = Rot, 200 = Weiß&amp;lt;br&amp;gt;&lt;br /&gt;
Werte dazwischen ergeben Mischfarben, z.B. 15 = Gelb, 150 = Lila. Weiß zusammen mit R, G oder B zu mischen ist offenbar nicht möglich. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. Ein Wert von 0 lässt die LEDs dauerhaft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Auto Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightAuto &amp;lt;bright&amp;gt; &amp;lt;colProg&amp;gt; &amp;lt;min&amp;gt; &amp;lt;max&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analog zum brightCol-Befehl im Color-Kanal gibt es eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Grund-Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. In beiden Phasen wird ein vordefiniertes Programm abgespielt und während dessen blinkt die Automatiktaste regelmäßig 1x lang.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; steuert die Grund-Helligkeit analog zum brightCol-Befehl im Color-Kanal. Je nach Programm schwankt die Helligkeit während der Programmausführung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colProg&amp;gt;&#039;&#039;&#039; definiert welches Programm abgespielt wird. Im Auslieferungszustand sind folgende Programm-Nummern vorhanden:&lt;br /&gt;
&lt;br /&gt;
1: Farbverlauf langsam (Geschwindigkeit Farbwechsel: 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang, default: 20 Sekunden). &lt;br /&gt;
Der Farbverlauf geht von colVal &amp;lt;min&amp;gt; bis colVal &amp;lt;max&amp;gt;. colVal ist analog zum brightCol-Befehl im Color-Kanal. Nach der &amp;lt;max&amp;gt; Farbe geht es sofort bei der &amp;lt;min&amp;gt; Farbe weiter. Das kann zu Farbsprüngen führen. Die Geschwindigkeit des Farbwechsels kann mit dem Register colChangeSpeed geändert werden (default: colChangeSpeed = 10 Sekunden pro Durchgang). In Programm 1 dauert ein Durchgang von Farbe 0 (&amp;lt;min&amp;gt; = 0) bis Farbe 200 (&amp;lt;max&amp;gt; = 200) genau 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden (default also 20 Sekunden). Wenn weniger Farben durchlaufen werden, ist der Durchlauf entsprechend schneller.&lt;br /&gt;
&lt;br /&gt;
2: Farbverlauf normal (Geschwindigkeit Farbwechsel: &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit normaler Geschwindigkeit (default: 10 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
3: Farbverlauf schnell (Geschwindigkeit Farbwechsel: 0.5 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit doppelter Geschwindigkeit (default: 5 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
4: Kaminfeuer (rotes Licht, das ein Feuer simuliert). &amp;lt;min&amp;gt; und &amp;lt;max&amp;gt; haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
5: Wasserfall (blaues Licht, das die Helligkeit verändert). &amp;lt;min&amp;gt; und &amp;lt;max&amp;gt; haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
6: TV-Simulation (Farb- und Helligkeitsschwankungen simulieren ein eingeschaltetes TV-Gerät, dient zur Abwehr von Einbrechern). &amp;lt;min&amp;gt; und &amp;lt;max&amp;gt; haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;min&amp;gt;&#039;&#039;&#039; siehe Programme 1 bis 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;max&amp;gt;&#039;&#039;&#039; siehe Programme 1 bis 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
=== Peering ===&lt;br /&gt;
Die folgenden Befehle peeren die ersten 3 Tasten (=Kanäle) eines HomeMatic 6-fach Tasters (HM-PB-6-WM55) mit den 3 Kanälen des RGBW-Controllers. Die Bedienung ist dann in etwa wie auf S. 12+13 der Bedienungsanleitung beschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_01 peerChan 0 rgbw_Dim single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_02 peerChan 0 rgbw_Color single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_03 peerChan 0 rgbw_Auto single set&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein HomeMatic 2-Kanal Funk-Sender (HM-RC-2-PBU-FM) kann wie folgt mit dem Dim-Kanal gepeert werden. Mit kurzem Druck nach oben/unten werden die LEDs ein-/ausgeschaltet und mit langem Druck hoch- und runtergedimmt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster2_Btn_01 peerChan 0 rgbw_Dim dual set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Readings ===&lt;br /&gt;
&lt;br /&gt;
=== Events Auszug ===&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
&lt;br /&gt;
== Logging/Graph. Darstellung ==&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Bedienungsanleitung: [http://files.elv.de/Assets/Produkte/14/1419/141952/Downloads/141952_rgbw_controller_um.pdf]&lt;br /&gt;
* Produktseite ELV: [http://www.elv.de/homematic-funk-rgbw-controller-bausatz.html] &lt;br /&gt;
* Diskussion im FHEM Forum: [http://forum.fhem.de/index.php/topic,39719.0.html]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Dimmer]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=14309</id>
		<title>HM-LC-RGBW-WM Funk-RGBW-Controller</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=14309"/>
		<updated>2016-02-20T21:40:00Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* Probleme */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{Todo|Dieses Device ist seit Anfang Oktober 2015 als Bausatz auf dem Markt - dieser Artikel ist noch im Aufbau - bitte Verständnis für Unvollständigkeiten und fehlende Bereiche}}&lt;br /&gt;
&lt;br /&gt;
{{Infobox Hardware&lt;br /&gt;
|Bild=HM-LC-RGBW-WM.jpg&lt;br /&gt;
|Bildbeschreibung=HomeMatic Funk-RGBW-Controller &lt;br /&gt;
|HWProtocol=HomeMatic&lt;br /&gt;
|HWType=Dimmer&lt;br /&gt;
|HWCategory=HomeMatic&lt;br /&gt;
|HWComm=868&amp;amp;nbsp;MHz&lt;br /&gt;
|HWChannels=3&lt;br /&gt;
|HWVoltage=12-24 V DC&lt;br /&gt;
|HWPowerConsumption=15 mA max. (LED&#039;s aus)&lt;br /&gt;
|HWPoweredBy=externe Stromversorgung&lt;br /&gt;
|HWSize=89x99x26mm&lt;br /&gt;
|HWDeviceFHEM=[http://fhem.de/commandref.html#CUL_HM CUL_HM]&lt;br /&gt;
|HWManufacturer=ELV / eQ-3 &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
Der Funk-RGBW-Controller erlaubt das Dimmen von 12/24 Volt Gleichstrom LED-Stripes mit gemeinsamer Anode (+). Es können max. 34W pro Kanal angesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Technische Daten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Gewicht: 90 g&lt;br /&gt;
&lt;br /&gt;
== Anwendungsszenarien ==&lt;br /&gt;
&lt;br /&gt;
Der Controller ist für die Montage an Ebenen Flächen gedacht. Es ist eine eigene vorhandene 12/24V Stromversorgung notwendig (nicht im Lieferumfang enthalten). Direkt am Controller können dann LED-Stripes direkt angeklemmt werden. Es ist dabei auf die max. zulässige Leistung pro Kanal zu achten. Diese kann je nach Stripe variieren.&lt;br /&gt;
&lt;br /&gt;
Im Oktober 2015 hat die Auslieferung der Geräte als (einfacher) Bausatz begonnen.&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
 &lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
* Die Befehle im Dim Kanal sind noch nicht vollständig implementiert.&lt;br /&gt;
* Die Farbe weiß zusammen mit rot, grün oder blau zu mischen ist offenbar nicht möglich. &lt;br /&gt;
* Unklar ist, wie neue Programme erstellt und gespeichert werden können.&lt;br /&gt;
* Bei langsamen Farb- und Helligkeitsänderungen sind deutliche Farb- und Helligkeitssprünge wahrnehmbar, da die Änderung nicht kontinuierlich abläuft, sondern sprunghaft.&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit FHEM ==&lt;br /&gt;
&lt;br /&gt;
Der Controller hat drei Kanäle, die jeweils verschiedene Befehle ermöglichen:&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Dim Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe dauerhaft ein. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-for-timer &amp;lt;ontime&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe ein und nach &amp;lt;ontime&amp;gt; Sekunden wieder aus. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-till &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe ein und um &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; Uhr wieder aus. &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; hat das Format hh:mm:ss&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; off&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs dauerhaft aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; press&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sanft ausgeschaltet. Sind sie ausgeschaltet, werden sie mit der zuletzt eingestellten Farbe sanft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; toogle&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sofort ausgeschaltet. Sind sie ausgeschaltet, werden sie mit der zuletzt eingestellten Farbe sofort eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; pct&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; up&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; down&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Color Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightCol &amp;lt;bright&amp;gt; &amp;lt;colVal&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. Die LED-Farbe ist in allen Phasen gleich.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; regelt die Helligkeit in der Duration-Phase und geht von 0 (=0%) bis 200 (=100%)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colVal&amp;gt;&#039;&#039;&#039; regelt die Farbe in der Ramp- und Duration-Phase und geht von 0 bis 200:&amp;lt;br&amp;gt;&lt;br /&gt;
0 = Rot, 66 = Grün, 133 = Blau, 199 = Rot, 200 = Weiß&amp;lt;br&amp;gt;&lt;br /&gt;
Werte dazwischen ergeben Mischfarben, z.B. 15 = Gelb, 150 = Lila. Weiß zusammen mit R, G oder B zu mischen ist offenbar nicht möglich. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. Ein Wert von 0 lässt die LEDs dauerhaft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Auto Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightAuto &amp;lt;bright&amp;gt; &amp;lt;colProg&amp;gt; &amp;lt;min&amp;gt; &amp;lt;max&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analog zum brightCol-Befehl im Color-Kanal gibt es eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Grund-Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. In beiden Phasen wird ein vordefiniertes Programm abgespielt und während dessen blinkt die Automatiktaste regelmäßig 1x lang.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; steuert die Grund-Helligkeit analog zum brightCol-Befehl im Color-Kanal. Je nach Programm schwankt die Helligkeit während der Programmausführung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colProg&amp;gt;&#039;&#039;&#039; definiert welches Programm abgespielt wird. Im Auslieferungszustand sind folgende Programm-Nummern vorhanden:&lt;br /&gt;
&lt;br /&gt;
1: Farbverlauf langsam (Geschwindigkeit Farbwechsel: 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang, default: 20 Sekunden). &lt;br /&gt;
Der Farbverlauf geht von colVal &amp;lt;min&amp;gt; bis colVal &amp;lt;max&amp;gt;. colVal ist analog zum brightCol-Befehl im Color-Kanal. Nach der &amp;lt;max&amp;gt; Farbe geht es sofort bei der &amp;lt;min&amp;gt; Farbe weiter. Das kann zu Farbsprüngen führen. Die Geschwindigkeit des Farbwechsels kann mit dem Register colChangeSpeed geändert werden (default: colChangeSpeed = 10 Sekunden pro Durchgang). In Programm 1 dauert ein Durchgang von Farbe 0 (&amp;lt;min&amp;gt; = 0) bis Farbe 200 (&amp;lt;max&amp;gt; = 200) genau 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden (default also 20 Sekunden). Wenn weniger Farben durchlaufen werden, ist der Durchlauf entsprechend schneller.&lt;br /&gt;
&lt;br /&gt;
2: Farbverlauf normal (Geschwindigkeit Farbwechsel: &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit normaler Geschwindigkeit (default: 10 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
3: Farbverlauf schnell (Geschwindigkeit Farbwechsel: 0.5 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit doppelter Geschwindigkeit (default: 5 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
4: Kaminfeuer (rotes Licht, das ein Feuer simuliert). Min und Max haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
5: Wasserfall (blaues Licht, das die Helligkeit verändert). Min und Max haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
6: TV-Simulation (Farb- und Helligkeitsschwankungen simulieren ein eingeschaltetes TV-Gerät, dient zur Abwehr von Einbrechern). Min und Max haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;min&amp;gt;&#039;&#039;&#039; siehe Programme 1-3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;max&amp;gt;&#039;&#039;&#039; siehe Programme 1-3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
=== Peering ===&lt;br /&gt;
Die folgenden Befehle peeren die ersten 3 Tasten (=Kanäle) eines HomeMatic 6-fach Tasters (HM-PB-6-WM55) mit den 3 Kanälen des RGBW-Controllers. Die Bedienung ist dann in etwa wie auf S. 12+13 der Bedienungsanleitung beschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_01 peerChan 0 rgbw_Dim single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_02 peerChan 0 rgbw_Color single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_03 peerChan 0 rgbw_Auto single set&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein HomeMatic 2-Kanal Funk-Sender (HM-RC-2-PBU-FM) kann wie folgt mit dem Dim-Kanal gepeert werden. Mit kurzem Druck nach oben/unten werden die LEDs ein-/ausgeschaltet und mit langem Druck hoch- und runtergedimmt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster2_Btn_01 peerChan 0 rgbw_Dim dual set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Readings ===&lt;br /&gt;
&lt;br /&gt;
=== Events Auszug ===&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
&lt;br /&gt;
== Logging/Graph. Darstellung ==&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Bedienungsanleitung: [http://files.elv.de/Assets/Produkte/14/1419/141952/Downloads/141952_rgbw_controller_um.pdf]&lt;br /&gt;
* Produktseite ELV: [http://www.elv.de/homematic-funk-rgbw-controller-bausatz.html] &lt;br /&gt;
* Diskussion im FHEM Forum: [http://forum.fhem.de/index.php/topic,39719.0.html]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Dimmer]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=14301</id>
		<title>HM-LC-RGBW-WM Funk-RGBW-Controller</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=14301"/>
		<updated>2016-02-20T13:59:04Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* Befehle im Dim Kanal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{Todo|Dieses Device ist seit Anfang Oktober 2015 als Bausatz auf dem Markt - dieser Artikel ist noch im Aufbau - bitte Verständnis für Unvollständigkeiten und fehlende Bereiche}}&lt;br /&gt;
&lt;br /&gt;
{{Infobox Hardware&lt;br /&gt;
|Bild=HM-LC-RGBW-WM.jpg&lt;br /&gt;
|Bildbeschreibung=HomeMatic Funk-RGBW-Controller &lt;br /&gt;
|HWProtocol=HomeMatic&lt;br /&gt;
|HWType=Dimmer&lt;br /&gt;
|HWCategory=HomeMatic&lt;br /&gt;
|HWComm=868&amp;amp;nbsp;MHz&lt;br /&gt;
|HWChannels=3&lt;br /&gt;
|HWVoltage=12-24 V DC&lt;br /&gt;
|HWPowerConsumption=15 mA max. (LED&#039;s aus)&lt;br /&gt;
|HWPoweredBy=externe Stromversorgung&lt;br /&gt;
|HWSize=89x99x26mm&lt;br /&gt;
|HWDeviceFHEM=[http://fhem.de/commandref.html#CUL_HM CUL_HM]&lt;br /&gt;
|HWManufacturer=ELV / eQ-3 &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
Der Funk-RGBW-Controller erlaubt das Dimmen von 12/24 Volt Gleichstrom LED-Stripes mit gemeinsamer Anode (+). Es können max. 34W pro Kanal angesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Technische Daten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Gewicht: 90 g&lt;br /&gt;
&lt;br /&gt;
== Anwendungsszenarien ==&lt;br /&gt;
&lt;br /&gt;
Der Controller ist für die Montage an Ebenen Flächen gedacht. Es ist eine eigene vorhandene 12/24V Stromversorgung notwendig (nicht im Lieferumfang enthalten). Direkt am Controller können dann LED-Stripes direkt angeklemmt werden. Es ist dabei auf die max. zulässige Leistung pro Kanal zu achten. Diese kann je nach Stripe variieren.&lt;br /&gt;
&lt;br /&gt;
Im Oktober 2015 hat die Auslieferung der Geräte als (einfacher) Bausatz begonnen.&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
 &lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
* Die Befehle im Dim Kanal sind noch nicht vollständig implementiert.&lt;br /&gt;
* Die Farbe weiß zusammen mit rot, grün oder blau zu mischen ist offenbar nicht möglich. &lt;br /&gt;
* Unklar ist, wie neue Programme erstellt und gespeichert werden können.&lt;br /&gt;
* Bei langsamen Farb- und Helligkeitsänderungen sind deutliche Farb- und Helligskeitssprünge wahrnehmbar, da die Änderung nicht kontinuierlich abläuft, sondern sprunghaft.&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit FHEM ==&lt;br /&gt;
&lt;br /&gt;
Der Controller hat drei Kanäle, die jeweils verschiedene Befehle ermöglichen:&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Dim Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe dauerhaft ein. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-for-timer &amp;lt;ontime&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe ein und nach &amp;lt;ontime&amp;gt; Sekunden wieder aus. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-till &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe ein und um &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; Uhr wieder aus. &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; hat das Format hh:mm:ss&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; off&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs dauerhaft aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; press&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sanft ausgeschaltet. Sind sie ausgeschaltet, werden sie mit der zuletzt eingestellten Farbe sanft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; toogle&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sofort ausgeschaltet. Sind sie ausgeschaltet, werden sie mit der zuletzt eingestellten Farbe sofort eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; pct&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; up&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; down&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Color Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightCol &amp;lt;bright&amp;gt; &amp;lt;colVal&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. Die LED-Farbe ist in allen Phasen gleich.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; regelt die Helligkeit in der Duration-Phase und geht von 0 (=0%) bis 200 (=100%)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colVal&amp;gt;&#039;&#039;&#039; regelt die Farbe in der Ramp- und Duration-Phase und geht von 0 bis 200:&amp;lt;br&amp;gt;&lt;br /&gt;
0 = Rot, 66 = Grün, 133 = Blau, 199 = Rot, 200 = Weiß&amp;lt;br&amp;gt;&lt;br /&gt;
Werte dazwischen ergeben Mischfarben, z.B. 15 = Gelb, 150 = Lila. Weiß zusammen mit R, G oder B zu mischen ist offenbar nicht möglich. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. Ein Wert von 0 lässt die LEDs dauerhaft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Auto Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightAuto &amp;lt;bright&amp;gt; &amp;lt;colProg&amp;gt; &amp;lt;min&amp;gt; &amp;lt;max&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analog zum brightCol-Befehl im Color-Kanal gibt es eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Grund-Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. In beiden Phasen wird ein vordefiniertes Programm abgespielt und während dessen blinkt die Automatiktaste regelmäßig 1x lang.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; steuert die Grund-Helligkeit analog zum brightCol-Befehl im Color-Kanal. Je nach Programm schwankt die Helligkeit während der Programmausführung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colProg&amp;gt;&#039;&#039;&#039; definiert welches Programm abgespielt wird. Im Auslieferungszustand sind folgende Programm-Nummern vorhanden:&lt;br /&gt;
&lt;br /&gt;
1: Farbverlauf langsam (Geschwindigkeit Farbwechsel: 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang, default: 20 Sekunden). &lt;br /&gt;
Der Farbverlauf geht von colVal &amp;lt;min&amp;gt; bis colVal &amp;lt;max&amp;gt;. colVal ist analog zum brightCol-Befehl im Color-Kanal. Nach der &amp;lt;max&amp;gt; Farbe geht es sofort bei der &amp;lt;min&amp;gt; Farbe weiter. Das kann zu Farbsprüngen führen. Die Geschwindigkeit des Farbwechsels kann mit dem Register colChangeSpeed geändert werden (default: colChangeSpeed = 10 Sekunden pro Durchgang). In Programm 1 dauert ein Durchgang von Farbe 0 (&amp;lt;min&amp;gt; = 0) bis Farbe 200 (&amp;lt;max&amp;gt; = 200) genau 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden (default also 20 Sekunden). Wenn weniger Farben durchlaufen werden, ist der Durchlauf entsprechend schneller.&lt;br /&gt;
&lt;br /&gt;
2: Farbverlauf normal (Geschwindigkeit Farbwechsel: &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit normaler Geschwindigkeit (default: 10 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
3: Farbverlauf schnell (Geschwindigkeit Farbwechsel: 0.5 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit doppelter Geschwindigkeit (default: 5 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
4: Kaminfeuer (rotes Licht, das ein Feuer simuliert). Min und Max haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
5: Wasserfall (blaues Licht, das die Helligkeit verändert). Min und Max haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
6: TV-Simulation (Farb- und Helligkeitsschwankungen simulieren ein eingeschaltetes TV-Gerät, dient zur Abwehr von Einbrechern). Min und Max haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;min&amp;gt;&#039;&#039;&#039; siehe Programme 1-3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;max&amp;gt;&#039;&#039;&#039; siehe Programme 1-3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
=== Peering ===&lt;br /&gt;
Die folgenden Befehle peeren die ersten 3 Tasten (=Kanäle) eines HomeMatic 6-fach Tasters (HM-PB-6-WM55) mit den 3 Kanälen des RGBW-Controllers. Die Bedienung ist dann in etwa wie auf S. 12+13 der Bedienungsanleitung beschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_01 peerChan 0 rgbw_Dim single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_02 peerChan 0 rgbw_Color single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_03 peerChan 0 rgbw_Auto single set&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein HomeMatic 2-Kanal Funk-Sender (HM-RC-2-PBU-FM) kann wie folgt mit dem Dim-Kanal gepeert werden. Mit kurzem Druck nach oben/unten werden die LEDs ein-/ausgeschaltet und mit langem Druck hoch- und runtergedimmt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster2_Btn_01 peerChan 0 rgbw_Dim dual set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Readings ===&lt;br /&gt;
&lt;br /&gt;
=== Events Auszug ===&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
&lt;br /&gt;
== Logging/Graph. Darstellung ==&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Bedienungsanleitung: [http://files.elv.de/Assets/Produkte/14/1419/141952/Downloads/141952_rgbw_controller_um.pdf]&lt;br /&gt;
* Produktseite ELV: [http://www.elv.de/homematic-funk-rgbw-controller-bausatz.html] &lt;br /&gt;
* Diskussion im FHEM Forum: [http://forum.fhem.de/index.php/topic,39719.0.html]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Dimmer]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=14300</id>
		<title>HM-LC-RGBW-WM Funk-RGBW-Controller</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=14300"/>
		<updated>2016-02-20T13:58:11Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* Befehle im Dim Kanal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{Todo|Dieses Device ist seit Anfang Oktober 2015 als Bausatz auf dem Markt - dieser Artikel ist noch im Aufbau - bitte Verständnis für Unvollständigkeiten und fehlende Bereiche}}&lt;br /&gt;
&lt;br /&gt;
{{Infobox Hardware&lt;br /&gt;
|Bild=HM-LC-RGBW-WM.jpg&lt;br /&gt;
|Bildbeschreibung=HomeMatic Funk-RGBW-Controller &lt;br /&gt;
|HWProtocol=HomeMatic&lt;br /&gt;
|HWType=Dimmer&lt;br /&gt;
|HWCategory=HomeMatic&lt;br /&gt;
|HWComm=868&amp;amp;nbsp;MHz&lt;br /&gt;
|HWChannels=3&lt;br /&gt;
|HWVoltage=12-24 V DC&lt;br /&gt;
|HWPowerConsumption=15 mA max. (LED&#039;s aus)&lt;br /&gt;
|HWPoweredBy=externe Stromversorgung&lt;br /&gt;
|HWSize=89x99x26mm&lt;br /&gt;
|HWDeviceFHEM=[http://fhem.de/commandref.html#CUL_HM CUL_HM]&lt;br /&gt;
|HWManufacturer=ELV / eQ-3 &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
Der Funk-RGBW-Controller erlaubt das Dimmen von 12/24 Volt Gleichstrom LED-Stripes mit gemeinsamer Anode (+). Es können max. 34W pro Kanal angesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Technische Daten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Gewicht: 90 g&lt;br /&gt;
&lt;br /&gt;
== Anwendungsszenarien ==&lt;br /&gt;
&lt;br /&gt;
Der Controller ist für die Montage an Ebenen Flächen gedacht. Es ist eine eigene vorhandene 12/24V Stromversorgung notwendig (nicht im Lieferumfang enthalten). Direkt am Controller können dann LED-Stripes direkt angeklemmt werden. Es ist dabei auf die max. zulässige Leistung pro Kanal zu achten. Diese kann je nach Stripe variieren.&lt;br /&gt;
&lt;br /&gt;
Im Oktober 2015 hat die Auslieferung der Geräte als (einfacher) Bausatz begonnen.&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
 &lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
* Die Befehle im Dim Kanal sind noch nicht vollständig implementiert.&lt;br /&gt;
* Die Farbe weiß zusammen mit rot, grün oder blau zu mischen ist offenbar nicht möglich. &lt;br /&gt;
* Unklar ist, wie neue Programme erstellt und gespeichert werden können.&lt;br /&gt;
* Bei langsamen Farb- und Helligkeitsänderungen sind deutliche Farb- und Helligskeitssprünge wahrnehmbar, da die Änderung nicht kontinuierlich abläuft, sondern sprunghaft.&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit FHEM ==&lt;br /&gt;
&lt;br /&gt;
Der Controller hat drei Kanäle, die jeweils verschiedene Befehle ermöglichen:&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Dim Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe dauerhaft ein. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-for-timer &amp;lt;ontime&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe ein und nach &amp;lt;ontime&amp;gt; Sekunden wieder aus. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-till &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs mit der zuletzt eingestellten Farbe ein und um &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; Uhr wieder aus. &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; hat das Format hh:mm:ss&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; off&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs dauerhaft aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; press&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sanft ausgeschaltet. Sind sie ausgeschaltet, werden sie mit der zuletzt eingestellten Farbe sanft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; toogle&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sofort ausgeschaltet. Sind sie ausgeschaltet, werden sie mit der zuletzt eingestellten Farbe sofort eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; pct&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; up&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; down&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Color Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightCol &amp;lt;bright&amp;gt; &amp;lt;colVal&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. Die LED-Farbe ist in allen Phasen gleich.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; regelt die Helligkeit in der Duration-Phase und geht von 0 (=0%) bis 200 (=100%)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colVal&amp;gt;&#039;&#039;&#039; regelt die Farbe in der Ramp- und Duration-Phase und geht von 0 bis 200:&amp;lt;br&amp;gt;&lt;br /&gt;
0 = Rot, 66 = Grün, 133 = Blau, 199 = Rot, 200 = Weiß&amp;lt;br&amp;gt;&lt;br /&gt;
Werte dazwischen ergeben Mischfarben, z.B. 15 = Gelb, 150 = Lila. Weiß zusammen mit R, G oder B zu mischen ist offenbar nicht möglich. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. Ein Wert von 0 lässt die LEDs dauerhaft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Auto Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightAuto &amp;lt;bright&amp;gt; &amp;lt;colProg&amp;gt; &amp;lt;min&amp;gt; &amp;lt;max&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analog zum brightCol-Befehl im Color-Kanal gibt es eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Grund-Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. In beiden Phasen wird ein vordefiniertes Programm abgespielt und während dessen blinkt die Automatiktaste regelmäßig 1x lang.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; steuert die Grund-Helligkeit analog zum brightCol-Befehl im Color-Kanal. Je nach Programm schwankt die Helligkeit während der Programmausführung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colProg&amp;gt;&#039;&#039;&#039; definiert welches Programm abgespielt wird. Im Auslieferungszustand sind folgende Programm-Nummern vorhanden:&lt;br /&gt;
&lt;br /&gt;
1: Farbverlauf langsam (Geschwindigkeit Farbwechsel: 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang, default: 20 Sekunden). &lt;br /&gt;
Der Farbverlauf geht von colVal &amp;lt;min&amp;gt; bis colVal &amp;lt;max&amp;gt;. colVal ist analog zum brightCol-Befehl im Color-Kanal. Nach der &amp;lt;max&amp;gt; Farbe geht es sofort bei der &amp;lt;min&amp;gt; Farbe weiter. Das kann zu Farbsprüngen führen. Die Geschwindigkeit des Farbwechsels kann mit dem Register colChangeSpeed geändert werden (default: colChangeSpeed = 10 Sekunden pro Durchgang). In Programm 1 dauert ein Durchgang von Farbe 0 (&amp;lt;min&amp;gt; = 0) bis Farbe 200 (&amp;lt;max&amp;gt; = 200) genau 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden (default also 20 Sekunden). Wenn weniger Farben durchlaufen werden, ist der Durchlauf entsprechend schneller.&lt;br /&gt;
&lt;br /&gt;
2: Farbverlauf normal (Geschwindigkeit Farbwechsel: &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit normaler Geschwindigkeit (default: 10 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
3: Farbverlauf schnell (Geschwindigkeit Farbwechsel: 0.5 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit doppelter Geschwindigkeit (default: 5 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
4: Kaminfeuer (rotes Licht, das ein Feuer simuliert). Min und Max haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
5: Wasserfall (blaues Licht, das die Helligkeit verändert). Min und Max haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
6: TV-Simulation (Farb- und Helligkeitsschwankungen simulieren ein eingeschaltetes TV-Gerät, dient zur Abwehr von Einbrechern). Min und Max haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;min&amp;gt;&#039;&#039;&#039; siehe Programme 1-3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;max&amp;gt;&#039;&#039;&#039; siehe Programme 1-3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
=== Peering ===&lt;br /&gt;
Die folgenden Befehle peeren die ersten 3 Tasten (=Kanäle) eines HomeMatic 6-fach Tasters (HM-PB-6-WM55) mit den 3 Kanälen des RGBW-Controllers. Die Bedienung ist dann in etwa wie auf S. 12+13 der Bedienungsanleitung beschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_01 peerChan 0 rgbw_Dim single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_02 peerChan 0 rgbw_Color single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_03 peerChan 0 rgbw_Auto single set&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein HomeMatic 2-Kanal Funk-Sender (HM-RC-2-PBU-FM) kann wie folgt mit dem Dim-Kanal gepeert werden. Mit kurzem Druck nach oben/unten werden die LEDs ein-/ausgeschaltet und mit langem Druck hoch- und runtergedimmt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster2_Btn_01 peerChan 0 rgbw_Dim dual set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Readings ===&lt;br /&gt;
&lt;br /&gt;
=== Events Auszug ===&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
&lt;br /&gt;
== Logging/Graph. Darstellung ==&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Bedienungsanleitung: [http://files.elv.de/Assets/Produkte/14/1419/141952/Downloads/141952_rgbw_controller_um.pdf]&lt;br /&gt;
* Produktseite ELV: [http://www.elv.de/homematic-funk-rgbw-controller-bausatz.html] &lt;br /&gt;
* Diskussion im FHEM Forum: [http://forum.fhem.de/index.php/topic,39719.0.html]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Dimmer]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=14299</id>
		<title>HM-LC-RGBW-WM Funk-RGBW-Controller</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-LC-RGBW-WM_Funk-RGBW-Controller&amp;diff=14299"/>
		<updated>2016-02-20T13:37:06Z</updated>

		<summary type="html">&lt;p&gt;All-Ex: /* Befehle im Dim Kanal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{Todo|Dieses Device ist seit Anfang Oktober 2015 als Bausatz auf dem Markt - dieser Artikel ist noch im Aufbau - bitte Verständnis für Unvollständigkeiten und fehlende Bereiche}}&lt;br /&gt;
&lt;br /&gt;
{{Infobox Hardware&lt;br /&gt;
|Bild=HM-LC-RGBW-WM.jpg&lt;br /&gt;
|Bildbeschreibung=HomeMatic Funk-RGBW-Controller &lt;br /&gt;
|HWProtocol=HomeMatic&lt;br /&gt;
|HWType=Dimmer&lt;br /&gt;
|HWCategory=HomeMatic&lt;br /&gt;
|HWComm=868&amp;amp;nbsp;MHz&lt;br /&gt;
|HWChannels=3&lt;br /&gt;
|HWVoltage=12-24 V DC&lt;br /&gt;
|HWPowerConsumption=15 mA max. (LED&#039;s aus)&lt;br /&gt;
|HWPoweredBy=externe Stromversorgung&lt;br /&gt;
|HWSize=89x99x26mm&lt;br /&gt;
|HWDeviceFHEM=[http://fhem.de/commandref.html#CUL_HM CUL_HM]&lt;br /&gt;
|HWManufacturer=ELV / eQ-3 &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
Der Funk-RGBW-Controller erlaubt das Dimmen von 12/24 Volt Gleichstrom LED-Stripes mit gemeinsamer Anode (+). Es können max. 34W pro Kanal angesteuert werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Technische Daten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Gewicht: 90 g&lt;br /&gt;
&lt;br /&gt;
== Anwendungsszenarien ==&lt;br /&gt;
&lt;br /&gt;
Der Controller ist für die Montage an Ebenen Flächen gedacht. Es ist eine eigene vorhandene 12/24V Stromversorgung notwendig (nicht im Lieferumfang enthalten). Direkt am Controller können dann LED-Stripes direkt angeklemmt werden. Es ist dabei auf die max. zulässige Leistung pro Kanal zu achten. Diese kann je nach Stripe variieren.&lt;br /&gt;
&lt;br /&gt;
Im Oktober 2015 hat die Auslieferung der Geräte als (einfacher) Bausatz begonnen.&lt;br /&gt;
&lt;br /&gt;
== Parameter ==&lt;br /&gt;
 &lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
* Die Befehle im Dim Kanal sind noch nicht vollständig implementiert.&lt;br /&gt;
* Die Farbe weiß zusammen mit rot, grün oder blau zu mischen ist offenbar nicht möglich. &lt;br /&gt;
* Unklar ist, wie neue Programme erstellt und gespeichert werden können.&lt;br /&gt;
* Bei langsamen Farb- und Helligkeitsänderungen sind deutliche Farb- und Helligskeitssprünge wahrnehmbar, da die Änderung nicht kontinuierlich abläuft, sondern sprunghaft.&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit FHEM ==&lt;br /&gt;
&lt;br /&gt;
Der Controller hat drei Kanäle, die jeweils verschiedene Befehle ermöglichen:&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Dim Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs dauerhaft ein. Es wird die zuletzt eingestellte Farbe übernommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-for-timer &amp;lt;ontime&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs ein und nach &amp;lt;ontime&amp;gt; Sekunden wieder aus. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; on-till &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs ein und um &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; Uhr wieder aus. &amp;lt;nowiki&amp;gt;&amp;lt;time&amp;gt;&amp;lt;/nowiki&amp;gt; hat das Format hh:mm:ss&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; off&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Schaltet die LEDs dauerhaft aus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; press&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sanft ausgeschaltet und umgekehrt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; toogle&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn die LEDs eingeschaltet sind, werden sie sofort ausgeschaltet und umgekehrt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; pct&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; up&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; down&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Color Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightCol &amp;lt;bright&amp;gt; &amp;lt;colVal&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. Die LED-Farbe ist in allen Phasen gleich.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; regelt die Helligkeit in der Duration-Phase und geht von 0 (=0%) bis 200 (=100%)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colVal&amp;gt;&#039;&#039;&#039; regelt die Farbe in der Ramp- und Duration-Phase und geht von 0 bis 200:&amp;lt;br&amp;gt;&lt;br /&gt;
0 = Rot, 66 = Grün, 133 = Blau, 199 = Rot, 200 = Weiß&amp;lt;br&amp;gt;&lt;br /&gt;
Werte dazwischen ergeben Mischfarben, z.B. 15 = Gelb, 150 = Lila. Weiß zusammen mit R, G oder B zu mischen ist offenbar nicht möglich. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. Ein Wert von 0 lässt die LEDs dauerhaft eingeschaltet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
=== Befehle im Auto Kanal ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set &amp;lt;device&amp;gt; brightAuto &amp;lt;bright&amp;gt; &amp;lt;colProg&amp;gt; &amp;lt;min&amp;gt; &amp;lt;max&amp;gt; &amp;lt;duration&amp;gt; &amp;lt;ramp&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analog zum brightCol-Befehl im Color-Kanal gibt es eine Ramp-Phase, in der die LEDs von 0% hochgedimmt werden und anschließend eine Duration-Phase, in der sie mit konstanter Grund-Helligkeit angeschaltet bleiben. Nach der Duration-Phase dimmen die LEDs innnerhalb von 1 Sekunde auf 0% herunter. In beiden Phasen wird ein vordefiniertes Programm abgespielt und während dessen blinkt die Automatiktaste regelmäßig 1x lang.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;bright&amp;gt;&#039;&#039;&#039; steuert die Grund-Helligkeit analog zum brightCol-Befehl im Color-Kanal. Je nach Programm schwankt die Helligkeit während der Programmausführung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;colProg&amp;gt;&#039;&#039;&#039; definiert welches Programm abgespielt wird. Im Auslieferungszustand sind folgende Programm-Nummern vorhanden:&lt;br /&gt;
&lt;br /&gt;
1: Farbverlauf langsam (Geschwindigkeit Farbwechsel: 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang, default: 20 Sekunden). &lt;br /&gt;
Der Farbverlauf geht von colVal &amp;lt;min&amp;gt; bis colVal &amp;lt;max&amp;gt;. colVal ist analog zum brightCol-Befehl im Color-Kanal. Nach der &amp;lt;max&amp;gt; Farbe geht es sofort bei der &amp;lt;min&amp;gt; Farbe weiter. Das kann zu Farbsprüngen führen. Die Geschwindigkeit des Farbwechsels kann mit dem Register colChangeSpeed geändert werden (default: colChangeSpeed = 10 Sekunden pro Durchgang). In Programm 1 dauert ein Durchgang von Farbe 0 (&amp;lt;min&amp;gt; = 0) bis Farbe 200 (&amp;lt;max&amp;gt; = 200) genau 2 * &amp;lt;colChangeSpeed&amp;gt; Sekunden (default also 20 Sekunden). Wenn weniger Farben durchlaufen werden, ist der Durchlauf entsprechend schneller.&lt;br /&gt;
&lt;br /&gt;
2: Farbverlauf normal (Geschwindigkeit Farbwechsel: &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit normaler Geschwindigkeit (default: 10 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
3: Farbverlauf schnell (Geschwindigkeit Farbwechsel: 0.5 * &amp;lt;colChangeSpeed&amp;gt; Sekunden pro Durchgang). Wie Programm 1, jedoch mit doppelter Geschwindigkeit (default: 5 Sekunden pro Durchgang).&lt;br /&gt;
&lt;br /&gt;
4: Kaminfeuer (rotes Licht, das ein Feuer simuliert). Min und Max haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
5: Wasserfall (blaues Licht, das die Helligkeit verändert). Min und Max haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
6: TV-Simulation (Farb- und Helligkeitsschwankungen simulieren ein eingeschaltetes TV-Gerät, dient zur Abwehr von Einbrechern). Min und Max haben keine Bedeutung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;min&amp;gt;&#039;&#039;&#039; siehe Programme 1-3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;max&amp;gt;&#039;&#039;&#039; siehe Programme 1-3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;duration&amp;gt;&#039;&#039;&#039; definiert, wie viele Sekunden die LEDs nach der Ramp-Phase eingeschaltet bleiben. Während der Duration-Phase blinkt die Helligkeittaste regelmäßig 1x lang. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;ramp&amp;gt;&#039;&#039;&#039; definiert, in wie vielen Sekunden die LEDs von 0% auf &amp;lt;bright&amp;gt; % hochgedimmt werden. Während der Ramp-Phase blinkt die Helligkeittaste regelmäßig 2x kurz und 1x lang. Bei &amp;lt;ramp&amp;gt; = 0 gehen die LEDs sofort an.&lt;br /&gt;
&lt;br /&gt;
=== Peering ===&lt;br /&gt;
Die folgenden Befehle peeren die ersten 3 Tasten (=Kanäle) eines HomeMatic 6-fach Tasters (HM-PB-6-WM55) mit den 3 Kanälen des RGBW-Controllers. Die Bedienung ist dann in etwa wie auf S. 12+13 der Bedienungsanleitung beschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_01 peerChan 0 rgbw_Dim single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_02 peerChan 0 rgbw_Color single set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;set taster1_Btn_03 peerChan 0 rgbw_Auto single set&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein HomeMatic 2-Kanal Funk-Sender (HM-RC-2-PBU-FM) kann wie folgt mit dem Dim-Kanal gepeert werden. Mit kurzem Druck nach oben/unten werden die LEDs ein-/ausgeschaltet und mit langem Druck hoch- und runtergedimmt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set taster2_Btn_01 peerChan 0 rgbw_Dim dual set&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Readings ===&lt;br /&gt;
&lt;br /&gt;
=== Events Auszug ===&lt;br /&gt;
&lt;br /&gt;
=== Konfiguration ===&lt;br /&gt;
&lt;br /&gt;
== Logging/Graph. Darstellung ==&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Bedienungsanleitung: [http://files.elv.de/Assets/Produkte/14/1419/141952/Downloads/141952_rgbw_controller_um.pdf]&lt;br /&gt;
* Produktseite ELV: [http://www.elv.de/homematic-funk-rgbw-controller-bausatz.html] &lt;br /&gt;
* Diskussion im FHEM Forum: [http://forum.fhem.de/index.php/topic,39719.0.html]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Dimmer]]&lt;/div&gt;</summary>
		<author><name>All-Ex</name></author>
	</entry>
</feed>