<?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=Neubert</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=Neubert"/>
	<link rel="alternate" type="text/html" href="http://wiki.fhem.de/wiki/Spezial:Beitr%C3%A4ge/Neubert"/>
	<updated>2026-04-12T10:41:29Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40950</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40950"/>
		<updated>2026-04-10T17:28:25Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Einleitung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|links]]&lt;br /&gt;
[[Datei:GIFTV.png|mini|240x240px|links]]&lt;br /&gt;
Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
==== Einleitung ====&lt;br /&gt;
Der readingsProxy wird benötigt, um aus verschiedenen Geräten Werte zusammenzuziehen, diese verständlich zu benennen, und weitere Werte mit userReadings zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Ich möchte im Mini-Dashboard gerne folgende Werte sehen:&lt;br /&gt;
* Momentane Leistung der PV-Anlage in Watt: PVPowerSourceW&lt;br /&gt;
* Tageserzeugung Solarstrom in kWh: PVEnergySourcekWh&lt;br /&gt;
* Momentaner Stromverbrauch des Hauses in Watt: HousePowerSinkW&lt;br /&gt;
* Tagesverbrauch des Hauses in kWh: HouseEnergySinkkWh&lt;br /&gt;
* Momentane Netzeinspeisung oder Netzbezug in W: GridPowerW = GridPowerSourceW + GridPowerSinkW&lt;br /&gt;
* Netzbezug des Tages in kWh: GridEnergySourcekWh&lt;br /&gt;
* Momentane Batterieladung oder -entladung in W: BatteryPowerW = BatteryPowerSourceW + BatteryPowerSinkW&lt;br /&gt;
* Ladezustand der Batterie in %: BatteryPercent&lt;br /&gt;
Die Benennung der Werte und deren Vorzeichen folgen einer Logik: &lt;br /&gt;
&lt;br /&gt;
* Es gibt Quellen (Source) und Senken (Sink) von Strom. &lt;br /&gt;
* Zufluss: Leistung mit positivem Vorzeichen wird einer Komponente entnommen (Quellen: PV-Anlage, Netzbezug, Batterieentladung).&lt;br /&gt;
* Abfluss: Leistung mit negativem Vorzeichen wird einer Komponente hinzugefügt (Senken: Netzeinspeisung, Hausstromverbrauch, Batterieladung).&lt;br /&gt;
* Die Energiemengen (PV-Anlage, Netzbezug, Netzeinspeisung, Batterieladung, Batterieentladung, Hausstromverbrauch) sind immer positiv.&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
Inspiration fand ich auf der Webseite [https://www.juergenstechnikwelt.de/photovoltaik/pv-anlage-in-fhem-die-datenbasis-fuer-das-dashboard/ Jürgens Technikwelt]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
define aggr.PV readingsProxy \&lt;br /&gt;
  smainverter:SPOT_PDC_SUM:PVPowerSourceW \&lt;br /&gt;
  smainverter:SPOT_EPVTODAY:PVEnergySourceWh \       &lt;br /&gt;
  smaem:SMAEM1234567890_Bezug_Wirkleistung:GridPowerSourceW \&lt;br /&gt;
  smaem:SMAEM1234567890_Einspeisung_Wirkleistung:GridPowerSinkW \&lt;br /&gt;
  calc.Netzbezug:smaem_SMAEM1234567890_Bezug_Wirkleistung_Zaehler_EnergyDay:GridEnergySourcekWh \&lt;br /&gt;
  calc.Netzeinspeisung:smaem_SMAEM1234567890_Einspeisung_Wirkleistung_Zaehler_EnergyDay:GridEnergySinkkWh \&lt;br /&gt;
  smainverter:BAT_P_CHARGE:BatteryPowerSinkW \&lt;br /&gt;
  smainverter:BAT_P_DISCHARGE:BatteryPowerSourceW \ &lt;br /&gt;
  smainverter:ChargeStatus:BatteryPercent \ &lt;br /&gt;
  smainverter:BAT_LOADTODAY:BatteryEnergySinkWh \&lt;br /&gt;
  smainverter:BAT_UNLOADTODAY:BatteryEnergySourceWh \&lt;br /&gt;
  smaem:SMAEM1234567890_GridFreq:GridFrequencyHz&lt;br /&gt;
attr aggr.PV stateFormat PV: PVPowerSourceW W &amp;lt; PVEnergySourcekWh kWh | Haus: HousePowerSinkW W &amp;gt; HouseEnergySinkkWh kWh | Netz: GridPowerW W &amp;lt; GridEnergySourcekWh kWh &amp;gt; GridEnergySinkkWh kWh | Batterie: BatteryPowerW W BatteryPercent % &amp;lt; BatteryEnergySourcekWh kWh &amp;gt; BatteryEnergySinkkWh kWh&lt;br /&gt;
attr aggr.PV userReadings \&lt;br /&gt;
  GridPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  BatteryPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  PVEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  HousePowerSinkW { -( ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVPowerSourceW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerW&amp;quot;, 0) ) }, \&lt;br /&gt;
  HouseEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;,&amp;quot;GridEnergySinkkWh&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkkWh&amp;quot;,0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourcekWh&amp;quot;, 0) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild &amp;lt;code&amp;gt;/opt/fhem/PictureFrame/sensorfeed2&amp;lt;/code&amp;gt; dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Die Widgets werden über das Element &amp;lt;code&amp;gt;img&amp;lt;/code&amp;gt; mit Typ &amp;lt;code&amp;gt;svg data&amp;lt;/code&amp;gt; als Perl-Kode mit dem Widget &amp;lt;code&amp;gt;ui_Table::ring2()&amp;lt;/code&amp;gt; erzeugt. Dessen ellenlange Parameterliste kann in [https://wiki.fhem.de/wiki/DOIF/uiTable_Schnelleinstieg#Aufbau_des_uiTable-Attributs dem Abschnitt zu diesem Widget] nachgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &#039;c0c0c0&#039;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &#039;PV&#039;, 100, undef, &#039;0,font-family:sans-serif;font-weight:normal,font-family:sans-serif;font-weight:normal,W&#039;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &#039;0,font-family:sans-serif;font-weight:normal,font-family:sans-serif;font-weight:normal,kWh&#039;, &#039;50,50,50,80,80,40&#039; ) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &#039;Haus&#039;, 100, undef, &#039;0,font-family:sans-serif;font-weight:normal,font-family:sans-serif;font-weight:normal,W&#039;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &#039;0,font-family:sans-serif;font-weight:normal,font-family:sans-serif;font-weight:normal,kWh&#039;, &#039;50,50,50,80,80,40&#039;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &#039;Netz&#039;, 100, undef, &#039;0,font-family:sans-serif;font-weight:normal,font-family:sans-serif;font-weight:normal,W&#039;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &#039;0,font-family:sans-serif;font-weight:normal,font-family:sans-serif;font-weight:normal,kWh&#039;, &#039;50,50,50,80,80,40&#039;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &#039;Batt&#039;, 100, undef, &#039;0,font-family:sans-serif;font-weight:normal,font-family:sans-serif;font-weight:normal,W&#039;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &#039;0,font-family:sans-serif;font-weight:normal,font-family:sans-serif;font-weight:normal,%&#039;, &#039;50,50,50,80,80,40&#039;) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Ordner FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40946</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40946"/>
		<updated>2026-04-07T17:33:10Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Layout */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|links]]&lt;br /&gt;
[[Datei:GIFTV.png|mini|240x240px|links]]&lt;br /&gt;
Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
==== Einleitung ====&lt;br /&gt;
Der readingsProxy wird benötigt, um aus verschiedenen Geräten Werte zusammenzuziehen, diese verständlich zu benennen, und weitere Werte mit userReadings zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Ich möchte im Mini-Dashboard gerne folgende Werte sehen:&lt;br /&gt;
* Momentane Leistung der PV-Anlage in Watt: PVPowerSourceW&lt;br /&gt;
* Tageserzeugung Solarstrom in kWh: PVEnergySourcekWh&lt;br /&gt;
* Momentaner Stromverbrauch des Hauses in Watt: HousePowerSinkW&lt;br /&gt;
* Tagesverbrauch des Hauses in kWh: HouseEnergySinkkWh&lt;br /&gt;
* Momentane Netzeinspeisung oder Netzbezug in W: GridPowerW = GridPowerSourceW + GridPowerSinkW&lt;br /&gt;
* Netzbezug des Tages in kWh: GridEnergySourcekWh&lt;br /&gt;
* Momentane Batterieladung oder -entladung in W: BatteryPowerW = BatteryPowerSourceW + BatteryPowerSinkW&lt;br /&gt;
* Ladezustand der Batterie in %: BatteryPercent&lt;br /&gt;
Die Benennung der Werte und deren Vorzeichen folgen einer Logik: &lt;br /&gt;
&lt;br /&gt;
* Es gibt Quellen (Source) und Senken (Sink) von Strom. &lt;br /&gt;
* Leistung mit positivem Vorzeichen wird einer Komponente entnommen (Quellen: PV-Anlage, Netzbezug, Batterieentladung). &lt;br /&gt;
* Leistung mit negativem Vorzeichen wird einer Komponente hinzugefügt (Senken: Netzeinspeisung, Hausstromverbrauch, Batterieladung).&lt;br /&gt;
* Die Energiemengen (PV-Anlage, Netzbezug, Netzeinspeisung, Batterieladung, Batterieentladung, Hausstromverbrauch) sind immer positiv.&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
Inspiration fand ich auf der Webseite [https://www.juergenstechnikwelt.de/photovoltaik/pv-anlage-in-fhem-die-datenbasis-fuer-das-dashboard/ Jürgens Technikwelt]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
define aggr.PV readingsProxy \&lt;br /&gt;
  smainverter:SPOT_PDC_SUM:PVPowerSourceW \&lt;br /&gt;
  smainverter:SPOT_EPVTODAY:PVEnergySourceWh \       &lt;br /&gt;
  smaem:SMAEM1234567890_Bezug_Wirkleistung:GridPowerSourceW \&lt;br /&gt;
  smaem:SMAEM1234567890_Einspeisung_Wirkleistung:GridPowerSinkW \&lt;br /&gt;
  calc.Netzbezug:smaem_SMAEM1234567890_Bezug_Wirkleistung_Zaehler_EnergyDay:GridEnergySourcekWh \&lt;br /&gt;
  calc.Netzeinspeisung:smaem_SMAEM1234567890_Einspeisung_Wirkleistung_Zaehler_EnergyDay:GridEnergySinkkWh \&lt;br /&gt;
  smainverter:BAT_P_CHARGE:BatteryPowerSinkW \&lt;br /&gt;
  smainverter:BAT_P_DISCHARGE:BatteryPowerSourceW \ &lt;br /&gt;
  smainverter:ChargeStatus:BatteryPercent \ &lt;br /&gt;
  smainverter:BAT_LOADTODAY:BatteryEnergySinkWh \&lt;br /&gt;
  smainverter:BAT_UNLOADTODAY:BatteryEnergySourceWh \&lt;br /&gt;
  smaem:SMAEM1234567890_GridFreq:GridFrequencyHz&lt;br /&gt;
attr aggr.PV stateFormat PV: PVPowerSourceW W &amp;lt; PVEnergySourcekWh kWh | Haus: HousePowerSinkW W &amp;gt; HouseEnergySinkkWh kWh | Netz: GridPowerW W &amp;lt; GridEnergySourcekWh kWh &amp;gt; GridEnergySinkkWh kWh | Batterie: BatteryPowerW W BatteryPercent % &amp;lt; BatteryEnergySourcekWh kWh &amp;gt; BatteryEnergySinkkWh kWh&lt;br /&gt;
attr aggr.PV userReadings \&lt;br /&gt;
  GridPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  BatteryPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  PVEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  HousePowerSinkW { -( ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVPowerSourceW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerW&amp;quot;, 0) ) }, \&lt;br /&gt;
  HouseEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;,&amp;quot;GridEnergySinkkWh&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkkWh&amp;quot;,0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourcekWh&amp;quot;, 0) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild &amp;lt;code&amp;gt;/opt/fhem/PictureFrame/sensorfeed2&amp;lt;/code&amp;gt; dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Die Widgets werden über das Element &amp;lt;code&amp;gt;img&amp;lt;/code&amp;gt; mit Typ &amp;lt;code&amp;gt;svg data&amp;lt;/code&amp;gt; als Perl-Kode mit dem Widget &amp;lt;code&amp;gt;ui_Table::ring2()&amp;lt;/code&amp;gt; erzeugt. Dessen ellenlange Parameterliste kann in [https://wiki.fhem.de/wiki/DOIF/uiTable_Schnelleinstieg#Aufbau_des_uiTable-Attributs dem Abschnitt zu diesem Widget] nachgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &#039;c0c0c0&#039;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &#039;PV&#039;, 100, undef, &#039;0,font-family:sans-serif;font-weight:normal,font-family:sans-serif;font-weight:normal,W&#039;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &#039;0,font-family:sans-serif;font-weight:normal,font-family:sans-serif;font-weight:normal,kWh&#039;, &#039;50,50,50,80,80,40&#039; ) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &#039;Haus&#039;, 100, undef, &#039;0,font-family:sans-serif;font-weight:normal,font-family:sans-serif;font-weight:normal,W&#039;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &#039;0,font-family:sans-serif;font-weight:normal,font-family:sans-serif;font-weight:normal,kWh&#039;, &#039;50,50,50,80,80,40&#039;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &#039;Netz&#039;, 100, undef, &#039;0,font-family:sans-serif;font-weight:normal,font-family:sans-serif;font-weight:normal,W&#039;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &#039;0,font-family:sans-serif;font-weight:normal,font-family:sans-serif;font-weight:normal,kWh&#039;, &#039;50,50,50,80,80,40&#039;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &#039;Batt&#039;, 100, undef, &#039;0,font-family:sans-serif;font-weight:normal,font-family:sans-serif;font-weight:normal,W&#039;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &#039;0,font-family:sans-serif;font-weight:normal,font-family:sans-serif;font-weight:normal,%&#039;, &#039;50,50,50,80,80,40&#039;) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Ordner FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40945</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40945"/>
		<updated>2026-04-07T17:20:30Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Sinn und Zweck */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|links]]&lt;br /&gt;
[[Datei:GIFTV.png|mini|240x240px|links]]&lt;br /&gt;
Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
==== Einleitung ====&lt;br /&gt;
Der readingsProxy wird benötigt, um aus verschiedenen Geräten Werte zusammenzuziehen, diese verständlich zu benennen, und weitere Werte mit userReadings zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Ich möchte im Mini-Dashboard gerne folgende Werte sehen:&lt;br /&gt;
* Momentane Leistung der PV-Anlage in Watt: PVPowerSourceW&lt;br /&gt;
* Tageserzeugung Solarstrom in kWh: PVEnergySourcekWh&lt;br /&gt;
* Momentaner Stromverbrauch des Hauses in Watt: HousePowerSinkW&lt;br /&gt;
* Tagesverbrauch des Hauses in kWh: HouseEnergySinkkWh&lt;br /&gt;
* Momentane Netzeinspeisung oder Netzbezug in W: GridPowerW = GridPowerSourceW + GridPowerSinkW&lt;br /&gt;
* Netzbezug des Tages in kWh: GridEnergySourcekWh&lt;br /&gt;
* Momentane Batterieladung oder -entladung in W: BatteryPowerW = BatteryPowerSourceW + BatteryPowerSinkW&lt;br /&gt;
* Ladezustand der Batterie in %: BatteryPercent&lt;br /&gt;
Die Benennung der Werte und deren Vorzeichen folgen einer Logik: &lt;br /&gt;
&lt;br /&gt;
* Es gibt Quellen (Source) und Senken (Sink) von Strom. &lt;br /&gt;
* Leistung mit positivem Vorzeichen wird einer Komponente entnommen (Quellen: PV-Anlage, Netzbezug, Batterieentladung). &lt;br /&gt;
* Leistung mit negativem Vorzeichen wird einer Komponente hinzugefügt (Senken: Netzeinspeisung, Hausstromverbrauch, Batterieladung).&lt;br /&gt;
* Die Energiemengen (PV-Anlage, Netzbezug, Netzeinspeisung, Batterieladung, Batterieentladung, Hausstromverbrauch) sind immer positiv.&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
Inspiration fand ich auf der Webseite [https://www.juergenstechnikwelt.de/photovoltaik/pv-anlage-in-fhem-die-datenbasis-fuer-das-dashboard/ Jürgens Technikwelt]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
define aggr.PV readingsProxy \&lt;br /&gt;
  smainverter:SPOT_PDC_SUM:PVPowerSourceW \&lt;br /&gt;
  smainverter:SPOT_EPVTODAY:PVEnergySourceWh \       &lt;br /&gt;
  smaem:SMAEM1234567890_Bezug_Wirkleistung:GridPowerSourceW \&lt;br /&gt;
  smaem:SMAEM1234567890_Einspeisung_Wirkleistung:GridPowerSinkW \&lt;br /&gt;
  calc.Netzbezug:smaem_SMAEM1234567890_Bezug_Wirkleistung_Zaehler_EnergyDay:GridEnergySourcekWh \&lt;br /&gt;
  calc.Netzeinspeisung:smaem_SMAEM1234567890_Einspeisung_Wirkleistung_Zaehler_EnergyDay:GridEnergySinkkWh \&lt;br /&gt;
  smainverter:BAT_P_CHARGE:BatteryPowerSinkW \&lt;br /&gt;
  smainverter:BAT_P_DISCHARGE:BatteryPowerSourceW \ &lt;br /&gt;
  smainverter:ChargeStatus:BatteryPercent \ &lt;br /&gt;
  smainverter:BAT_LOADTODAY:BatteryEnergySinkWh \&lt;br /&gt;
  smainverter:BAT_UNLOADTODAY:BatteryEnergySourceWh \&lt;br /&gt;
  smaem:SMAEM1234567890_GridFreq:GridFrequencyHz&lt;br /&gt;
attr aggr.PV stateFormat PV: PVPowerSourceW W &amp;lt; PVEnergySourcekWh kWh | Haus: HousePowerSinkW W &amp;gt; HouseEnergySinkkWh kWh | Netz: GridPowerW W &amp;lt; GridEnergySourcekWh kWh &amp;gt; GridEnergySinkkWh kWh | Batterie: BatteryPowerW W BatteryPercent % &amp;lt; BatteryEnergySourcekWh kWh &amp;gt; BatteryEnergySinkkWh kWh&lt;br /&gt;
attr aggr.PV userReadings \&lt;br /&gt;
  GridPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  BatteryPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  PVEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  HousePowerSinkW { -( ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVPowerSourceW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerW&amp;quot;, 0) ) }, \&lt;br /&gt;
  HouseEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;,&amp;quot;GridEnergySinkkWh&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkkWh&amp;quot;,0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourcekWh&amp;quot;, 0) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild &amp;lt;code&amp;gt;/opt/fhem/PictureFrame/sensorfeed2&amp;lt;/code&amp;gt; dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Die Widgets werden über das Element &amp;lt;code&amp;gt;img&amp;lt;/code&amp;gt; mit Typ &amp;lt;code&amp;gt;svg data&amp;lt;/code&amp;gt; als Perl-Kode mit dem Widget &amp;lt;code&amp;gt;ui_Table::ring2()&amp;lt;/code&amp;gt; erzeugt. Dessen ellenlange Parameterliste kann in [https://wiki.fhem.de/wiki/DOIF/uiTable_Schnelleinstieg#Aufbau_des_uiTable-Attributs dem Abschnitt zu diesem Widget] nachgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Ordner FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Datei:Sensorfeed2.jpg&amp;diff=40944</id>
		<title>Datei:Sensorfeed2.jpg</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Datei:Sensorfeed2.jpg&amp;diff=40944"/>
		<updated>2026-04-07T17:19:06Z</updated>

		<summary type="html">&lt;p&gt;Neubert: Neubert lud eine neue Version von Datei:Sensorfeed2.jpg hoch&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;240x240 Pixel großes JPG-Bild der Anzeige im Mini-Dashboard&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40900</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40900"/>
		<updated>2026-04-01T17:49:08Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Layout */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]&lt;br /&gt;
[[Datei:GIFTV.png|mini|240x240px|links]]&lt;br /&gt;
Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
==== Einleitung ====&lt;br /&gt;
Der readingsProxy wird benötigt, um aus verschiedenen Geräten Werte zusammenzuziehen, diese verständlich zu benennen, und weitere Werte mit userReadings zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Ich möchte im Mini-Dashboard gerne folgende Werte sehen:&lt;br /&gt;
* Momentane Leistung der PV-Anlage in Watt: PVPowerSourceW&lt;br /&gt;
* Tageserzeugung Solarstrom in kWh: PVEnergySourcekWh&lt;br /&gt;
* Momentaner Stromverbrauch des Hauses in Watt: HousePowerSinkW&lt;br /&gt;
* Tagesverbrauch des Hauses in kWh: HouseEnergySinkkWh&lt;br /&gt;
* Momentane Netzeinspeisung oder Netzbezug in W: GridPowerW = GridPowerSourceW + GridPowerSinkW&lt;br /&gt;
* Netzbezug des Tages in kWh: GridEnergySourcekWh&lt;br /&gt;
* Momentane Batterieladung oder -entladung in W: BatteryPowerW = BatteryPowerSourceW + BatteryPowerSinkW&lt;br /&gt;
* Ladezustand der Batterie in %: BatteryPercent&lt;br /&gt;
Die Benennung der Werte und deren Vorzeichen folgen einer Logik: &lt;br /&gt;
&lt;br /&gt;
* Es gibt Quellen (Source) und Senken (Sink) von Strom. &lt;br /&gt;
* Leistung mit positivem Vorzeichen wird einer Komponente entnommen (Quellen: PV-Anlage, Netzbezug, Batterieentladung). &lt;br /&gt;
* Leistung mit negativem Vorzeichen wird einer Komponente hinzugefügt (Senken: Netzeinspeisung, Hausstromverbrauch, Batterieladung).&lt;br /&gt;
* Die Energiemengen (PV-Anlage, Netzbezug, Netzeinspeisung, Batterieladung, Batterieentladung, Hausstromverbrauch) sind immer positiv.&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
Inspiration fand ich auf der Webseite [https://www.juergenstechnikwelt.de/photovoltaik/pv-anlage-in-fhem-die-datenbasis-fuer-das-dashboard/ Jürgens Technikwelt]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
define aggr.PV readingsProxy \&lt;br /&gt;
  smainverter:SPOT_PDC_SUM:PVPowerSourceW \&lt;br /&gt;
  smainverter:SPOT_EPVTODAY:PVEnergySourceWh \       &lt;br /&gt;
  smaem:SMAEM1234567890_Bezug_Wirkleistung:GridPowerSourceW \&lt;br /&gt;
  smaem:SMAEM1234567890_Einspeisung_Wirkleistung:GridPowerSinkW \&lt;br /&gt;
  calc.Netzbezug:smaem_SMAEM1234567890_Bezug_Wirkleistung_Zaehler_EnergyDay:GridEnergySourcekWh \&lt;br /&gt;
  calc.Netzeinspeisung:smaem_SMAEM1234567890_Einspeisung_Wirkleistung_Zaehler_EnergyDay:GridEnergySinkkWh \&lt;br /&gt;
  smainverter:BAT_P_CHARGE:BatteryPowerSinkW \&lt;br /&gt;
  smainverter:BAT_P_DISCHARGE:BatteryPowerSourceW \ &lt;br /&gt;
  smainverter:ChargeStatus:BatteryPercent \ &lt;br /&gt;
  smainverter:BAT_LOADTODAY:BatteryEnergySinkWh \&lt;br /&gt;
  smainverter:BAT_UNLOADTODAY:BatteryEnergySourceWh \&lt;br /&gt;
  smaem:SMAEM1234567890_GridFreq:GridFrequencyHz&lt;br /&gt;
attr aggr.PV stateFormat PV: PVPowerSourceW W &amp;lt; PVEnergySourcekWh kWh | Haus: HousePowerSinkW W &amp;gt; HouseEnergySinkkWh kWh | Netz: GridPowerW W &amp;lt; GridEnergySourcekWh kWh &amp;gt; GridEnergySinkkWh kWh | Batterie: BatteryPowerW W BatteryPercent % &amp;lt; BatteryEnergySourcekWh kWh &amp;gt; BatteryEnergySinkkWh kWh&lt;br /&gt;
attr aggr.PV userReadings \&lt;br /&gt;
  GridPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  BatteryPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  PVEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  HousePowerSinkW { -( ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVPowerSourceW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerW&amp;quot;, 0) ) }, \&lt;br /&gt;
  HouseEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;,&amp;quot;GridEnergySinkkWh&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkkWh&amp;quot;,0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourcekWh&amp;quot;, 0) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild &amp;lt;code&amp;gt;/opt/fhem/PictureFrame/sensorfeed2&amp;lt;/code&amp;gt; dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Die Widgets werden über das Element &amp;lt;code&amp;gt;img&amp;lt;/code&amp;gt; mit Typ &amp;lt;code&amp;gt;svg data&amp;lt;/code&amp;gt; als Perl-Kode mit dem Widget &amp;lt;code&amp;gt;ui_Table::ring2()&amp;lt;/code&amp;gt; erzeugt. Dessen ellenlange Parameterliste kann in [https://wiki.fhem.de/wiki/DOIF/uiTable_Schnelleinstieg#Aufbau_des_uiTable-Attributs dem Abschnitt zu diesem Widget] nachgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Ordner FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40899</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40899"/>
		<updated>2026-04-01T17:48:23Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Layout */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]&lt;br /&gt;
[[Datei:GIFTV.png|mini|240x240px|links]]&lt;br /&gt;
Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
==== Einleitung ====&lt;br /&gt;
Der readingsProxy wird benötigt, um aus verschiedenen Geräten Werte zusammenzuziehen, diese verständlich zu benennen, und weitere Werte mit userReadings zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Ich möchte im Mini-Dashboard gerne folgende Werte sehen:&lt;br /&gt;
* Momentane Leistung der PV-Anlage in Watt: PVPowerSourceW&lt;br /&gt;
* Tageserzeugung Solarstrom in kWh: PVEnergySourcekWh&lt;br /&gt;
* Momentaner Stromverbrauch des Hauses in Watt: HousePowerSinkW&lt;br /&gt;
* Tagesverbrauch des Hauses in kWh: HouseEnergySinkkWh&lt;br /&gt;
* Momentane Netzeinspeisung oder Netzbezug in W: GridPowerW = GridPowerSourceW + GridPowerSinkW&lt;br /&gt;
* Netzbezug des Tages in kWh: GridEnergySourcekWh&lt;br /&gt;
* Momentane Batterieladung oder -entladung in W: BatteryPowerW = BatteryPowerSourceW + BatteryPowerSinkW&lt;br /&gt;
* Ladezustand der Batterie in %: BatteryPercent&lt;br /&gt;
Die Benennung der Werte und deren Vorzeichen folgen einer Logik: &lt;br /&gt;
&lt;br /&gt;
* Es gibt Quellen (Source) und Senken (Sink) von Strom. &lt;br /&gt;
* Leistung mit positivem Vorzeichen wird einer Komponente entnommen (Quellen: PV-Anlage, Netzbezug, Batterieentladung). &lt;br /&gt;
* Leistung mit negativem Vorzeichen wird einer Komponente hinzugefügt (Senken: Netzeinspeisung, Hausstromverbrauch, Batterieladung).&lt;br /&gt;
* Die Energiemengen (PV-Anlage, Netzbezug, Netzeinspeisung, Batterieladung, Batterieentladung, Hausstromverbrauch) sind immer positiv.&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
Inspiration fand ich auf der Webseite [https://www.juergenstechnikwelt.de/photovoltaik/pv-anlage-in-fhem-die-datenbasis-fuer-das-dashboard/ Jürgens Technikwelt]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
define aggr.PV readingsProxy \&lt;br /&gt;
  smainverter:SPOT_PDC_SUM:PVPowerSourceW \&lt;br /&gt;
  smainverter:SPOT_EPVTODAY:PVEnergySourceWh \       &lt;br /&gt;
  smaem:SMAEM1234567890_Bezug_Wirkleistung:GridPowerSourceW \&lt;br /&gt;
  smaem:SMAEM1234567890_Einspeisung_Wirkleistung:GridPowerSinkW \&lt;br /&gt;
  calc.Netzbezug:smaem_SMAEM1234567890_Bezug_Wirkleistung_Zaehler_EnergyDay:GridEnergySourcekWh \&lt;br /&gt;
  calc.Netzeinspeisung:smaem_SMAEM1234567890_Einspeisung_Wirkleistung_Zaehler_EnergyDay:GridEnergySinkkWh \&lt;br /&gt;
  smainverter:BAT_P_CHARGE:BatteryPowerSinkW \&lt;br /&gt;
  smainverter:BAT_P_DISCHARGE:BatteryPowerSourceW \ &lt;br /&gt;
  smainverter:ChargeStatus:BatteryPercent \ &lt;br /&gt;
  smainverter:BAT_LOADTODAY:BatteryEnergySinkWh \&lt;br /&gt;
  smainverter:BAT_UNLOADTODAY:BatteryEnergySourceWh \&lt;br /&gt;
  smaem:SMAEM1234567890_GridFreq:GridFrequencyHz&lt;br /&gt;
attr aggr.PV stateFormat PV: PVPowerSourceW W &amp;lt; PVEnergySourcekWh kWh | Haus: HousePowerSinkW W &amp;gt; HouseEnergySinkkWh kWh | Netz: GridPowerW W &amp;lt; GridEnergySourcekWh kWh &amp;gt; GridEnergySinkkWh kWh | Batterie: BatteryPowerW W BatteryPercent % &amp;lt; BatteryEnergySourcekWh kWh &amp;gt; BatteryEnergySinkkWh kWh&lt;br /&gt;
attr aggr.PV userReadings \&lt;br /&gt;
  GridPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  BatteryPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  PVEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  HousePowerSinkW { -( ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVPowerSourceW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerW&amp;quot;, 0) ) }, \&lt;br /&gt;
  HouseEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;,&amp;quot;GridEnergySinkkWh&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkkWh&amp;quot;,0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourcekWh&amp;quot;, 0) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild &amp;lt;code&amp;gt;/opt/fhem/PictureFrame/sensorfeed2&amp;lt;/code&amp;gt; dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Die Widgets werden über das Element &amp;lt;nowiki&amp;gt;&amp;lt;code&amp;gt;img&amp;lt;/code&amp;gt;&amp;lt;/nowiki&amp;gt; mit Typ &amp;lt;nowiki&amp;gt;&amp;lt;code&amp;gt;svg data&amp;lt;/code&amp;gt;&amp;lt;/nowiki&amp;gt; als Perl-Kode mit dem Widget &amp;lt;nowiki&amp;gt;&amp;lt;code&amp;gt;ui_Table::ring2()&amp;lt;/code&amp;gt;&amp;lt;/nowiki&amp;gt; erzeugt. Dessen ellenlange Parameterliste kann in [https://wiki.fhem.de/wiki/DOIF/uiTable_Schnelleinstieg#Aufbau_des_uiTable-Attributs dem Abschnitt zu diesem Widget] nachgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Ordner FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40895</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40895"/>
		<updated>2026-03-30T18:22:56Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* push2giftv() */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]&lt;br /&gt;
[[Datei:GIFTV.png|mini|240x240px|links]]&lt;br /&gt;
Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
==== Einleitung ====&lt;br /&gt;
Der readingsProxy wird benötigt, um aus verschiedenen Geräten Werte zusammenzuziehen, diese verständlich zu benennen, und weitere Werte mit userReadings zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Ich möchte im Mini-Dashboard gerne folgende Werte sehen:&lt;br /&gt;
* Momentane Leistung der PV-Anlage in Watt: PVPowerSourceW&lt;br /&gt;
* Tageserzeugung Solarstrom in kWh: PVEnergySourcekWh&lt;br /&gt;
* Momentaner Stromverbrauch des Hauses in Watt: HousePowerSinkW&lt;br /&gt;
* Tagesverbrauch des Hauses in kWh: HouseEnergySinkkWh&lt;br /&gt;
* Momentane Netzeinspeisung oder Netzbezug in W: GridPowerW = GridPowerSourceW + GridPowerSinkW&lt;br /&gt;
* Netzbezug des Tages in kWh: GridEnergySourcekWh&lt;br /&gt;
* Momentane Batterieladung oder -entladung in W: BatteryPowerW = BatteryPowerSourceW + BatteryPowerSinkW&lt;br /&gt;
* Ladezustand der Batterie in %: BatteryPercent&lt;br /&gt;
Die Benennung der Werte und deren Vorzeichen folgen einer Logik: &lt;br /&gt;
&lt;br /&gt;
* Es gibt Quellen (Source) und Senken (Sink) von Strom. &lt;br /&gt;
* Leistung mit positivem Vorzeichen wird einer Komponente entnommen (Quellen: PV-Anlage, Netzbezug, Batterieentladung). &lt;br /&gt;
* Leistung mit negativem Vorzeichen wird einer Komponente hinzugefügt (Senken: Netzeinspeisung, Hausstromverbrauch, Batterieladung).&lt;br /&gt;
* Die Energiemengen (PV-Anlage, Netzbezug, Netzeinspeisung, Batterieladung, Batterieentladung, Hausstromverbrauch) sind immer positiv.&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
Inspiration fand ich auf der Webseite [https://www.juergenstechnikwelt.de/photovoltaik/pv-anlage-in-fhem-die-datenbasis-fuer-das-dashboard/ Jürgens Technikwelt]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
define aggr.PV readingsProxy \&lt;br /&gt;
  smainverter:SPOT_PDC_SUM:PVPowerSourceW \&lt;br /&gt;
  smainverter:SPOT_EPVTODAY:PVEnergySourceWh \       &lt;br /&gt;
  smaem:SMAEM1234567890_Bezug_Wirkleistung:GridPowerSourceW \&lt;br /&gt;
  smaem:SMAEM1234567890_Einspeisung_Wirkleistung:GridPowerSinkW \&lt;br /&gt;
  calc.Netzbezug:smaem_SMAEM1234567890_Bezug_Wirkleistung_Zaehler_EnergyDay:GridEnergySourcekWh \&lt;br /&gt;
  calc.Netzeinspeisung:smaem_SMAEM1234567890_Einspeisung_Wirkleistung_Zaehler_EnergyDay:GridEnergySinkkWh \&lt;br /&gt;
  smainverter:BAT_P_CHARGE:BatteryPowerSinkW \&lt;br /&gt;
  smainverter:BAT_P_DISCHARGE:BatteryPowerSourceW \ &lt;br /&gt;
  smainverter:ChargeStatus:BatteryPercent \ &lt;br /&gt;
  smainverter:BAT_LOADTODAY:BatteryEnergySinkWh \&lt;br /&gt;
  smainverter:BAT_UNLOADTODAY:BatteryEnergySourceWh \&lt;br /&gt;
  smaem:SMAEM1234567890_GridFreq:GridFrequencyHz&lt;br /&gt;
attr aggr.PV stateFormat PV: PVPowerSourceW W &amp;lt; PVEnergySourcekWh kWh | Haus: HousePowerSinkW W &amp;gt; HouseEnergySinkkWh kWh | Netz: GridPowerW W &amp;lt; GridEnergySourcekWh kWh &amp;gt; GridEnergySinkkWh kWh | Batterie: BatteryPowerW W BatteryPercent % &amp;lt; BatteryEnergySourcekWh kWh &amp;gt; BatteryEnergySinkkWh kWh&lt;br /&gt;
attr aggr.PV userReadings \&lt;br /&gt;
  GridPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  BatteryPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  PVEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  HousePowerSinkW { -( ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVPowerSourceW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerW&amp;quot;, 0) ) }, \&lt;br /&gt;
  HouseEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;,&amp;quot;GridEnergySinkkWh&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkkWh&amp;quot;,0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourcekWh&amp;quot;, 0) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild &amp;lt;code&amp;gt;/opt/fhem/PictureFrame/sensorfeed2&amp;lt;/code&amp;gt; dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Ordner FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40894</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40894"/>
		<updated>2026-03-30T18:22:04Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* at */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]&lt;br /&gt;
[[Datei:GIFTV.png|mini|240x240px|links]]&lt;br /&gt;
Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
==== Einleitung ====&lt;br /&gt;
Der readingsProxy wird benötigt, um aus verschiedenen Geräten Werte zusammenzuziehen, diese verständlich zu benennen, und weitere Werte mit userReadings zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Ich möchte im Mini-Dashboard gerne folgende Werte sehen:&lt;br /&gt;
* Momentane Leistung der PV-Anlage in Watt: PVPowerSourceW&lt;br /&gt;
* Tageserzeugung Solarstrom in kWh: PVEnergySourcekWh&lt;br /&gt;
* Momentaner Stromverbrauch des Hauses in Watt: HousePowerSinkW&lt;br /&gt;
* Tagesverbrauch des Hauses in kWh: HouseEnergySinkkWh&lt;br /&gt;
* Momentane Netzeinspeisung oder Netzbezug in W: GridPowerW = GridPowerSourceW + GridPowerSinkW&lt;br /&gt;
* Netzbezug des Tages in kWh: GridEnergySourcekWh&lt;br /&gt;
* Momentane Batterieladung oder -entladung in W: BatteryPowerW = BatteryPowerSourceW + BatteryPowerSinkW&lt;br /&gt;
* Ladezustand der Batterie in %: BatteryPercent&lt;br /&gt;
Die Benennung der Werte und deren Vorzeichen folgen einer Logik: &lt;br /&gt;
&lt;br /&gt;
* Es gibt Quellen (Source) und Senken (Sink) von Strom. &lt;br /&gt;
* Leistung mit positivem Vorzeichen wird einer Komponente entnommen (Quellen: PV-Anlage, Netzbezug, Batterieentladung). &lt;br /&gt;
* Leistung mit negativem Vorzeichen wird einer Komponente hinzugefügt (Senken: Netzeinspeisung, Hausstromverbrauch, Batterieladung).&lt;br /&gt;
* Die Energiemengen (PV-Anlage, Netzbezug, Netzeinspeisung, Batterieladung, Batterieentladung, Hausstromverbrauch) sind immer positiv.&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
Inspiration fand ich auf der Webseite [https://www.juergenstechnikwelt.de/photovoltaik/pv-anlage-in-fhem-die-datenbasis-fuer-das-dashboard/ Jürgens Technikwelt]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
define aggr.PV readingsProxy \&lt;br /&gt;
  smainverter:SPOT_PDC_SUM:PVPowerSourceW \&lt;br /&gt;
  smainverter:SPOT_EPVTODAY:PVEnergySourceWh \       &lt;br /&gt;
  smaem:SMAEM1234567890_Bezug_Wirkleistung:GridPowerSourceW \&lt;br /&gt;
  smaem:SMAEM1234567890_Einspeisung_Wirkleistung:GridPowerSinkW \&lt;br /&gt;
  calc.Netzbezug:smaem_SMAEM1234567890_Bezug_Wirkleistung_Zaehler_EnergyDay:GridEnergySourcekWh \&lt;br /&gt;
  calc.Netzeinspeisung:smaem_SMAEM1234567890_Einspeisung_Wirkleistung_Zaehler_EnergyDay:GridEnergySinkkWh \&lt;br /&gt;
  smainverter:BAT_P_CHARGE:BatteryPowerSinkW \&lt;br /&gt;
  smainverter:BAT_P_DISCHARGE:BatteryPowerSourceW \ &lt;br /&gt;
  smainverter:ChargeStatus:BatteryPercent \ &lt;br /&gt;
  smainverter:BAT_LOADTODAY:BatteryEnergySinkWh \&lt;br /&gt;
  smainverter:BAT_UNLOADTODAY:BatteryEnergySourceWh \&lt;br /&gt;
  smaem:SMAEM1234567890_GridFreq:GridFrequencyHz&lt;br /&gt;
attr aggr.PV stateFormat PV: PVPowerSourceW W &amp;lt; PVEnergySourcekWh kWh | Haus: HousePowerSinkW W &amp;gt; HouseEnergySinkkWh kWh | Netz: GridPowerW W &amp;lt; GridEnergySourcekWh kWh &amp;gt; GridEnergySinkkWh kWh | Batterie: BatteryPowerW W BatteryPercent % &amp;lt; BatteryEnergySourcekWh kWh &amp;gt; BatteryEnergySinkkWh kWh&lt;br /&gt;
attr aggr.PV userReadings \&lt;br /&gt;
  GridPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  BatteryPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  PVEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  HousePowerSinkW { -( ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVPowerSourceW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerW&amp;quot;, 0) ) }, \&lt;br /&gt;
  HouseEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;,&amp;quot;GridEnergySinkkWh&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkkWh&amp;quot;,0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourcekWh&amp;quot;, 0) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild &amp;lt;code&amp;gt;/opt/fhem/PictureFrame/sensorfeed2&amp;lt;/code&amp;gt; dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Ordner FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40893</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40893"/>
		<updated>2026-03-30T18:21:25Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Layout */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]&lt;br /&gt;
[[Datei:GIFTV.png|mini|240x240px|links]]&lt;br /&gt;
Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
==== Einleitung ====&lt;br /&gt;
Der readingsProxy wird benötigt, um aus verschiedenen Geräten Werte zusammenzuziehen, diese verständlich zu benennen, und weitere Werte mit userReadings zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Ich möchte im Mini-Dashboard gerne folgende Werte sehen:&lt;br /&gt;
* Momentane Leistung der PV-Anlage in Watt: PVPowerSourceW&lt;br /&gt;
* Tageserzeugung Solarstrom in kWh: PVEnergySourcekWh&lt;br /&gt;
* Momentaner Stromverbrauch des Hauses in Watt: HousePowerSinkW&lt;br /&gt;
* Tagesverbrauch des Hauses in kWh: HouseEnergySinkkWh&lt;br /&gt;
* Momentane Netzeinspeisung oder Netzbezug in W: GridPowerW = GridPowerSourceW + GridPowerSinkW&lt;br /&gt;
* Netzbezug des Tages in kWh: GridEnergySourcekWh&lt;br /&gt;
* Momentane Batterieladung oder -entladung in W: BatteryPowerW = BatteryPowerSourceW + BatteryPowerSinkW&lt;br /&gt;
* Ladezustand der Batterie in %: BatteryPercent&lt;br /&gt;
Die Benennung der Werte und deren Vorzeichen folgen einer Logik: &lt;br /&gt;
&lt;br /&gt;
* Es gibt Quellen (Source) und Senken (Sink) von Strom. &lt;br /&gt;
* Leistung mit positivem Vorzeichen wird einer Komponente entnommen (Quellen: PV-Anlage, Netzbezug, Batterieentladung). &lt;br /&gt;
* Leistung mit negativem Vorzeichen wird einer Komponente hinzugefügt (Senken: Netzeinspeisung, Hausstromverbrauch, Batterieladung).&lt;br /&gt;
* Die Energiemengen (PV-Anlage, Netzbezug, Netzeinspeisung, Batterieladung, Batterieentladung, Hausstromverbrauch) sind immer positiv.&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
Inspiration fand ich auf der Webseite [https://www.juergenstechnikwelt.de/photovoltaik/pv-anlage-in-fhem-die-datenbasis-fuer-das-dashboard/ Jürgens Technikwelt]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
define aggr.PV readingsProxy \&lt;br /&gt;
  smainverter:SPOT_PDC_SUM:PVPowerSourceW \&lt;br /&gt;
  smainverter:SPOT_EPVTODAY:PVEnergySourceWh \       &lt;br /&gt;
  smaem:SMAEM1234567890_Bezug_Wirkleistung:GridPowerSourceW \&lt;br /&gt;
  smaem:SMAEM1234567890_Einspeisung_Wirkleistung:GridPowerSinkW \&lt;br /&gt;
  calc.Netzbezug:smaem_SMAEM1234567890_Bezug_Wirkleistung_Zaehler_EnergyDay:GridEnergySourcekWh \&lt;br /&gt;
  calc.Netzeinspeisung:smaem_SMAEM1234567890_Einspeisung_Wirkleistung_Zaehler_EnergyDay:GridEnergySinkkWh \&lt;br /&gt;
  smainverter:BAT_P_CHARGE:BatteryPowerSinkW \&lt;br /&gt;
  smainverter:BAT_P_DISCHARGE:BatteryPowerSourceW \ &lt;br /&gt;
  smainverter:ChargeStatus:BatteryPercent \ &lt;br /&gt;
  smainverter:BAT_LOADTODAY:BatteryEnergySinkWh \&lt;br /&gt;
  smainverter:BAT_UNLOADTODAY:BatteryEnergySourceWh \&lt;br /&gt;
  smaem:SMAEM1234567890_GridFreq:GridFrequencyHz&lt;br /&gt;
attr aggr.PV stateFormat PV: PVPowerSourceW W &amp;lt; PVEnergySourcekWh kWh | Haus: HousePowerSinkW W &amp;gt; HouseEnergySinkkWh kWh | Netz: GridPowerW W &amp;lt; GridEnergySourcekWh kWh &amp;gt; GridEnergySinkkWh kWh | Batterie: BatteryPowerW W BatteryPercent % &amp;lt; BatteryEnergySourcekWh kWh &amp;gt; BatteryEnergySinkkWh kWh&lt;br /&gt;
attr aggr.PV userReadings \&lt;br /&gt;
  GridPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  BatteryPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  PVEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  HousePowerSinkW { -( ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVPowerSourceW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerW&amp;quot;, 0) ) }, \&lt;br /&gt;
  HouseEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;,&amp;quot;GridEnergySinkkWh&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkkWh&amp;quot;,0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourcekWh&amp;quot;, 0) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild &amp;lt;code&amp;gt;/opt/fhem/PictureFrame/sensorfeed2&amp;lt;/code&amp;gt; dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Ordner FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40892</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40892"/>
		<updated>2026-03-30T18:20:40Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Definition */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]&lt;br /&gt;
[[Datei:GIFTV.png|mini|240x240px|links]]&lt;br /&gt;
Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
==== Einleitung ====&lt;br /&gt;
Der readingsProxy wird benötigt, um aus verschiedenen Geräten Werte zusammenzuziehen, diese verständlich zu benennen, und weitere Werte mit userReadings zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Ich möchte im Mini-Dashboard gerne folgende Werte sehen:&lt;br /&gt;
* Momentane Leistung der PV-Anlage in Watt: PVPowerSourceW&lt;br /&gt;
* Tageserzeugung Solarstrom in kWh: PVEnergySourcekWh&lt;br /&gt;
* Momentaner Stromverbrauch des Hauses in Watt: HousePowerSinkW&lt;br /&gt;
* Tagesverbrauch des Hauses in kWh: HouseEnergySinkkWh&lt;br /&gt;
* Momentane Netzeinspeisung oder Netzbezug in W: GridPowerW = GridPowerSourceW + GridPowerSinkW&lt;br /&gt;
* Netzbezug des Tages in kWh: GridEnergySourcekWh&lt;br /&gt;
* Momentane Batterieladung oder -entladung in W: BatteryPowerW = BatteryPowerSourceW + BatteryPowerSinkW&lt;br /&gt;
* Ladezustand der Batterie in %: BatteryPercent&lt;br /&gt;
Die Benennung der Werte und deren Vorzeichen folgen einer Logik: &lt;br /&gt;
&lt;br /&gt;
* Es gibt Quellen (Source) und Senken (Sink) von Strom. &lt;br /&gt;
* Leistung mit positivem Vorzeichen wird einer Komponente entnommen (Quellen: PV-Anlage, Netzbezug, Batterieentladung). &lt;br /&gt;
* Leistung mit negativem Vorzeichen wird einer Komponente hinzugefügt (Senken: Netzeinspeisung, Hausstromverbrauch, Batterieladung).&lt;br /&gt;
* Die Energiemengen (PV-Anlage, Netzbezug, Netzeinspeisung, Batterieladung, Batterieentladung, Hausstromverbrauch) sind immer positiv.&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
Inspiration fand ich auf der Webseite [https://www.juergenstechnikwelt.de/photovoltaik/pv-anlage-in-fhem-die-datenbasis-fuer-das-dashboard/ Jürgens Technikwelt]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
define aggr.PV readingsProxy \&lt;br /&gt;
  smainverter:SPOT_PDC_SUM:PVPowerSourceW \&lt;br /&gt;
  smainverter:SPOT_EPVTODAY:PVEnergySourceWh \       &lt;br /&gt;
  smaem:SMAEM1234567890_Bezug_Wirkleistung:GridPowerSourceW \&lt;br /&gt;
  smaem:SMAEM1234567890_Einspeisung_Wirkleistung:GridPowerSinkW \&lt;br /&gt;
  calc.Netzbezug:smaem_SMAEM1234567890_Bezug_Wirkleistung_Zaehler_EnergyDay:GridEnergySourcekWh \&lt;br /&gt;
  calc.Netzeinspeisung:smaem_SMAEM1234567890_Einspeisung_Wirkleistung_Zaehler_EnergyDay:GridEnergySinkkWh \&lt;br /&gt;
  smainverter:BAT_P_CHARGE:BatteryPowerSinkW \&lt;br /&gt;
  smainverter:BAT_P_DISCHARGE:BatteryPowerSourceW \ &lt;br /&gt;
  smainverter:ChargeStatus:BatteryPercent \ &lt;br /&gt;
  smainverter:BAT_LOADTODAY:BatteryEnergySinkWh \&lt;br /&gt;
  smainverter:BAT_UNLOADTODAY:BatteryEnergySourceWh \&lt;br /&gt;
  smaem:SMAEM1234567890_GridFreq:GridFrequencyHz&lt;br /&gt;
attr aggr.PV stateFormat PV: PVPowerSourceW W &amp;lt; PVEnergySourcekWh kWh | Haus: HousePowerSinkW W &amp;gt; HouseEnergySinkkWh kWh | Netz: GridPowerW W &amp;lt; GridEnergySourcekWh kWh &amp;gt; GridEnergySinkkWh kWh | Batterie: BatteryPowerW W BatteryPercent % &amp;lt; BatteryEnergySourcekWh kWh &amp;gt; BatteryEnergySinkkWh kWh&lt;br /&gt;
attr aggr.PV userReadings \&lt;br /&gt;
  GridPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  BatteryPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  PVEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  HousePowerSinkW { -( ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVPowerSourceW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerW&amp;quot;, 0) ) }, \&lt;br /&gt;
  HouseEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;,&amp;quot;GridEnergySinkkWh&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkkWh&amp;quot;,0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourcekWh&amp;quot;, 0) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild &amp;lt;code&amp;gt;/opt/fhem/PictureFrame/sensorfeed2&amp;lt;/code&amp;gt; dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Ordner FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40891</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40891"/>
		<updated>2026-03-30T18:19:44Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Definition */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]&lt;br /&gt;
[[Datei:GIFTV.png|mini|240x240px|links]]&lt;br /&gt;
Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
==== Einleitung ====&lt;br /&gt;
Der readingsProxy wird benötigt, um aus verschiedenen Geräten Werte zusammenzuziehen, diese verständlich zu benennen, und weitere Werte mit userReadings zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Ich möchte im Mini-Dashboard gerne folgende Werte sehen:&lt;br /&gt;
* Momentane Leistung der PV-Anlage in Watt: PVPowerSourceW&lt;br /&gt;
* Tageserzeugung Solarstrom in kWh: PVEnergySourcekWh&lt;br /&gt;
* Momentaner Stromverbrauch des Hauses in Watt: HousePowerSinkW&lt;br /&gt;
* Tagesverbrauch des Hauses in kWh: HouseEnergySinkkWh&lt;br /&gt;
* Momentane Netzeinspeisung oder Netzbezug in W: GridPowerW = GridPowerSourceW + GridPowerSinkW&lt;br /&gt;
* Netzbezug des Tages in kWh: GridEnergySourcekWh&lt;br /&gt;
* Momentane Batterieladung oder -entladung in W: BatteryPowerW = BatteryPowerSourceW + BatteryPowerSinkW&lt;br /&gt;
* Ladezustand der Batterie in %: BatteryPercent&lt;br /&gt;
Die Benennung der Werte und deren Vorzeichen folgen einer Logik: &lt;br /&gt;
&lt;br /&gt;
* Es gibt Quellen (Source) und Senken (Sink) von Strom. &lt;br /&gt;
* Leistung mit positivem Vorzeichen wird einer Komponente entnommen (Quellen: PV-Anlage, Netzbezug, Batterieentladung). &lt;br /&gt;
* Leistung mit negativem Vorzeichen wird einer Komponente hinzugefügt (Senken: Netzeinspeisung, Hausstromverbrauch, Batterieladung).&lt;br /&gt;
* Die Energiemengen (PV-Anlage, Netzbezug, Netzeinspeisung, Batterieladung, Batterieentladung, Hausstromverbrauch) sind immer positiv.&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
Inspiration fand ich auf der Webseite [https://www.juergenstechnikwelt.de/photovoltaik/pv-anlage-in-fhem-die-datenbasis-fuer-das-dashboard/ Jürgens Technikwelt]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
define aggr.PV readingsProxy \&lt;br /&gt;
  smainverter:SPOT_PDC_SUM:PVPowerSourceW \&lt;br /&gt;
  smainverter:SPOT_EPVTODAY:PVEnergySourceWh \       &lt;br /&gt;
  smaem:SMAEM1234567890_Bezug_Wirkleistung:GridPowerSourceW \&lt;br /&gt;
  smaem:SMAEM1234567890_Einspeisung_Wirkleistung:GridPowerSinkW \&lt;br /&gt;
  calc.Netzbezug:smaem_SMAEM1234567890_Bezug_Wirkleistung_Zaehler_EnergyDay:GridEnergySourcekWh \&lt;br /&gt;
  calc.Netzeinspeisung:smaem_SMAEM1234567890_Einspeisung_Wirkleistung_Zaehler_EnergyDay:GridEnergySinkkWh \&lt;br /&gt;
  smainverter:BAT_P_CHARGE:BatteryPowerSinkW \&lt;br /&gt;
  smainverter:BAT_P_DISCHARGE:BatteryPowerSourceW \ &lt;br /&gt;
  smainverter:ChargeStatus:BatteryPercent \ &lt;br /&gt;
  smainverter:BAT_LOADTODAY:BatteryEnergySinkWh \&lt;br /&gt;
  smainverter:BAT_UNLOADTODAY:BatteryEnergySourceWh \&lt;br /&gt;
  smaem:SMAEM1234567890_GridFreq:GridFrequencyHz&lt;br /&gt;
attr aggr.PV stateFormat PV: PVPowerSourceW W &amp;lt; PVEnergySourcekWh kWh | Haus: HousePowerSinkW W &amp;gt; HouseEnergySinkkWh kWh | Netz: GridPowerW W &amp;lt; GridEnergySourcekWh kWh &amp;gt; GridEnergySinkkWh kWh | Batterie: BatteryPowerW W BatteryPercent % &amp;lt; BatteryEnergySourcekWh kWh &amp;gt; BatteryEnergySinkkWh kWh&lt;br /&gt;
attr aggr.PV userReadings \&lt;br /&gt;
  GridPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  BatteryPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  PVEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  HousePowerSinkW { -( ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVPowerSourceW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerW&amp;quot;, 0) ) }, \&lt;br /&gt;
  HouseEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;,&amp;quot;GridEnergySinkkWh&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkkWh&amp;quot;,0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourcekWh&amp;quot;, 0) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild /opt/fhem/PictureFrame/sensorfeed2 dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Ordner FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40882</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40882"/>
		<updated>2026-03-29T16:35:09Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Sinn und Zweck */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]&lt;br /&gt;
[[Datei:GIFTV.png|mini|240x240px|links]]&lt;br /&gt;
Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
==== Einleitung ====&lt;br /&gt;
Der readingsProxy wird benötigt, um aus verschiedenen Geräten Werte zusammenzuziehen, diese verständlich zu benennen, und weitere Werte mit userReadings zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Ich möchte im Mini-Dashboard gerne folgende Werte sehen:&lt;br /&gt;
* Momentane Leistung der PV-Anlage in Watt: PVPowerSourceW&lt;br /&gt;
* Tageserzeugung Solarstrom in kWh: PVEnergySourcekWh&lt;br /&gt;
* Momentaner Stromverbrauch des Hauses in Watt: HousePowerSinkW&lt;br /&gt;
* Tagesverbrauch des Hauses in kWh: HouseEnergySinkkWh&lt;br /&gt;
* Momentane Netzeinspeisung oder Netzbezug in W: GridPowerW = GridPowerSourceW + GridPowerSinkW&lt;br /&gt;
* Netzbezug des Tages in kWh: GridEnergySourcekWh&lt;br /&gt;
* Momentane Batterieladung oder -entladung in W: BatteryPowerW = BatteryPowerSourceW + BatteryPowerSinkW&lt;br /&gt;
* Ladezustand der Batterie in %: BatteryPercent&lt;br /&gt;
Die Benennung der Werte und deren Vorzeichen folgen einer Logik: &lt;br /&gt;
&lt;br /&gt;
* Es gibt Quellen (Source) und Senken (Sink) von Strom. &lt;br /&gt;
* Leistung mit positivem Vorzeichen wird einer Komponente entnommen (Quellen: PV-Anlage, Netzbezug, Batterieentladung). &lt;br /&gt;
* Leistung mit negativem Vorzeichen wird einer Komponente hinzugefügt (Senken: Netzeinspeisung, Hausstromverbrauch, Batterieladung).&lt;br /&gt;
* Die Energiemengen (PV-Anlage, Netzbezug, Netzeinspeisung, Batterieladung, Batterieentladung, Hausstromverbrauch) sind immer positiv.&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
Inspiration fand ich auf der Webseite [https://www.juergenstechnikwelt.de/photovoltaik/pv-anlage-in-fhem-die-datenbasis-fuer-das-dashboard/ Jürgens Technikwelt]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;define aggr.PV readingsProxy \&lt;br /&gt;
  smainverter:SPOT_PDC_SUM:PVPowerSourceW \&lt;br /&gt;
  smainverter:SPOT_EPVTODAY:PVEnergySourceWh \       &lt;br /&gt;
  smaem:SMAEM1234567890_Bezug_Wirkleistung:GridPowerSourceW \&lt;br /&gt;
  smaem:SMAEM1234567890_Einspeisung_Wirkleistung:GridPowerSinkW \&lt;br /&gt;
  calc.Netzbezug:smaem_SMAEM1234567890_Bezug_Wirkleistung_Zaehler_EnergyDay:GridEnergySourcekWh \&lt;br /&gt;
  calc.Netzeinspeisung:smaem_SMAEM1234567890_Einspeisung_Wirkleistung_Zaehler_EnergyDay:GridEnergySinkkWh \&lt;br /&gt;
  smainverter:BAT_P_CHARGE:BatteryPowerSinkW \&lt;br /&gt;
  smainverter:BAT_P_DISCHARGE:BatteryPowerSourceW \ &lt;br /&gt;
  smainverter:ChargeStatus:BatteryPercent \ &lt;br /&gt;
  smainverter:BAT_LOADTODAY:BatteryEnergySinkWh \&lt;br /&gt;
  smainverter:BAT_UNLOADTODAY:BatteryEnergySourceWh \&lt;br /&gt;
  smaem:SMAEM1234567890_GridFreq:GridFrequencyHz&lt;br /&gt;
attr aggr.PV stateFormat PV: PVPowerSourceW W &amp;lt; PVEnergySourcekWh kWh | Haus: HousePowerSinkW W &amp;gt; HouseEnergySinkkWh kWh | Netz: GridPowerW W &amp;lt; GridEnergySourcekWh kWh &amp;gt; GridEnergySinkkWh kWh | Batterie: BatteryPowerW W BatteryPercent % &amp;lt; BatteryEnergySourcekWh kWh &amp;gt; BatteryEnergySinkkWh kWh&lt;br /&gt;
attr aggr.PV userReadings \&lt;br /&gt;
  GridPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  BatteryPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  PVEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  HousePowerSinkW { -( ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVPowerSourceW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerW&amp;quot;, 0) ) }, \&lt;br /&gt;
  HouseEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;,&amp;quot;GridEnergySinkkWh&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkkWh&amp;quot;,0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourcekWh&amp;quot;, 0) \&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild /opt/fhem/PictureFrame/sensorfeed2 dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Ordner FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40881</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40881"/>
		<updated>2026-03-29T16:34:27Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Sinn und Zweck */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]&lt;br /&gt;
[[Datei:GIFTV.png|zentriert|mini|240x240px]]&lt;br /&gt;
Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
==== Einleitung ====&lt;br /&gt;
Der readingsProxy wird benötigt, um aus verschiedenen Geräten Werte zusammenzuziehen, diese verständlich zu benennen, und weitere Werte mit userReadings zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Ich möchte im Mini-Dashboard gerne folgende Werte sehen:&lt;br /&gt;
* Momentane Leistung der PV-Anlage in Watt: PVPowerSourceW&lt;br /&gt;
* Tageserzeugung Solarstrom in kWh: PVEnergySourcekWh&lt;br /&gt;
* Momentaner Stromverbrauch des Hauses in Watt: HousePowerSinkW&lt;br /&gt;
* Tagesverbrauch des Hauses in kWh: HouseEnergySinkkWh&lt;br /&gt;
* Momentane Netzeinspeisung oder Netzbezug in W: GridPowerW = GridPowerSourceW + GridPowerSinkW&lt;br /&gt;
* Netzbezug des Tages in kWh: GridEnergySourcekWh&lt;br /&gt;
* Momentane Batterieladung oder -entladung in W: BatteryPowerW = BatteryPowerSourceW + BatteryPowerSinkW&lt;br /&gt;
* Ladezustand der Batterie in %: BatteryPercent&lt;br /&gt;
Die Benennung der Werte und deren Vorzeichen folgen einer Logik: &lt;br /&gt;
&lt;br /&gt;
* Es gibt Quellen (Source) und Senken (Sink) von Strom. &lt;br /&gt;
* Leistung mit positivem Vorzeichen wird einer Komponente entnommen (Quellen: PV-Anlage, Netzbezug, Batterieentladung). &lt;br /&gt;
* Leistung mit negativem Vorzeichen wird einer Komponente hinzugefügt (Senken: Netzeinspeisung, Hausstromverbrauch, Batterieladung).&lt;br /&gt;
* Die Energiemengen (PV-Anlage, Netzbezug, Netzeinspeisung, Batterieladung, Batterieentladung, Hausstromverbrauch) sind immer positiv.&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
Inspiration fand ich auf der Webseite [https://www.juergenstechnikwelt.de/photovoltaik/pv-anlage-in-fhem-die-datenbasis-fuer-das-dashboard/ Jürgens Technikwelt]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;define aggr.PV readingsProxy \&lt;br /&gt;
  smainverter:SPOT_PDC_SUM:PVPowerSourceW \&lt;br /&gt;
  smainverter:SPOT_EPVTODAY:PVEnergySourceWh \       &lt;br /&gt;
  smaem:SMAEM1234567890_Bezug_Wirkleistung:GridPowerSourceW \&lt;br /&gt;
  smaem:SMAEM1234567890_Einspeisung_Wirkleistung:GridPowerSinkW \&lt;br /&gt;
  calc.Netzbezug:smaem_SMAEM1234567890_Bezug_Wirkleistung_Zaehler_EnergyDay:GridEnergySourcekWh \&lt;br /&gt;
  calc.Netzeinspeisung:smaem_SMAEM1234567890_Einspeisung_Wirkleistung_Zaehler_EnergyDay:GridEnergySinkkWh \&lt;br /&gt;
  smainverter:BAT_P_CHARGE:BatteryPowerSinkW \&lt;br /&gt;
  smainverter:BAT_P_DISCHARGE:BatteryPowerSourceW \ &lt;br /&gt;
  smainverter:ChargeStatus:BatteryPercent \ &lt;br /&gt;
  smainverter:BAT_LOADTODAY:BatteryEnergySinkWh \&lt;br /&gt;
  smainverter:BAT_UNLOADTODAY:BatteryEnergySourceWh \&lt;br /&gt;
  smaem:SMAEM1234567890_GridFreq:GridFrequencyHz&lt;br /&gt;
attr aggr.PV stateFormat PV: PVPowerSourceW W &amp;lt; PVEnergySourcekWh kWh | Haus: HousePowerSinkW W &amp;gt; HouseEnergySinkkWh kWh | Netz: GridPowerW W &amp;lt; GridEnergySourcekWh kWh &amp;gt; GridEnergySinkkWh kWh | Batterie: BatteryPowerW W BatteryPercent % &amp;lt; BatteryEnergySourcekWh kWh &amp;gt; BatteryEnergySinkkWh kWh&lt;br /&gt;
attr aggr.PV userReadings \&lt;br /&gt;
  GridPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  BatteryPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  PVEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  HousePowerSinkW { -( ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVPowerSourceW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerW&amp;quot;, 0) ) }, \&lt;br /&gt;
  HouseEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;,&amp;quot;GridEnergySinkkWh&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkkWh&amp;quot;,0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourcekWh&amp;quot;, 0) \&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild /opt/fhem/PictureFrame/sensorfeed2 dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Ordner FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Datei:GIFTV.png&amp;diff=40880</id>
		<title>Datei:GIFTV.png</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Datei:GIFTV.png&amp;diff=40880"/>
		<updated>2026-03-29T16:33:28Z</updated>

		<summary type="html">&lt;p&gt;Neubert: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Bild eines GIFTV von GeekMagic&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40879</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40879"/>
		<updated>2026-03-29T16:28:10Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Definition */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
==== Einleitung ====&lt;br /&gt;
Der readingsProxy wird benötigt, um aus verschiedenen Geräten Werte zusammenzuziehen, diese verständlich zu benennen, und weitere Werte mit userReadings zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Ich möchte im Mini-Dashboard gerne folgende Werte sehen:&lt;br /&gt;
* Momentane Leistung der PV-Anlage in Watt: PVPowerSourceW&lt;br /&gt;
* Tageserzeugung Solarstrom in kWh: PVEnergySourcekWh&lt;br /&gt;
* Momentaner Stromverbrauch des Hauses in Watt: HousePowerSinkW&lt;br /&gt;
* Tagesverbrauch des Hauses in kWh: HouseEnergySinkkWh&lt;br /&gt;
* Momentane Netzeinspeisung oder Netzbezug in W: GridPowerW = GridPowerSourceW + GridPowerSinkW&lt;br /&gt;
* Netzbezug des Tages in kWh: GridEnergySourcekWh&lt;br /&gt;
* Momentane Batterieladung oder -entladung in W: BatteryPowerW = BatteryPowerSourceW + BatteryPowerSinkW&lt;br /&gt;
* Ladezustand der Batterie in %: BatteryPercent&lt;br /&gt;
Die Benennung der Werte und deren Vorzeichen folgen einer Logik: &lt;br /&gt;
&lt;br /&gt;
* Es gibt Quellen (Source) und Senken (Sink) von Strom. &lt;br /&gt;
* Leistung mit positivem Vorzeichen wird einer Komponente entnommen (Quellen: PV-Anlage, Netzbezug, Batterieentladung). &lt;br /&gt;
* Leistung mit negativem Vorzeichen wird einer Komponente hinzugefügt (Senken: Netzeinspeisung, Hausstromverbrauch, Batterieladung).&lt;br /&gt;
* Die Energiemengen (PV-Anlage, Netzbezug, Netzeinspeisung, Batterieladung, Batterieentladung, Hausstromverbrauch) sind immer positiv.&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
Inspiration fand ich auf der Webseite [https://www.juergenstechnikwelt.de/photovoltaik/pv-anlage-in-fhem-die-datenbasis-fuer-das-dashboard/ Jürgens Technikwelt]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;define aggr.PV readingsProxy \&lt;br /&gt;
  smainverter:SPOT_PDC_SUM:PVPowerSourceW \&lt;br /&gt;
  smainverter:SPOT_EPVTODAY:PVEnergySourceWh \       &lt;br /&gt;
  smaem:SMAEM1234567890_Bezug_Wirkleistung:GridPowerSourceW \&lt;br /&gt;
  smaem:SMAEM1234567890_Einspeisung_Wirkleistung:GridPowerSinkW \&lt;br /&gt;
  calc.Netzbezug:smaem_SMAEM1234567890_Bezug_Wirkleistung_Zaehler_EnergyDay:GridEnergySourcekWh \&lt;br /&gt;
  calc.Netzeinspeisung:smaem_SMAEM1234567890_Einspeisung_Wirkleistung_Zaehler_EnergyDay:GridEnergySinkkWh \&lt;br /&gt;
  smainverter:BAT_P_CHARGE:BatteryPowerSinkW \&lt;br /&gt;
  smainverter:BAT_P_DISCHARGE:BatteryPowerSourceW \ &lt;br /&gt;
  smainverter:ChargeStatus:BatteryPercent \ &lt;br /&gt;
  smainverter:BAT_LOADTODAY:BatteryEnergySinkWh \&lt;br /&gt;
  smainverter:BAT_UNLOADTODAY:BatteryEnergySourceWh \&lt;br /&gt;
  smaem:SMAEM1234567890_GridFreq:GridFrequencyHz&lt;br /&gt;
attr aggr.PV stateFormat PV: PVPowerSourceW W &amp;lt; PVEnergySourcekWh kWh | Haus: HousePowerSinkW W &amp;gt; HouseEnergySinkkWh kWh | Netz: GridPowerW W &amp;lt; GridEnergySourcekWh kWh &amp;gt; GridEnergySinkkWh kWh | Batterie: BatteryPowerW W BatteryPercent % &amp;lt; BatteryEnergySourcekWh kWh &amp;gt; BatteryEnergySinkkWh kWh&lt;br /&gt;
attr aggr.PV userReadings \&lt;br /&gt;
  GridPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  BatteryPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  PVEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  HousePowerSinkW { -( ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVPowerSourceW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerW&amp;quot;, 0) ) }, \&lt;br /&gt;
  HouseEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;,&amp;quot;GridEnergySinkkWh&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkkWh&amp;quot;,0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourcekWh&amp;quot;, 0) \&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild /opt/fhem/PictureFrame/sensorfeed2 dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Ordner FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40878</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40878"/>
		<updated>2026-03-29T16:27:11Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* readingsProxy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
==== Einleitung ====&lt;br /&gt;
Der readingsProxy wird benötigt, um aus verschiedenen Geräten Werte zusammenzuziehen, diese verständlich zu benennen, und weitere Werte mit userReadings zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Ich möchte im Mini-Dashboard gerne folgende Werte sehen:&lt;br /&gt;
* Momentane Leistung der PV-Anlage in Watt: PVPowerSourceW&lt;br /&gt;
* Tageserzeugung Solarstrom in kWh: PVEnergySourcekWh&lt;br /&gt;
* Momentaner Stromverbrauch des Hauses in Watt: HousePowerSinkW&lt;br /&gt;
* Tagesverbrauch des Hauses in kWh: HouseEnergySinkkWh&lt;br /&gt;
* Momentane Netzeinspeisung oder Netzbezug in W: GridPowerW = GridPowerSourceW + GridPowerSinkW&lt;br /&gt;
* Netzbezug des Tages in kWh: GridEnergySourcekWh&lt;br /&gt;
* Momentane Batterieladung oder -entladung in W: BatteryPowerW = BatteryPowerSourceW + BatteryPowerSinkW&lt;br /&gt;
* Ladezustand der Batterie in %: BatteryPercent&lt;br /&gt;
Die Benennung der Werte und deren Vorzeichen folgen einer Logik: &lt;br /&gt;
&lt;br /&gt;
* Es gibt Quellen (Source) und Senken (Sink) von Strom. &lt;br /&gt;
* Leistung mit positivem Vorzeichen wird einer Komponente entnommen (Quellen: PV-Anlage, Netzbezug, Batterieentladung). &lt;br /&gt;
* Leistung mit negativem Vorzeichen wird einer Komponente hinzugefügt (Senken: Netzeinspeisung, Hausstromverbrauch, Batterieladung).&lt;br /&gt;
* Die Energiemengen (PV-Anlage, Netzbezug, Netzeinspeisung, Batterieladung, Batterieentladung, Hausstromverbrauch) sind immer positiv.&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
Inspiration fand ich auf der Webseite [https://www.juergenstechnikwelt.de/photovoltaik/pv-anlage-in-fhem-die-datenbasis-fuer-das-dashboard/ Jürgens Technikwelt]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;define aggr.PV readingsProxy \&lt;br /&gt;
  smainverter:SPOT_PDC_SUM:PVPowerSourceW \&lt;br /&gt;
  smainverter:SPOT_EPVTODAY:PVEnergySourceWh \       &lt;br /&gt;
  smaem:SMAEM1234567890_Bezug_Wirkleistung:GridPowerSourceW \&lt;br /&gt;
  smaem:SMAEM1234567890_Einspeisung_Wirkleistung:GridPowerSinkW \&lt;br /&gt;
  calc.Netzbezug:smaem_SMAEM1234567890_Bezug_Wirkleistung_Zaehler_EnergyDay:GridEnergySourcekWh \&lt;br /&gt;
  calc.Netzeinspeisung:smaem_SMAEM1234567890_Einspeisung_Wirkleistung_Zaehler_EnergyDay:GridEnergySinkkWh \&lt;br /&gt;
  smainverter:BAT_P_CHARGE:BatteryPowerSinkW \&lt;br /&gt;
  smainverter:BAT_P_DISCHARGE:BatteryPowerSourceW \ &lt;br /&gt;
  smainverter:ChargeStatus:BatteryPercent \ &lt;br /&gt;
  smainverter:BAT_LOADTODAY:BatteryEnergySinkWh \&lt;br /&gt;
  smainverter:BAT_UNLOADTODAY:BatteryEnergySourceWh \&lt;br /&gt;
  smaem:SMAEM1234567890_GridFreq:GridFrequencyHz&lt;br /&gt;
attr aggr.PV stateFormat PV: PVPowerSourceW W &amp;lt; PVEnergySourcekWh kWh | Haus: HousePowerSinkW W &amp;gt; HouseEnergySinkkWh kWh | Netz: GridPowerW W &amp;lt; GridEnergySourcekWh kWh &amp;gt; GridEnergySinkkWh kWh | Batterie: BatteryPowerW W BatteryPercent % &amp;lt; BatteryEnergySourcekWh kWh &amp;gt; BatteryEnergySinkkWh kWh&lt;br /&gt;
attr aggr.PV userReadings \&lt;br /&gt;
  GridPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  BatteryPowerW { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSourceW&amp;quot;, 0) - ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerSinkW&amp;quot;, 0) }, \&lt;br /&gt;
  PVEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySourcekWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourceWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  BatteryEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkWh&amp;quot;, 0)/1000.0 }, \&lt;br /&gt;
  HousePowerSinkW { -( ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVPowerSourceW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridPowerW&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryPowerW&amp;quot;, 0) ) }, \&lt;br /&gt;
  HouseEnergySinkkWh { ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;PVEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;,&amp;quot;GridEnergySinkkWh&amp;quot;, 0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;GridEnergySourcekWh&amp;quot;, 0)-ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySinkkWh&amp;quot;,0)+ReadingsNum(&amp;quot;aggr.PV&amp;quot;, &amp;quot;BatteryEnergySourcekWh&amp;quot;, 0) \&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild /opt/fhem/PictureFrame/sensorfeed2 dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Ordner FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40877</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40877"/>
		<updated>2026-03-29T16:06:34Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* push2giftv() */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
Der readingsProxy wird benötigt, um aus verschiedenen Geräten Werte zusammenzuziehen, diese verständlich zu benennen, und weitere Werte mit userReadings zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Ich möchte im Mini-Dashboard gerne folgende Werte sehen:&lt;br /&gt;
* Momentane Leistung der PV-Anlage in Watt: PVPowerSourceW&lt;br /&gt;
* Tageserzeugung Solarstrom in kWh: PVEnergySourcekWh&lt;br /&gt;
* Momentaner Stromverbrauch des Hauses in Watt: HousePowerSinkW&lt;br /&gt;
* Tagesverbrauch des Hauses in kWh: HouseEnergySinkkWh&lt;br /&gt;
* Momentane Netzeinspeisung oder Netzbezug in W: GridPowerW&lt;br /&gt;
* Netzbezug des Tages in kWh: GridEnergySourcekWh&lt;br /&gt;
* Momentane Batterieladung oder -entladung in W: BatteryPowerW&lt;br /&gt;
* Ladezustand der Batterie in %: BatteryPercent&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild /opt/fhem/PictureFrame/sensorfeed2 dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Ordner FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40876</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40876"/>
		<updated>2026-03-29T15:44:10Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* readingsProxy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
Der readingsProxy wird benötigt, um aus verschiedenen Geräten Werte zusammenzuziehen, diese verständlich zu benennen, und weitere Werte mit userReadings zu berechnen.&lt;br /&gt;
&lt;br /&gt;
Ich möchte im Mini-Dashboard gerne folgende Werte sehen:&lt;br /&gt;
* Momentane Leistung der PV-Anlage in Watt: PVPowerSourceW&lt;br /&gt;
* Tageserzeugung Solarstrom in kWh: PVEnergySourcekWh&lt;br /&gt;
* Momentaner Stromverbrauch des Hauses in Watt: HousePowerSinkW&lt;br /&gt;
* Tagesverbrauch des Hauses in kWh: HouseEnergySinkkWh&lt;br /&gt;
* Momentane Netzeinspeisung oder Netzbezug in W: GridPowerW&lt;br /&gt;
* Netzbezug des Tages in kWh: GridEnergySourcekWh&lt;br /&gt;
* Momentane Batterieladung oder -entladung in W: BatteryPowerW&lt;br /&gt;
* Ladezustand der Batterie in %: BatteryPercent&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild /opt/fhem/PictureFrame/sensorfeed2 dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Order FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40875</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40875"/>
		<updated>2026-03-29T15:36:50Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* push2giftv() */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild /opt/fhem/PictureFrame/sensorfeed2 dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Order FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40874</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40874"/>
		<updated>2026-03-29T15:35:28Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* push2giftv() */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild /opt/fhem/PictureFrame/sensorfeed2 dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Order FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40873</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40873"/>
		<updated>2026-03-29T15:34:09Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Layout */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild /opt/fhem/PictureFrame/sensorfeed2 dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;code&amp;gt;/opt/fhem/conf/sensorfeed2.layout&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Order FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40872</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40872"/>
		<updated>2026-03-29T15:23:17Z</updated>

		<summary type="html">&lt;p&gt;Neubert: Teile geschrieben&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini|links]]Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Das Dashboard wird als JPG-Bild mit dem Modul RSS on-the-fly erstellt. Ein at-Kommando ruft jede Minute ein Bild vom Modul ab und schiebt es über eine Perl-Funktion auf das GIFTV. Das GIFTV arbeitet dabei mit seiner Standard-Firmware im Bilderalbum-Modus. &lt;br /&gt;
&lt;br /&gt;
Die Werte für das Dashboard stammen aus einem readingsProxy (neue Version ab April 2026), der die angezeigten Werte aus mehreren Geräten (SMA Energy Meter, SMA Inverter, Electricity Calculator) zusammenführt. Die Anzeige im Dashboard bedient sich der Widgets von DOIF (siehe [[DOIF/uiTable Schnelleinstieg]]).&lt;br /&gt;
&lt;br /&gt;
=== readingsProxy ===&lt;br /&gt;
&lt;br /&gt;
=== RSS ===&lt;br /&gt;
&lt;br /&gt;
==== Definition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define sensorfeed2 RSS jpg has-1.example.com /opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
attr sensorfeed2 bg /opt/fhem/PictureFrame/sensorfeed2&lt;br /&gt;
attr sensorfeed2 size 240x240&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das KI-generierte Hintergrundbild /opt/fhem/PictureFrame/sensorfeed2 dient als Symbolbild.&lt;br /&gt;
&lt;br /&gt;
==== Layout ====&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann. Wenn man kein DOIF benutzt, muss man das Modul mit &amp;lt;code&amp;gt;require 98_DOIF.pm&amp;lt;/code&amp;gt; im Perl-Kode laden - das erfolgt unprätentiös in dem automatisch geladenen 99_GIFTV.pm.&lt;br /&gt;
&lt;br /&gt;
/opt/fhem/conf/sensorfeed2.layout&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# ------------------&lt;br /&gt;
# font&lt;br /&gt;
# ------------------&lt;br /&gt;
font /opt/fhem/conf/DroidSans.ttf&lt;br /&gt;
# ------------------&lt;br /&gt;
# bottom left corner&lt;br /&gt;
# ------------------&lt;br /&gt;
#&lt;br /&gt;
# date/time&lt;br /&gt;
#&lt;br /&gt;
rgb &amp;quot;c0c0c0&amp;quot;&lt;br /&gt;
pt 10&lt;br /&gt;
date  10 230&lt;br /&gt;
time 100 230&lt;br /&gt;
#&lt;br /&gt;
# links oben: Erzeugung&lt;br /&gt;
#&lt;br /&gt;
img  10  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVPowerSourceW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;PV&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;PVEnergySourcekWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts oben: Verbrauch&lt;br /&gt;
#&lt;br /&gt;
img 130  10 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HousePowerSinkW&#039;,0.0), 0.0, 4.0, 0, 240, &amp;quot;Haus&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;HouseEnergySinkkWh&#039;,0.0), 0, 50, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# links unten: Netzbezug (+)/Netzeinspeisung (-)&lt;br /&gt;
#&lt;br /&gt;
img  10 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Netz&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;GridEnergySourcekWh&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,kWh&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
#&lt;br /&gt;
# rechts unten: Batterie&lt;br /&gt;
#&lt;br /&gt;
img 130 130 100w svg data { ui_Table::ring2( \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPowerW&#039;,0.0), -4.0, 4.0, 0, 240, &amp;quot;Batt&amp;quot;, 100, undef, &amp;quot;0,,,W&amp;quot;, \&lt;br /&gt;
        main::ReadingsVal(&#039;aggr.PV&#039;,&#039;BatteryPercent&#039;,0.0), 0, 100, 0, 120, undef, undef, &amp;quot;0,,,%&amp;quot;) \&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bespielung des GIFTV ===&lt;br /&gt;
&lt;br /&gt;
==== at ====&lt;br /&gt;
&lt;br /&gt;
Der at-Befehl schiebt durch Aufruf von push2giftv() in Sekunde 1 jeder Minute das Bild vom RSS-Gerät sensorfeed2 auf zwei im Haus verteilte GIFTVs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define at.sensorfeed at +*00:01:00 { push2giftv( { &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&lt;br /&gt;
attr at.sensorfeed alignTime 01:01:01&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== push2giftv() ====&lt;br /&gt;
&lt;br /&gt;
Es wird ein automatisch von FHEM geladenes Modul 99_GIFTV.pm mit folgendem Inhalt im Order FHEM (unter Linux üblicherweise &amp;lt;code&amp;gt;/opt/fhem/FHEM/99_GIFTV.pm&amp;lt;/code&amp;gt;) bei den anderen Modulen angelegt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;require &#039;98_DOIF.pm&#039;;&lt;br /&gt;
&lt;br /&gt;
sub push2giftv {&lt;br /&gt;
    my $uploadsref = shift;&lt;br /&gt;
    # wrap code in eval to avoid lethal errors crashing FHEM&lt;br /&gt;
    eval {&lt;br /&gt;
      my $type = &amp;quot;jpg&amp;quot;;&lt;br /&gt;
      while( my ($rssname, $hostnamesref) = each(%$uploadsref) ) {&lt;br /&gt;
        # make RSS generate the image&lt;br /&gt;
        my ($mimetype, $image) = RSS_returnIMG($rssname, $type);&lt;br /&gt;
        my $targetfilename = &amp;quot;$rssname.$type&amp;quot;;&lt;br /&gt;
        foreach my $hostname (@$hostnamesref) {&lt;br /&gt;
          # parameters for GIFTV&lt;br /&gt;
          my $url = &amp;quot;http://$hostname/doUpload?dir=%2Fimage%2F&amp;quot;;&lt;br /&gt;
          my $param = {&lt;br /&gt;
                loglevel =&amp;gt; 4,&lt;br /&gt;
                url =&amp;gt; $url,&lt;br /&gt;
                method =&amp;gt; &amp;quot;POST&amp;quot;,&lt;br /&gt;
                hideurl =&amp;gt; 0,&lt;br /&gt;
                noshutdown =&amp;gt; 0,&lt;br /&gt;
                callback =&amp;gt; sub($$$) { Log3 $name, 1,&amp;quot;ERR:$_[1] DATA:&amp;quot;.length($_[2]) },&lt;br /&gt;
          };&lt;br /&gt;
          # add image as multipart form data&lt;br /&gt;
          HttpUtils_AddMultipartData($param, $image,&lt;br /&gt;
              {&amp;quot;Content-Disposition&amp;quot; =&amp;gt; &amp;quot;form-data; name=\&amp;quot;file\&amp;quot;; filename=\&amp;quot;$targetfilename\&amp;quot;&amp;quot;, &amp;quot;Content-Type&amp;quot; =&amp;gt; $mimetype }&lt;br /&gt;
          );&lt;br /&gt;
          # upload to GIFTV $hostname&lt;br /&gt;
          HttpUtils_NonblockingGet($param);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
    if ($@) {&lt;br /&gt;
        my $msg = $@;&lt;br /&gt;
        chomp $msg;&lt;br /&gt;
        Log3 $name, 2, $msg;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul 98_DOIF.pm wird benötigt, damit RSS die darin enthaltenen Widgets verwenden kann.&lt;br /&gt;
&lt;br /&gt;
push2giftv() nimmt als Argument ein Hash, das jedem RSS-Gerät (hier sensorfeed2) ein Array mit den Hostnamen oder IP-Adressen der GIFTVs zuordnet, auf die das Bild vom RSS-Gerät geschoben wird.&lt;br /&gt;
&lt;br /&gt;
Beispielaufruf, um mehrere Dashboards (sensorfeed1 und sensorfeed2) auf zwei GIFTVs zu schieben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;push2giftv( { &amp;quot;sensorfeed1&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;], &amp;quot;sensorfeed2&amp;quot; =&amp;gt; [&amp;quot;giftv-1.example.com&amp;quot;,&amp;quot;giftv-3.example.com&amp;quot;] } ) }&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GIFTV zeigt dann die beiden Dashboards im Wechsel an.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40871</id>
		<title>Mini-Dashboard für PV-Anlage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mini-Dashboard_f%C3%BCr_PV-Anlage&amp;diff=40871"/>
		<updated>2026-03-29T14:45:21Z</updated>

		<summary type="html">&lt;p&gt;Neubert: Seite wurde neu angelegt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Sinn und Zweck ==&lt;br /&gt;
Aus Fernost gab es gerade sehr billig ein Gadget in Form eines Mini-Fernsehers, der im wesentlichen aus einem ESP32 mit einem 240x240 Pixel großen Farb-LCD besteht: das GIFTV von GeekMagic. Ich habe mir damit ein Mini-Dashboard für meine Photovoltaik-Anlage gebaut.&lt;br /&gt;
[[Datei:Sensorfeed2.jpg|mini]]&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Datei:Sensorfeed2.jpg&amp;diff=40870</id>
		<title>Datei:Sensorfeed2.jpg</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Datei:Sensorfeed2.jpg&amp;diff=40870"/>
		<updated>2026-03-29T14:44:46Z</updated>

		<summary type="html">&lt;p&gt;Neubert: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;240x240 Pixel großes JPG-Bild der Anzeige im Mini-Dashboard&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Anwendungsszenarien&amp;diff=40869</id>
		<title>Anwendungsszenarien</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Anwendungsszenarien&amp;diff=40869"/>
		<updated>2026-03-29T14:38:18Z</updated>

		<summary type="html">&lt;p&gt;Neubert: Fallstudien verlinkt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Diese Seite stellt eine &amp;quot;redaktionell bearbeitete&amp;quot; Liste von Anwendungsszenarien dar. Weitere, ähnliche  Aufstellungen finden sich in den Kategorielisten &lt;br /&gt;
* [[:Kategorie:Examples|Examples]] für komplette Beispiele&lt;br /&gt;
* [[:Kategorie:Code Snippets|Code Snippets]] für kleine Schnipsel mit einzelnen Befehlen und/oder Definitionen&lt;br /&gt;
* und auf der Seite &amp;quot;[[Wie kann ich...]]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Finden sich hier Links auf Forenbeiträge oder externe Seiten, so sind diese als &amp;quot;gewünschte Seite&amp;quot; zu interpretieren.&lt;br /&gt;
&lt;br /&gt;
== Szenarien ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;width:50%&amp;quot; |&amp;lt;!-- Spalte 1 (links) --&amp;gt;&lt;br /&gt;
* (Haus-)Informations- und Steuerzentrale&lt;br /&gt;
** [[Fallstudie: Haus automatisieren]]&lt;br /&gt;
** Mittels [[RSS]] generiertes Übersichtsbild (ausführlicher Workshop verfügbar)&lt;br /&gt;
** Digitaler Bilderrahmen mit [[Digitaler Bilderrahmen | eingeblendeten FHEM-Daten]] oder zur [[Digitaler_Bilderrahmen_mit_lcd4linux| Anzeige von FHEM-Grafiken]]&lt;br /&gt;
** [[Statusdisplay Fritzbox 7390]]&lt;br /&gt;
** [[Kindle_Display]] (FHEM Informationen als Screensaver)&lt;br /&gt;
** [[Mini-Dashboard für PV-Anlage]]&lt;br /&gt;
&lt;br /&gt;
* Telefon &lt;br /&gt;
** [[Telefonat als Auslöser für Aktionen]]&lt;br /&gt;
** ...&lt;br /&gt;
&lt;br /&gt;
* Rollladensteuerung&lt;br /&gt;
** [[Jalousie und Beleuchtung in mehreren Räumen]]&lt;br /&gt;
** [[Slider für HM-Rolladensteuerung anzeigen]]&lt;br /&gt;
** [[Rolladensteuerung mit FS20SM8]]&lt;br /&gt;
** ...&lt;br /&gt;
&lt;br /&gt;
* Heizungssteuerung&lt;br /&gt;
** [[Grundlagen der Heizungssteuerung]]&lt;br /&gt;
** [[Heizungskontrolle Einfach]] (Englische Version: [[Heating Control Basic]])&lt;br /&gt;
** [[Junkers Therme Stetigregelung]]&lt;br /&gt;
** Heizungssteuerung mit [[HCS]] und/oder [[Heating Control]]&lt;br /&gt;
** 3/4-Wege-Mischer-Steuerung mit [[STELLMOTOR]]: [[Mischersteuerung]]&lt;br /&gt;
** Vorlauf-Energiebedarf mit [[VALVES]]: [[Raumbedarfsabhängige Heizungssteuerung]]&lt;br /&gt;
** Heizungsoptimierung (Mischer, Pumpe) [[Heizung:_Verbrauchsoptimierung,_Radiator/Fußboden-Steuerung]]&lt;br /&gt;
** [[Luxtronik 1 in FHEM]] einbinden&lt;br /&gt;
** [[Effizienter Betrieb einer Fußbodenheizung mit Luft-Wasser-Wärmepumpe (Fallbeispiel)]]&lt;br /&gt;
&lt;br /&gt;
* Balkon und Garten&lt;br /&gt;
** [[Bewässerungssteuerung]] &lt;br /&gt;
** ...&lt;br /&gt;
&lt;br /&gt;
* Lüftung und Klima&lt;br /&gt;
** [[Energiesparende Schimmelbekämpfung / Luftentfeuchtung in kritischen Räumen‎]]&lt;br /&gt;
** ...&lt;br /&gt;
&lt;br /&gt;
* Auto, Verkehr&lt;br /&gt;
** [[Spritpreismonitor]] sammelt und visualisiert die Preisentwicklung an ausgewählten Tankstellen&lt;br /&gt;
&lt;br /&gt;
| style=&amp;quot;width:50%&amp;quot; |&amp;lt;!-- Spalte 2 (rechts) --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Finanzen&lt;br /&gt;
** [[STOCKQUOTES|Wertpapierkurse verfolgen/protokollieren]]&lt;br /&gt;
** ...&lt;br /&gt;
&lt;br /&gt;
* Helligkeitsgeführte Steuerung&lt;br /&gt;
** [[Twilight Anwendungsbeispiel]]&lt;br /&gt;
** ...&lt;br /&gt;
&lt;br /&gt;
* Terminerinnerungen, Kalenderintegration&lt;br /&gt;
** Erinnerung an Müllabfuhr, etc.: {{Link2Forum|Topic=26209|LinkText=Forenthema}} und ein {{Link2Forum|Topic=32382|LinkText=weiteres Forenthema}}&lt;br /&gt;
** ...&lt;br /&gt;
&lt;br /&gt;
* Zugriff auf FHEM &amp;quot;von außen&amp;quot;&lt;br /&gt;
** [[FritzBox Webzugriff absichern]]&lt;br /&gt;
** [[FB7390 VPN-Zugang einrichten]]&lt;br /&gt;
** ...&lt;br /&gt;
&lt;br /&gt;
* Anwesenheitssimulation / -steuerung&lt;br /&gt;
** [[Anwesenheitserkennung]]&lt;br /&gt;
** ...&lt;br /&gt;
&lt;br /&gt;
* Zugangskontrolle, Fenster, Tür und Tor&lt;br /&gt;
** [[DoorPi_und_FHEM |Türsprechstelle mit DoorPi]]&lt;br /&gt;
** [[Garagentorsteuerung]]&lt;br /&gt;
** {{Link2Forum|Topic=11715|LinkText=Zugangskontrolle mit Keymatic, Fingerabdruck, RFID}} (Forum; sollte noch ins Wiki integriert werden)&lt;br /&gt;
** ...&lt;br /&gt;
&lt;br /&gt;
* (Video-)Überwachung&lt;br /&gt;
** Einbindung von (Web-)Cam Bildern / Streams&lt;br /&gt;
** ...&lt;br /&gt;
&lt;br /&gt;
* Energieverbrauch / -erzeugung&lt;br /&gt;
** [[Ertragsmessung Solarthermie]]&lt;br /&gt;
** [[Heizleistung und Gasverbrauch]]&lt;br /&gt;
&lt;br /&gt;
* Rundfunk / Fernsehen / Multimedia&lt;br /&gt;
** {{Link2Forum|Topic=28123|LinkText=Aktuelles TV-Programm}} auflisten (Forenthema)&lt;br /&gt;
** ...&lt;br /&gt;
&lt;br /&gt;
* Sonstiges&lt;br /&gt;
** [[Watchdog kombiniert mit Threshold|Auf ausbleibende Aktionen oder Ereignisse reagieren]]&lt;br /&gt;
** mit FHEM realisierte [[Zeitschaltuhr]]&lt;br /&gt;
** [[Temperaturfarbe | Temperatur in Farbe]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Sofern hier statt Verweisen auf andere Wiki-Seiten Forenthemen verlinkt sind, sind alle Wiki-Schreiber herzlich eingeladen, die Informationen aus dem Forum in einer (neuen) Wiki-Seite zu konsolidieren.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Examples]]&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40816</id>
		<title>Fallstudie: Haus automatisieren</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40816"/>
		<updated>2026-03-05T18:17:17Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Leuchtmittel */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel ist eine Fallstudie zum Einsatz von FHEM für die Hausautomation mit Anwendungsfeldern von FHEM, die für die meisten Anwender üblich sind. Er soll Einsteigern in FHEM die Nutzung von FHEM erleichtern.&lt;br /&gt;
&lt;br /&gt;
Ich bin ein FHEM-Nutzer der ersten Stunde und FHEM-Entwickler seit 2007. Dieser Artikel beschreibt die aufgrund von Umzügen vierte Installation von FHEM in einer von mir bewohnten Liegenschaft, nicht eingerechnet Aktualisierungen und Veränderungen an der Hausautomation aufgrund von Wechseln bei der eingesetzen Server-Hardware und -Software und den verwendeten Hausautomationssystemen.&lt;br /&gt;
&lt;br /&gt;
Ich bringe in diesen Artikel meine Erfahrungen ein, was sich als nützlich und praktisch erwiesen hat, und möchte dem FHEM-Anwender helfen, die Herausforderungen beim Einsatz bei FHEM durch konkrete Beispiele anhand meiner Anwendungsfälle zu bewältigen.&lt;br /&gt;
&lt;br /&gt;
== Automatisierte Liegenschaft ==&lt;br /&gt;
&lt;br /&gt;
Bei der Liegenschaft handelt es sich um ein Einfamilienhaus mit vier Etagen (Keller, Erdgeschoss, Obergeschoss, Dachgeschoss), Garage und Garten.&lt;br /&gt;
&lt;br /&gt;
== Hausautomationsserver ==&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
&lt;br /&gt;
==== Anforderungen ====&lt;br /&gt;
&lt;br /&gt;
Die Server-Hardware sollte zum einen ausreichend Rechenleistung für den Betrieb des FHEM-Frontends FHEMWEB bereitstellen, andererseits sparsam im Stromverbrauch sein, sowie autark.&lt;br /&gt;
&lt;br /&gt;
Die Autarkie spricht dafür, einen dedizierten Rechner für FHEM zum Einsatz zu bringen, denn die Hausautomation sollte durchgehend laufen, unabhängig von den anderen Spielereien im Home Lab.&lt;br /&gt;
&lt;br /&gt;
==== Geräteauswahl ====&lt;br /&gt;
&lt;br /&gt;
Es lag zunächst nahe, einen Raspberry Pi zum Einsatz zu bringen. Während die Modelle bis zum Raspberry Pi 3 bei der Darstellung von SVG-Plots mit längeren Zeitreihen überfordert waren, liefern die Versionen 4 und 5 mit viel RAM genügend Leistung. Allerdings sind die Flaggschiffe mittlerweile recht teuer, wenn man alle erforderlichen Komponenten (Computer, SD-Karte für Boot-Partition, SSD für Root- und Daten-Partionen, Netzteil, Gehäuse) zusammennimmt. Da ich die I/O-Ports des Raspberry Pi für Basteleien nicht benötige, habe ich mich in der Welt der Mini-PCs umgesehen.&lt;br /&gt;
&lt;br /&gt;
Meine Wahl fiel auf einen [https://minisforumpc.eu/ Minisforum] UN150P. Das Gerät bietet für knapp über 200 € eine grandiose Ausstattung und Leistung ([https://www.heise.de/bestenlisten/testbericht/minisforum-un150p-im-test/jn4g3l4 Testbericht]). Im Dezember 2025 ist das Gerät nicht (mehr) verfügbar. Es gibt aber eine Reihe vergleichbar leistungsstarker Mini-PCs in dieser Preisklasse.&lt;br /&gt;
&lt;br /&gt;
==== Aufstellort ====&lt;br /&gt;
&lt;br /&gt;
Um mit den anzuschließenden Funk-Interfaces das Haus möglichst gut abzudecken, empfiehlt sich ein zentraler Aufstellort. Bei mir ist das unter dem Schreibtisch im Arbeitszimmer im Obergeschoss.&lt;br /&gt;
&lt;br /&gt;
Eine Aufstellung im Serverschrank im Keller ist wegen der abseitigen Lage und der elektromagnetischen Abschirmung nicht sinnvoll.&lt;br /&gt;
&lt;br /&gt;
==== Peripherie ==== &lt;br /&gt;
&lt;br /&gt;
Für die Erstinstallation habe ich Tastatur, Maus und HDMI-Monitor an den Mini-PC angeschlossen. Später läuft der Mini-PC ohne Peripherie (&amp;quot;Headless&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Alternativ kann man einen Remote-KVM-Adapter anschließen. Dieser überträgt die Anschlüsse inklusive Bild hardwareseitig an einen entfernten Rechner. Im Gegensatz zu Remotedesktopsoftware, die ein laufendes Betriebssystem auf dem ferngesteuerten Rechner erfordert, kann man mit dem Remote-KVM-Adapter bereits den Boot-Vorgang beobachten und Einstellungen im BIOS aus der Ferne machen. &lt;br /&gt;
&lt;br /&gt;
Ich verwende dafür an einem anderen Rechner den [https://www.gl-inet.com/products/gl-rm1/ GL.iNet Comet (GL-RM1)] in der PoE-Variante. Für rund 100 € erhält man damit eine Funktionalität, für die man sonst ein sehr viel teureres Server-Mainboard benötigen würde.&lt;br /&gt;
&lt;br /&gt;
=== Software ===&lt;br /&gt;
&lt;br /&gt;
==== Überblick ====&lt;br /&gt;
Der Softwarestack auf dem Hautomationsserver besteht aus Proxmox Virtual Enviromnent und darauf ein Linux-Container mit Debian Linux 13 (Trixie) und FHEM als Hausautomationssoftware sowie Zigbee2MQTT für das Management der Zigbee-Geräte. Die Installation ist im folgenden skizziert.&lt;br /&gt;
&lt;br /&gt;
==== Installation des Proxmox Virtual Environments ====&lt;br /&gt;
&lt;br /&gt;
==== Installation des Linux-Containers ====&lt;br /&gt;
Hostname: has.example.org&lt;br /&gt;
&lt;br /&gt;
==== Installation von FHEM im Linux-Container ====&lt;br /&gt;
&lt;br /&gt;
== Anwendungsfelder ==&lt;br /&gt;
&lt;br /&gt;
Die gängigen Anwendungsfelder sind&lt;br /&gt;
* Beleuchtungssteuerung&lt;br /&gt;
* Raumklimaüberwachung und Heizungssteuerung&lt;br /&gt;
* Wetteraufzeichnung&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hausautomationssysteme ==&lt;br /&gt;
&lt;br /&gt;
=== Zigbee ===&lt;br /&gt;
&lt;br /&gt;
==== Hardware ====&lt;br /&gt;
[https://de.wikipedia.org/wiki/ZigBee Zigbee] braucht eine Zentraleinheit, die Koordinator genannt wird. Es kommt dafür ein [https://phoscon.de/de/conbee2 ConBee II von Phoscon]  zum Einsatz, der direkt am USB-Port des Hausautomationsservers angeschlossen ist. Das Gerät hatte ich mir vor einigen Jahren für Testzwecke zugelegt. Heute würde ich zu einem Flagschiff-Produkt von [https://smlight.tech/ SMLIGHT] greifen, das unabhängig vom Hausautomationsserver ans LAN angeschlossen und via PoE mit Strom versorgt wird.&lt;br /&gt;
&lt;br /&gt;
Der ConBee II erscheint auf dem Host (auf der Konsole mit &amp;lt;code&amp;gt;lsusb&amp;lt;/code&amp;gt; anzeigen):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Bus XXX Device XXX: ID 1cf1:0030 Dresden Elektronik ZigBee gateway [ConBee II]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Device dazu ist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/dev/serial/by-id/usb-dresden_elektronik_ingenieurtechnik_GmbH_ConBee_II_DExxxxxxx-if00&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Unter Proxmox fügt man zum Container unter &#039;&#039;Resources&#039;&#039; mit &#039;&#039;Add&#039;&#039; ein &#039;&#039;Device Passtrough&#039;&#039; hinzu mit dem o.a. &#039;&#039;Device Path, UID in CT: 0, GID in CT: 20, Access Mode in CT: 0660, Read only: aus&#039;&#039;. UID 0 ist &#039;&#039;root&#039;&#039; und GID 20 ist &#039;&#039;dialout&#039;&#039;. Das Gerät erscheint dann im Container genau mit demselben Device Path und Besitzer &#039;&#039;root:dialout&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Software ====&lt;br /&gt;
Für die Steuerung des Zigbee-Netzwerks kommt [https://www.zigbee2mqtt.io/ zigbee2mqtt] (kurz: z2m) zum Einsatz, was eine absolut spitzenmäßige Unterstützung für alle möglichen Fabrikate bietet. Die Software wird im Container installiert. Dazu folgt man der [https://www.zigbee2mqtt.io/guide/getting-started/ Anleitung für zigbee2mqtt]. Die Weboberfläche von zigbee2mqtt ist dann unter &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://has.example.org:8080&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; zu erreichen.&lt;br /&gt;
&lt;br /&gt;
==== Zigbee-Geräte ====&lt;br /&gt;
Um Zigbee-Geräte mit dem Koordinator zu paaren, also sie anzulernen, aktiviert man das Anlernen in der Weboberfläche von zigbee2mqtt wie in dessen Anleitung beschrieben.&lt;br /&gt;
&lt;br /&gt;
===== Leuchtmittel =====&lt;br /&gt;
Um Zigbee-Leuchtmittel zu paaren, hat sich eine &amp;quot;Paarungsstation&amp;quot; bewährt. Dabei handelt es sich um eine E27-Baufassung, die mit einem Schukostecker in eine schaltbare Steckdose eingesteckt wird.&lt;br /&gt;
[[Datei:Zigbee Paarung.jpg|mini]]&lt;br /&gt;
Dies ermöglicht es bequem vom Schreibtisch aus die Zigbee-Leuchtmittel mit dem Zigbee-Coordinator zu paaren.&lt;br /&gt;
&lt;br /&gt;
Die bekannten Paarungssequenzen für Leuchtmittel sind:&lt;br /&gt;
* IKEA-Tradfri: 6 Mal im Sekundentakt aus- und anschalten&lt;br /&gt;
* EGLO-Z (AwoX): 30 s aus, 1 s ein, 6 s aus, 1 s ein, 6 s aus, 1 s ein, 6 s aus, 12 s ein, 6 s aus, 12 s ein, 6 s aus, einschalten (siehe [https://www.eglo.com/de/connect-z-general-q2 Wie kann ich eine Leuchte auf Werkseinstellung zurücksetzen. (RESET)])&lt;br /&gt;
Die Sequenz von EGLO-Z kann man am besten wie folgt realisieren: Man lässt die Lampe mindestens 30 Sekunden aus. Dann startet man die Stoppuhr vom Smartphone und legt den Schalter jeweils um, wenn die folgenden Sekunden verstrichen sind: 0 (Stoppuhr starten und anschalten) 7 8 14 15 21 33 39 51 57 (Licht ist an und Lampe paarungsbereit). Es kommt übrigens nicht darauf an, die Zeit exakt zu treffen; es funktioniert auch schon, wenn man die Sequenz zeitlich so gut abarbeitet, wie man eben kann.&lt;br /&gt;
&lt;br /&gt;
== Nomenklatur ==&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40815</id>
		<title>Fallstudie: Haus automatisieren</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40815"/>
		<updated>2026-02-28T18:41:53Z</updated>

		<summary type="html">&lt;p&gt;Neubert: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel ist eine Fallstudie zum Einsatz von FHEM für die Hausautomation mit Anwendungsfeldern von FHEM, die für die meisten Anwender üblich sind. Er soll Einsteigern in FHEM die Nutzung von FHEM erleichtern.&lt;br /&gt;
&lt;br /&gt;
Ich bin ein FHEM-Nutzer der ersten Stunde und FHEM-Entwickler seit 2007. Dieser Artikel beschreibt die aufgrund von Umzügen vierte Installation von FHEM in einer von mir bewohnten Liegenschaft, nicht eingerechnet Aktualisierungen und Veränderungen an der Hausautomation aufgrund von Wechseln bei der eingesetzen Server-Hardware und -Software und den verwendeten Hausautomationssystemen.&lt;br /&gt;
&lt;br /&gt;
Ich bringe in diesen Artikel meine Erfahrungen ein, was sich als nützlich und praktisch erwiesen hat, und möchte dem FHEM-Anwender helfen, die Herausforderungen beim Einsatz bei FHEM durch konkrete Beispiele anhand meiner Anwendungsfälle zu bewältigen.&lt;br /&gt;
&lt;br /&gt;
== Automatisierte Liegenschaft ==&lt;br /&gt;
&lt;br /&gt;
Bei der Liegenschaft handelt es sich um ein Einfamilienhaus mit vier Etagen (Keller, Erdgeschoss, Obergeschoss, Dachgeschoss), Garage und Garten.&lt;br /&gt;
&lt;br /&gt;
== Hausautomationsserver ==&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
&lt;br /&gt;
==== Anforderungen ====&lt;br /&gt;
&lt;br /&gt;
Die Server-Hardware sollte zum einen ausreichend Rechenleistung für den Betrieb des FHEM-Frontends FHEMWEB bereitstellen, andererseits sparsam im Stromverbrauch sein, sowie autark.&lt;br /&gt;
&lt;br /&gt;
Die Autarkie spricht dafür, einen dedizierten Rechner für FHEM zum Einsatz zu bringen, denn die Hausautomation sollte durchgehend laufen, unabhängig von den anderen Spielereien im Home Lab.&lt;br /&gt;
&lt;br /&gt;
==== Geräteauswahl ====&lt;br /&gt;
&lt;br /&gt;
Es lag zunächst nahe, einen Raspberry Pi zum Einsatz zu bringen. Während die Modelle bis zum Raspberry Pi 3 bei der Darstellung von SVG-Plots mit längeren Zeitreihen überfordert waren, liefern die Versionen 4 und 5 mit viel RAM genügend Leistung. Allerdings sind die Flaggschiffe mittlerweile recht teuer, wenn man alle erforderlichen Komponenten (Computer, SD-Karte für Boot-Partition, SSD für Root- und Daten-Partionen, Netzteil, Gehäuse) zusammennimmt. Da ich die I/O-Ports des Raspberry Pi für Basteleien nicht benötige, habe ich mich in der Welt der Mini-PCs umgesehen.&lt;br /&gt;
&lt;br /&gt;
Meine Wahl fiel auf einen [https://minisforumpc.eu/ Minisforum] UN150P. Das Gerät bietet für knapp über 200 € eine grandiose Ausstattung und Leistung ([https://www.heise.de/bestenlisten/testbericht/minisforum-un150p-im-test/jn4g3l4 Testbericht]). Im Dezember 2025 ist das Gerät nicht (mehr) verfügbar. Es gibt aber eine Reihe vergleichbar leistungsstarker Mini-PCs in dieser Preisklasse.&lt;br /&gt;
&lt;br /&gt;
==== Aufstellort ====&lt;br /&gt;
&lt;br /&gt;
Um mit den anzuschließenden Funk-Interfaces das Haus möglichst gut abzudecken, empfiehlt sich ein zentraler Aufstellort. Bei mir ist das unter dem Schreibtisch im Arbeitszimmer im Obergeschoss.&lt;br /&gt;
&lt;br /&gt;
Eine Aufstellung im Serverschrank im Keller ist wegen der abseitigen Lage und der elektromagnetischen Abschirmung nicht sinnvoll.&lt;br /&gt;
&lt;br /&gt;
==== Peripherie ==== &lt;br /&gt;
&lt;br /&gt;
Für die Erstinstallation habe ich Tastatur, Maus und HDMI-Monitor an den Mini-PC angeschlossen. Später läuft der Mini-PC ohne Peripherie (&amp;quot;Headless&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Alternativ kann man einen Remote-KVM-Adapter anschließen. Dieser überträgt die Anschlüsse inklusive Bild hardwareseitig an einen entfernten Rechner. Im Gegensatz zu Remotedesktopsoftware, die ein laufendes Betriebssystem auf dem ferngesteuerten Rechner erfordert, kann man mit dem Remote-KVM-Adapter bereits den Boot-Vorgang beobachten und Einstellungen im BIOS aus der Ferne machen. &lt;br /&gt;
&lt;br /&gt;
Ich verwende dafür an einem anderen Rechner den [https://www.gl-inet.com/products/gl-rm1/ GL.iNet Comet (GL-RM1)] in der PoE-Variante. Für rund 100 € erhält man damit eine Funktionalität, für die man sonst ein sehr viel teureres Server-Mainboard benötigen würde.&lt;br /&gt;
&lt;br /&gt;
=== Software ===&lt;br /&gt;
&lt;br /&gt;
==== Überblick ====&lt;br /&gt;
Der Softwarestack auf dem Hautomationsserver besteht aus Proxmox Virtual Enviromnent und darauf ein Linux-Container mit Debian Linux 13 (Trixie) und FHEM als Hausautomationssoftware sowie Zigbee2MQTT für das Management der Zigbee-Geräte. Die Installation ist im folgenden skizziert.&lt;br /&gt;
&lt;br /&gt;
==== Installation des Proxmox Virtual Environments ====&lt;br /&gt;
&lt;br /&gt;
==== Installation des Linux-Containers ====&lt;br /&gt;
Hostname: has.example.org&lt;br /&gt;
&lt;br /&gt;
==== Installation von FHEM im Linux-Container ====&lt;br /&gt;
&lt;br /&gt;
== Anwendungsfelder ==&lt;br /&gt;
&lt;br /&gt;
Die gängigen Anwendungsfelder sind&lt;br /&gt;
* Beleuchtungssteuerung&lt;br /&gt;
* Raumklimaüberwachung und Heizungssteuerung&lt;br /&gt;
* Wetteraufzeichnung&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hausautomationssysteme ==&lt;br /&gt;
&lt;br /&gt;
=== Zigbee ===&lt;br /&gt;
&lt;br /&gt;
==== Hardware ====&lt;br /&gt;
[https://de.wikipedia.org/wiki/ZigBee Zigbee] braucht eine Zentraleinheit, die Koordinator genannt wird. Es kommt dafür ein [https://phoscon.de/de/conbee2 ConBee II von Phoscon]  zum Einsatz, der direkt am USB-Port des Hausautomationsservers angeschlossen ist. Das Gerät hatte ich mir vor einigen Jahren für Testzwecke zugelegt. Heute würde ich zu einem Flagschiff-Produkt von [https://smlight.tech/ SMLIGHT] greifen, das unabhängig vom Hausautomationsserver ans LAN angeschlossen und via PoE mit Strom versorgt wird.&lt;br /&gt;
&lt;br /&gt;
Der ConBee II erscheint auf dem Host (auf der Konsole mit &amp;lt;code&amp;gt;lsusb&amp;lt;/code&amp;gt; anzeigen):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Bus XXX Device XXX: ID 1cf1:0030 Dresden Elektronik ZigBee gateway [ConBee II]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Device dazu ist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/dev/serial/by-id/usb-dresden_elektronik_ingenieurtechnik_GmbH_ConBee_II_DExxxxxxx-if00&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Unter Proxmox fügt man zum Container unter &#039;&#039;Resources&#039;&#039; mit &#039;&#039;Add&#039;&#039; ein &#039;&#039;Device Passtrough&#039;&#039; hinzu mit dem o.a. &#039;&#039;Device Path, UID in CT: 0, GID in CT: 20, Access Mode in CT: 0660, Read only: aus&#039;&#039;. UID 0 ist &#039;&#039;root&#039;&#039; und GID 20 ist &#039;&#039;dialout&#039;&#039;. Das Gerät erscheint dann im Container genau mit demselben Device Path und Besitzer &#039;&#039;root:dialout&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Software ====&lt;br /&gt;
Für die Steuerung des Zigbee-Netzwerks kommt [https://www.zigbee2mqtt.io/ zigbee2mqtt] (kurz: z2m) zum Einsatz, was eine absolut spitzenmäßige Unterstützung für alle möglichen Fabrikate bietet. Die Software wird im Container installiert. Dazu folgt man der [https://www.zigbee2mqtt.io/guide/getting-started/ Anleitung für zigbee2mqtt]. Die Weboberfläche von zigbee2mqtt ist dann unter &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://has.example.org:8080&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; zu erreichen.&lt;br /&gt;
&lt;br /&gt;
==== Zigbee-Geräte ====&lt;br /&gt;
Um Zigbee-Geräte mit dem Koordinator zu paaren, also sie anzulernen, aktiviert man das Anlernen in der Weboberfläche von zigbee2mqtt wie in dessen Anleitung beschrieben.&lt;br /&gt;
&lt;br /&gt;
===== Leuchtmittel =====&lt;br /&gt;
Um Zigbee-Leuchtmittel zu paaren, hat sich eine &amp;quot;Paarungsstation&amp;quot; bewährt. Dabei handelt es sich um eine E27-Baufassung, die mit einem Schukostecker in eine schaltbare Steckdose eingesteckt wird.&lt;br /&gt;
[[Datei:Zigbee Paarung.jpg|mini]]&lt;br /&gt;
Dies ermöglicht es bequem vom Schreibtisch aus die Zigbee-Leuchtmittel mit dem Zigbee-Coordinator zu paaren.&lt;br /&gt;
&lt;br /&gt;
Die bekannten Paarungssequenzen für Leuchtmittel sind:&lt;br /&gt;
* IKEA-Tradfri: 6 Mal im Sekundentakt aus- und anschalten&lt;br /&gt;
* EGLO-Z (AwoX): 30 s aus, 1 s ein, 6 s aus, 1 s ein, 6 s aus, 1 s ein, 6 s aus, 12 s ein, 6 s aus, 12 s ein, 6 s aus, einschalten (siehe [https://www.eglo.com/de/connect-z-general-q2 Wie kann ich eine Leuchte auf Werkseinstellung zurücksetzen. (RESET)])&lt;br /&gt;
Die Sequenz von EGLO-Z kann man am besten wie folgt realisieren: Man lässt die Lampe mindestens 30 Sekunden aus. Dann startet man die Stoppuhr vom Smartphone und legt den Schalter jeweils um, wenn die folgenden Sekunden verstrichen sind: 0 (Stoppuhr starten und anschalten) 7 8 14 15 21 33 39 51 57 (Licht ist an und Lampe paarungsbereit).&lt;br /&gt;
&lt;br /&gt;
== Nomenklatur ==&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40781</id>
		<title>Fallstudie: Haus automatisieren</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40781"/>
		<updated>2026-02-07T16:22:59Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Software */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel ist eine Fallstudie zum Einsatz von FHEM für die Hausautomation mit Anwendungsfeldern von FHEM, die für die meisten Anwender üblich sind. Er soll Einsteigern in FHEM die Nutzung von FHEM erleichtern.&lt;br /&gt;
&lt;br /&gt;
Ich bin ein FHEM-Nutzer der ersten Stunde und FHEM-Entwickler seit 2007. Dieser Artikel beschreibt die aufgrund von Umzügen vierte Installation von FHEM in einer von mir bewohnten Liegenschaft, nicht eingerechnet Aktualisierungen und Veränderungen an der Hausautomation aufgrund von Wechseln bei der eingesetzen Server-Hardware und -Software und den verwendeten Hausautomationssystemen.&lt;br /&gt;
&lt;br /&gt;
Ich bringe in diesen Artikel meine Erfahrungen ein, was sich als nützlich und praktisch erwiesen hat, und möchte dem FHEM-Anwender helfen, die Herausforderungen beim Einsatz bei FHEM durch konkrete Beispiele anhand meiner Anwendungsfälle zu bewältigen.&lt;br /&gt;
&lt;br /&gt;
== Automatisierte Liegenschaft ==&lt;br /&gt;
&lt;br /&gt;
Bei der Liegenschaft handelt es sich um ein Einfamilienhaus mit vier Etagen (Keller, Erdgeschoss, Obergeschoss, Dachgeschoss), Garage und Garten.&lt;br /&gt;
&lt;br /&gt;
== Hausautomationsserver ==&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
&lt;br /&gt;
==== Anforderungen ====&lt;br /&gt;
&lt;br /&gt;
Die Server-Hardware sollte zum einen ausreichend Rechenleistung für den Betrieb des FHEM-Frontends FHEMWEB bereitstellen, andererseits sparsam im Stromverbrauch sein, sowie autark.&lt;br /&gt;
&lt;br /&gt;
Die Autarkie spricht dafür, einen dedizierten Rechner für FHEM zum Einsatz zu bringen, denn die Hausautomation sollte durchgehend laufen, unabhängig von den anderen Spielereien im Home Lab.&lt;br /&gt;
&lt;br /&gt;
==== Geräteauswahl ====&lt;br /&gt;
&lt;br /&gt;
Es lag zunächst nahe, einen Raspberry Pi zum Einsatz zu bringen. Während die Modelle bis zum Raspberry Pi 3 bei der Darstellung von SVG-Plots mit längeren Zeitreihen überfordert waren, liefern die Versionen 4 und 5 mit viel RAM genügend Leistung. Allerdings sind die Flaggschiffe mittlerweile recht teuer, wenn man alle erforderlichen Komponenten (Computer, SD-Karte für Boot-Partition, SSD für Root- und Daten-Partionen, Netzteil, Gehäuse) zusammennimmt. Da ich die I/O-Ports des Raspberry Pi für Basteleien nicht benötige, habe ich mich in der Welt der Mini-PCs umgesehen.&lt;br /&gt;
&lt;br /&gt;
Meine Wahl fiel auf einen [https://minisforumpc.eu/ Minisforum] UN150P. Das Gerät bietet für knapp über 200 € eine grandiose Ausstattung und Leistung ([https://www.heise.de/bestenlisten/testbericht/minisforum-un150p-im-test/jn4g3l4 Testbericht]). Im Dezember 2025 ist das Gerät nicht (mehr) verfügbar. Es gibt aber eine Reihe vergleichbar leistungsstarker Mini-PCs in dieser Preisklasse.&lt;br /&gt;
&lt;br /&gt;
==== Aufstellort ====&lt;br /&gt;
&lt;br /&gt;
Um mit den anzuschließenden Funk-Interfaces das Haus möglichst gut abzudecken, empfiehlt sich ein zentraler Aufstellort. Bei mir ist das unter dem Schreibtisch im Arbeitszimmer im Obergeschoss.&lt;br /&gt;
&lt;br /&gt;
Eine Aufstellung im Serverschrank im Keller ist wegen der abseitigen Lage und der elektromagnetischen Abschirmung nicht sinnvoll.&lt;br /&gt;
&lt;br /&gt;
==== Peripherie ==== &lt;br /&gt;
&lt;br /&gt;
Für die Erstinstallation habe ich Tastatur, Maus und HDMI-Monitor an den Mini-PC angeschlossen. Später läuft der Mini-PC ohne Peripherie (&amp;quot;Headless&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Alternativ kann man einen Remote-KVM-Adapter anschließen. Dieser überträgt die Anschlüsse inklusive Bild hardwareseitig an einen entfernten Rechner. Im Gegensatz zu Remotedesktopsoftware, die ein laufendes Betriebssystem auf dem ferngesteuerten Rechner erfordert, kann man mit dem Remote-KVM-Adapter bereits den Boot-Vorgang beobachten und Einstellungen im BIOS aus der Ferne machen. &lt;br /&gt;
&lt;br /&gt;
Ich verwende dafür an einem anderen Rechner den [https://www.gl-inet.com/products/gl-rm1/ GL.iNet Comet (GL-RM1)] in der PoE-Variante. Für rund 100 € erhält man damit eine Funktionalität, für die man sonst ein sehr viel teureres Server-Mainboard benötigen würde.&lt;br /&gt;
&lt;br /&gt;
=== Software ===&lt;br /&gt;
&lt;br /&gt;
==== Überblick ====&lt;br /&gt;
Der Softwarestack auf dem Hautomationsserver besteht aus Proxmox Virtual Enviromnent und darauf ein Linux-Container mit Debian Linux 13 (Trixie) und FHEM als Hausautomationssoftware sowie Zigbee2MQTT für das Management der Zigbee-Geräte. Die Installation ist im folgenden skizziert.&lt;br /&gt;
&lt;br /&gt;
==== Installation des Proxmox Virtual Environments ====&lt;br /&gt;
&lt;br /&gt;
==== Installation des Linux-Containers ====&lt;br /&gt;
&lt;br /&gt;
==== Installation von FHEM im Linux-Container ====&lt;br /&gt;
&lt;br /&gt;
== Anwendungsfelder ==&lt;br /&gt;
&lt;br /&gt;
Die gängigen Anwendungsfelder sind&lt;br /&gt;
* Beleuchtungssteuerung&lt;br /&gt;
* Raumklimaüberwachung und Heizungssteuerung&lt;br /&gt;
* Wetteraufzeichnung&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hausautomationssysteme ==&lt;br /&gt;
&lt;br /&gt;
=== Zigbee ===&lt;br /&gt;
&lt;br /&gt;
===== Hardware =====&lt;br /&gt;
Um Zigbee-Leuchtmittel zu paaren, hat sich eine &amp;quot;Paarungsstation&amp;quot; bewährt. Dabei handelt es sich um eine E27-Baufassung, die mit einem Schukostecker in eine schaltbare Steckdose eingesteckt wird.&lt;br /&gt;
[[Datei:Zigbee Paarung.jpg|mini]]&lt;br /&gt;
Dies ermöglicht es bequem vom Schreibtisch aus die Zigbee-Leuchtmittel mit dem Zigbee-Coordinator zu paaren.&lt;br /&gt;
&lt;br /&gt;
Die bekannten Paarungssequenzen für Leuchtmittel sind:&lt;br /&gt;
* IKEA-Tradfri: 6 Mal im Sekundentakt aus- und anschalten&lt;br /&gt;
* EGLO-Z (AwoX): 30 s aus, 1 s ein, 6 s aus, 1 s ein, 6 s aus, 1 s ein, 6 s aus, 12 s ein, 6 s aus, 12 s ein, 6 s aus, einschalten (siehe [https://www.eglo.com/de/connect-z-general-q2 Wie kann ich eine Leuchte auf Werkseinstellung zurücksetzen. (RESET)])&lt;br /&gt;
&lt;br /&gt;
===== Software =====&lt;br /&gt;
Zigbee2MQTT&lt;br /&gt;
&lt;br /&gt;
== Nomenklatur ==&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40625</id>
		<title>Fallstudie: Haus automatisieren</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40625"/>
		<updated>2026-01-02T12:22:21Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Zigbee */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel ist eine Fallstudie zum Einsatz von FHEM für die Hausautomation mit Anwendungsfeldern von FHEM, die für die meisten Anwender üblich sind. Er soll Einsteigern in FHEM die Nutzung von FHEM erleichtern.&lt;br /&gt;
&lt;br /&gt;
Ich bin ein FHEM-Nutzer der ersten Stunde und FHEM-Entwickler seit 2007. Dieser Artikel beschreibt die aufgrund von Umzügen vierte Installation von FHEM in einer von mir bewohnten Liegenschaft, nicht eingerechnet Aktualisierungen und Veränderungen an der Hausautomation aufgrund von Wechseln bei der eingesetzen Server-Hardware und -Software und den verwendeten Hausautomationssystemen.&lt;br /&gt;
&lt;br /&gt;
Ich bringe in diesen Artikel meine Erfahrungen ein, was sich als nützlich und praktisch erwiesen hat, und möchte dem FHEM-Anwender helfen, die Herausforderungen beim Einsatz bei FHEM durch konkrete Beispiele anhand meiner Anwendungsfälle zu bewältigen.&lt;br /&gt;
&lt;br /&gt;
== Automatisierte Liegenschaft ==&lt;br /&gt;
&lt;br /&gt;
Bei der Liegenschaft handelt es sich um ein Einfamilienhaus mit vier Etagen (Keller, Erdgeschoss, Obergeschoss, Dachgeschoss), Garage und Garten.&lt;br /&gt;
&lt;br /&gt;
== Hausautomationsserver ==&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
&lt;br /&gt;
==== Anforderungen ====&lt;br /&gt;
&lt;br /&gt;
Die Server-Hardware sollte zum einen ausreichend Rechenleistung für den Betrieb des FHEM-Frontends FHEMWEB bereitstellen, andererseits sparsam im Stromverbrauch sein, sowie autark.&lt;br /&gt;
&lt;br /&gt;
Die Autarkie spricht dafür, einen dedizierten Rechner für FHEM zum Einsatz zu bringen, denn die Hausautomation sollte durchgehend laufen, unabhängig von den anderen Spielereien im Home Lab.&lt;br /&gt;
&lt;br /&gt;
==== Geräteauswahl ====&lt;br /&gt;
&lt;br /&gt;
Es lag zunächst nahe, einen Raspberry Pi zum Einsatz zu bringen. Während die Modelle bis zum Raspberry Pi 3 bei der Darstellung von SVG-Plots mit längeren Zeitreihen überfordert waren, liefern die Versionen 4 und 5 mit viel RAM genügend Leistung. Allerdings sind die Flaggschiffe mittlerweile recht teuer, wenn man alle erforderlichen Komponenten (Computer, SD-Karte für Boot-Partition, SSD für Root- und Daten-Partionen, Netzteil, Gehäuse) zusammennimmt. Da ich die I/O-Ports des Raspberry Pi für Basteleien nicht benötige, habe ich mich in der Welt der Mini-PCs umgesehen.&lt;br /&gt;
&lt;br /&gt;
Meine Wahl fiel auf einen [https://minisforumpc.eu/ Minisforum] UN150P. Das Gerät bietet für knapp über 200 € eine grandiose Ausstattung und Leistung ([https://www.heise.de/bestenlisten/testbericht/minisforum-un150p-im-test/jn4g3l4 Testbericht]). Im Dezember 2025 ist das Gerät nicht (mehr) verfügbar. Es gibt aber eine Reihe vergleichbar leistungsstarker Mini-PCs in dieser Preisklasse.&lt;br /&gt;
&lt;br /&gt;
==== Aufstellort ====&lt;br /&gt;
&lt;br /&gt;
Um mit den anzuschließenden Funk-Interfaces das Haus möglichst gut abzudecken, empfiehlt sich ein zentraler Aufstellort. Bei mir ist das unter dem Schreibtisch im Arbeitszimmer im Obergeschoss.&lt;br /&gt;
&lt;br /&gt;
Eine Aufstellung im Serverschrank im Keller ist wegen der abseitigen Lage und der elektromagnetischen Abschirmung nicht sinnvoll.&lt;br /&gt;
&lt;br /&gt;
==== Peripherie ==== &lt;br /&gt;
&lt;br /&gt;
Für die Erstinstallation habe ich Tastatur, Maus und HDMI-Monitor an den Mini-PC angeschlossen. Später läuft der Mini-PC ohne Peripherie (&amp;quot;Headless&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Alternativ kann man einen Remote-KVM-Adapter anschließen. Dieser überträgt die Anschlüsse inklusive Bild hardwareseitig an einen entfernten Rechner. Im Gegensatz zu Remotedesktopsoftware, die ein laufendes Betriebssystem auf dem ferngesteuerten Rechner erfordert, kann man mit dem Remote-KVM-Adapter bereits den Boot-Vorgang beobachten und Einstellungen im BIOS aus der Ferne machen. &lt;br /&gt;
&lt;br /&gt;
Ich verwende dafür an einem anderen Rechner den [https://www.gl-inet.com/products/gl-rm1/ GL.iNet Comet (GL-RM1)] in der PoE-Variante. Für rund 100 € erhält man damit eine Funktionalität, für die man sonst ein sehr viel teureres Server-Mainboard benötigen würde.&lt;br /&gt;
&lt;br /&gt;
=== Software ===&lt;br /&gt;
&lt;br /&gt;
==== Überblick ====&lt;br /&gt;
&lt;br /&gt;
==== Installation des Proxmox Virtual Environments ====&lt;br /&gt;
&lt;br /&gt;
==== Installation des Linux-Containers ====&lt;br /&gt;
&lt;br /&gt;
==== Installation von FHEM im Linux-Container ====&lt;br /&gt;
&lt;br /&gt;
== Anwendungsfelder ==&lt;br /&gt;
&lt;br /&gt;
Die gängigen Anwendungsfelder sind&lt;br /&gt;
* Beleuchtungssteuerung&lt;br /&gt;
* Raumklimaüberwachung und Heizungssteuerung&lt;br /&gt;
* Wetteraufzeichnung&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hausautomationssysteme ==&lt;br /&gt;
&lt;br /&gt;
=== Zigbee ===&lt;br /&gt;
&lt;br /&gt;
Um Zigbee-Leuchtmittel zu paaren, hat sich eine &amp;quot;Paarungsstation&amp;quot; bewährt. Dabei handelt es sich um eine E27-Baufassung, die mit einem Schukostecker in eine schaltbare Steckdose eingesteckt wird.&lt;br /&gt;
[[Datei:Zigbee Paarung.jpg|mini]]&lt;br /&gt;
Dies ermöglicht es bequem vom Schreibtisch aus die Zigbee-Leuchtmittel mit dem Zigbee-Coordinator zu paaren.&lt;br /&gt;
&lt;br /&gt;
Die bekannten Paarungssequenzen für Leuchtmittel sind:&lt;br /&gt;
* IKEA-Tradfri: 6 Mal im Sekundentakt aus- und anschalten&lt;br /&gt;
* EGLO-Z (AwoX): 30 s aus, 1 s ein, 6 s aus, 1 s ein, 6 s aus, 1 s ein, 6 s aus, 12 s ein, 6 s aus, 12 s ein, 6 s aus, einschalten (siehe [https://www.eglo.com/de/connect-z-general-q2 Wie kann ich eine Leuchte auf Werkseinstellung zurücksetzen. (RESET)])&lt;br /&gt;
&lt;br /&gt;
== Nomenklatur ==&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40624</id>
		<title>Fallstudie: Haus automatisieren</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40624"/>
		<updated>2026-01-02T12:21:28Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Anwendungsfelder */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel ist eine Fallstudie zum Einsatz von FHEM für die Hausautomation mit Anwendungsfeldern von FHEM, die für die meisten Anwender üblich sind. Er soll Einsteigern in FHEM die Nutzung von FHEM erleichtern.&lt;br /&gt;
&lt;br /&gt;
Ich bin ein FHEM-Nutzer der ersten Stunde und FHEM-Entwickler seit 2007. Dieser Artikel beschreibt die aufgrund von Umzügen vierte Installation von FHEM in einer von mir bewohnten Liegenschaft, nicht eingerechnet Aktualisierungen und Veränderungen an der Hausautomation aufgrund von Wechseln bei der eingesetzen Server-Hardware und -Software und den verwendeten Hausautomationssystemen.&lt;br /&gt;
&lt;br /&gt;
Ich bringe in diesen Artikel meine Erfahrungen ein, was sich als nützlich und praktisch erwiesen hat, und möchte dem FHEM-Anwender helfen, die Herausforderungen beim Einsatz bei FHEM durch konkrete Beispiele anhand meiner Anwendungsfälle zu bewältigen.&lt;br /&gt;
&lt;br /&gt;
== Automatisierte Liegenschaft ==&lt;br /&gt;
&lt;br /&gt;
Bei der Liegenschaft handelt es sich um ein Einfamilienhaus mit vier Etagen (Keller, Erdgeschoss, Obergeschoss, Dachgeschoss), Garage und Garten.&lt;br /&gt;
&lt;br /&gt;
== Hausautomationsserver ==&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
&lt;br /&gt;
==== Anforderungen ====&lt;br /&gt;
&lt;br /&gt;
Die Server-Hardware sollte zum einen ausreichend Rechenleistung für den Betrieb des FHEM-Frontends FHEMWEB bereitstellen, andererseits sparsam im Stromverbrauch sein, sowie autark.&lt;br /&gt;
&lt;br /&gt;
Die Autarkie spricht dafür, einen dedizierten Rechner für FHEM zum Einsatz zu bringen, denn die Hausautomation sollte durchgehend laufen, unabhängig von den anderen Spielereien im Home Lab.&lt;br /&gt;
&lt;br /&gt;
==== Geräteauswahl ====&lt;br /&gt;
&lt;br /&gt;
Es lag zunächst nahe, einen Raspberry Pi zum Einsatz zu bringen. Während die Modelle bis zum Raspberry Pi 3 bei der Darstellung von SVG-Plots mit längeren Zeitreihen überfordert waren, liefern die Versionen 4 und 5 mit viel RAM genügend Leistung. Allerdings sind die Flaggschiffe mittlerweile recht teuer, wenn man alle erforderlichen Komponenten (Computer, SD-Karte für Boot-Partition, SSD für Root- und Daten-Partionen, Netzteil, Gehäuse) zusammennimmt. Da ich die I/O-Ports des Raspberry Pi für Basteleien nicht benötige, habe ich mich in der Welt der Mini-PCs umgesehen.&lt;br /&gt;
&lt;br /&gt;
Meine Wahl fiel auf einen [https://minisforumpc.eu/ Minisforum] UN150P. Das Gerät bietet für knapp über 200 € eine grandiose Ausstattung und Leistung ([https://www.heise.de/bestenlisten/testbericht/minisforum-un150p-im-test/jn4g3l4 Testbericht]). Im Dezember 2025 ist das Gerät nicht (mehr) verfügbar. Es gibt aber eine Reihe vergleichbar leistungsstarker Mini-PCs in dieser Preisklasse.&lt;br /&gt;
&lt;br /&gt;
==== Aufstellort ====&lt;br /&gt;
&lt;br /&gt;
Um mit den anzuschließenden Funk-Interfaces das Haus möglichst gut abzudecken, empfiehlt sich ein zentraler Aufstellort. Bei mir ist das unter dem Schreibtisch im Arbeitszimmer im Obergeschoss.&lt;br /&gt;
&lt;br /&gt;
Eine Aufstellung im Serverschrank im Keller ist wegen der abseitigen Lage und der elektromagnetischen Abschirmung nicht sinnvoll.&lt;br /&gt;
&lt;br /&gt;
==== Peripherie ==== &lt;br /&gt;
&lt;br /&gt;
Für die Erstinstallation habe ich Tastatur, Maus und HDMI-Monitor an den Mini-PC angeschlossen. Später läuft der Mini-PC ohne Peripherie (&amp;quot;Headless&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Alternativ kann man einen Remote-KVM-Adapter anschließen. Dieser überträgt die Anschlüsse inklusive Bild hardwareseitig an einen entfernten Rechner. Im Gegensatz zu Remotedesktopsoftware, die ein laufendes Betriebssystem auf dem ferngesteuerten Rechner erfordert, kann man mit dem Remote-KVM-Adapter bereits den Boot-Vorgang beobachten und Einstellungen im BIOS aus der Ferne machen. &lt;br /&gt;
&lt;br /&gt;
Ich verwende dafür an einem anderen Rechner den [https://www.gl-inet.com/products/gl-rm1/ GL.iNet Comet (GL-RM1)] in der PoE-Variante. Für rund 100 € erhält man damit eine Funktionalität, für die man sonst ein sehr viel teureres Server-Mainboard benötigen würde.&lt;br /&gt;
&lt;br /&gt;
=== Software ===&lt;br /&gt;
&lt;br /&gt;
==== Überblick ====&lt;br /&gt;
&lt;br /&gt;
==== Installation des Proxmox Virtual Environments ====&lt;br /&gt;
&lt;br /&gt;
==== Installation des Linux-Containers ====&lt;br /&gt;
&lt;br /&gt;
==== Installation von FHEM im Linux-Container ====&lt;br /&gt;
&lt;br /&gt;
== Anwendungsfelder ==&lt;br /&gt;
&lt;br /&gt;
Die gängigen Anwendungsfelder sind&lt;br /&gt;
* Beleuchtungssteuerung&lt;br /&gt;
* Raumklimaüberwachung und Heizungssteuerung&lt;br /&gt;
* Wetteraufzeichnung&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hausautomationssysteme ==&lt;br /&gt;
&lt;br /&gt;
=== Zigbee ===&lt;br /&gt;
&lt;br /&gt;
Um Zigbee-Leuchtmittel zu paaren, hat sich eine &amp;quot;Paarungsstation&amp;quot; bewährt. Dabei handelt es sich um eine E27-Baufassung, die mit einem Schukostecker in eine schaltbare Steckdose eingesteckt wird.&lt;br /&gt;
[[Datei:Zigbee Paarung.jpg|mini]]&lt;br /&gt;
Dies ermöglicht es bequem vom Schreibtisch aus die Zigbee-Leuchtmittel mit dem Zigbee-Coordinator zu paaren.&lt;br /&gt;
&lt;br /&gt;
Die bekannten Paarungssequenzen für Leuchtmittel sind:&lt;br /&gt;
* IKEA-Tradfri: 6 Mal im Sekundentakt aus- und anschalten&lt;br /&gt;
* EGLO-Z (AwoX): 30 s aus, 1 s ein, 6 s aus, 1 s ein, 6 s aus, 1 s ein, 6 s aus, 12 s ein, 6 s aus, 12 s ein, 6 s aus, einschalten (siehe [https://www.eglo.com/de/connect-z-general-q2 Wie kann ich eine Leuchte auf Werkseinstellung zurücksetzen. (RESET)]&lt;br /&gt;
&lt;br /&gt;
== Nomenklatur ==&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Datei:Zigbee_Paarung.jpg&amp;diff=40623</id>
		<title>Datei:Zigbee Paarung.jpg</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Datei:Zigbee_Paarung.jpg&amp;diff=40623"/>
		<updated>2026-01-02T12:14:29Z</updated>

		<summary type="html">&lt;p&gt;Neubert: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gerät zur Paarung von Zigbee-Leuchtmitteln&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40622</id>
		<title>Fallstudie: Haus automatisieren</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40622"/>
		<updated>2026-01-02T12:09:59Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Anwendungsfelder */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel ist eine Fallstudie zum Einsatz von FHEM für die Hausautomation mit Anwendungsfeldern von FHEM, die für die meisten Anwender üblich sind. Er soll Einsteigern in FHEM die Nutzung von FHEM erleichtern.&lt;br /&gt;
&lt;br /&gt;
Ich bin ein FHEM-Nutzer der ersten Stunde und FHEM-Entwickler seit 2007. Dieser Artikel beschreibt die aufgrund von Umzügen vierte Installation von FHEM in einer von mir bewohnten Liegenschaft, nicht eingerechnet Aktualisierungen und Veränderungen an der Hausautomation aufgrund von Wechseln bei der eingesetzen Server-Hardware und -Software und den verwendeten Hausautomationssystemen.&lt;br /&gt;
&lt;br /&gt;
Ich bringe in diesen Artikel meine Erfahrungen ein, was sich als nützlich und praktisch erwiesen hat, und möchte dem FHEM-Anwender helfen, die Herausforderungen beim Einsatz bei FHEM durch konkrete Beispiele anhand meiner Anwendungsfälle zu bewältigen.&lt;br /&gt;
&lt;br /&gt;
== Automatisierte Liegenschaft ==&lt;br /&gt;
&lt;br /&gt;
Bei der Liegenschaft handelt es sich um ein Einfamilienhaus mit vier Etagen (Keller, Erdgeschoss, Obergeschoss, Dachgeschoss), Garage und Garten.&lt;br /&gt;
&lt;br /&gt;
== Hausautomationsserver ==&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
&lt;br /&gt;
==== Anforderungen ====&lt;br /&gt;
&lt;br /&gt;
Die Server-Hardware sollte zum einen ausreichend Rechenleistung für den Betrieb des FHEM-Frontends FHEMWEB bereitstellen, andererseits sparsam im Stromverbrauch sein, sowie autark.&lt;br /&gt;
&lt;br /&gt;
Die Autarkie spricht dafür, einen dedizierten Rechner für FHEM zum Einsatz zu bringen, denn die Hausautomation sollte durchgehend laufen, unabhängig von den anderen Spielereien im Home Lab.&lt;br /&gt;
&lt;br /&gt;
==== Geräteauswahl ====&lt;br /&gt;
&lt;br /&gt;
Es lag zunächst nahe, einen Raspberry Pi zum Einsatz zu bringen. Während die Modelle bis zum Raspberry Pi 3 bei der Darstellung von SVG-Plots mit längeren Zeitreihen überfordert waren, liefern die Versionen 4 und 5 mit viel RAM genügend Leistung. Allerdings sind die Flaggschiffe mittlerweile recht teuer, wenn man alle erforderlichen Komponenten (Computer, SD-Karte für Boot-Partition, SSD für Root- und Daten-Partionen, Netzteil, Gehäuse) zusammennimmt. Da ich die I/O-Ports des Raspberry Pi für Basteleien nicht benötige, habe ich mich in der Welt der Mini-PCs umgesehen.&lt;br /&gt;
&lt;br /&gt;
Meine Wahl fiel auf einen [https://minisforumpc.eu/ Minisforum] UN150P. Das Gerät bietet für knapp über 200 € eine grandiose Ausstattung und Leistung ([https://www.heise.de/bestenlisten/testbericht/minisforum-un150p-im-test/jn4g3l4 Testbericht]). Im Dezember 2025 ist das Gerät nicht (mehr) verfügbar. Es gibt aber eine Reihe vergleichbar leistungsstarker Mini-PCs in dieser Preisklasse.&lt;br /&gt;
&lt;br /&gt;
==== Aufstellort ====&lt;br /&gt;
&lt;br /&gt;
Um mit den anzuschließenden Funk-Interfaces das Haus möglichst gut abzudecken, empfiehlt sich ein zentraler Aufstellort. Bei mir ist das unter dem Schreibtisch im Arbeitszimmer im Obergeschoss.&lt;br /&gt;
&lt;br /&gt;
Eine Aufstellung im Serverschrank im Keller ist wegen der abseitigen Lage und der elektromagnetischen Abschirmung nicht sinnvoll.&lt;br /&gt;
&lt;br /&gt;
==== Peripherie ==== &lt;br /&gt;
&lt;br /&gt;
Für die Erstinstallation habe ich Tastatur, Maus und HDMI-Monitor an den Mini-PC angeschlossen. Später läuft der Mini-PC ohne Peripherie (&amp;quot;Headless&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Alternativ kann man einen Remote-KVM-Adapter anschließen. Dieser überträgt die Anschlüsse inklusive Bild hardwareseitig an einen entfernten Rechner. Im Gegensatz zu Remotedesktopsoftware, die ein laufendes Betriebssystem auf dem ferngesteuerten Rechner erfordert, kann man mit dem Remote-KVM-Adapter bereits den Boot-Vorgang beobachten und Einstellungen im BIOS aus der Ferne machen. &lt;br /&gt;
&lt;br /&gt;
Ich verwende dafür an einem anderen Rechner den [https://www.gl-inet.com/products/gl-rm1/ GL.iNet Comet (GL-RM1)] in der PoE-Variante. Für rund 100 € erhält man damit eine Funktionalität, für die man sonst ein sehr viel teureres Server-Mainboard benötigen würde.&lt;br /&gt;
&lt;br /&gt;
=== Software ===&lt;br /&gt;
&lt;br /&gt;
==== Überblick ====&lt;br /&gt;
&lt;br /&gt;
==== Installation des Proxmox Virtual Environments ====&lt;br /&gt;
&lt;br /&gt;
==== Installation des Linux-Containers ====&lt;br /&gt;
&lt;br /&gt;
==== Installation von FHEM im Linux-Container ====&lt;br /&gt;
&lt;br /&gt;
== Anwendungsfelder ==&lt;br /&gt;
&lt;br /&gt;
Die gängigen Anwendungsfelder sind&lt;br /&gt;
* Beleuchtungssteuerung&lt;br /&gt;
* Raumklimaüberwachung und Heizungssteuerung&lt;br /&gt;
* Wetteraufzeichnung&lt;br /&gt;
&lt;br /&gt;
== Nomenklatur ==&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40526</id>
		<title>Fallstudie: Haus automatisieren</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40526"/>
		<updated>2025-12-07T16:10:06Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Geräteauswahl */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel ist eine Fallstudie zum Einsatz von FHEM für die Hausautomation mit Anwendungsfeldern von FHEM, die für die meisten Anwender üblich sind. Er soll Einsteigern in FHEM die Nutzung von FHEM erleichtern.&lt;br /&gt;
&lt;br /&gt;
Ich bin ein FHEM-Nutzer der ersten Stunde und FHEM-Entwickler seit 2007. Dieser Artikel beschreibt die aufgrund von Umzügen vierte Installation von FHEM in einer von mir bewohnten Liegenschaft, nicht eingerechnet Aktualisierungen und Veränderungen an der Hausautomation aufgrund von Wechseln bei der eingesetzen Server-Hardware und -Software und den verwendeten Hausautomationssystemen.&lt;br /&gt;
&lt;br /&gt;
Ich bringe in diesen Artikel meine Erfahrungen ein, was sich als nützlich und praktisch erwiesen hat, und möchte dem FHEM-Anwender helfen, die Herausforderungen beim Einsatz bei FHEM durch konkrete Beispiele anhand meiner Anwendungsfälle zu bewältigen.&lt;br /&gt;
&lt;br /&gt;
== Automatisierte Liegenschaft ==&lt;br /&gt;
&lt;br /&gt;
Bei der Liegenschaft handelt es sich um ein Einfamilienhaus mit vier Etagen (Keller, Erdgeschoss, Obergeschoss, Dachgeschoss), Garage und Garten.&lt;br /&gt;
&lt;br /&gt;
== Hausautomationsserver ==&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
&lt;br /&gt;
==== Anforderungen ====&lt;br /&gt;
&lt;br /&gt;
Die Server-Hardware sollte zum einen ausreichend Rechenleistung für den Betrieb des FHEM-Frontends FHEMWEB bereitstellen, andererseits sparsam im Stromverbrauch sein, sowie autark.&lt;br /&gt;
&lt;br /&gt;
Die Autarkie spricht dafür, einen dedizierten Rechner für FHEM zum Einsatz zu bringen, denn die Hausautomation sollte durchgehend laufen, unabhängig von den anderen Spielereien im Home Lab.&lt;br /&gt;
&lt;br /&gt;
==== Geräteauswahl ====&lt;br /&gt;
&lt;br /&gt;
Es lag zunächst nahe, einen Raspberry Pi zum Einsatz zu bringen. Während die Modelle bis zum Raspberry Pi 3 bei der Darstellung von SVG-Plots mit längeren Zeitreihen überfordert waren, liefern die Versionen 4 und 5 mit viel RAM genügend Leistung. Allerdings sind die Flaggschiffe mittlerweile recht teuer, wenn man alle erforderlichen Komponenten (Computer, SD-Karte für Boot-Partition, SSD für Root- und Daten-Partionen, Netzteil, Gehäuse) zusammennimmt. Da ich die I/O-Ports des Raspberry Pi für Basteleien nicht benötige, habe ich mich in der Welt der Mini-PCs umgesehen.&lt;br /&gt;
&lt;br /&gt;
Meine Wahl fiel auf einen [https://minisforumpc.eu/ Minisforum] UN150P. Das Gerät bietet für knapp über 200 € eine grandiose Ausstattung und Leistung ([https://www.heise.de/bestenlisten/testbericht/minisforum-un150p-im-test/jn4g3l4 Testbericht]). Im Dezember 2025 ist das Gerät nicht (mehr) verfügbar. Es gibt aber eine Reihe vergleichbar leistungsstarker Mini-PCs in dieser Preisklasse.&lt;br /&gt;
&lt;br /&gt;
==== Aufstellort ====&lt;br /&gt;
&lt;br /&gt;
Um mit den anzuschließenden Funk-Interfaces das Haus möglichst gut abzudecken, empfiehlt sich ein zentraler Aufstellort. Bei mir ist das unter dem Schreibtisch im Arbeitszimmer im Obergeschoss.&lt;br /&gt;
&lt;br /&gt;
Eine Aufstellung im Serverschrank im Keller ist wegen der abseitigen Lage und der elektromagnetischen Abschirmung nicht sinnvoll.&lt;br /&gt;
&lt;br /&gt;
==== Peripherie ==== &lt;br /&gt;
&lt;br /&gt;
Für die Erstinstallation habe ich Tastatur, Maus und HDMI-Monitor an den Mini-PC angeschlossen. Später läuft der Mini-PC ohne Peripherie (&amp;quot;Headless&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Alternativ kann man einen Remote-KVM-Adapter anschließen. Dieser überträgt die Anschlüsse inklusive Bild hardwareseitig an einen entfernten Rechner. Im Gegensatz zu Remotedesktopsoftware, die ein laufendes Betriebssystem auf dem ferngesteuerten Rechner erfordert, kann man mit dem Remote-KVM-Adapter bereits den Boot-Vorgang beobachten und Einstellungen im BIOS aus der Ferne machen. &lt;br /&gt;
&lt;br /&gt;
Ich verwende dafür an einem anderen Rechner den [https://www.gl-inet.com/products/gl-rm1/ GL.iNet Comet (GL-RM1)] in der PoE-Variante. Für rund 100 € erhält man damit eine Funktionalität, für die man sonst ein sehr viel teureres Server-Mainboard benötigen würde.&lt;br /&gt;
&lt;br /&gt;
=== Software ===&lt;br /&gt;
&lt;br /&gt;
==== Überblick ====&lt;br /&gt;
&lt;br /&gt;
==== Installation des Proxmox Virtual Environments ====&lt;br /&gt;
&lt;br /&gt;
==== Installation des Linux-Containers ====&lt;br /&gt;
&lt;br /&gt;
==== Installation von FHEM im Linux-Container ====&lt;br /&gt;
&lt;br /&gt;
== Anwendungsfelder ==&lt;br /&gt;
&lt;br /&gt;
== Nomenklatur ==&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40525</id>
		<title>Fallstudie: Haus automatisieren</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40525"/>
		<updated>2025-12-07T16:09:18Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Hardware */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel ist eine Fallstudie zum Einsatz von FHEM für die Hausautomation mit Anwendungsfeldern von FHEM, die für die meisten Anwender üblich sind. Er soll Einsteigern in FHEM die Nutzung von FHEM erleichtern.&lt;br /&gt;
&lt;br /&gt;
Ich bin ein FHEM-Nutzer der ersten Stunde und FHEM-Entwickler seit 2007. Dieser Artikel beschreibt die aufgrund von Umzügen vierte Installation von FHEM in einer von mir bewohnten Liegenschaft, nicht eingerechnet Aktualisierungen und Veränderungen an der Hausautomation aufgrund von Wechseln bei der eingesetzen Server-Hardware und -Software und den verwendeten Hausautomationssystemen.&lt;br /&gt;
&lt;br /&gt;
Ich bringe in diesen Artikel meine Erfahrungen ein, was sich als nützlich und praktisch erwiesen hat, und möchte dem FHEM-Anwender helfen, die Herausforderungen beim Einsatz bei FHEM durch konkrete Beispiele anhand meiner Anwendungsfälle zu bewältigen.&lt;br /&gt;
&lt;br /&gt;
== Automatisierte Liegenschaft ==&lt;br /&gt;
&lt;br /&gt;
Bei der Liegenschaft handelt es sich um ein Einfamilienhaus mit vier Etagen (Keller, Erdgeschoss, Obergeschoss, Dachgeschoss), Garage und Garten.&lt;br /&gt;
&lt;br /&gt;
== Hausautomationsserver ==&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
&lt;br /&gt;
==== Anforderungen ====&lt;br /&gt;
&lt;br /&gt;
Die Server-Hardware sollte zum einen ausreichend Rechenleistung für den Betrieb des FHEM-Frontends FHEMWEB bereitstellen, andererseits sparsam im Stromverbrauch sein, sowie autark.&lt;br /&gt;
&lt;br /&gt;
Die Autarkie spricht dafür, einen dedizierten Rechner für FHEM zum Einsatz zu bringen, denn die Hausautomation sollte durchgehend laufen, unabhängig von den anderen Spielereien im Home Lab.&lt;br /&gt;
&lt;br /&gt;
==== Geräteauswahl ====&lt;br /&gt;
&lt;br /&gt;
Es lag zunächst nahe, einen Raspberry Pi zum Einsatz zu bringen. Während die Modelle bis zum Raspberry Pi 3 bei der Darstellung von SVG-Plots mit längeren Zeitreihen überfordert waren, liefern die Versionen 4 und 5 mit viel RAM genügend Leistung. Allerdings sind die Flaggschiffe mittlerweile recht teuer, wenn man alle erforderlichen Komponenten (Computer, SD-Karte für Boot-Partition, SSD für Root- und Daten-Partionen, Netzteil, Gehäuse) zusammennimmt. Da ich die I/O-Ports des Raspberry Pi für Basteleien nicht benötige, habe ich mich in der Welt der Mini-PCs umgesehen.&lt;br /&gt;
&lt;br /&gt;
Meine Wahl fiel auf einen [https://minisforumpc.eu/ Minisforum] UN150P. Das Gerät bietet für knapp über 200 € eine grandiose Ausstattung und Leistung ([https://www.heise.de/bestenlisten/testbericht/minisforum-un150p-im-test/jn4g3l4 Testbericht]). Im Dezember ist das Gerät nicht (mehr) verfügbar. Es gibt aber eine Reihe vergleichbar leistungsstarker Mini-PCs in dieser Preisklasse.&lt;br /&gt;
&lt;br /&gt;
==== Aufstellort ====&lt;br /&gt;
&lt;br /&gt;
Um mit den anzuschließenden Funk-Interfaces das Haus möglichst gut abzudecken, empfiehlt sich ein zentraler Aufstellort. Bei mir ist das unter dem Schreibtisch im Arbeitszimmer im Obergeschoss.&lt;br /&gt;
&lt;br /&gt;
Eine Aufstellung im Serverschrank im Keller ist wegen der abseitigen Lage und der elektromagnetischen Abschirmung nicht sinnvoll.&lt;br /&gt;
&lt;br /&gt;
==== Peripherie ==== &lt;br /&gt;
&lt;br /&gt;
Für die Erstinstallation habe ich Tastatur, Maus und HDMI-Monitor an den Mini-PC angeschlossen. Später läuft der Mini-PC ohne Peripherie (&amp;quot;Headless&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Alternativ kann man einen Remote-KVM-Adapter anschließen. Dieser überträgt die Anschlüsse inklusive Bild hardwareseitig an einen entfernten Rechner. Im Gegensatz zu Remotedesktopsoftware, die ein laufendes Betriebssystem auf dem ferngesteuerten Rechner erfordert, kann man mit dem Remote-KVM-Adapter bereits den Boot-Vorgang beobachten und Einstellungen im BIOS aus der Ferne machen. &lt;br /&gt;
&lt;br /&gt;
Ich verwende dafür an einem anderen Rechner den [https://www.gl-inet.com/products/gl-rm1/ GL.iNet Comet (GL-RM1)] in der PoE-Variante. Für rund 100 € erhält man damit eine Funktionalität, für die man sonst ein sehr viel teureres Server-Mainboard benötigen würde.&lt;br /&gt;
&lt;br /&gt;
=== Software ===&lt;br /&gt;
&lt;br /&gt;
==== Überblick ====&lt;br /&gt;
&lt;br /&gt;
==== Installation des Proxmox Virtual Environments ====&lt;br /&gt;
&lt;br /&gt;
==== Installation des Linux-Containers ====&lt;br /&gt;
&lt;br /&gt;
==== Installation von FHEM im Linux-Container ====&lt;br /&gt;
&lt;br /&gt;
== Anwendungsfelder ==&lt;br /&gt;
&lt;br /&gt;
== Nomenklatur ==&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40524</id>
		<title>Fallstudie: Haus automatisieren</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40524"/>
		<updated>2025-12-07T15:50:15Z</updated>

		<summary type="html">&lt;p&gt;Neubert: /* Hausautomationsserver */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel ist eine Fallstudie zum Einsatz von FHEM für die Hausautomation mit Anwendungsfeldern von FHEM, die für die meisten Anwender üblich sind. Er soll Einsteigern in FHEM die Nutzung von FHEM erleichtern.&lt;br /&gt;
&lt;br /&gt;
Ich bin ein FHEM-Nutzer der ersten Stunde und FHEM-Entwickler seit 2007. Dieser Artikel beschreibt die aufgrund von Umzügen vierte Installation von FHEM in einer von mir bewohnten Liegenschaft, nicht eingerechnet Aktualisierungen und Veränderungen an der Hausautomation aufgrund von Wechseln bei der eingesetzen Server-Hardware und -Software und den verwendeten Hausautomationssystemen.&lt;br /&gt;
&lt;br /&gt;
Ich bringe in diesen Artikel meine Erfahrungen ein, was sich als nützlich und praktisch erwiesen hat, und möchte dem FHEM-Anwender helfen, die Herausforderungen beim Einsatz bei FHEM durch konkrete Beispiele anhand meiner Anwendungsfälle zu bewältigen.&lt;br /&gt;
&lt;br /&gt;
== Automatisierte Liegenschaft ==&lt;br /&gt;
&lt;br /&gt;
Bei der Liegenschaft handelt es sich um ein Einfamilienhaus mit vier Etagen (Keller, Erdgeschoss, Obergeschoss, Dachgeschoss), Garage und Garten.&lt;br /&gt;
&lt;br /&gt;
== Hausautomationsserver ==&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
&lt;br /&gt;
Die Server-Hardware sollte zum einen ausreichend Rechenleistung für den Betrieb des FHEM-Frontends FHEMWEB bereitstellen, andererseits sparsam im Stromverbrauch sein, sowie autark.&lt;br /&gt;
&lt;br /&gt;
Die Autarkie spricht dafür, einen dedizierten Rechner für FHEM zum Einsatz zu bringen, denn die Hausautomation sollte durchgehend laufen, unabhängig von den anderen Spielereien im Home Lab.&lt;br /&gt;
&lt;br /&gt;
Es lag zunächst nahe, einen Raspberry Pi zum Einsatz zu bringen. Während die Modelle bis zum Raspberry Pi 3 bei der Darstellung von SVG-Plots mit längeren Zeitreihen überfordert waren, liefern die Versionen 4 und 5 mit viel RAM genügend Leistung. Allerdings sind die Flaggschiffe mittlerweile recht teuer, wenn man alle erforderlichen Komponenten (Computer, SD-Karte für Boot-Partition, SSD für Root- und Daten-Partionen, Netzteil, Gehäuse) zusammennimmt. Da ich die I/O-Ports des Raspberry Pi für Basteleien nicht benötige, habe ich mich in der Welt der Mini-PCs umgesehen.&lt;br /&gt;
&lt;br /&gt;
Meine Wahl fiel auf einen Minisforum UN150P.&lt;br /&gt;
&lt;br /&gt;
=== Software ===&lt;br /&gt;
&lt;br /&gt;
==== Überblick ====&lt;br /&gt;
&lt;br /&gt;
==== Installation des Proxmox Virtual Environments ====&lt;br /&gt;
&lt;br /&gt;
==== Installation des Linux-Containers ====&lt;br /&gt;
&lt;br /&gt;
==== Installation von FHEM im Linux-Container ====&lt;br /&gt;
&lt;br /&gt;
== Anwendungsfelder ==&lt;br /&gt;
&lt;br /&gt;
== Nomenklatur ==&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40514</id>
		<title>Fallstudie: Haus automatisieren</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Fallstudie:_Haus_automatisieren&amp;diff=40514"/>
		<updated>2025-12-07T00:02:51Z</updated>

		<summary type="html">&lt;p&gt;Neubert: Die Seite wurde neu angelegt: „== Einleitung ==  Dieser Artikel ist eine Fallstudie zum Einsatz von FHEM für die Hausautomation mit Anwendungsfeldern von FHEM, die für die meisten Anwender üblich sind. Er soll Einsteigern in FHEM die Nutzung von FHEM erleichtern.  Ich bin ein FHEM-Nutzer der ersten Stunde und FHEM-Entwickler seit 2007. Dieser Artikel beschreibt die aufgrund von Umzügen vierte Installation von FHEM in einer von mir bewohnten Liegenschaft, nicht eingerechnet Aktualis…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel ist eine Fallstudie zum Einsatz von FHEM für die Hausautomation mit Anwendungsfeldern von FHEM, die für die meisten Anwender üblich sind. Er soll Einsteigern in FHEM die Nutzung von FHEM erleichtern.&lt;br /&gt;
&lt;br /&gt;
Ich bin ein FHEM-Nutzer der ersten Stunde und FHEM-Entwickler seit 2007. Dieser Artikel beschreibt die aufgrund von Umzügen vierte Installation von FHEM in einer von mir bewohnten Liegenschaft, nicht eingerechnet Aktualisierungen und Veränderungen an der Hausautomation aufgrund von Wechseln bei der eingesetzen Server-Hardware und -Software und den verwendeten Hausautomationssystemen.&lt;br /&gt;
&lt;br /&gt;
Ich bringe in diesen Artikel meine Erfahrungen ein, was sich als nützlich und praktisch erwiesen hat, und möchte dem FHEM-Anwender helfen, die Herausforderungen beim Einsatz bei FHEM durch konkrete Beispiele anhand meiner Anwendungsfälle zu bewältigen.&lt;br /&gt;
&lt;br /&gt;
== Automatisierte Liegenschaft ==&lt;br /&gt;
&lt;br /&gt;
Bei der Liegenschaft handelt es sich um ein Einfamilienhaus mit vier Etagen (Keller, Erdgeschoss, Obergeschoss, Dachgeschoss), Garage und Garten.&lt;br /&gt;
&lt;br /&gt;
== Hausautomationsserver ==&lt;br /&gt;
&lt;br /&gt;
Die Server-Hardware sollte zum einen ausreichend Rechenleistung für den Betrieb des FHEM-Frontends FHEMWEB bereitstellen, andererseits sparsam im Stromverbrauch sein, sowie autark.&lt;br /&gt;
&lt;br /&gt;
Die Autarkie spricht dafür, einen dedizierten Rechner für FHEM zum Einsatz zu bringen, denn die Hausautomation sollte durchgehend laufen, unabhängig von den anderen Spielereien im Home Lab.&lt;br /&gt;
&lt;br /&gt;
Es lag zunächst nahe, einen Raspberry Pi zum Einsatz zu bringen. Während die Modelle bis zum Raspberry Pi 3 bei der Darstellung von SVG-Plots mit längeren Zeitreihen überfordert waren, liefern die Versionen 4 und 5 mit viel RAM genügend Leistung. Allerdings sind die Flaggschiffe mittlerweile recht teuer, wenn man alle erforderlichen Komponenten (Computer, SD-Karte für Boot-Partition, SSD für Root- und Daten-Partionen, Netzteil, Gehäuse) zusammennimmt. Da ich die I/O-Ports des Raspberry Pi für Basteleien nicht benötige, habe ich mich in der Welt der Mini-PCs umgesehen.&lt;br /&gt;
&lt;br /&gt;
Meine Wahl fiel auf einen Minisforum UN150P.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsfelder ==&lt;br /&gt;
&lt;br /&gt;
== Nomenklatur ==&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SiSi&amp;diff=28512</id>
		<title>SiSi</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=SiSi&amp;diff=28512"/>
		<updated>2018-11-24T21:26:11Z</updated>

		<summary type="html">&lt;p&gt;Neubert: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Diese Seite beschreibt, wie man das Signal Messenger Command Line Interface (CLI) unter Raspbian installiert und mit FHEM benutzt.&lt;br /&gt;
&lt;br /&gt;
Wir lassen &#039;&#039;&#039;signal-cli&#039;&#039;&#039; unter dem Benutzer &#039;&#039;&#039;fhem&#039;&#039;&#039; laufen, abweichend von der Dokumentation auf GitHub. Das Home-Verzeichnis dieses Users ist bei mir &#039;&#039;&#039;/opt/fhem/home&#039;&#039;&#039;. Dies muss im Folgenden angepasst werden, wenn Du ein anderes Home-Verzeichnis für den Benutzer &#039;&#039;&#039;fhem&#039;&#039;&#039; hast.&lt;br /&gt;
&lt;br /&gt;
Was man alles mit dem Signal Messenger CLI machen kann, ist auf der o.g. Github-Seite beschrieben. &lt;br /&gt;
&lt;br /&gt;
== Installation von signal-cli ==&lt;br /&gt;
&lt;br /&gt;
Es werden die Pakete &#039;&#039;&#039;haveged&#039;&#039;&#039; und &#039;&#039;&#039;openjdk-9-jre-headless&#039;&#039;&#039; benötigt.&lt;br /&gt;
&lt;br /&gt;
haveged dient dazu, genügend Entropie für den Zufallszahlengenerator zu erzeugen. Das Java-9-Runtime-Environment bringt schon die unbeschränkten kryptographischen Funktionen vorkonfiguriert mit, die in älteren Version mühsam nachinstalliert werden müssten. Ältere Java-Versionen müssen zuvor deinstalliert werden.&lt;br /&gt;
&lt;br /&gt;
Als nächstes lädt man &#039;&#039;&#039;signal-cli-0.6.0.tar.gz&#039;&#039;&#039; von https://github.com/AsamK/signal-cli herunter. Im Abschnitt Installation der Beschreibung findet man einen Link zu den Binaries. Zum Zeitpunkt, an dem dieser Text verfasst wurde (12.11.2018) ist die aktuelle Version 0.6.0. Das Archiv wird ins Home-Verzeichnis von FHEM entpackt.&lt;br /&gt;
&lt;br /&gt;
Das folgende wird als Benutzer &#039;&#039;&#039;fhem&#039;&#039;&#039; ausgeführt, damit die Konfiguration im Home-Verzeichnis von &#039;&#039;&#039;fhem&#039;&#039;&#039; landet, und zwar in &#039;&#039;&#039;/opt/fhem/home/.config/signal&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Man registriert man seine Festnetznummer (im Beispiel: +49xxxxxxxxxx) mittels &#039;&#039;&#039;signal-cli&#039;&#039;&#039; in einer Shell, um davon Signal-Nachrichten zu versenden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;signal-cli-0.6.0/bin/signal-cli -u +49xxxxxxxxxx register --voice&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn alles in Ordnung ist, erhält man keine Rückmeldung. Wenn es lange dauert, hat man nicht genug Entropie. &lt;br /&gt;
Kurz darauf erhält man einen Sprachanruf auf Englisch, mit dem einem der sechsstellige Registrierungscode yyyyyy mitgeteilt wird. Um die Registrierung abzuschließen, führt man&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;signal-cli-0.6.0/bin/signal-cli -u +49xxxxxxxxxx verify yyyyyy&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in der Shell aus. Wenn alles in Ordnung ist, erhält man keine Rückmeldung.&lt;br /&gt;
&lt;br /&gt;
Dann kann man Nachrichten an einen Signal Messenger auf dem Mobiltelefon mit der Nummer 49170zzzzzzzz mittels&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;signal-cli-0.6.0/bin/signal-cli -u +49xxxxxxxxxx send -m &amp;quot;Greetings from FHEM!&amp;quot; +49170zzzzzzzz&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
senden. Wenn die Schlüssellänge bemängelt wird, hat man nicht die Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files installiert oder konfiguriert. Das sollte bei Java 9 aber nicht vorkommen.&lt;br /&gt;
&lt;br /&gt;
Ich hatte das Problem, dass die Sprachanrufe erst mit Stunden oder Tagen Verzögerung kamen (siehe [https://community.signalusers.org/t/call-verification-takes-forever/4479/11 Thread im Signal-Forum]). Dabei handelte es sich um einen vorübergehenden serverseitigen Fehler, der einige Tage bestand.&lt;br /&gt;
&lt;br /&gt;
Um bei Updates von &#039;&#039;&#039;signal-cli&#039;&#039;&#039; nicht die Pfade anpassen zu müssen, kann man noch im Home-Verzeichnis von &#039;&#039;&#039;fhem&#039;&#039;&#039; einen symbolischen Link anlegen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;ln -s signal-cli-0.6.0 signal-cli&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Einrichten der Kommunikation über DBus ==&lt;br /&gt;
&lt;br /&gt;
Es werden die Pakete &#039;&#039;&#039;libunixsocket-java&#039;&#039;&#039;, &#039;&#039;&#039;dbus&#039;&#039;&#039; und &#039;&#039;&#039;dbus-x11&#039;&#039;&#039; benötigt.&lt;br /&gt;
&lt;br /&gt;
Es müssen als Benutzer &#039;&#039;&#039;root&#039;&#039;&#039; die folgenden Dateien angelegt werden:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;/etc/dbus-1/system.d/org.asamk.Signal.conf&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt; &amp;lt;!--*-nxml-*--&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE busconfig PUBLIC &amp;quot;-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN&amp;quot;&lt;br /&gt;
        &amp;quot;http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;busconfig&amp;gt;&lt;br /&gt;
        &amp;lt;policy user=&amp;quot;fhem&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;allow own=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;allow send_destination=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;allow receive_sender=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;/policy&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;policy context=&amp;quot;default&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;allow send_destination=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;allow receive_sender=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;/policy&amp;gt;&lt;br /&gt;
&amp;lt;/busconfig&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;/usr/share/dbus-1/system-services/org.asamk.Signal.service&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[D-BUS Service]&lt;br /&gt;
Name=org.asamk.Signal&lt;br /&gt;
Exec=/bin/false&lt;br /&gt;
SystemdService=dbus-org.asamk.Signal.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;/etc/systemd/system/signal.service&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Send secure messages to Signal clients&lt;br /&gt;
Requires=dbus.socket&lt;br /&gt;
After=dbus.socket&lt;br /&gt;
Wants=network-online.target&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=dbus&lt;br /&gt;
Environment=&amp;quot;SIGNAL_CLI_OPTS=-Xms2m&amp;quot;&lt;br /&gt;
ExecStart=/opt/fhem/signal-cli/bin/signal-cli -u +49xxxxxxxxxx --config /opt/fhem/home/.config/signal daemon --system&lt;br /&gt;
User=fhem&lt;br /&gt;
BusName=org.asamk.Signal&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
Alias=dbus-org.asamk.Signal.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aktiviert wird das alles mit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl daemon-reload&lt;br /&gt;
systemctl enable signal.service&lt;br /&gt;
systemctl reload dbus.service&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ob es funktioniert, kann man mit&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;signal-cli/bin/signal-cli --dbus-system  send -m &amp;quot;dbus working&amp;quot; +49170zzzzzzzz&amp;lt;/source&amp;gt;&lt;br /&gt;
austesten.&lt;br /&gt;
&lt;br /&gt;
== Verwendung mit FHEM ==&lt;br /&gt;
&lt;br /&gt;
Es wird das Paket &#039;&#039;&#039;libnet-dbus-perl&#039;&#039;&#039; benötigt.&lt;br /&gt;
&lt;br /&gt;
Es wird das Modul &#039;&#039;&#039;32_SiSi.pm&#039;&#039;&#039; von [https://github.com/Quantum1337/32_SiSi.pm Quantum1337] verwendet. Am einfachsten wechselt man als Benutzer &#039;&#039;&#039;fhem&#039;&#039;&#039; ins Verzeichnis &#039;&#039;&#039;FHEM&#039;&#039;&#039; mit den Modulen und führt&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;wget https://raw.githubusercontent.com/Quantum1337/32_SiSi.pm/master/FHEM/32_SiSi.pm&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
aus. Die Datei sollte den richtigen Eigentümer haben. Bei mir sieht das so aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;-rw-r--r-- 1 fhem dialout 29375 Nov 24 22:09 FHEM/32_SiSi.pm&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Idealerweise führt man jetzt noch &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;/opt/fhem/contrib/commandref_join.pl&amp;lt;/source&amp;gt; aus, um die Commandref zu regenerieren.&lt;br /&gt;
&lt;br /&gt;
Eine simple Definition in FHEM sieht so aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
define sisi SiSi&lt;br /&gt;
attr sisi enable yes&lt;br /&gt;
attr sisi defaultPeer +49170zzzzzzzz&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Du schickst eine Nachricht aus FHEM mit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;set sisi msg Hurra, es funktioniert!&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Signal]]&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SiSi&amp;diff=28511</id>
		<title>SiSi</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=SiSi&amp;diff=28511"/>
		<updated>2018-11-24T21:24:49Z</updated>

		<summary type="html">&lt;p&gt;Neubert: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Diese Seite beschreibt, wie man das Signal Messenger Command Line Interface (CLI) unter Raspbian installiert und mit FHEM benutzt.&lt;br /&gt;
&lt;br /&gt;
Wir lassen &#039;&#039;&#039;signal-cli&#039;&#039;&#039; unter dem Benutzer &#039;&#039;&#039;fhem&#039;&#039;&#039; laufen, abweichend von der Dokumentation auf GitHub. Das Home-Verzeichnis dieses Users ist bei mir &#039;&#039;&#039;/opt/fhem/home&#039;&#039;&#039;. Dies muss im Folgenden angepasst werden, wenn Du ein anderes Home-Verzeichnis für den Benutzer &#039;&#039;&#039;fhem&#039;&#039;&#039; hast.&lt;br /&gt;
&lt;br /&gt;
Was man alles mit dem Signal Messenger CLI machen kann, ist auf der o.g. Github-Seite beschrieben. &lt;br /&gt;
&lt;br /&gt;
== Installation von signal-cli ==&lt;br /&gt;
&lt;br /&gt;
Es werden die Pakete &#039;&#039;&#039;haveged&#039;&#039;&#039; und &#039;&#039;&#039;openjdk-9-jre-headless&#039;&#039;&#039; benötigt.&lt;br /&gt;
&lt;br /&gt;
haveged dient dazu, genügend Entropie für den Zufallszahlengenerator zu erzeugen. Das Java-9-Runtime-Environment bringt schon die unbeschränkten kryptographischen Funktionen vorkonfiguriert mit, die in älteren Version mühsam nachinstalliert werden müssten. Ältere Java-Versionen müssen zuvor deinstalliert werden.&lt;br /&gt;
&lt;br /&gt;
Als nächstes lädt man &#039;&#039;&#039;signal-cli-0.6.0.tar.gz&#039;&#039;&#039; von https://github.com/AsamK/signal-cli herunter. Im Abschnitt Installation der Beschreibung findet man einen Link zu den Binaries. Zum Zeitpunkt, an dem dieser Text verfasst wurde (12.11.2018) ist die aktuelle Version 0.6.0. Das Archiv wird ins Home-Verzeichnis von FHEM entpackt.&lt;br /&gt;
&lt;br /&gt;
Das folgende wird als Benutzer &#039;&#039;&#039;fhem&#039;&#039;&#039; ausgeführt, damit die Konfiguration im Home-Verzeichnis von &#039;&#039;&#039;fhem&#039;&#039;&#039; landet, und zwar in &#039;&#039;&#039;/opt/fhem/home/.config/signal&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Man registriert man seine Festnetznummer (im Beispiel: +49xxxxxxxxxx) mittels &#039;&#039;&#039;signal-cli&#039;&#039;&#039; in einer Shell, um davon Signal-Nachrichten zu versenden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;signal-cli-0.6.0/bin/signal-cli -u +49xxxxxxxxxx register --voice&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn alles in Ordnung ist, erhält man keine Rückmeldung. Wenn es lange dauert, hat man nicht genug Entropie. &lt;br /&gt;
Kurz darauf erhält man einen Sprachanruf auf Englisch, mit dem einem der sechsstellige Registrierungscode yyyyyy mitgeteilt wird. Um die Registrierung abzuschließen, führt man&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;signal-cli-0.6.0/bin/signal-cli -u +49xxxxxxxxxx verify yyyyyy&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in der Shell aus. Wenn alles in Ordnung ist, erhält man keine Rückmeldung.&lt;br /&gt;
&lt;br /&gt;
Dann kann man Nachrichten an einen Signal Messenger auf dem Mobiltelefon mit der Nummer 49170zzzzzzzz mittels&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;signal-cli-0.6.0/bin/signal-cli -u +49xxxxxxxxxx send -m &amp;quot;Greetings from FHEM!&amp;quot; +49170zzzzzzzz&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
senden. Wenn die Schlüssellänge bemängelt wird, hat man nicht die Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files installiert oder konfiguriert. Das sollte bei Java 9 aber nicht vorkommen.&lt;br /&gt;
&lt;br /&gt;
Ich hatte das Problem, dass die Sprachanrufe erst mit Stunden oder Tagen Verzögerung kamen (siehe [https://community.signalusers.org/t/call-verification-takes-forever/4479/11 Thread im Signal-Forum]). Dabei handelte es sich um einen vorübergehenden serverseitigen Fehler, der einige Tage bestand.&lt;br /&gt;
&lt;br /&gt;
Um bei Updates von &#039;&#039;&#039;signal-cli&#039;&#039;&#039; nicht die Pfade anpassen zu müssen, kann man noch im Home-Verzeichnis von &#039;&#039;&#039;fhem&#039;&#039;&#039; einen symbolischen Link anlegen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;ln -s signal-cli-0.6.0 signal-cli&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Einrichten der Kommunikation über DBus ==&lt;br /&gt;
&lt;br /&gt;
Es werden die Pakete &#039;&#039;&#039;libunixsocket-java&#039;&#039;&#039;, &#039;&#039;&#039;dbus&#039;&#039;&#039; und &#039;&#039;&#039;dbus-x11&#039;&#039;&#039; benötigt.&lt;br /&gt;
&lt;br /&gt;
Es müssen als Benutzer &#039;&#039;&#039;root&#039;&#039;&#039; die folgenden Dateien angelegt werden:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;/etc/dbus-1/system.d/org.asamk.Signal.conf&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt; &amp;lt;!--*-nxml-*--&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE busconfig PUBLIC &amp;quot;-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN&amp;quot;&lt;br /&gt;
        &amp;quot;http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;busconfig&amp;gt;&lt;br /&gt;
        &amp;lt;policy user=&amp;quot;fhem&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;allow own=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;allow send_destination=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;allow receive_sender=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;/policy&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;policy context=&amp;quot;default&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;allow send_destination=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;allow receive_sender=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;/policy&amp;gt;&lt;br /&gt;
&amp;lt;/busconfig&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;/usr/share/dbus-1/system-services/org.asamk.Signal.service&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[D-BUS Service]&lt;br /&gt;
Name=org.asamk.Signal&lt;br /&gt;
Exec=/bin/false&lt;br /&gt;
SystemdService=dbus-org.asamk.Signal.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;/etc/systemd/system/signal.service&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Send secure messages to Signal clients&lt;br /&gt;
Requires=dbus.socket&lt;br /&gt;
After=dbus.socket&lt;br /&gt;
Wants=network-online.target&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=dbus&lt;br /&gt;
Environment=&amp;quot;SIGNAL_CLI_OPTS=-Xms2m&amp;quot;&lt;br /&gt;
ExecStart=/opt/fhem/signal-cli/bin/signal-cli -u +49xxxxxxxxxx --config /opt/fhem/home/.config/signal daemon --system&lt;br /&gt;
User=fhem&lt;br /&gt;
BusName=org.asamk.Signal&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
Alias=dbus-org.asamk.Signal.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aktiviert wird das alles mit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl daemon-reload&lt;br /&gt;
systemctl enable signal.service&lt;br /&gt;
systemctl reload dbus.service&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ob es funktioniert, kann man mit&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;signal-cli/bin/signal-cli --dbus-system  send -m &amp;quot;dbus working&amp;quot; +49170zzzzzzzz&amp;lt;/source&amp;gt;&lt;br /&gt;
austesten.&lt;br /&gt;
&lt;br /&gt;
== Verwendung mit FHEM ==&lt;br /&gt;
&lt;br /&gt;
Es wird das Paket &#039;&#039;&#039;libnet-dbus-perl&#039;&#039;&#039; benötigt.&lt;br /&gt;
&lt;br /&gt;
Es wird das Modul &#039;&#039;&#039;32_SiSi.pm&#039;&#039; von https://github.com/Quantum1337/32_SiSi.pm verwendet. Am einfachsten wechselt man als Benutzer &#039;&#039;&#039;fhem&#039;&#039;&#039; ins Verzeichnis &#039;&#039;&#039;FHEM&#039;&#039;&#039; mit den Modulen und führt&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;wget https://raw.githubusercontent.com/Quantum1337/32_SiSi.pm/master/FHEM/32_SiSi.pm&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
aus. Die Datei sollte den richtigen Eigentümer haben. Bei mir sieht das so aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;-rw-r--r-- 1 fhem dialout 29375 Nov 24 22:09 FHEM/32_SiSi.pm&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Idealerweise führt man jetzt noch &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;/opt/fhem/contrib/commandref_join.pl&amp;lt;/source&amp;gt; aus, um die Commandref zu regenerieren.&lt;br /&gt;
&lt;br /&gt;
Eine simple Definition in FHEM sieht so aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
define sisi SiSi&lt;br /&gt;
attr sisi enable yes&lt;br /&gt;
attr sisi defaultPeer +49170zzzzzzzz&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Du schickst eine Nachricht aus FHEM mit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;set sisi msg Hurra, es funktioniert!&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Signal]]&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SiSi&amp;diff=28510</id>
		<title>SiSi</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=SiSi&amp;diff=28510"/>
		<updated>2018-11-24T21:05:59Z</updated>

		<summary type="html">&lt;p&gt;Neubert: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Diese Seite beschreibt, wie man das Signal Messenger Command Line Interface (CLI) unter Raspbian installiert.&lt;br /&gt;
&lt;br /&gt;
Wir lassen &#039;&#039;&#039;signal-cli&#039;&#039;&#039; unter dem Benutzer &#039;&#039;&#039;fhem&#039;&#039;&#039; laufen, abweichend von der Dokumentation auf GitHub. Das Home-Verzeichnis dieses Users ist bei mir &#039;&#039;&#039;/opt/fhem/home&#039;&#039;&#039;. Dies muss im Folgenden angepasst werden, wenn Du ein anderes Home-Verzeichnis für den Benutzer &#039;&#039;&#039;fhem&#039;&#039;&#039; hast.&lt;br /&gt;
&lt;br /&gt;
Was man alles mit dem Signal Messenger CLI machen kann, ist auf der o.g. Github-Seite beschrieben. Sobald ich Signal in FHEM eingebunden habe, wird diese Anleitung erweitert.&lt;br /&gt;
&lt;br /&gt;
== Installation von signal-cli ==&lt;br /&gt;
&lt;br /&gt;
Es werden die Pakete &#039;&#039;&#039;haveged&#039;&#039;&#039; und &#039;&#039;&#039;openjdk-9-jre-headless&#039;&#039;&#039; benötigt.&lt;br /&gt;
&lt;br /&gt;
haveged dient dazu, genügend Entropie für den Zufallszahlengenerator zu erzeugen. Das Java-9-Runtime-Environment bringt schon die unbeschränkten kryptographischen Funktionen vorkonfiguriert mit, die in älteren Version mühsam nachinstalliert werden müssten. Ältere Java-Versionen müssen zuvor deinstalliert werden.&lt;br /&gt;
&lt;br /&gt;
Als nächstes lädt man &#039;&#039;&#039;signal-cli-0.6.0.tar.gz&#039;&#039;&#039; von https://github.com/AsamK/signal-cli herunter. Im Abschnitt Installation der Beschreibung findet man einen Link zu den Binaries. Zum Zeitpunkt, an dem dieser Text verfasst wurde (12.11.2018) ist die aktuelle Version 0.6.0. Das Archiv wird ins Home-Verzeichnis von FHEM entpackt.&lt;br /&gt;
&lt;br /&gt;
Das folgende wird als Benutzer &#039;&#039;&#039;fhem&#039;&#039;&#039; ausgeführt, damit die Konfiguration im Home-Verzeichnis von &#039;&#039;&#039;fhem&#039;&#039;&#039; landet, und zwar in &#039;&#039;&#039;/opt/fhem/home/.config/signal&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Man registriert man seine Festnetznummer (im Beispiel: +49xxxxxxxxxx) mittels &#039;&#039;&#039;signal-cli&#039;&#039;&#039; in einer Shell, um davon Signal-Nachrichten zu versenden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;signal-cli-0.6.0/bin/signal-cli -u +49xxxxxxxxxx register --voice&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn alles in Ordnung ist, erhält man keine Rückmeldung. Wenn es lange dauert, hat man nicht genug Entropie. &lt;br /&gt;
Kurz darauf erhält man einen Sprachanruf auf Englisch, mit dem einem der sechsstellige Registrierungscode yyyyyy mitgeteilt wird. Um die Registrierung abzuschließen, führt man&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;signal-cli-0.6.0/bin/signal-cli -u +49xxxxxxxxxx verify yyyyyy&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in der Shell aus. Wenn alles in Ordnung ist, erhält man keine Rückmeldung.&lt;br /&gt;
&lt;br /&gt;
Dann kann man Nachrichten an einen Signal Messenger auf dem Mobiltelefon mit der Nummer 49170zzzzzzzz mittels&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;signal-cli-0.6.0/bin/signal-cli -u +49xxxxxxxxxx send -m &amp;quot;Greetings from FHEM!&amp;quot; +49170zzzzzzzz&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
senden. Wenn die Schlüssellänge bemängelt wird, hat man nicht die Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files installiert oder konfiguriert. Das sollte bei Java 9 aber nicht vorkommen.&lt;br /&gt;
&lt;br /&gt;
Ich hatte das Problem, dass die Sprachanrufe erst mit Stunden oder Tagen Verzögerung kamen (siehe [https://community.signalusers.org/t/call-verification-takes-forever/4479/11 Thread im Signal-Forum]). Dabei handelte es sich um einen vorübergehenden serverseitigen Fehler, der einige Tage bestand.&lt;br /&gt;
&lt;br /&gt;
Um bei Updates von &#039;&#039;&#039;signal-cli&#039;&#039;&#039; nicht die Pfade anpassen zu müssen, kann man noch im Home-Verzeichnis von &#039;&#039;&#039;fhem&#039;&#039;&#039; einen symbolischen Link anlegen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;ln -s signal-cli-0.6.0 signal-cli&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Einrichten der Kommunikation über DBus ==&lt;br /&gt;
&lt;br /&gt;
Es werden die Pakete &#039;&#039;&#039;libunixsocket-java&#039;&#039;&#039;, &#039;&#039;&#039;dbus&#039;&#039;&#039; und &#039;&#039;&#039;dbus-x11&#039;&#039;&#039; benötigt.&lt;br /&gt;
&lt;br /&gt;
Es müssen als Benutzer &#039;&#039;&#039;root&#039;&#039;&#039; die folgenden Dateien angelegt werden:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;/etc/dbus-1/system.d/org.asamk.Signal.conf&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt; &amp;lt;!--*-nxml-*--&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE busconfig PUBLIC &amp;quot;-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN&amp;quot;&lt;br /&gt;
        &amp;quot;http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;busconfig&amp;gt;&lt;br /&gt;
        &amp;lt;policy user=&amp;quot;fhem&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;allow own=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;allow send_destination=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;allow receive_sender=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;/policy&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;policy context=&amp;quot;default&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;allow send_destination=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;allow receive_sender=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;/policy&amp;gt;&lt;br /&gt;
&amp;lt;/busconfig&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;/usr/share/dbus-1/system-services/org.asamk.Signal.service&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[D-BUS Service]&lt;br /&gt;
Name=org.asamk.Signal&lt;br /&gt;
Exec=/bin/false&lt;br /&gt;
SystemdService=dbus-org.asamk.Signal.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;/etc/systemd/system/signal.service&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Send secure messages to Signal clients&lt;br /&gt;
Requires=dbus.socket&lt;br /&gt;
After=dbus.socket&lt;br /&gt;
Wants=network-online.target&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=dbus&lt;br /&gt;
Environment=&amp;quot;SIGNAL_CLI_OPTS=-Xms2m&amp;quot;&lt;br /&gt;
ExecStart=/opt/fhem/signal-cli/bin/signal-cli -u +49xxxxxxxxxx --config /opt/fhem/home/.config/signal daemon --system&lt;br /&gt;
User=fhem&lt;br /&gt;
BusName=org.asamk.Signal&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
Alias=dbus-org.asamk.Signal.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aktiviert wird das alles mit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl daemon-reload&lt;br /&gt;
systemctl enable signal.service&lt;br /&gt;
systemctl reload dbus.service&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ob es funktioniert, kann man mit&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;signal-cli/bin/signal-cli --dbus-system  send -m &amp;quot;dbus working&amp;quot; +49170zzzzzzzz&amp;lt;/source&amp;gt;&lt;br /&gt;
austesten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Signal]]&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SiSi&amp;diff=28301</id>
		<title>SiSi</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=SiSi&amp;diff=28301"/>
		<updated>2018-11-12T20:17:48Z</updated>

		<summary type="html">&lt;p&gt;Neubert: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Diese Seite beschreibt, wie man das Signal Messenger Command Line Interface (CLI) unter Raspbian installiert.&lt;br /&gt;
&lt;br /&gt;
Es werden die Pakete &#039;&#039;&#039;haveged&#039;&#039;&#039; und &#039;&#039;&#039;openjdk-9-jre-headless&#039;&#039;&#039; benötigt.&lt;br /&gt;
&lt;br /&gt;
haveged dient dazu, genügend Entropie für den Zufallszahlengenerator zu erzeugen. Das Java-9-Runtime-Environment bringt schon die unbeschränkten kryptographischen Funktionen vorkonfiguriert mit, die in älteren Version mühsam nachinstalliert werden müssten. Ältere Java-Versionen müssen zuvor deinstalliert werden.&lt;br /&gt;
&lt;br /&gt;
Als nächstes lädt man &#039;&#039;&#039;signal-cli-0.6.0.tar.gz&#039;&#039;&#039; von https://github.com/AsamK/signal-cli herunter. Im Abschnitt Installation der Beschreibung findet man einen Link zu den Binaries. Zum Zeitpunkt, an dem dieser Text verfasst wurde (12.11.2018) ist die aktuelle Version 0.6.0. Das Archiv wird ins Home-Verzeichnis von FHEM entpackt.&lt;br /&gt;
&lt;br /&gt;
Nun registriert man seine Festnetznummer (im Beispiel: +49xxxxxxxxxx) mittels &#039;&#039;&#039;signal-cli&#039;&#039;&#039; in einer Shell, um davon Signal-Nachrichten zu versenden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;signal-cli-0.6.0/bin/signal-cli -u +49xxxxxxxxxx register --voice&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn alles in Ordnung ist, erhält man keine Rückmeldung. Wenn es lange dauert, hat man nicht genug Entropie. &lt;br /&gt;
Kurz darauf erhält man einen Sprachanruf auf Englisch, mit dem einem der sechsstellige Registrierungscode yyyyyy mitgeteilt wird. Um die Registrierung abzuschließen, führt man&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;signal-cli-0.6.0/bin/signal-cli -u +49xxxxxxxxxx verify yyyyyy&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in der Shell aus. Wenn alles in Ordnung ist, erhält man keine Rückmeldung.&lt;br /&gt;
&lt;br /&gt;
Dann kann man Nachrichten an einen Signal Messenger auf dem Mobiltelefon mit der Nummer 49170zzzzzzzz mittels&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;signal-cli-0.6.0/bin/signal-cli -u +49xxxxxxxxxx send -m &amp;quot;Greetings from FHEM!&amp;quot; +49170zzzzzzzz&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
senden. Wenn die Schlüssellänge bemängelt wird, hat man nicht die Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files installiert oder konfiguriert. Das sollte bei Java 9 aber nicht vorkommen.&lt;br /&gt;
&lt;br /&gt;
Ich hatte das Problem, dass die Sprachanrufe erst mit Stunden oder Tagen Verzögerung kamen (siehe [https://community.signalusers.org/t/call-verification-takes-forever/4479/11 Thread im Signal-Forum]). Dabei handelte es sich um einen vorübergehenden serverseitigen Fehler, der einige Tage bestand.&lt;br /&gt;
&lt;br /&gt;
Was man alles mit dem Signal Messenger CLI machen kann, ist auf der o.g. Github-Seite beschrieben. Sobald ich Signal in FHEM eingebunden habe, wird diese Anleitung erweitert.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SiSi&amp;diff=28300</id>
		<title>SiSi</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=SiSi&amp;diff=28300"/>
		<updated>2018-11-12T18:41:34Z</updated>

		<summary type="html">&lt;p&gt;Neubert: Die Seite wurde neu angelegt: „Diese Seite beschreibt, wie man das Signal Messenger Command Line Interface (CLI) unter Raspbian installiert.  Es werden die Pakete haveged und openjdk-9-jre-h…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Diese Seite beschreibt, wie man das Signal Messenger Command Line Interface (CLI) unter Raspbian installiert.&lt;br /&gt;
&lt;br /&gt;
Es werden die Pakete haveged und openjdk-9-jre-headless benötigt.&lt;br /&gt;
&lt;br /&gt;
haveged dient dazu, genügend Entropie für den Zufallszahlengenerator zu erzeugen. Das Java-9-Runtime-Environment bringt schon die unbeschränkten kryptographischen Funktionen vorkonfiguriert mit, die in älteren Version mühsam nachinstalliert werden müssten. Ältere Java-Versionen müssen zuvor deinstalliert werden.&lt;br /&gt;
&lt;br /&gt;
Als nächstes lädt man signal-cli-0.6.0.tar.gz von https://github.com/AsamK/signal-cli herunter. Im Abschnitt Installation der Beschreibung findet man einen Link zu den Binaries. Zum Zeitpunkt, an dem dieser Text verfasst wurde (12.11.2018) ist die aktuelle Version 0.6.0. Das Archiv wird ins Home-Verzeichnis von FHEM entpackt.&lt;br /&gt;
&lt;br /&gt;
Nun registriert man seine Festnetznummer (im Beispiel: +49xxxxxxxxxx) mittels signal-cli in einer Shell, um davon Signal-Nachrichten zu versenden:&lt;br /&gt;
&lt;br /&gt;
signal-cli-0.6.0/bin/signal-cli -u +49xxxxxxxxxx register --voice&lt;br /&gt;
&lt;br /&gt;
Wenn alles in Ordnung ist, erhält man keine Rückmeldung. Wenn es lange dauert, hat man nicht genug Entropie. &lt;br /&gt;
Kurz darauf erhält man einen Sprachanruf auf Englisch, mit dem einem der sechsstellige Registrierungscode yyyyyy mitgeteilt wird. Um die Registrierung abzuschließen, führt man&lt;br /&gt;
&lt;br /&gt;
signal-cli-0.6.0/bin/signal-cli -u +49xxxxxxxxxx verify yyyyyy&lt;br /&gt;
&lt;br /&gt;
in der Shell aus. Wenn alles in Ordnung ist, erhält man keine Rückmeldung.&lt;br /&gt;
&lt;br /&gt;
Dann kann man Nachrichten an einen Signal Messenger auf dem Mobiltelefon mit der Nummer 49170zzzzzzzz mittels&lt;br /&gt;
&lt;br /&gt;
signal-cli-0.6.0/bin/signal-cli -u +49xxxxxxxxxx send -m &amp;quot;Greetings from FHEM!&amp;quot; +49170zzzzzzzz&lt;br /&gt;
&lt;br /&gt;
senden. Wenn die Schlüssellänge bemängelt wird, hat man nicht die Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files installiert oder konfiguriert. Das sollte bei Java 9 aber nicht vorkommen.&lt;br /&gt;
&lt;br /&gt;
Ich hatte das Problem, dass die Sprachanrufe erst mit Stunden oder Tagen Verzögerung kamen (siehe [https://community.signalusers.org/t/call-verification-takes-forever/4479/11 Thread im Signal-Forum]). Dabei handelte es sich um einen vorübergehenden serverseitigen Fehler, der einige Tage bestand.&lt;br /&gt;
&lt;br /&gt;
Was man alles mit dem Signal Messenger CLI machen kann, ist auf der o.g. Github-Seite beschrieben. Sobald ich Signal in FHEM eingebunden habe, wird diese Anleitung erweitert.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=DevelopmentUpdate&amp;diff=26193</id>
		<title>DevelopmentUpdate</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=DevelopmentUpdate&amp;diff=26193"/>
		<updated>2018-03-22T17:19:34Z</updated>

		<summary type="html">&lt;p&gt;Neubert: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Updatemechanismus ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Diese Seite ist frisch dem Ei entschlüpft und noch nicht qualitätsgesichert.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn der Benutzer den FHEM-Befehl update in seiner FHEM-Installation aufruft, werden aus allen Repositories, die er für Updates registriert hat, aktualisierte Dateien heruntergeladen. Dieser Artikel beschreibt den Mechanismus hinter der Bereitstellung des Updates aus dem zentralen FHEM-Repository.&lt;br /&gt;
&lt;br /&gt;
Jeden Tag um X:00 Uhr wird auf dem FHEM-Updateserver fhemupdate.pl (siehe contrib) ausgeführt. Ab diesem Zeitpunkt kann ein Benutzer von FHEM die zu diesem Zeitpunkt neuesten Dateien per update-Befehl beziehen. Abends in SVN-Repository eingecheckte Dateien stehen damit am nächsten Morgen per Update zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
fhemupdate.pl stellt im SVN-Repository neue und geänderte Dateien aus FHEM, FHEM/lib sowie einige weitere Dateien von FHEM sowie CUL-Firmware für das Update bereit. Die Liste der Dateien steht am Anfang von contrib/fhemupdate.pl. Insbesondere werden außer den Dateien zur Erzeugung der commandref keine Dateien aus contrib über update verteilt.&lt;br /&gt;
&lt;br /&gt;
Ohne weiteres Zutun löscht das Update keine Dateien in der Installation des Users, wenn diese im SVN-Repository fehlen, und liefert auch keine neuen Verzeichnisse und darin enthaltene Dateien aus.&lt;br /&gt;
&lt;br /&gt;
fhemupdate.pl wird von Rudolf König gepflegt. Ein Entwickler, der neue Verzeichnisse und deren Inhalte über Update verteilen möchte oder Dateien in den Benutzerinstallationen per Update löschen lassen möchte, stellt diesen Wunsch zunächst im [https://forum.fhem.de/index.php/board,48.0.html Forum im Board FHEM Development] zur Diskussion. Hintergrund ist es, die Entwicklung in geordnete Bahnen zu lenken. Da es in der Natur von FHEM liegt, mit unterschiedlichen Systemen zu kommunizieren, wird es nur natürlich sein, dass immer mehr Fremdpakete in FHEM abgelegt werden sollen.&lt;br /&gt;
Es soll einerseits den Anwendern das Leben leicht gemacht werden, andererseits soll aber FHEM weder den Paketmanager des Systems ersetzen noch als Repository für Fremdsoftware dienen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Development]]&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=DevelopmentUpdate&amp;diff=26192</id>
		<title>DevelopmentUpdate</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=DevelopmentUpdate&amp;diff=26192"/>
		<updated>2018-03-22T17:18:45Z</updated>

		<summary type="html">&lt;p&gt;Neubert: Die Seite wurde neu angelegt: „== Updatemechanismus ==  &amp;#039;&amp;#039;&amp;#039;Diese Seite ist frisch dem Ei entschlüpft und noch nicht qualitätsgesichert.&amp;#039;&amp;#039;&amp;#039;  Wenn der Benutzer den FHEM-Befehl update in sein…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Updatemechanismus ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Diese Seite ist frisch dem Ei entschlüpft und noch nicht qualitätsgesichert.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn der Benutzer den FHEM-Befehl update in seiner FHEM-Installation aufruft, werden aus allen Repositories, die er für Updates registriert hat, aktualisierte Dateien heruntergeladen. Dieser Artikel beschreibt den Mechanismus hinter der Bereitstellung des Updates aus dem zentralen FHEM-Repository.&lt;br /&gt;
&lt;br /&gt;
Jeden Tag um X:00 Uhr wird auf dem FHEM-Updateserver fhemupdate.pl (siehe contrib) ausgeführt. Ab diesem Zeitpunkt kann ein Benutzer von FHEM die zu diesem Zeitpunkt neuesten Dateien per update-Befehl beziehen. Abends in SVN-Repository eingecheckte Dateien stehen damit am nächsten Morgen per Update zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
fhemupdate.pl stellt im SVN-Repository neue und geänderte Dateien aus FHEM, FHEM/lib sowie einige weitere Dateien von FHEM sowie CUL-Firmware für das Update bereit. Die Liste der Dateien steht am Anfang von contrib/fhemupdate.pl. Insbesondere werden außer den Dateien zur Erzeugung der commandref keine Dateien aus contrib über update verteilt.&lt;br /&gt;
&lt;br /&gt;
Ohne weiteres Zutun löscht das Update keine Dateien in der Installation des Users, wenn diese im SVN-Repository fehlen, und liefert auch keine neuen Verzeichnisse und darin enthaltene Dateien aus.&lt;br /&gt;
&lt;br /&gt;
fhemupdate.pl wird von Rudolf König gepflegt. Ein Entwickler, der neue Verzeichnisse und deren Inhalte über Update verteilen möchte oder Dateien in den Benutzerinstallationen per Update löschen lassen möchte, stellt diesen Wunsch zunächst im [https://forum.fhem.de/index.php/board,48.0.html Forum im Board FHEM Development] zur Diskussion. Hintergrund ist es, die Entwicklung in geordnete Bahnen zu lenken. Da es in der Natur von FHEM liegt, mit unterschiedlichen Systemen zu kommunizieren, wird es nur natürlich sein, dass immer mehr Fremdpakete in FHEM abgelegt werden sollen.&lt;br /&gt;
Es soll einerseits den Anwendern das Leben leicht gemacht werden, andererseits soll aber FHEM weder den Paketmanager des Systems ersetzen noch als Repository für Fremdsoftware dienen.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=OWServer_%26_OWDevice&amp;diff=11261</id>
		<title>OWServer &amp; OWDevice</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=OWServer_%26_OWDevice&amp;diff=11261"/>
		<updated>2015-05-14T12:03:15Z</updated>

		<summary type="html">&lt;p&gt;Neubert: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
==Einleitung==&lt;br /&gt;
&lt;br /&gt;
Bei OWServer handelt es sich um eine 1-Wire Server Komponente und bei OWDevice um eine Geräte-Komponente, die die angeschlossenen Module definiert-&lt;br /&gt;
Die Module benötigen die Serverkomponente von [http://www.owfs.org OWFS].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Die Module sind eine eigenständige Möglichkeit, den 1-Wire Bus anzusteuern und kommen ohne die Module aus, deren Namen aus Großbuchstaben bestehen (wie OWX, OWSWITCH, OWTHERM, etc.). &lt;br /&gt;
Umgekehrt können die Module OWSWITCH, OWTHERM, etc. auch mit dem Backendmodul OWServer zusammenarbeiten, siehe dazu die commandref der betreffenden Module.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Vorbereitung==&lt;br /&gt;
&lt;br /&gt;
Wie oben erwähnt, setzt OWServer/OWDevice auf OWFS auf. Dazu ist eine funktionierende OWFS Installation notwendig. Die Installation ist auf der selben Plattform (Debian-based) möglich oder auch Remote (zBsp Dockstar oder RPi). Eine gute [http://owfs.org/index.php?page=standard-devices Liste der Standard Devices]auf der Homepage von OWFS einzusehen. Nicht alle Standard Devices sind in OWDevice verfügbar (siehe unten).Wenn OWFS funktioniert kann&#039;s weiter gehen...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===owfs Pakete installieren===&lt;br /&gt;
&lt;br /&gt;
1) entweder sind die Pakete bereits vorpaketiert und man muss nur das [http://owfs.davromaniak.eu/ Repository] noch in /etc/apt/sources.list eintragen&lt;br /&gt;
&lt;br /&gt;
2) oder man muss selber kompilieren ([http://www.navitron.org.uk/forum/index.php?topic=12604.msg151750#msg151750 Quelle]). &lt;br /&gt;
Für den RaspberryPi wurde dies schon durchgeführt: [http://forum.fhem.de/index.php?action=dlattach;topic=12219.0;attach=2463 owfs_2.8p17-1_all.zip]&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;sudo apt-get install automake autoconf autotools-dev gcc g++ libtool libusb-dev fuse-utils libfuse-dev swig python-dev tcl-dev php5-dev&lt;br /&gt;
sudo apt-get install git git-buildpackage dh-make quilt php5-cli&lt;br /&gt;
git clone [git://git.debian.org/collab-maint/owfs.git git://git.debian.org/collab-maint/owfs.git] git&lt;br /&gt;
git-buildpackage -uc -us&lt;br /&gt;
cd ..&lt;br /&gt;
sudo dpkg -i ./owserver_2.8p7+cvs20110310-1_i386.deb ./libow-2.8-7_2.8p7+cvs20110310-1_i386.deb ./owfs-common_2.8p7+cvs20110310-1_all.deb&lt;br /&gt;
sudo dpkg -i ./owhttpd_2.8p7+cvs20110310-1_i386.deb&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
diese Pakete werden alle gebaut:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;libow-2.8-7_2.8p7+cvs20110310-1_i386.deb   owfs-common_2.8p7+cvs20110310-1_all.deb&lt;br /&gt;
libowcapi-2.8-7_2.8p7+cvs20110310-1_i386.deb owfs-dbg_2.8p7+cvs20110310-1_i386.deb&lt;br /&gt;
libow-dev_2.8p7+cvs20110310-1_i386.deb    owfs-doc_2.8p7+cvs20110310-1_all.deb&lt;br /&gt;
libownet-2.8-7_2.8p7+cvs20110310-1_i386.deb  owfs-fuse_2.8p7+cvs20110310-1_i386.deb&lt;br /&gt;
libownet-dev_2.8p7+cvs20110310-1_i386.deb   owftpd_2.8p7+cvs20110310-1_i386.deb&lt;br /&gt;
libownet-perl_2.8p7+cvs20110310-1_all.deb   owhttpd_2.8p7+cvs20110310-1_i386.deb&lt;br /&gt;
libownet-php_2.8p7+cvs20110310-1_all.deb   owserver_2.8p7+cvs20110310-1_i386.deb&lt;br /&gt;
libow-perl_2.8p7+cvs20110310-1_i386.deb    ow-shell_2.8p7+cvs20110310-1_i386.deb&lt;br /&gt;
libow-php5_2.8p7+cvs20110310-1_i386.deb    python-ow_2.8p7+cvs20110310-1_i386.deb&lt;br /&gt;
libow-tcl_2.8p7+cvs20110310-1_i386.deb    python-ownet_2.8p7+cvs20110310-1_all.deb&lt;br /&gt;
owfs_2.8p7+cvs20110310-1_all.deb&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) In aktuellen Versionen von Raspbian sind die notwendigen Pakete schon in den konfigurierten Quellen vorhanden. Es reicht ein&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo apt-get install owserver ow-shell owhttpd owftpd&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unterstütze Geräte===&lt;br /&gt;
Eine aktuelle Liste der von OWDevice unterstützen Geräte findet man im [http://fhem.de/commandref.html#OWDevice FHEM-Commandref].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Konfiguration von owserver==&lt;br /&gt;
&lt;br /&gt;
Folgendes ist eine beispielhafte Konfiguration für OWFS mit einem am USB-Port angeschlossenen [http://denkovi.com/usb-to-one-wire-interface-adaptor-converter-thermometer Denkovi-Adapter] (Klon von DS9097U).&lt;br /&gt;
&lt;br /&gt;
Es ist praktisch, dem Adapter ein festes Device zuzuordnen. Dazu legt man in /etc/udev/rules.d/ eine Datei 11-onewire.rules mit folgendem Inhalt an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;ATTRS{idVendor}==&amp;quot;0403&amp;quot;, ATTRS{idProduct}==&amp;quot;6001&amp;quot;, ATTRS{serial}==&amp;quot;DAE001nq&amp;quot;, SUBSYSTEMS==&amp;quot;usb&amp;quot;, ACTION==&amp;quot;add&amp;quot;, MODE=&amp;quot;0660&amp;quot;, GROUP=&amp;quot;plugdev&amp;quot;, SYMLINK+=&amp;quot;onewire&amp;quot;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach dem Einstöpseln des USB-Kabels vom Adapter wird über die Seriennummer DAE001nq des USB-Wandlers auf dem Adapter das Gerät erkannt und der Symlink /dev/onewire auf das eigentliche USB-Gerät (z.B. /dev/ttyUSB1) erstellt.&lt;br /&gt;
&lt;br /&gt;
Eine Minimalkonfiguration für /etc/owfs.conf ist&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;server: device = /dev/onewire&lt;br /&gt;
http: port = 2121&lt;br /&gt;
ftp: port = 2120&lt;br /&gt;
server: port = 4304&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es ist sinnvoll, owhttpd installiert und laufen zu haben, um über die URL http://deinRaspberryPi:2121 zu sehen, dass owserver läuft und die Geräte am 1-wire-Bus erkennt.&lt;br /&gt;
&lt;br /&gt;
==Konfiguration in FHEM==&lt;br /&gt;
Als erstes definiert man OWServer. Hiermit wird ein logischer OWServer definiert, auf welchem OWFS installiert ist&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define &amp;amp;lt;name&amp;amp;gt; OWServer &amp;amp;lt;protocol&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;amp;lt;protocol&amp;amp;gt; hat das Format &amp;amp;lt;hostname&amp;amp;gt;:&amp;amp;lt;port&amp;amp;gt;.&lt;br /&gt;
&lt;br /&gt;
zBsp:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define myOWServer OWServer 192.168.14.100:4304&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
oder wenn sich OWFS auf dem gleichen Server befindet wie FHEM:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define myOWServer OWServer localhost:4304&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Nach erfolgreichem &amp;quot;define&amp;quot; ist ein Klick auf den &amp;quot;Save&amp;quot; Button notwenig. Wenn nun der Status von myOWServer auf &amp;quot;Initialized&amp;quot; steht, ist der Server verbunden. Um sicher zu sein, dass der OWServer funktioniert, kann eine manuelle Abfrage der Device durchgeführt werden mit:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;get myOWServer devices&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Danach werden sämtliche angeschlossene Geräte angezeigt, inkl. Busmaster&lt;br /&gt;
&lt;br /&gt;
===OWServer Set Befehle===&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;set &amp;amp;lt;name&amp;amp;gt; &amp;amp;lt;value&amp;amp;gt;&lt;br /&gt;
value:&lt;br /&gt;
timeout/directory&lt;br /&gt;
timeout/ftp&lt;br /&gt;
timeout/ha7&lt;br /&gt;
timeout/network&lt;br /&gt;
timeout/presence&lt;br /&gt;
timeout/serial&lt;br /&gt;
timeout/server&lt;br /&gt;
timeout/stable&lt;br /&gt;
timeout/uncached&lt;br /&gt;
timeout/usb&lt;br /&gt;
timeout/volatile&lt;br /&gt;
timeout/w1&lt;br /&gt;
units/pressure_scale&lt;br /&gt;
units/temperature_scale&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Weitere Informationen zu den Set Befehlen sind im [http://owfs.org/uploads/owserver.1.html#sect41 OWServer Manual] zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
===OWServer Get Befehle===&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;get &amp;amp;lt;name&amp;amp;gt; &amp;amp;lt;value&amp;amp;gt;&lt;br /&gt;
value:&lt;br /&gt;
/settings/timeout/directory&lt;br /&gt;
/settings/timeout/ftp&lt;br /&gt;
/settings/timeout/ha7&lt;br /&gt;
/settings/timeout/network&lt;br /&gt;
/settings/timeout/presence&lt;br /&gt;
/settings/timeout/serial&lt;br /&gt;
/settings/timeout/server&lt;br /&gt;
/settings/timeout/stable&lt;br /&gt;
/settings/timeout/uncached&lt;br /&gt;
/settings/timeout/usb&lt;br /&gt;
/settings/timeout/volatile&lt;br /&gt;
/settings/timeout/w1&lt;br /&gt;
/settings/units/pressure_scale&lt;br /&gt;
/settings/units/temperature_scale&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Zusätzlich stehen die FHEM-internen Befehle &amp;quot;errors&amp;quot; und &amp;quot;devices&amp;quot; zur Verfügung.&lt;br /&gt;
zBsp:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;get &amp;amp;lt;Devicename&amp;amp;gt; errors #listet die Fehler des Device auf&lt;br /&gt;
get &amp;amp;lt;Devicename&amp;amp;gt; devices #scan den Server nach Device&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Angeschlossene Geräte auslesen===&lt;br /&gt;
Grundsätzlich werden die am Busmaster von OWFS angeschlossenen 1-Wire Geräte durch aktives autocreate nach einem Neustart (erfordert shutdown restart) selber in FHEM definiert.&lt;br /&gt;
Der Busmaster (zBsp ein DS9490r) selbst wird ebenfalls eingelesen und angezeigt.&lt;br /&gt;
&lt;br /&gt;
===Definition von Geräten===&lt;br /&gt;
Es ist auch möglich, Geräte manuell anzulegen. Dies erfolgt in folgendem Format:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define &amp;amp;lt;name&amp;amp;gt; OWDevice &amp;amp;lt;address&amp;amp;gt; [&amp;amp;lt;interval&amp;amp;gt;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
zBsp:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define Vorlauftemp OWDevice 28.334F2B040000 60&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Wobei der Wert 60 als Abfrageintervall in Sekunden zu verstehen ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===OWDevice State===&lt;br /&gt;
Bei Temperaturfühler wie DS18S20 wird das Reading &amp;quot;state&amp;quot; wie folgt ausgegeben:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;temperature: 56.1875 alarm: 1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Um die Temperatur wie bei anderen Temperatur-Sensoren (zBsp. CUL_WS) anzuzeigen, hilft das Attribut &amp;quot;stateFormat&amp;quot;. Dies kann wie folgt definiert werden:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;attr &amp;amp;lt;Devicename&amp;amp;gt; stateFormat T: &amp;amp;lt;wert&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
zBsp:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;attr Boiler stateFormat T: temperature&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
alternativ&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;attr &amp;amp;lt;Devicename&amp;amp;gt; stateFormat {sprintf(&amp;quot;%.1f&amp;quot;,ReadingsVal(&amp;quot;&amp;amp;lt;Devicename&amp;amp;gt;&amp;quot;,&amp;quot;temperature&amp;quot;,0)).&amp;quot;°C&amp;quot;}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Zusätzlich rundet das obenstehende Attribut mit &amp;quot;%.1f&amp;quot; die Temperatur auf eine Kommastelle.&lt;br /&gt;
&lt;br /&gt;
==Tipps und Tricks==&lt;br /&gt;
1-wire-Geräte sind häufig generische Geräte, wie Zähler und Spannungsmesser (A/D-Wandler), an denen Sensorik hängt. Die rohen Werte vom 1-wire-Gerät (Zählimpulse, Spannungen) sind dann noch in menschenlesbare Werte zu verwandeln. Hier helfen userReadings, z.B.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;attr myEnergyMeter userReadings energy { (ReadingsVal(&amp;quot;myEnergyMeter&amp;quot;,&amp;quot;count.A&amp;quot;,0)+AttrVal(&amp;quot;myEnergyMeter&amp;quot;,&amp;quot;myBasis&amp;quot;,0))/1250.0;; }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Anwendungsbeispiele==&lt;br /&gt;
[[Stromzähler_und_1-Wire,_OWServer,_OWDevice|Hier]] findet man ein Beispiel einer Anbindung zweier Leistungsmesser (aka Stromzähler) mit S0 Ausgang über einen 1-wire-S0-Zähler an FHEM. &lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
=== Fhem hängt, wenn OWServer nicht erreichbar ist ===&lt;br /&gt;
Am Anfang gab es mit OWServer das Problem, dass Fhem immer komplett hing, wenn OWServer nicht erreichbar war (siehe z.&amp;amp;nbsp;B. [http://www.fischer-net.de/hausautomation/haustechnik/1-wire/60-1-wire-integration-in-fhem.html hier am Ende]). Das Problem wurde inzwischen dankenswerterweise für den laufenden Betrieb {{Link2Forum|Topic=16945|LinkText=behoben}} - &amp;lt;code&amp;gt;attr myOWServer nonblocking 1&amp;lt;/code&amp;gt; muss dazu gesetzt werden -, aber zumindest beim Start hängt Fhem nach wie vor, wenn OWServer nicht erreichbar ist.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:1-Wire]]&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=DevelopmentReadingsAPI&amp;diff=8557</id>
		<title>DevelopmentReadingsAPI</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=DevelopmentReadingsAPI&amp;diff=8557"/>
		<updated>2014-11-22T08:18:40Z</updated>

		<summary type="html">&lt;p&gt;Neubert: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Kategorie:Development]]&lt;br /&gt;
&lt;br /&gt;
== Abstract ==&lt;br /&gt;
&lt;br /&gt;
Diese Seite beschreibt ein Konzept für ein API für Readings in FHEM. Diese Seite dokumentiert den aktuellen Stand der Diskussion. &lt;br /&gt;
&lt;br /&gt;
Ausgangspunkt ist [http://forum.fhem.de/index.php/topic,21247.0.html dieser Thread].&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
&lt;br /&gt;
In FHEM besitzen Geräte sogenannte Readings (Anzeigewerte). Diese bestehen aus einem Zeitstempel und einem Wert. Die Änderung eines Readings wird in der Regel durch einen Event daran interessierten Geräten über die NotifyFn mitgeteilt. Die Werte von Readings sind Zeichenketten. Sie können beim Herunterfahren in einer eigenen Datei (fhem.save) gesichert und beim Neustarten von FHEM wiederhergestellt werden. Readings sind von der Natur her schnellveränderlich.&lt;br /&gt;
&lt;br /&gt;
Geräte können Attribute besitzen. Attribute besitzen nur einen Werte ohne Zeitstempel. Sie sind in der Regel un- bzw. langsamveränderlich und dienen typischerweise zur Konfiguration. Attribute werden persistent in der Konfiguration abgelegt. Änderungen an Attributen werden auch analog zu Reading-änderungen durch Events distributiert. Auch Attribute sind Zeichenketten.&lt;br /&gt;
&lt;br /&gt;
Geräte besitzen interne Werte (sog. Internals). Auch diese besitzen nur einen Werte ohne Zeitstempel. Internals können perl-skalare oder Referenztypen (z.B. hashes oder Arrays) sein. Änderungen an Internals werden nicht per Event weitergegeben, die Werte werden nicht persistiert.&lt;br /&gt;
&lt;br /&gt;
Readings, Attribute und Internals genügen keiner festgelegten Syntax: es gibt bezüglich der Werte keine Vorgaben zur Standardisierung. Diese können z. B. Zahlenwerte, Kombinationen aus Zahlen und physikalischen Einheiten oder Texte enthalten. Beispielsweise können Readings, die Temperaturen darstellen, die Temperatur in Celsius-Graden oder Kelvin-Graden mit oder ohne Einheitensymbol enthalten. Das erschwert die Weiterverarbeitung. Soll beispielsweise eine Temperatur in einer graphischen Benutzeroberfläche mit einem Thermometer-Widget dargestellt werden, müssen für jede Geräteklasse individuelle Transformationsregeln von der Darstellung im Reading auf den Eingangsparameter im Widget transformiert werden.&lt;br /&gt;
&lt;br /&gt;
Keine Semantik: Es gibt kein API, anhand dessen eine Funktion erkennen kann, was das Reading inhaltlich darstellt. Eine graphische Benutzeroberfläche kann beispielsweise nicht ermitteln, ob für ein bestimmtes Reading ein Thermometer-Widget oder eine Lampe dargestellt werden soll.&lt;br /&gt;
&lt;br /&gt;
== Zielsetzung ==&lt;br /&gt;
&lt;br /&gt;
Es soll ein API eingeführt werden, das einen bzgl. Syntax und Semantik standardisierten Zugriff auf Readings, Attribute und Internals erlaubt.&lt;br /&gt;
&lt;br /&gt;
Gehören Attribute und Internals wirklich hierher?&lt;br /&gt;
* Internals sind device-intern und normalerweise nicht für Dritte gedacht. Wenn etwas &#039;öffentlich&#039; und auswertebar sein soll gehört es womöglich in ein Reading oder Attribut.&lt;br /&gt;
* manche Devices legen aus der Definition abgeleitete Werte in Internals ab. Auch diese sollten externen Schnittstellen einheitlich zugänglich gemacht werden können.&lt;br /&gt;
* Attribute sind für den Endanwender gedacht. Was gibt es hier zu Standardisieren ausser den möglichen Werten?&lt;br /&gt;
* Eine externe Schnittstelle kennt die FHEM-interne Struktur nicht, soll aber ggf. trotzdem vereinheitlichen Zugriff auf die Konfiguration (= die Attribute) bekommen können.&lt;br /&gt;
&lt;br /&gt;
Frühere Ansätze sind [[DevelopmentInterfaces|Interfaces]] und [[DevelopmentGuidelines|Guidelines]] und [https://groups.google.com/forum/#!searchin/fhem-users/fhem$20standards/fhem-users/fGUMddl2Br0/w99_8GHMxEMJ diese Diskussion].&lt;br /&gt;
&lt;br /&gt;
== Anforderungen an das API ==&lt;br /&gt;
&lt;br /&gt;
# Funktionale Anforderungen&lt;br /&gt;
#* Es soll möglich sein einen aus den Werten von Readings, Attributen und Internals abgeleiteten Wert abzufragen&lt;br /&gt;
#* die Zugrunde liegenden Werte (Readings, Attribute und Internals) sollen beliebigen Devices zuordenbar sein. Es soll z.B. ermöglicht werden mehrere getrennte Analoge Ausgabedevices zu einem einzigen RGB-Wert zu aggregieren.&lt;br /&gt;
#* Sofern die Abbildevorschrift bijektiv ist, soll es möglich sein durch Setzen des abgeleiteten Wertes die zugrunde liegenden Größen zu verändern. Readings sind per definitionem nur aus dem Gerät selbst heraus und nicht in das Gerät hinein veränderbar. Oder wollen wir zulassen, dass Readings manipuliert werden können? Welchen Anwendungsfall gibt es dafür?&lt;br /&gt;
#* Es soll möglich sein eine Benachrichtigung zu erhalten, wenn sich dieser abgeleitete Wert ändert (ggf. mit Verzicht auf Änderungen von Internals die ja keine Events auslösen).&lt;br /&gt;
#* Es soll sich die Bedeutung eines abgeleiteten Wertes ermitteln lassen (Temperatur, Schaltzustand, Länge, Füllmenge, ...).&lt;br /&gt;
#* Es sollen sich bei physikalischen Größen Wert und Einheit ermitteln lassen.&lt;br /&gt;
#* Es soll möglich sein, physikalische Größen in andere Einheitensysteme umrechnen zu können (z.B. K in °C, °C in °F, l im cbm, ...).&lt;br /&gt;
#* Es sollen Formatierungen unterstützt werden (globaler Default, Default je physikalischer Größe, individuell je Geräteklasse, individuell je Gerät), z.B. Temperaturen grundsätzlich in °C mit einer Nachkommastelle, Uhrzeiten grundsätzlich in 24-Stunden-Notation oder in AM/PM-Schreibweise.&lt;br /&gt;
#* Es soll sich der Wertebereich ermitteln lassen. Ein Wertebereich könnte zur sinnvollen Skalierung analoger Werte (z.B. Slider) benutzt werden.&lt;br /&gt;
#* Es soll möglich sein mehrere Sets von Abildungsvorschriften konfigurativ hinterlegen zu können. Damit können unterschiedliche Schnittstellen oder Frontends parallel nutzbar gemacht werden. Unterschiedliche Frontends benötigen z.B. RGB-Werte in unterschiedlichen Formaten auf ggf. auf einen oder mehrere Kanäle abgebildet. -&amp;gt; Widerspricht das nicht dem Standardgedanken? Sollte es nicht eine Weise geben, wie RGB-Werte bereit gestellt werden, und der Kunde sollte diese dann in das eigene Format bringen?&lt;br /&gt;
# Nichtfunktionale Anforderungen&lt;br /&gt;
#* Kein Modul soll das API unterstützen müssen, damit althergebrachte Module ohne Anpassungen weiterfunktionieren.&lt;br /&gt;
#* das API soll abwärtskompatibel sein und einen (bidirektionalen) Zugriff auf bestehende Module ermöglichen.&lt;br /&gt;
#* Das API soll nur unwesentlichen Overhead bzgl. Speicherverbrauch und Verarbeitungszeiten erzeugen.&lt;br /&gt;
#* Es soll keine Vereinheitlichung von Readings-Namen erfolgen (temp, temperature) (das war früher einmal eine Forderung).&lt;br /&gt;
&lt;br /&gt;
== Erste Überlegungen ==&lt;br /&gt;
&lt;br /&gt;
* Einheiten alleine genügen nicht, es sollte die physikalische Größe bekannt sein, die von dem Reading repräsentiert wird (Temperatur, Druck, ...).&lt;br /&gt;
* Dazu eine Regel, in welcher Einheit diese physikalische Größe vorliegt.&lt;br /&gt;
* Es bringt keinen Zusatznutzen, die physikalische Größe am Reading verfügbar zu haben.&lt;br /&gt;
* Stattdessen meldet das Device, dass es einem Standard gehorcht (ein Interface implementiert, z.B &amp;quot;temperature&amp;quot;).&lt;br /&gt;
* Ein GUI weiß dadurch, was es anzuzeigen hat. &lt;br /&gt;
* KEINE Einheiten im {readings}{VAL}. Das muß bei wirklich jeder anderen Verwendung außer &amp;quot;Anzeige für Mensch mit selben Locale wie Entwickler.&amp;quot; gestrippt werden.&lt;br /&gt;
* An jedes Reading werden Metainformationen geklebt. Welche?&lt;br /&gt;
* Die Metainformationen könnten Zeiger in eine hierarchische Liste standardisierter Beschreibungen sein. Sind die [[DevelopmentInterfaces|Interfaces]] modellhaft?&lt;br /&gt;
* Es ist klar, dass die Bedeutung eine Vereinbarung darstellt, die außerhalb des Systems liegt. GGf. kann man die Implementierung aber ihre eigene Dokumentation enthalten lassen.&lt;br /&gt;
* Wir brauchen für die Formatierungen einen Speicher für die globalen Defaults und die Geräteklassen- und Geräte- und Readings-spezifischen Überschreibungen.&lt;br /&gt;
* Die allgemeinen Zugriffsmethoden können in RTypes.pm eingefügt werden. So was wie RUnit($hash, &amp;quot;desired-temp&amp;quot;).&lt;br /&gt;
* Wie wäre es, erst die Zugriffsmethoden zu definieren? Z.B. RUnit, RValue, RValue(..., $unit), RType, ...? Das macht es griffig. Ich meine damit, dass die Kunden sagen, was sie brauchen, und wir daraus das API definieren.&lt;br /&gt;
* Wir müssen darüber nachdenken, welche Kunden das API hat und was es denen nutzen soll. FHEMWEB, DBLog, MQTT, smartVisu, mobile Clients sind Kunden.&lt;br /&gt;
* Zum Frontend: man kann sich ja viel fürs Backend ausdenken. Aber das richtige Gespür dafür, ob das Design auch wirklich was taugt, bekomme ich erst, wenn ich es einsetze und sehe, wie es sich für den Verwender anfühlt. Daher die Idee für einen Durchstich, ein Proof-of-Concept eben.&lt;br /&gt;
* Think big, start small: vermutlich bringen wir nur etwas zu Wege, wenn wir nicht gleich den großen Wurf anstreben, sondern mit einem Aspekt beginnen (de facto Readings) und dabei stets das gesamte Zielbild im Auge halten.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=DevelopmentReadingsAPI&amp;diff=8547</id>
		<title>DevelopmentReadingsAPI</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=DevelopmentReadingsAPI&amp;diff=8547"/>
		<updated>2014-11-21T20:36:44Z</updated>

		<summary type="html">&lt;p&gt;Neubert: Die Seite wurde neu angelegt: „Kategorie:Development  == Abstract ==  Diese Seite beschreibt ein Konzept für ein API für Readings in FHEM. Diese Seite dokumentiert den aktuellen Stand …“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Kategorie:Development]]&lt;br /&gt;
&lt;br /&gt;
== Abstract ==&lt;br /&gt;
&lt;br /&gt;
Diese Seite beschreibt ein Konzept für ein API für Readings in FHEM. Diese Seite dokumentiert den aktuellen Stand der Diskussion. &lt;br /&gt;
&lt;br /&gt;
Ausgangspunkt ist [http://forum.fhem.de/index.php/topic,21247.0.html dieser Thread].&lt;br /&gt;
&lt;br /&gt;
== Ausgangssituation ==&lt;br /&gt;
&lt;br /&gt;
In FHEM besitzen Geräte sogenannte Readings (Anzeigewerte). Diese bestehen aus einem Zeitstempel und einem Wert. &lt;br /&gt;
&lt;br /&gt;
Keine Syntax: es gibt bezüglich der Werte keine Vorgaben zur Standardisierung. Diese können z. B. Zahlenwerte, Kombinationen aus Zahlen und physikalischen Einheiten oder Texte enthalten. Beispielsweise können Readings, die Temperaturen darstellen, die Temperatur in Celsius-Graden oder Kelvin-Graden mit oder ohne Einheitensymbol enthalten. Das erschwert die Weiterverarbeitung. Soll beispielsweise eine Temperatur in einer graphischen Benutzeroberfläche mit einem Thermometer-Widget dargestellt werden, müssen für jede Geräteklasse individuelle Transformationsregeln von der Darstellung im Reading auf den Eingangsparameter im Widget transformiert werden.&lt;br /&gt;
&lt;br /&gt;
Keine Semantik: Es gibt kein API, anhand dessen eine Funktion erkennen kann, was das Reading inhaltlich darstellt. Eine graphische Benutzeroberfläche kann beispielsweise nicht ermitteln, ob für ein bestimmtes Reading ein Thermometer-Widget oder eine Lampe dargestellt werden soll.&lt;br /&gt;
&lt;br /&gt;
== Zielsetzung ==&lt;br /&gt;
&lt;br /&gt;
Es soll ein API eingeführt werden, das einen bzgl. Syntax und Semantik standardisierten Zugriff auf Readings erlaubt.&lt;br /&gt;
&lt;br /&gt;
Frühere Ansätze sind [[DevelopmentInterfaces|Interfaces]] und [[DevelopmentGuidelines|Guidelines]] und [https://groups.google.com/forum/#!searchin/fhem-users/fhem$20standards/fhem-users/fGUMddl2Br0/w99_8GHMxEMJ diese Diskussion].&lt;br /&gt;
&lt;br /&gt;
== Anforderungen an das API ==&lt;br /&gt;
&lt;br /&gt;
# Funktionale Anforderungen&lt;br /&gt;
#* Es soll sich die Bedeutung eines Readings ermitteln lassen (Temperatur, Schaltzustand, Länge, Füllmenge, ...).&lt;br /&gt;
#* Es sollen sich bei physikalischen Größen Wert und Einheit ermitteln lassen.&lt;br /&gt;
#* Es soll möglich sein, physikalische Größen in andere Einheitensysteme umrechnen zu können (z.B. K in °C, °C in °F, l im cbm, ...).&lt;br /&gt;
#* Es sollen Formatierungen unterstützt werden (globaler Default, Default je physikalischer Größe, individuell je Geräteklasse, individuell je Gerät), z.B. Temperaturen grundsätzlich in °C mit einer Nachkommastelle, Uhrzeiten grundsätzlich in 24-Stunden-Notation oder in AM/PM-Schreibweise.&lt;br /&gt;
#* Es wurde die Anforderung genannt, dass sich der Wertebereich ermitteln lassen sollte. Mir ist nicht klar, ob dies für Readings erforderlich ist (es wäre für Settings erforderlich).&lt;br /&gt;
# Nichtfunktionale Anforderungen&lt;br /&gt;
#* Kein Modul soll das API unterstützen müssen, damit althergebrachte Module ohne Anpassungen weiterfunktionieren.&lt;br /&gt;
#* Das API soll nur unwesentlichen Overhead bzgl. Speicherverbrauch und Verarbeitungszeiten erzeugen.&lt;br /&gt;
#* Es soll keine Vereinheitlichung von Readings-Namen erfolgen (temp, temperature) (das war früher einmal eine Forderung).&lt;br /&gt;
&lt;br /&gt;
== Erste Überlegungen ==&lt;br /&gt;
&lt;br /&gt;
* Einheiten alleine genügen nicht, es sollte die physikalische Größe bekannt sein, die von dem Reading repräsentiert wird (Temperatur, Druck, ...).&lt;br /&gt;
* Dazu eine Regel, in welcher Einheit diese physikalische Größe vorliegt.&lt;br /&gt;
* Es bringt keinen Zusatznutzen, die physikalische Größe am Reading verfügbar zu haben.&lt;br /&gt;
* Stattdessen meldet das Device, dass es einem Standard gehorcht (ein Interface implementiert, z.B &amp;quot;temperature&amp;quot;).&lt;br /&gt;
* Ein GUI weiß dadurch, was es anzuzeigen hat. &lt;br /&gt;
* KEINE Einheiten im {readings}{VAL}. Das muß bei wirklich jeder anderen Verwendung außer &amp;quot;Anzeige für Mensch mit selben Locale wie Entwickler.&amp;quot; gestrippt werden.&lt;br /&gt;
* An jedes Reading werden Metainformationen geklebt. Welche?&lt;br /&gt;
* Die Metainformationen könnten Zeiger in eine hierarchische Liste standardisierter Beschreibungen sein. Sind die [[DevelopmentInterfaces|Interfaces]] modellhaft?&lt;br /&gt;
* Es ist klar, dass die Bedeutung eine Vereinbarung darstellt, die außerhalb des Systems liegt. GGf. kann man die Implementierung aber ihre eigene Dokumentation enthalten lassen.&lt;br /&gt;
* Wir brauchen für die Formatierungen einen Speicher für die globalen Defaults und die Geräteklassen- und Geräte- und Readings-spezifischen Überschreibungen.&lt;br /&gt;
* Die allgemeinen Zugriffsmethoden können in RTypes.pm eingefügt werden. So was wie RUnit($hash, &amp;quot;desired-temp&amp;quot;).&lt;br /&gt;
* Wir müssen darüber nachdenken, welche Kunden das API hat und was es denen nutzen soll. FHEMWEB und DBLog sind Kunden.&lt;br /&gt;
* Zum Frontend: man kann sich ja viel fürs Backend ausdenken. Aber das richtige Gespür dafür, ob das Design auch wirklich was taugt, bekomme ich erst, wenn ich es einsetze und sehe, wie es sich für den Verwender anfühlt. Daher die Idee für einen Durchstich, ein Proof-of-Concept eben.&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Strace_verwenden&amp;diff=6985</id>
		<title>Strace verwenden</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Strace_verwenden&amp;diff=6985"/>
		<updated>2014-07-23T07:07:53Z</updated>

		<summary type="html">&lt;p&gt;Neubert: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Auf Linux-Maschinen können mit dem Befehl&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
strace -p PIDvonFHEM -ttT -o strace.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
sämtliche Systemaufrufe von FHEM in eine Datei protokolliert werden. Dabei wird jeder Zeile ein Zeitstempel (aktuelle Uhrzeit) vorangestellt und die Dauer des Systemaufrufs in Sekunden in spitzen Klammern hintenangestellt.&lt;br /&gt;
&lt;br /&gt;
Um nur Aufrufe von select und write zu sehen, kann man mit der Option&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-e trace=select,write&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
vorfiltern. Näheres ist der Manpage von strace zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
Lang laufende Operationen (eine Sekunde oder länger) werden dann parallel dazu in einem anderen Terminal mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tail -f strace.log | grep -v &#039;&amp;lt;0.&#039; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
herausgefiltert.&lt;br /&gt;
&lt;br /&gt;
Um herauszufinden, was die Filedeskriptoren bedeuten, wird der Befehl&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list .* FD&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
auf der FHEM-Kommandozeile aufgerufen. Ist der Filedeskriptor nicht dabei, wird man im Verzeichnis&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/proc/PIDvonFHEM/fd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
fündig.&lt;br /&gt;
&lt;br /&gt;
Um sich alle offenen Files, Sockets und Pipes anzusehen, dient der Befehl:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lsof -p PIDvonFHEM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Strace_verwenden&amp;diff=6967</id>
		<title>Strace verwenden</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Strace_verwenden&amp;diff=6967"/>
		<updated>2014-07-21T14:31:13Z</updated>

		<summary type="html">&lt;p&gt;Neubert: Die Seite wurde neu angelegt: „ Auf Linux-Maschinen können mit dem Befehl &amp;lt;pre&amp;gt; strace -p PIDvonFHEM -ttT -o strace.log &amp;lt;/pre&amp;gt; sämtliche Systemaufrufe von FHEM in eine Datei protokolliert …“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Auf Linux-Maschinen können mit dem Befehl&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
strace -p PIDvonFHEM -ttT -o strace.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
sämtliche Systemaufrufe von FHEM in eine Datei protokolliert werden. Dabei wird jeder Zeile ein Zeitstempel (aktuelle Uhrzeit) vorangestellt und die Dauer des Systemaufrufs in Sekunden in spitzen Klammern hintenangestellt.&lt;br /&gt;
&lt;br /&gt;
Um nur Aufrufe von select und write zu sehen, kann man mit der Option&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-e trace=select,write&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
vorfiltern. Näheres ist der Manpage von strace zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
Lang laufende Operationen (eine Sekunde oder länger) werden dann parallel dazu in einem anderen Terminal mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tail -f strace.log | grep -v &#039;&amp;lt;0.&#039; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
herausgefiltert.&lt;br /&gt;
&lt;br /&gt;
Um herauszufinden, was die Filedeskriptoren bedeuten, wird der Befehl&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
list .* FD&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
auf der FHEM-Kommandozeile aufgerufen. Ist der Filedeskriptor nicht dabei, wird man im Verzeichnis&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/proc/PIDvonFHEM/fd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
fündig.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;/div&gt;</summary>
		<author><name>Neubert</name></author>
	</entry>
</feed>