<?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=Ansgru</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=Ansgru"/>
	<link rel="alternate" type="text/html" href="http://wiki.fhem.de/wiki/Spezial:Beitr%C3%A4ge/Ansgru"/>
	<updated>2026-04-10T22:56:26Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=DOIF/uiTable_Schnelleinstieg&amp;diff=40943</id>
		<title>DOIF/uiTable Schnelleinstieg</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=DOIF/uiTable_Schnelleinstieg&amp;diff=40943"/>
		<updated>2026-04-07T16:27:40Z</updated>

		<summary type="html">&lt;p&gt;Ansgru: /* Die Tabellendefinition */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Datei:UiTable state state.jpg|950x950px|rechts|Webansicht bestehend aus mehreren DOIF/uiTable-Definitionen]]&lt;br /&gt;
An dieser Stelle wird das DOIF-Web-Interface erklärt, welches über das DOIF-Attribut &#039;&#039;&#039;uiTable&#039;&#039;&#039; realisiert wurde. &lt;br /&gt;
&lt;br /&gt;
Abhängig von der Art der Funktion können in einer tabellarischen Darstellung FHEM-Geräte visualisiert und über die Web-Oberfläche bedient werden. Eventbasierte Änderungen visualisierter Readings werden unmittelbar in der Web-Ansicht aktualisiert. Eine erstellte Tabelle erscheint unterhalb der Statuszeile eines DOIF-Devices. Das uiTable-Attribut kann in bereits bestehenden DOIFs oder in funktionslosen DOIFs, wie in den unteren Beispielen, als reines WEB-Interface erstellt werden. In der obigen Abbildung ist ein Statusbildschirm aus mehreren Spalten mit mehreren DOIF/uiTable-Definitionen aufgebaut worden.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Darstellungsmöglichkeiten werden anhand von Beispielen insb. mit Hilfe bereits im DOIF-Modul vordefinierter uiTable-Funktionen aufgezeigt. Diese Perlfunktionen sind in einem eigenen Package namens &#039;ui_Table&#039; definiert worden. Mit Hilfe dieser Funktionen lassen sich recht einfach, ohne tiefere HTML/CSS-Kenntnisse, eigene Übersichten definieren. Im Anschluss werden typische &#039;&#039;&#039;[[DOIF/uiTable Schnelleinstieg#Anwendungsbeispiele|Anwendungsbeispiele]]&#039;&#039;&#039; aufgezeigt.&lt;br /&gt;
&lt;br /&gt;
Die folgenden Beispieldefinitionen arbeiten mit konkreten Geräten und Readings, sie können als RAW-Definition [https://wiki.fhem.de/wiki/Import_von_Code_Snippets] ins eigene System übernommen werden, dazu müssen die Gerätenamen, Readings, ggf. auch Icons den existierenden Namen des eigenen Systems angepasst werden. Zum Ausprobieren der Beispiele können statt echter Geräte auch Dummys benutzt werden. &lt;br /&gt;
&lt;br /&gt;
Es gibt ebenfalls das Attribut &#039;&#039;&#039;uiState&#039;&#039;&#039;, welches die gleiche Syntax wie uiTable nutzt. Die definierte Tabelle erscheint im Gegensatz zu uiTable jedoch im Status des DOIF-Devices. uiState und uiTable können gleichzeitig in einem DOIF-Device definiert werden.  &lt;br /&gt;
&lt;br /&gt;
== Aufbau des uiTable-Attributs ==&lt;br /&gt;
Im uiTable-Attribut wird in erster Linie die zu visualisierende Tabelle definiert. Optional können zuvor ein Perlblock sowie Templates definiert werden.&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;Aufbau des Attributs&#039;&#039;&#039;&lt;br /&gt;
* das uiTable-Attribut besteht aus drei Bereichen:&lt;br /&gt;
* [[DOIF/uiTable Schnelleinstieg#Der Perlblock|Perlblock]]&lt;br /&gt;
* [[DOIF/uiTable Schnelleinstieg#uiTable-Templates|Templates-Definitionen]] &lt;br /&gt;
* [[DOIF/uiTable Schnelleinstieg#Die Tabellendefinition|Tabellendefinition]]&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;Aufbaustruktur&#039;&#039;&#039; &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
&amp;lt;Perlblock, optional&amp;gt;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Templates-Definitionen, optional&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Tabellendefinition&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Der Perlblock ===&lt;br /&gt;
Der Perlblock dient dazu, das Layout der Tabelle zu beeinflussen sowie eigene uiTable-Funktionen zu definieren. Hier wird insb. das Package definiert, welches für die Tabellendefinition gilt. Ebenfalls können CSS-Variablen sowie Steuerungsattribute gesetzt werden. Der Perlblock beginnt und endet mit einer geschweiften Klammer.&lt;br /&gt;
&lt;br /&gt;
==== CSS-Variablen und Steuerungsattribute ====&lt;br /&gt;
Mit Hilfe von CSS-Variablen kann das Layout der Tabelle beeinflusst werden. Die Steuerungsattribute beeinflussen die Statuszeile sowie die Detailansicht des DOIF-Moduls.&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;CSS-Variablen und Steuerungsattribute&#039;&#039;&#039;&lt;br /&gt;
*Das Layout der gesamten Tabelle wird beeinflusst über die Variablendefinition: &#039;&#039;&#039;$TABLE=&amp;quot;&amp;lt;CSS-Attribute der Tabelle&amp;gt;&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
*Spaltenformatierungen werden beeinflusst mit Hilfe der Variablendefinition: &#039;&#039;&#039;$TC{&amp;lt;Zellenbereich für Spalten&amp;gt;}=&amp;quot;&amp;lt;CSS-Attribute der Spalten&amp;gt;&amp;quot;&#039;&#039;&#039; &lt;br /&gt;
*Zeilenformatierungen werden beeinflusst mit Hilfe der Variablendefinition: &#039;&#039;&#039;$TR{Zeilenbereich}=&amp;quot;&amp;lt;CSS-Attribute der Zeilen&amp;gt;&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
*einzelne Zellen werden beeinflusst mit Hilfe der Variablen: &#039;&#039;&#039;$TD{&amp;lt;Zellenbereich für Zeilen&amp;gt;}{&amp;lt;Zellenbereich für Spalten&amp;gt;}=&amp;quot;&amp;lt;CSS-Attribute der Zellen&amp;gt;&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
*für Zellen-, Spalten- und Zeilen-Bereich gilt: &#039;&#039;&#039;&amp;lt;Zahl&amp;gt;&amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt;&amp;lt;kommagetrennte Aufzählung&amp;gt;&amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt;&amp;lt;Bereich von..bis&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
*Der Status in der Statuszeile des DOIFs wird ausgeblendet mit &#039;&#039;&#039;$SHOWNOSTATE=1&#039;&#039;&#039;&lt;br /&gt;
*Die Gerätezeile des DOIFs wird ausgeblendet mit &#039;&#039;&#039;$SHOWNODEVICELINE = &amp;quot;&amp;lt;regex room&amp;gt;&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
*Die Tabelle des DOIFs wird ausgeblendet mit &#039;&#039;&#039;$SHOWNOUITABLE = &amp;quot;&amp;lt;regex room&amp;gt;&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
*Die Detailansicht wird umorganisiert mit &#039;&#039;&#039;$ATTRIBUTESFIRST=1&#039;&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;Bespieldefinition&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_bsp_layout DOIF ##&lt;br /&gt;
attr di_bsp_layout uiTable { ## Beginn des Perlblocks\&lt;br /&gt;
## CSS-Variablen\&lt;br /&gt;
\&lt;br /&gt;
## Die Tabelle soll ein Hintergrundbild der Größe 300x300 Pixel haben\&lt;br /&gt;
$TABLE = &amp;quot;width:300px;; height:300px;; background-image:url(/fhem/www/pgm2/images/Grundriss.png);; background-size: 300px 300px;;&amp;quot;;;\&lt;br /&gt;
\&lt;br /&gt;
## die Zelle der ersten Zeile und der ersten Spalte soll rechts eine Rahmenlinie haben\&lt;br /&gt;
$TD{0}{0} = &amp;quot;style=&#039;border-right-style:solid;; border-right-width:10px&#039;&amp;quot;;;\&lt;br /&gt;
\&lt;br /&gt;
## Die erste Zeile soll aus der Klasse &#039;odd&#039; sein und fett-Schrift haben\&lt;br /&gt;
$TR{0} = &amp;quot;class=&#039;odd&#039; style=&#039;font-weight:bold&#039;&amp;quot;;;\&lt;br /&gt;
\&lt;br /&gt;
## die Spalten 2 bis 6 sollen zentriert sein\&lt;br /&gt;
$TC{1..5} = &amp;quot;align=&#039;center&#039;&amp;quot;;;\&lt;br /&gt;
\&lt;br /&gt;
## die Spalten 2, 4 und 5 sollen zentriert sein\&lt;br /&gt;
$TC{1,3,5} = &amp;quot;align=&#039;center&#039;&amp;quot;;;\&lt;br /&gt;
\&lt;br /&gt;
## die letzte Spalte der Tabelle soll fett sein\&lt;br /&gt;
$TC{last} = &amp;quot;style=&#039;font-weight:bold&#039;&amp;quot;;;\&lt;br /&gt;
\&lt;br /&gt;
\## Steuerungsattribute\&lt;br /&gt;
\&lt;br /&gt;
\## Ausblenden des Status in der Statuszeile\&lt;br /&gt;
$SHOWNOSTATE=1;;\&lt;br /&gt;
\&lt;br /&gt;
## Die Gerätezeile wird ausgeblendet in allen Räumen\&lt;br /&gt;
$SHOWNODEVICELINE = &#039;.*&#039;;;\&lt;br /&gt;
\&lt;br /&gt;
## Die Tabelle wird im Raum info ausgeblendet\&lt;br /&gt;
$SHOWNOUITABLE = &#039;^info$&#039;;;\&lt;br /&gt;
\&lt;br /&gt;
## Die Detailansicht wird umorganisiert, hilfreich beim Editieren längerer uiTable-Definitionen\&lt;br /&gt;
$ATTRIBUTESFIRST = 1;;\&lt;br /&gt;
} ## Ende des Perlblocks&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Die Tabellendefinition ===&lt;br /&gt;
==== Einfache Tabellendefinition ohne Funktionen ====&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;Tabellendefinition&#039;&#039;&#039;&lt;br /&gt;
* eine Tabelle wird aus Zellen zusammengebaut&lt;br /&gt;
* mehrere Zellen werden mit &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; von einander getrennt, sie bilden eine Tabellenzeile&lt;br /&gt;
* eine neue Tabellenzeile beginnt mit einer neuen Zeile in der Tabellendefinition&lt;br /&gt;
* eine Tabellenzeile kann auch in mehreren Zeilen definiert werden, diese müssen dann mit &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; enden&lt;br /&gt;
* Texte werden in Anführungszeichen angegeben&lt;br /&gt;
* Text kann mit Befehlen etc. durch einen Punkt verknüpft werden&lt;br /&gt;
* Readings werden in der Form [&amp;lt;device&amp;gt;:&amp;lt;reading&amp;gt;] angegeben&lt;br /&gt;
* Kommentare beginnen mit ## und enden mit Zeilenende&lt;br /&gt;
* Events eines definierten Readings, führen sofort zu Aktualisierung seines Inhalts in der visualisierten Tabelle&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod ui_Table_definition DOIF ##&lt;br /&gt;
attr ui_Table_definition uiTable { ## Perlblock für globale Tabellendefinitionen\&lt;br /&gt;
 \&lt;br /&gt;
 $TC{1..2}=&amp;quot;align=&#039;center&#039;&amp;quot; ## zentrierte Ausrichtung der zweiten und dritten Spalte\&lt;br /&gt;
\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
## Tabellendefinition\&lt;br /&gt;
\&lt;br /&gt;
&amp;quot;Warmwasser&amp;quot;|&amp;quot;Vorlauf&amp;quot;|&amp;quot;Rücklauf&amp;quot;   ## erste Tabellenzeile\&lt;br /&gt;
									## zweite Tabellenzeile\&lt;br /&gt;
[T_Warmwasserspeicher:temperature]| ## Zeile wird fortgesetzt, da sie mit | endet\&lt;br /&gt;
[T_Vorlauf:temperature]|            ## Zeile wird fortgesetzt, da sie mit | endet\&lt;br /&gt;
[T_Ruecklauf:temperature]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable Definition.png|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
==== Tabellendefinition mit Berechnungen ====&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;Zellenauswertung&#039;&#039;&#039;&lt;br /&gt;
* jede Zelle der Tabelle wird über Perl ausgewertet&lt;br /&gt;
* Readingangaben der Form [&amp;lt;device&amp;gt;:&amp;lt;reading&amp;gt;] werden in eine Perlfunktion übersetzt&lt;br /&gt;
* das Ergebnis des ausgewerteten Perlausdrucks wird ausgegeben&lt;br /&gt;
* in einer Zelle können beliebige Perlfunktionen genutzt werden&lt;br /&gt;
* Texte oder Funktionen können mit Punkt aneinander gehängt werden&lt;br /&gt;
* mit Komma werden Texte oder Werte untereinander dargestellt&lt;br /&gt;
* wird eine Zeile mit &amp;lt; abgeschlossen, so wird die aktuelle Tabelle abgeschlossen, die nächste Zeile beginnt in einer neuen Tabelle&lt;br /&gt;
* in einer Berechnung sollte ein Trigger in Form einer Readingangabe [&amp;lt;device&amp;gt;:&amp;lt;reading&amp;gt;] vorkommen, sonst wäre das Ergebnis statisch und würde sich nicht ändern &lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_uiTable_calc DOIF ##&lt;br /&gt;
attr di_uiTable_calc uiTable ## Tabellendefinition\&lt;br /&gt;
&amp;quot;Differenz&amp;quot;|[T_Ruecklauf:temperature]-[T_Vorlauf:temperature]\&lt;br /&gt;
&amp;quot;Minimum&amp;quot;|minNum([TH_WZ_HM:measured-temp],[TH_Keller_HM:measured-temp])\&lt;br /&gt;
&amp;quot;Durchschnitt&amp;quot;|([T_Ruecklauf:temperature]+[T_Vorlauf:temperature])/2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable calc.png|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
== Vordefinierte uiTable-Funktionen ==&lt;br /&gt;
Typische Widgets bzw. Styles wurden als Perl-Funktionen im package ui_Table für eine einfache Tabellendefinition programmiert. Im folgenden wird näher auf die einzelnen uiTable-Funktionen eingegangen.&lt;br /&gt;
&lt;br /&gt;
=== FHEM-Widgets mit der Funktion &#039;&#039;&#039;widget&#039;&#039;&#039; ===&lt;br /&gt;
Alle in FHEM vorhanden Widgets können mit Hilfe der Perlfunktion &#039;&#039;&#039;widget&#039;&#039;&#039; genutzt werden. Bei häufiger Nutzung eines bestimmten Widgets bietet sich alternativ die Definition einer uiTable-Funktion (Typ 3) mit dem jeweiligen Widget an, siehe: [[DOIF/uiTable Schnelleinstieg#Eigene uiTable-Funktionen programmieren|uiTable-Funktion]]&lt;br /&gt;
{{Randnotiz|RNText=Funktion &#039;&#039;&#039;widget&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
widget(&amp;lt;Reading&amp;gt;,$fhem_widget,$set)&lt;br /&gt;
&lt;br /&gt;
Reading      # [&amp;lt;device&amp;gt;:&amp;lt;reading&amp;gt;]&lt;br /&gt;
$fhem_widget # Angabe des FHEM-Widgets&lt;br /&gt;
$set         # optional, undef zum Setzen beliebiger Readings (entspricht setreading), &amp;quot;set&amp;quot; wenn das Reading per set-Befehl gesetzt wird (siehe Attribut ReadingList), &amp;quot;set &amp;lt;Befehl&amp;gt;&amp;quot;, wenn sich der Befehl vom Reading unterscheidet, default undef&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nützliche Links&#039;&#039;&#039;&lt;br /&gt;
* [[FHEMWEB/Widgets|Fhem-Widgets]]&lt;br /&gt;
* Fhem-Widgets als [[DOIF/uiTable Schnelleinstieg#Eigene uiTable-Funktionen programmieren|uiTable-Funktion]]&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_uiTable_widget DOIF ##&lt;br /&gt;
attr di_uiTable_widget uiTable ## FHEM-Widgets mit Hilfe der WID-Funktion\&lt;br /&gt;
{package ui_Table}\&lt;br /&gt;
&amp;quot;Widget&amp;quot;\&lt;br /&gt;
&amp;quot;Select&amp;quot;| widget([uhr:wochentag],&amp;quot;select,Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag,Sonntag&amp;quot;)\&lt;br /&gt;
&amp;quot;Selectnumbers&amp;quot;| widget([motor:spannung],&amp;quot;selectnumbers,0,0.5,12,1,lin&amp;quot;)\&lt;br /&gt;
&amp;quot;Slider&amp;quot;| widget([bla:wert],&amp;quot;slider,0,5,100,1&amp;quot;)\&lt;br /&gt;
&amp;quot;Colorpicker RGB&amp;quot;| widget([Lampe:farbe],&amp;quot;colorpicker,RGB&amp;quot;)\&lt;br /&gt;
&amp;quot;Colorpicker HSV&amp;quot;| widget([Lampe:farbe],&amp;quot;colorpicker,HSV&amp;quot;)\&lt;br /&gt;
&amp;quot;Colorpicker CT&amp;quot;| widget([Lampe:waerme],&amp;quot;colorpicker,CT,2000,10,6500&amp;quot;)\&lt;br /&gt;
&amp;quot;Colorpicker HUE&amp;quot;| widget([Lampe:farbe],&amp;quot;colorpicker,HUE,0,1,359&amp;quot;)\&lt;br /&gt;
&amp;quot;Colorpicker BRI&amp;quot;| widget([Lampe:helligkeit],&amp;quot;colorpicker,BRI,0,1,100&amp;quot;)\&lt;br /&gt;
&amp;quot;Time&amp;quot;| widget([start:zeit],&amp;quot;time&amp;quot;)\&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable WID.png|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
=== SVG-uiTable-Funktionen ===&lt;br /&gt;
SVG-uiTable-Funktionen sind skalierbare Widgets, die auf SVG-Elementen basieren. Diese Funktionen befinden sich im Namensraum &#039;&#039;&#039;ui_Table&#039;&#039;&#039;, daher muss vor deren Nutzung der Namensraum im Perlblock mit &#039;&#039;&#039;package ui_Table&#039;&#039;&#039; festgelegt werden (siehe Beispiele unten). Funktionen aus dem Namensraum &#039;&#039;&#039;main&#039;&#039;&#039; - das ist der Standard-Namensraum in FHEM - müssen in diesem Fall mit vorangestelltem Namensraum angegeben werden: &#039;&#039;&#039;main::&amp;lt;perlfunction&amp;gt;&#039;&#039;&#039; oder kürzer &#039;&#039;&#039;::&amp;lt;perlfunction&amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;ring&#039;&#039;&#039;-Funktionen ====&lt;br /&gt;
===== Farbskalierte Temperaturanzeige mit Hilfe der SVG-Funktionen &#039;&#039;&#039;temp_ring/temp_mring&#039;&#039;&#039; =====&lt;br /&gt;
Die Farbe der dargestellten Temperatur ist abhängig vom Temperaturwert. Die Helligkeit der Farbgebung ist einstellbar. Bei der &#039;&#039;&#039;temp_mring&#039;&#039;&#039;-SVG-Funktion wird der Ring einfarbig dargestellt.&lt;br /&gt;
&lt;br /&gt;
Farbskalierung der &#039;&#039;&#039;temp_ring&#039;&#039;&#039;-SVG-Funktion:&lt;br /&gt;
[[Datei:Farbskalierung temp_ring_scaling.png|600px|ohne]]&lt;br /&gt;
&lt;br /&gt;
Farbskalierung der &#039;&#039;&#039;temp_mring&#039;&#039;&#039;-SVG-Funktion:&lt;br /&gt;
[[Datei:Farbskalierung temp_mring_scaling.png|600px|ohne]]&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;temp_ring/temp_mring&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
temp_ring/temp_mring ($temp_value,$temp_min,$temp_max,$sizeHalf, $lightring,$lightnumber,$decFont) &lt;br /&gt;
&lt;br /&gt;
$temp_value  # Temperatur&lt;br /&gt;
$temp_min,   # minimale Temperatur, optional, default=-20&lt;br /&gt;
$temp_max,   # maximale Temperatur, optional, default=60&lt;br /&gt;
$sizeHalf    # &amp;quot;&amp;lt;size&amp;gt;,&amp;lt;half ring&amp;gt;&amp;quot; size: Größe der Grafik, optional, default = 80, half ring: 1 für Halbring&lt;br /&gt;
$lightring,  # Helligkeit des Ringes (0-100), optional, default=50&lt;br /&gt;
$lightnumber # Helligkeit der Zahl (0-100), optional, default=50&lt;br /&gt;
$decFont     # &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_temp_ring DOIF ##&lt;br /&gt;
attr di_temp_ring uiTable {package ui_Table}\&lt;br /&gt;
&amp;quot;außen (standard)&amp;quot;|temp_ring([Aussensensor:temperature])\&lt;br /&gt;
&amp;quot;Warmwasser (größer,aufgehellt,Normalschrift)&amp;quot; |temp_mring([vaillant:WWSpeicher],15,70,110,90,100,&amp;quot;1,font-weight:normal&amp;quot;)\&lt;br /&gt;
&amp;quot;Vorlauf (größer)&amp;quot;| temp_mring([ESPEasy_ESP_Temp_Vorlauf:Temperature],15,45,100)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:temp_ring_bsp.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
===== Farbskalierte Feuchtigkeitsanzeige mit Hilfe der SVG-Funktionen &#039;&#039;&#039;hum_ring/hum_mring&#039;&#039;&#039; =====&lt;br /&gt;
Die Farbe der dargestellten Feuchtigkeit ist abhängig vom Feuchtigkeitswert. Die Helligkeit der Farbgebung ist einstellbar. Bei der &#039;&#039;&#039;hum_mring&#039;&#039;&#039;-SVG-Funktion wird der Ring einfarbig dargestellt.&lt;br /&gt;
&lt;br /&gt;
Farbskalierung der &#039;&#039;&#039;hum_ring&#039;&#039;&#039;-SVG-Funktion: &lt;br /&gt;
[[Datei:Farbskalierung hum_ring_scaling.png|600px|ohne]]&lt;br /&gt;
&lt;br /&gt;
Farbskalierung der &#039;&#039;&#039;hum_mring&#039;&#039;&#039;-SVG-Funktion:&lt;br /&gt;
[[Datei:Farbskalierung hum_mring_scaling.png|600px|ohne]]&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;hum_ring/hum_mring&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
hum_ring/hum_mring ($hum_value,$sizeHalf,$lightring,$lightnumber,$decFont) &lt;br /&gt;
$hum_value   # Feuchtigkeit&lt;br /&gt;
$sizeHalf  # &amp;quot;&amp;lt;size&amp;gt;,&amp;lt;half ring&amp;gt;&amp;quot; size: Größe der Grafik, optional, default = 80, half ring: 1 für Halbring&lt;br /&gt;
$lightring   # Helligkeit des Ringes (0-100), optional, default=50&lt;br /&gt;
$lightnumber # Helligkeit der Zahl (0-100), optional, default=50&lt;br /&gt;
$decFont     # &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_hum_ring DOIF ##&lt;br /&gt;
attr di_hum_ring room test2&lt;br /&gt;
attr di_hum_ring uiTable {package ui_Table}\&lt;br /&gt;
&amp;quot;klein ohne Farbverlauf&amp;quot;|hum_mring([Aussensensor:humidity],60)\&lt;br /&gt;
&amp;quot;normal groß mit Farbverlauf&amp;quot;|hum_ring([Aussensensor:humidity])\&lt;br /&gt;
&amp;quot;groß ohne Farbverlauf aufgehellt&amp;quot;|hum_mring([Aussensensor:humidity],100,80)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:hum_ring_bsp.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
===== Farbskalierte Anzeige eines Zahlenwertes mit Hilfe der universellen SVG-Funktion &#039;&#039;&#039;ring&#039;&#039;&#039; =====&lt;br /&gt;
Die Farbe des dargestellten Wertes kann abhängig vom Wert bestimmt werden. Dabei wird die Farbe mit Anleihen aus dem [https://de.wikipedia.org/wiki/HSV-Farbraum HSV-Farbraum] bestimmt. Dieser Farbraum benötigt eigentlich drei Werte, wobei die erste den Farbton (hue) bestimmt; hier wird nur dieser Wert verwendet (Sättigung und Hellwert sind nicht einstellbar). Der Farbton geht von rot (hue-Wert = 0) über gelb (hue-Wert = 60), dann grün (hue-Wert = 120) und blau (hue-Wert = 240) zurück zu rot (hue-Wert = 360), siehe dazu auch die [https://de.wikipedia.org/wiki/HSV-Farbraum#/media/Datei:HueScale.svg Farbtontafel] auf der Wikipedia-Seite.&lt;br /&gt;
Die unten $colorRef genannte Funktion kann zum Beispiel in der Tabelle selbst definiert werden, beispielsweise kann man in dem device &amp;amp;onoff_hue verwenden, wenn man es vorab definiert (siehe [https://forum.fhem.de/index.php/topic,120088.msg1204341.html#msg1204341 Link zum Forum]):&amp;lt;blockquote&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr &amp;lt;ui device Name&amp;gt; {&lt;br /&gt;
  package ui_Table;&lt;br /&gt;
    sub onoff_hue {&lt;br /&gt;
    my($irgendeinVariablenname)=@_;&lt;br /&gt;
    return ($irgendeinVariablenname == 0 ? 240 : 0); &lt;br /&gt;
  }&lt;br /&gt;
## Tabellendefinition&lt;br /&gt;
...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/blockquote&amp;gt;{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;ring&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
ring ($value,$min,$max,$minColor,$maxColor,$desc, $sizeHalf,$colorRef,$decFontUnit,$model,$lightness)&lt;br /&gt;
&lt;br /&gt;
$value     # darzustellender Wert&lt;br /&gt;
$min       # minimaler Wert, optional, default=0&lt;br /&gt;
$max       # maximaler Wert, optional, default=100&lt;br /&gt;
$minColor  # Farbe (hue: 0-360) des kleinsten Wertes, optional, default = undef&lt;br /&gt;
$maxColor  # Farbe (hue: 0-360) des maximalen Wertes, optional, default = undef&lt;br /&gt;
$desc      # Beschreibung des Wertes, optional, default = undef&lt;br /&gt;
$sizeHalf  # &amp;quot;&amp;lt;size&amp;gt;,&amp;lt;half ring&amp;gt;&amp;quot; size: Größe der Grafik, optional, default = 100, half ring: 1 für Halbring&lt;br /&gt;
$colorRef  # Referenz auf eine Funktion, die zu einem Wert einen Farbwert (hue: 0-360) bestimmt, oder eine Referenz auf eine Arrayliste mit Grenzwerten und Farben, optional, default = undef&lt;br /&gt;
$decFontUnit # &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;,&amp;lt;Einheit hinter dem Zahlenwert&amp;gt;&amp;quot;, optional&lt;br /&gt;
$model     # &#039;&amp;lt;color gradient&amp;gt;,&amp;lt;min/max&amp;gt;,&amp;lt;inner ring&amp;gt;,&amp;lt;pointer&amp;gt;,&amp;lt;mode&amp;gt;&#039;&lt;br /&gt;
# &amp;lt;color gradient&amp;gt;: &amp;quot;gradient&amp;quot; (undef),&amp;quot;nogradient&amp;quot; (1)&lt;br /&gt;
# &amp;lt;min/max&amp;gt;: Style-SVG-Attribute oder &amp;quot;nominmaxvalue&amp;quot; (undef), &amp;quot;minmaxvalue&amp;quot; (1)&lt;br /&gt;
# &amp;lt;inner ring&amp;gt;: Style-SVG-Attribute oder &amp;quot;innerring&amp;quot; (1), &amp;quot;noinnerring&amp;quot; (undef)&lt;br /&gt;
# &amp;lt;pointer&amp;gt;: Breite des Zeigers in Pixel, &amp;quot;nopointer&amp;quot; (undef)&lt;br /&gt;
# &amp;lt;mode&amp;gt;: &amp;quot;minmax&amp;quot; (undef), &amp;quot;negzeropos&amp;quot; (1), &amp;quot;zeronegpos&amp;quot; (2)&lt;br /&gt;
# alle Parameter sind optional, default keine Angaben: &#039;,,,,,,&#039;&lt;br /&gt;
$lightness  # Helligkeit einzelner Elemente (0-100) &amp;quot;&amp;lt;ring&amp;gt;,&amp;lt;inner ring&amp;gt;,&amp;lt;minMax&amp;gt;,&amp;lt;unit&amp;gt;,&amp;lt;value&amp;gt;&amp;quot;, optional, default: &amp;quot;50,50,50,40,50&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Wird &#039;&#039;&#039;$colorFunc&#039;&#039;&#039; nicht angegeben, so wird der Farbwert zwischen &#039;&#039;&#039;$minColor&#039;&#039;&#039; und &#039;&#039;&#039;$maxColor&#039;&#039;&#039; linear interpoliert&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_ring DOIF (1)&lt;br /&gt;
attr di_ring room test20,test5&lt;br /&gt;
attr di_ring uiTable {package ui_Table;; \&lt;br /&gt;
 $SHOWNOSTATE=1}\&lt;br /&gt;
## von 0 bis 20 in Farben von grün (hue:120) bis rot (hue:0)\&lt;br /&gt;
&amp;quot;Umlaufmenge&amp;quot;|ring([heating:pump],0,20,120,0,&amp;quot;l/min&amp;quot;,100)\&lt;br /&gt;
\&lt;br /&gt;
## von 0 bis 3 in Farben von rot (hue:0) bis türkis (hue:180), eine Nachkommastelle, Schriftgröße 170%\&lt;br /&gt;
## Innenring mit Min-, Max-Beschriftung\&lt;br /&gt;
&amp;quot;Wasserdruck&amp;quot;|ring([heating:pressure],0,3,0,180,&amp;quot;bar&amp;quot;,100,undef,&amp;quot;1,font-size:170%,fill:silver;;font-size:50%&amp;quot;,&amp;quot;0,1,1&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
## Temperaturdarstellung, entspricht dem Funktionsaufruf:\&lt;br /&gt;
## temp_ring ([outdoor:temperature],-20,60,100,&amp;quot;1,font-weight:normal;;font-size:140%&amp;quot;)\&lt;br /&gt;
## Eine Nachkommastelle, Normalschrift, Schriftgröße 140%\&lt;br /&gt;
&amp;quot;Temperatur&amp;quot;|ring([outdoor:temperature,-20,60,undef,undef,&amp;quot;°C&amp;quot;,100,\&amp;amp;temp_hue,&amp;quot;1,font-weight:normal;;font-size:140%&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
## Lufdruck als Halbring\&lt;br /&gt;
&amp;quot;Luftdruck&amp;quot;|ring([weather:barometer],970,1045,30,90,&amp;quot;hPa&amp;quot;,&amp;quot;100,1&amp;quot;,undef,0)\&lt;br /&gt;
\&lt;br /&gt;
## Co2 als Halbring, Farbgebung als Array mit drei Bereichen, Innenring mit Zeiger\&lt;br /&gt;
&amp;quot;Co2&amp;quot;|ring([livingroom:co2],400,1200,undef,undef,&#039;ppm&#039;,&amp;quot;100,1&amp;quot;,[(600,120,1000,60,1200,0)],0,&#039;0,0,1,5&#039;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:ring_bsp.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
===== Farbskalierte Temperatur- und Feuchtigkeitsanzeige mit Hilfe der SVG-Funktion &#039;&#039;&#039;temp_hum_ring&#039;&#039;&#039; =====&lt;br /&gt;
Die Farbe ist jeweils abhängig vom dargestellten Temperatur- bzw. Feuchtigkeitswert. Die Helligkeit der Farbgebung ist einstellbar:&lt;br /&gt;
[[Datei:Farbskalierung temp_hum_ring_scaling.png|600px|ohne]]&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;temp_hum_ring&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
temp_hum_ring ($temp_value,$hum_value,$temp_min,$temp_max,$size, $lightring,$lightnumber,$decFontTemp,$decFontHum)&lt;br /&gt;
&lt;br /&gt;
$temp_value # Temperatur&lt;br /&gt;
$hum_value  # Feuchtigkeit&lt;br /&gt;
$temp_min   # minimale Temperatur, optional, default=-20&lt;br /&gt;
$temp_max   # maximale Temperatur, optional, default=60&lt;br /&gt;
$size       # Größe der Grafik, optional, default=90&lt;br /&gt;
$lightring   # Helligkeit des Ringes (0-100), optional, default=50&lt;br /&gt;
$lightnumber # Helligkeit der Zahl (0-100), optional, default=50&lt;br /&gt;
$decFontTemp # Temperatur: &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional&lt;br /&gt;
$decFontHum  # Feuchtigkeit: &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_temp_hum_ring DOIF ##&lt;br /&gt;
attr di_temp_hum_ring uiTable {package ui_Table}\&lt;br /&gt;
\&lt;br /&gt;
&amp;quot;klein&amp;quot;|temp_hum_ring([Aussensensor:temperature],[Aussensensor:humidity],undef,undef,60)\&lt;br /&gt;
&amp;quot;normal&amp;quot;|temp_hum_ring([Aussensensor:temperature],[Aussensensor:humidity])\&lt;br /&gt;
&amp;quot;größer, aufgehellt&amp;quot;|temp_hum_ring([Aussensensor:temperature],[Aussensensor:humidity],undef,undef,100,undef,80)\&lt;br /&gt;
&amp;quot;größer, Ring aufgehellt, Normalschrift&amp;quot;|temp_hum_ring([Aussensensor:temperature],[Aussensensor:humidity],undef,undef,100,80,50,&amp;quot;1,font-weight:normal&amp;quot;,&amp;quot;0,font-weight:normal&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:temp_hum_ring_bsp.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
===== Farbskalierte Anzeige von zwei Temperaturwerten mit Hilfe der SVG-Funktion &#039;&#039;&#039;temp_temp_ring&#039;&#039;&#039; =====&lt;br /&gt;
Die Farbe ist jeweils abhängig vom dargestellten Temperaturwert. Die Helligkeit der Farbgebung ist einstellbar:&lt;br /&gt;
[[Datei:Farbskalierung temp_temp_ring_scaling.png|600px|ohne]]&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;temp_temp_ring&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
temp_temp_ring ($temp1_value,$temp2_value,$temp_min,$temp_max,$size, $lightring,$lightnumber,$decFontTemp1,$decFontTemp2)&lt;br /&gt;
&lt;br /&gt;
$temp1_value # erster Temperaturwert&lt;br /&gt;
$temp2_value # zweiter Temperaturwert&lt;br /&gt;
$temp_min    # minimale Temperatur, optional, default=-20&lt;br /&gt;
$temp_max    # maximale Temperatur, optional, default=60&lt;br /&gt;
$size        # Größe der Grafik, optional, default=90&lt;br /&gt;
$lightring   # Helligkeit des Ringes (0-100), optional, default=50&lt;br /&gt;
$lightnumber # Helligkeit der Zahl (0-100), optional, default=50&lt;br /&gt;
$decFontTemp1 # Temperatur1: &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional&lt;br /&gt;
$decFontTemp2 # Temperatur2: &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_temp_temp_ring DOIF ##&lt;br /&gt;
attr di_temp_temp_ring uiTable {package ui_Table}\&lt;br /&gt;
&amp;quot;klein, Ring augehellt&amp;quot;|temp_temp_ring([Vorlauf:Temperature],[Ruecklauf:Temperature],15,60,60,80,50)\&lt;br /&gt;
&amp;quot;normal&amp;quot;|temp_temp_ring([Vorlauf:Temperature],[Ruecklauf:Temperature],15,60)\&lt;br /&gt;
&amp;quot;groß, Zahlen aufgehellt&amp;quot;|temp_temp_ring([Vorlauf:Temperature],[Ruecklauf:Temperature],15,60,100,undef,80)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:temp_hum_temp_bsp.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===== Farbskalierte Anzeige von zwei Zahlenwerten mit Hilfe der universellen SVG-Funktion &#039;&#039;&#039;ring2&#039;&#039;&#039; =====&lt;br /&gt;
Die Farbe der dargestellten Werte kann abhängig vom Wert bestimmt werden.&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;ring2&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
ring2 ($value1,$min1,$max1,$minColor1,$maxColor1,$desc1,$size,$colorFunc1,$decFont1, $value2,$min2,$max2,$minColor2,$maxColor2,$desc2,$colorFunc2,$decFont2, $lightness,$icon,$model)&lt;br /&gt;
&lt;br /&gt;
$value1     # darzustellender Wert1&lt;br /&gt;
$min1       # minimaler Wert, optional, default=0&lt;br /&gt;
$max1       # maximaler Wert, optional, default=100&lt;br /&gt;
$minColor1  # Farbe (hue: 0-360) des kleinsten Wertes, optional, default = undef&lt;br /&gt;
$maxColor1  # Farbe (hue: 0-360) des maximalen Wertes, optional, default = undef&lt;br /&gt;
$desc1      # Beschreibung des Wertes, optional, default = undef&lt;br /&gt;
$size       # Größe der Grafik, optional, default = 100&lt;br /&gt;
$colorFunc1 # Funktion, die zu einem Wert einen Farbwert (hue: 0-360) bestimmt, optional, default = undef&lt;br /&gt;
$decFontUnit1 # &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;,&amp;lt;Einheit hinter dem Zahlenwert&amp;gt;&amp;quot;, optional&lt;br /&gt;
$value2     # darzustellender Wert2&lt;br /&gt;
...&lt;br /&gt;
$decFontUnit2 # &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;,&amp;lt;Einheit hinter dem Zahlenwert&amp;gt;&amp;quot;, optional&lt;br /&gt;
$lightness  # Helligkeit einzelner Elemente (0-100) &amp;quot;&amp;lt;ring&amp;gt;,&amp;lt;inner ring&amp;gt;,&amp;lt;minMax&amp;gt;,&amp;lt;unit&amp;gt;,&amp;lt;value&amp;gt;,&amp;lt;icon&amp;gt;&amp;quot;, optional, default: &amp;quot;50,50,50,40,50,40&amp;quot;&lt;br /&gt;
$model     # &#039;&amp;lt;color gradient&amp;gt;,&amp;lt;min/max&amp;gt;,&amp;lt;inner ring&amp;gt;,&amp;lt;pointer&amp;gt;,&amp;lt;mode&amp;gt;&#039;&lt;br /&gt;
# &amp;lt;color gradient&amp;gt;: &amp;quot;gradient&amp;quot; (undef),&amp;quot;nogradient&amp;quot; (1)&lt;br /&gt;
# &amp;lt;min/max&amp;gt;: Style-SVG-Attribute oder &amp;quot;nominmaxvalue&amp;quot; (undef), &amp;quot;minmaxvalue&amp;quot; (1)&lt;br /&gt;
# &amp;lt;inner ring&amp;gt;: Style-SVG-Attribute oder &amp;quot;innerring&amp;quot; (1), &amp;quot;noinnerring&amp;quot; (undef)&lt;br /&gt;
# &amp;lt;pointer&amp;gt;: Breite des Zeigers in Pixel, &amp;quot;nopointer&amp;quot; (undef)&lt;br /&gt;
# &amp;lt;mode&amp;gt;: &amp;quot;minmax&amp;quot; (undef), &amp;quot;negzeropos&amp;quot; (1), &amp;quot;zeronegpos&amp;quot; (2)&lt;br /&gt;
# alle Parameter sind optional, default keine Angaben: &#039;,,,,,,&#039;&lt;br /&gt;
&lt;br /&gt;
Argumente für den zweiten Wert entsprechend den Argumenten des ersten Wertes&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Wird &#039;&#039;&#039;$colorFunc...&#039;&#039;&#039; nicht angegeben, so wird der Farbwert zwischen &#039;&#039;&#039;$minColor...&#039;&#039;&#039; und &#039;&#039;&#039;$maxColor...&#039;&#039;&#039; linear interpoliert&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_ring2 DOIF ##&lt;br /&gt;
attr di_ring2 uiTable {package ui_Table;;}\&lt;br /&gt;
## Leistungsaufnahme von 0 kW bis 3,6 kW in Farben von grün (hue:120) bis rot (hue:0)\&lt;br /&gt;
## Kapazität von 0 % bis 100 % V in Farben von rot (hue:0) bis grün (hue:120)\&lt;br /&gt;
&amp;quot;Wallbox&amp;quot;| ring2([tesla:Leistung],0,3.6,120,0,&amp;quot;kW&amp;quot;,undef,undef,&amp;quot;1,font-weight:normal&amp;quot;,[tesla:Kapazitaet],0,100,0,120,&amp;quot;%&amp;quot;,undef,&amp;quot;0,font-weight:normal&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
## Stromstärke von 0 A bis 2 A in Farben von grün (hue:120) bis rot (hue:0)\&lt;br /&gt;
## Spannung von 1 V bis 1.5 V in Farben von rot (hue:0) bis grün (hue:120)\&lt;br /&gt;
## 3 Nachkommastellen, Normalschrift, Schriftgröße 80%  \&lt;br /&gt;
&amp;quot;Akku&amp;quot;| ring2([akku:Strom],0,2,120,0,&amp;quot;A&amp;quot;,undef,undef,&amp;quot;3,font-weight:normal;;font-size:80%&amp;quot;,[akku:Spannung],1,1.5,0,120,&amp;quot;V&amp;quot;,undef,&amp;quot;3,font-weight:normal;;font-size:80%&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:ring2_bsp.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition Innenring, Farb-Array, Ringmodi&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_solar DOIF {}&lt;br /&gt;
attr di_solar uiTable {package ui_Table}\&lt;br /&gt;
&amp;quot;Farb-Array, ringMode 1&amp;quot;|\&lt;br /&gt;
ring2([zaehler:Produktion],-20,30,undef,undef,&amp;quot;PV kWh&amp;quot;,130,[(-10,0,-0.001,30,10,60,30,90)],&amp;quot;2&amp;quot;,[test:Bezug],-20,30,undef,undef,&amp;quot;Bezug&amp;quot;,[(-10,0,-0.001,30,10,60,30,90)],&amp;quot;2&amp;quot;,undef,undef,&amp;quot;0,1,1,0,1&amp;quot;)\&lt;br /&gt;
&amp;quot;Farbe linear, ringMode 1&amp;quot;|\&lt;br /&gt;
ring2([zeahler:Produktion],-20,30,0,120,&amp;quot;PV kWh&amp;quot;,130,undef,&amp;quot;2&amp;quot;,[test:Bezug],-20,30,0,120,&amp;quot;Bezug&amp;quot;,undef,&amp;quot;2&amp;quot;,undef,undef,&amp;quot;0,1,1,0,1&amp;quot;)\&lt;br /&gt;
&amp;quot;Farbe linear, ringMode 2&amp;quot;|\&lt;br /&gt;
ring2([zaehler:Produktion],0,30,60,120,&amp;quot;PV kWh&amp;quot;,130,undef,&amp;quot;2&amp;quot;,[test:Bezug],-20,0,0,120,&amp;quot;Bezug&amp;quot;,undef,&amp;quot;2&amp;quot;,undef,undef,&amp;quot;0,,,0,2&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:ring2_ringMode.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;icon_ring&#039;&#039;&#039;-Funktionen ====&lt;br /&gt;
===== Farbskalierte Temperaturanzeige mit einem Icon mit Hilfe der SVG-Funktionen &#039;&#039;&#039;icon_temp_ring/icon_temp_mring&#039;&#039;&#039; =====&lt;br /&gt;
Diese Funktionen basieren auf den obigen temp_ring-Funktionen, zusätzlich wird ein SVG-Icon dargestellt. Die Farbe des Icons kann mit @ an den Iconnamen angehängt werden, ansonsten wird die Farbe der Temperatur für das Icon verwendet. Die Größe des Icons kann skaliert werden, ebenso kann die Positionen des Icons verschoben werden.&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;icon_temp_ring/icon_temp_mring&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
icon_temp_ring/icon_temp_mring ($icon,$temp_value,$temp_min,$temp_max,$size,$lightring,$lightnumber,$decFont) &lt;br /&gt;
&lt;br /&gt;
$icon        # &amp;quot;Iconname\@Farbe,Skalierungsfaktor,x-Position,y-Position,Rotation&amp;quot;, \@Farbe, Skalierungsfaktor, x-Position, y-Position, Rotation (0-360) sind optional&lt;br /&gt;
$temp_value  # Temperatur&lt;br /&gt;
$temp_min,   # minimale Temperatur, optional, default=-20&lt;br /&gt;
$temp_max,   # maximale Temperatur, optional, default=60&lt;br /&gt;
$size,       # Größe der Grafik, optional, default=80&lt;br /&gt;
$lightring,  # Helligkeit des Ringes (0-100), optional, default=50&lt;br /&gt;
$lightnumber # Helligkeit der Zahl (0-100), optional, default=50&lt;br /&gt;
$decFont # &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_Heizung_temp DOIF ##&lt;br /&gt;
attr di_Heizung_temp uiTable {\&lt;br /&gt;
  package ui_Table;;\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
icon_temp_ring(&amp;quot;temp_outside&amp;quot;,[vaillant:Aussentemp],-15,40)|\&lt;br /&gt;
icon_temp_mring(([vaillant:Flame] eq &amp;quot;off&amp;quot;?&amp;quot;sani_boiler_temp\@white&amp;quot;:&amp;quot;sani_boiler_temp\@Darkorange&amp;quot;),[vaillant:Vorlauf],15,70)|\&lt;br /&gt;
icon_temp_mring(([vaillant:Pumpenstatus] eq &amp;quot;4&amp;quot; ? &amp;quot;sani_buffer_temp_down\@Darkorange&amp;quot; : &amp;quot;sani_buffer_temp_down\@white&amp;quot;),[vaillant:WWSpeicher],15,70)|\&lt;br /&gt;
icon_temp_mring(([Zirk] eq &amp;quot;off&amp;quot;?&amp;quot;sani_pump\@white&amp;quot;:&amp;quot;sani_pump\@Darkorange&amp;quot;),[ESPEasy_ESP_Temp_Zirkulation:Temperature],15,70)|\&lt;br /&gt;
icon_temp_mring(([vaillant:Pumpenstatus] eq &amp;quot;on&amp;quot; ? &amp;quot;sani_floor_heating\@Darkorange&amp;quot; : &amp;quot;sani_floor_heating_neutral\@white&amp;quot;),[ESPEasy_ESP_Temp_Vorlauf:Temperature],15,70)|\&lt;br /&gt;
icon_temp_mring(&amp;quot;sani_floor_heating_neutral\@white&amp;quot;,[ESPEasy_ESP_Temp_Keller_Ruecklauf:Temperature],15,70)|&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:icon_temp_ring_bsp.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
===== Farbskalierte Feuchtigkeitsanzeige mit einem Icon mit Hilfe der SVG-Funktionen &#039;&#039;&#039;icon_hum_ring/icon_hum_mring&#039;&#039;&#039; =====&lt;br /&gt;
Diese Funktionen basieren auf den obigen hum_ring-Funktionen, zusätzlich wird ein SVG-Icon dargestellt. Die Farbe des Icons kann mit @ an den Iconnamen angehängt werden, ansonsten wird die Farbe der Feuchtigkeit für das Icon verwendet. Die Größe des Icons kann skaliert werden, ebenso kann die Positionen des Icons verschoben werden. &lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;icon_hum_ring/icon_hum_mring&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
icon_hum_ring/icon_hum_mring ($icon,$hum_value,$size,$lightring,$lightnumber,$decFont) &lt;br /&gt;
&lt;br /&gt;
$icon        # &amp;quot;Iconname\@Farbe,Skalierungsfaktor,x-Position,y-Position,Rotation&amp;quot;, \@Farbe, Skalierungsfaktor, x-Position, y-Position, Rotation sind optional&lt;br /&gt;
$hum_value   # Feuchtigkeit&lt;br /&gt;
$size        # Größe der Grafik, optional, default=80&lt;br /&gt;
$lightring   # Helligkeit des Ringes (0-100), optional, default=50&lt;br /&gt;
$lightnumber # Helligkeit der Zahl (0-100), optional, default=50&lt;br /&gt;
$decFont     # &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_icon_hum_ring DOIF ##&lt;br /&gt;
attr di_icon_hum_ring room test5&lt;br /&gt;
attr di_icon_hum_ring uiTable {package ui_Table}\&lt;br /&gt;
&amp;quot;klein ohne Farbverlauf&amp;quot;|icon_hum_mring(&amp;quot;weather_humidity&amp;quot;,[Aussensensor:humidity],60)\&lt;br /&gt;
&amp;quot;normal groß mit Farbverlauf&amp;quot;|icon_hum_ring(&amp;quot;weather_humidity&amp;quot;,[Aussensensor:humidity])\&lt;br /&gt;
&amp;quot;groß ohne Farbverlauf aufgehellt&amp;quot;|icon_hum_mring(&amp;quot;weather_humidity&amp;quot;,[Aussensensor:humidity],100,80)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:icon_hum_ring_bsp.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
===== Farbskalierte Anzeige eines Icons mit einem Zahlenwert mit Hilfe der universellen SVG-Funktion &#039;&#039;&#039;icon_ring/icon_mring/icon_uring&#039;&#039;&#039; =====&lt;br /&gt;
Diese Funktionen basieren auf der universellen ring-Funktion. Die Farbe des dargestellten Icons und des Wertes kann abhängig vom Wert bestimmt werden. Die Funktion &#039;&#039;&#039;icon_ring&#039;&#039;&#039; stellt den Farbring mit Farbverlauf dar, die Funktion &#039;&#039;&#039;icon_mring&#039;&#039;&#039; stellt den Farbring einfarbig dar. Die universelle Funktion &#039;&#039;&#039;icon_uring&#039;&#039;&#039; kann über den Parameter &#039;&#039;&#039;$model&#039;&#039;&#039; das Erscheinungsbild der Grafik verändern.&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;icon_ring/icon_mring/icon_uring&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
icon_ring ($icon,$value,$min,$max,$minColor,$maxColor, $unit,$decFont,$size,$colorRef,$lightness,$model)&lt;br /&gt;
&lt;br /&gt;
icon_mring ($icon,$value,$min,$max,$minColor,$maxColor, $unit,$decFont,$size,$colorRef,$lightness)&lt;br /&gt;
&lt;br /&gt;
icon_uring ($model,$icon,$value,$min,$max,$minColor,$maxColor, $unit,$decFont,$size,$colorRef,$lightness)&lt;br /&gt;
&lt;br /&gt;
$icon      # &amp;quot;Iconname\@Farbe,Skalierungsfaktor,x-Position,y-Position,Rotation&amp;quot;, \@Farbe, Skalierungsfaktor, x-Position, y-Position, Rotation sind optional&lt;br /&gt;
$value     # darzustellender Wert&lt;br /&gt;
$min       # minimaler Wert, optional, default=0&lt;br /&gt;
$max       # maximaler Wert, optional, default=100&lt;br /&gt;
$minColor  # Farbe (hue: 0-360) des kleinsten Wertes, optional, default = undef&lt;br /&gt;
$maxColor  # Farbe (hue: 0-360) des maximalen Wertes, optional, default = undef&lt;br /&gt;
$unit      # Einheit des Wertes, optional, default = undef&lt;br /&gt;
$decFont   # &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Style-SVG-Attribute Wert&amp;gt;,&amp;lt;Style-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional&lt;br /&gt;
$size      # Größe der Grafik, optional, default = 100&lt;br /&gt;
$colorRef  # Referenz auf eine Funktion, die zu einem Wert einen Farbwert (hue: 0-360) bestimmt, oder eine Referenz auf eine Arrayliste mit Grenzwerten und Farben, optional, default = undef&lt;br /&gt;
$lightness # Helligkeit einzelner Elemente (0-100) &amp;quot;&amp;lt;ring&amp;gt;,&amp;lt;inner ring&amp;gt;,&amp;lt;minMax&amp;gt;,&amp;lt;unit&amp;gt;,&amp;lt;value&amp;gt;,&amp;lt;icon&amp;gt;&amp;quot;, optional, default: &amp;quot;50,50,50,40,50,40&amp;quot;&lt;br /&gt;
$model     # &#039;&amp;lt;color gradient&amp;gt;,&amp;lt;min/max&amp;gt;,&amp;lt;inner ring&amp;gt;,&amp;lt;pointer&amp;gt;,&amp;lt;mode&amp;gt;&#039;&lt;br /&gt;
# &amp;lt;color gradient&amp;gt;: &amp;quot;gradient&amp;quot; (undef),&amp;quot;nogradient&amp;quot; (1)&lt;br /&gt;
# &amp;lt;min/max&amp;gt;: Style-SVG-Attribute oder &amp;quot;nominmaxvalue&amp;quot; (undef), &amp;quot;minmaxvalue&amp;quot; (1)&lt;br /&gt;
# &amp;lt;inner ring&amp;gt;: Style-SVG-Attribute oder &amp;quot;innerring&amp;quot; (1), &amp;quot;noinnerring&amp;quot; (undef)&lt;br /&gt;
# &amp;lt;pointer&amp;gt;: Breite des Zeigers in Pixel, &amp;quot;nopointer&amp;quot; (undef)&lt;br /&gt;
# &amp;lt;mode&amp;gt;: &amp;quot;minmax&amp;quot; (undef), &amp;quot;negzeropos&amp;quot; (1), &amp;quot;zeronegpos&amp;quot; (2)&lt;br /&gt;
# alle Parameter sind optional, default keine Angaben: &#039;,,,,,,&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Wird &#039;&#039;&#039;$colorRef&#039;&#039;&#039; nicht angegeben, so wird der Farbwert zwischen &#039;&#039;&#039;$minColor&#039;&#039;&#039; und &#039;&#039;&#039;$maxColor&#039;&#039;&#039; linear interpoliert&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_icon_ring DOIF ##&lt;br /&gt;
attr di_icon_ring uiTable {package ui_Table}\&lt;br /&gt;
\&lt;br /&gt;
icon_ring (&#039;sani_floor_heating_neutral&#039;,[Heizenergie:Vortag_hc],0,150,120,0,&#039;kWh&#039;)|\&lt;br /&gt;
icon_mring (&#039;fuel&#039;,[Tankstelle:Diesel],1.10,1.30,120,0,&#039;€&#039;,2)|\&lt;br /&gt;
icon_uring (&#039;0,1,1&#039;,&amp;quot;air&amp;quot;,[ESPEasy_Eingang_CO2:PPM],400,1200,undef,undef,&#039;ppm&#039;,0,100,[(600,120,1000,60,1200,0)])|\&lt;br /&gt;
icon_uring (&#039;0,1&#039;,&#039;Zisterne&#039;,([Wasserzisterne]/3.4),0,100,0,120,&#039;%&#039;,0)##/\&lt;br /&gt;
\&lt;br /&gt;
icon_uring (&#039;1,1,0,8&#039;,&amp;quot;measure_water_meter&amp;quot;,[Wasserverbrauch:heute],0,600,120,0,&#039;l&#039;,0)|\&lt;br /&gt;
icon_uring (&#039;0,fill:white,opacity:0.4&#039;,([vaillant:Pumpenstatus] eq &#039;4&#039; ? &#039;sani_buffer_temp_down@Darkorange&#039; : &#039;sani_buffer_temp_down@white&#039;),[vaillant:Umlaufmenge],0,20,120,0,&#039;l/min&#039;)|\&lt;br /&gt;
icon_uring(&#039;0,1,1,4&#039;,&#039;weather_barometric_pressure&#039;,[vaillant:Wasserdruck],0,3,undef,undef,&#039;bar&#039;,1,100,[(0.8,0,1,60,1.5,120,1.7,60,3,0)])|\&lt;br /&gt;
icon_uring(&#039;0,opacity:0.8,1,6&#039;,&#039;sani_water_tap&#039;,[vaillant:HwcHours_hoursum2_value],0,2000,120,0,&#039;h&#039;,0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:icon_ring_bsp.png|ohne|mini]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Farbskalierte Temperatur- und Feuchtigkeitsanzeige mit einem Icon mit Hilfe der SVG-Funktion &#039;&#039;&#039;icon_temp_hum_ring&#039;&#039;&#039; =====&lt;br /&gt;
Die Farbe ist jeweils abhängig vom dargestellten Temperatur- bzw. Feuchtigkeitswert. Die Helligkeit der Farbgebung ist einstellbar:&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;icon_temp_hum_ring&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
icon_temp_hum_ring ($icon,$temp_value,$hum_value,$temp_min,$temp_max,$size, $lightring,$lightnumber,$decFontTemp,$decFontHum)&lt;br /&gt;
&lt;br /&gt;
$icon      # &amp;quot;Iconname\@Farbe,Skalierungsfaktor,x-Position,y-Position,Rotation&amp;quot;, \@Farbe, Skalierungsfaktor, x-Position, y-Position, Rotation sind optional&lt;br /&gt;
$temp_value # Temperatur&lt;br /&gt;
$hum_value  # Feuchtigkeit&lt;br /&gt;
$temp_min   # minimale Temperatur, optional, default=-20&lt;br /&gt;
$temp_max   # maximale Temperatur, optional, default=60&lt;br /&gt;
$size       # Größe der Grafik, optional, default=90&lt;br /&gt;
$lightring   # Helligkeit des Ringes (0-100), optional, default=50&lt;br /&gt;
$lightnumber # Helligkeit der Zahl (0-100), optional, default=50&lt;br /&gt;
$decFontTemp # Temperatur: &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional&lt;br /&gt;
$decFontHum  # Feuchtigkeit: &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_icon_temp_hum_ring DOIF ##&lt;br /&gt;
attr di_icon_temp_hum_ring uiTable {package ui_Table}\&lt;br /&gt;
\&lt;br /&gt;
&amp;quot;normal&amp;quot;|icon_temp_hum_ring(&amp;quot;temp_outside&amp;quot;,[Aussensensor:temperature],[Aussensensor:humidity])\&lt;br /&gt;
&amp;quot;mit Normalschrift&amp;quot;|icon_temp_hum_ring(&amp;quot;temp_outside&amp;quot;,[Aussensensor:temperature],[Aussensensor:humidity], undef,undef,undef,undef,undef,&amp;quot;1,font-weight:normal&amp;quot;,&amp;quot;0,font-weight:normal&amp;quot;)\&lt;br /&gt;
&amp;quot;größer aufgehellt&amp;quot;|icon_temp_hum_ring(&amp;quot;temp_outside&amp;quot;,[Aussensensor:temperature],[Aussensensor:humidity], undef,undef,120,undef,80)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:icon_temp_hum_ring.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
===== Farbskalierte Anzeige von zwei Temperaturwerten mit einem Icon mit Hilfe der SVG-Funktion &#039;&#039;&#039;icon_temp_temp_ring&#039;&#039;&#039; =====&lt;br /&gt;
Die Farbe ist jeweils abhängig vom dargestellten Temperaturwert. Die Helligkeit der Farbgebung ist einstellbar:&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;icon_temp_temp_ring&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
icon_temp_temp_ring ($icon,$temp1_value,$temp2_value,$temp_min,$temp_max,$size, $lightring,$lightnumber,$decFontTemp1,$decFontTemp2)&lt;br /&gt;
&lt;br /&gt;
$icon        # &amp;quot;Iconname\@Farbe,Skalierungsfaktor,x-Position,y-Position,Rotation&amp;quot;, \@Farbe, Skalierungsfaktor, x-Position, y-Position, Rotation sind optional&lt;br /&gt;
$temp1_value # erster Temperaturwert&lt;br /&gt;
$temp2_value # zweiter Temperaturwert&lt;br /&gt;
$temp_min    # minimale Temperatur, optional, default=-20&lt;br /&gt;
$temp_max    # maximale Temperatur, optional, default=60&lt;br /&gt;
$size        # Größe der Grafik, optional, default=90&lt;br /&gt;
$lightring   # Helligkeit des Ringes (0-100), optional, default=50&lt;br /&gt;
$lightnumber # Helligkeit der Zahl (0-100), optional, default=50&lt;br /&gt;
$decFontTemp1 # Temperatur1: &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional&lt;br /&gt;
$decFontTemp2 # Temperatur2: &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_icon_temp_temp_ring DOIF ##&lt;br /&gt;
attr di_icon_temp_temp_ring uiTable {package ui_Table}\&lt;br /&gt;
## Größe 120%\&lt;br /&gt;
&amp;quot;FB-Heizung&amp;quot;|icon_temp_temp_ring(([vaillant:Pumpenstatus] eq &amp;quot;on&amp;quot; ? &amp;quot;sani_floor_heating\@Darkorange&amp;quot; : &amp;quot;sani_floor_heating_neutral\@white&amp;quot;),[ESPEasy_ESP_Temp_Vorlauf:Temperature],[ESPEasy_ESP_Temp_Keller_Ruecklauf:Temperature],15,70,120)\&lt;br /&gt;
\&lt;br /&gt;
## Größe 120%, Normalschrift\&lt;br /&gt;
&amp;quot;Temperatur&amp;quot;,&amp;quot;Taupunkt&amp;quot;|icon_temp_temp_ring(&amp;quot;temp_outside&amp;quot;,[Aussensensor:temperature],[Aussensensor:dewpoint],undef,undef,120,undef,undef,&amp;quot;1,font-weight:normal&amp;quot;,&amp;quot;1,font-weight:normal&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:icon_temp_temp_ring.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
===== Farbskalierte Anzeige von zwei Zahlenwerten mit einem Icon mit Hilfe der universellen SVG-Funktion &#039;&#039;&#039;icon_ring2&#039;&#039;&#039; =====&lt;br /&gt;
Die Farbe der dargestellten Werte kann abhängig vom Wert bestimmt werden.&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;icon_ring2&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
icon_ring2 ($icon,$value1,$min1,$max1,$minColor1,$maxColor1,$desc1,$size,$colorFunc1,$decFont1, $value2,$min2,$max2,$minColor2,$maxColor2,$desc2,$colorFunc2,$decFont2,$lightnesss,$model)&lt;br /&gt;
&lt;br /&gt;
$icon       # &amp;quot;Iconname\@Farbe,Skalierungsfaktor,x-Position,y-Position,Rotation&amp;quot;, \@Farbe, Skalierungsfaktor, x-Position, y-Position, Rotation sind optional&lt;br /&gt;
$value1     # darzustellender Wert1&lt;br /&gt;
$min1       # minimaler Wert, optional, default=0&lt;br /&gt;
$max1       # maximaler Wert, optional, default=100&lt;br /&gt;
$minColor1  # Farbe (hue: 0-360) des kleinsten Wertes, optional, default = undef&lt;br /&gt;
$maxColor1  # Farbe (hue: 0-360) des maximalen Wertes, optional, default = undef&lt;br /&gt;
$desc1      # Beschreibung des Wertes, optional, default = undef&lt;br /&gt;
$size       # Größe der Grafik, optional, default = 100&lt;br /&gt;
$colorFunc1 # Funktion, die zu einem Wert einen Farbwert (hue: 0-360) bestimmt, optional, default = undef&lt;br /&gt;
$decFont1   # &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;,&amp;quot;&amp;lt;Einheit hinter dem Zahlenwert&amp;gt;&amp;quot; optional&lt;br /&gt;
$value2     ## darzustellender Wert2&lt;br /&gt;
...&lt;br /&gt;
$desc2      # Beschreibung des Wertes, optional, default = undef&lt;br /&gt;
$colorFunc2 # Funktion, die zu einem Wert einen Farbwert (hue: 0-360) bestimmt, optional, default = undef&lt;br /&gt;
$decFont2   # &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;,&amp;quot;&amp;lt;Einheit hinter dem Zahlenwert&amp;gt;&amp;quot; optional&lt;br /&gt;
$lightness  # Helligkeit einzelner Elemente (0-100) &amp;quot;&amp;lt;ring&amp;gt;,&amp;lt;inner ring&amp;gt;,&amp;lt;minMax&amp;gt;,&amp;lt;unit&amp;gt;,&amp;lt;value&amp;gt;,&amp;lt;icon&amp;gt;&amp;quot;, optional, default: &amp;quot;50,50,50,40,50,40&amp;quot;&lt;br /&gt;
$model     # &#039;&amp;lt;color gradient&amp;gt;,&amp;lt;min/max&amp;gt;,&amp;lt;inner ring&amp;gt;,&amp;lt;pointer&amp;gt;,&amp;lt;mode&amp;gt;&#039;&lt;br /&gt;
# &amp;lt;color gradient&amp;gt;: &amp;quot;gradient&amp;quot; (undef),&amp;quot;nogradient&amp;quot; (1)&lt;br /&gt;
# &amp;lt;min/max&amp;gt;: Style-SVG-Attribute oder &amp;quot;nominmaxvalue&amp;quot; (undef), &amp;quot;minmaxvalue&amp;quot; (1)&lt;br /&gt;
# &amp;lt;inner ring&amp;gt;: Style-SVG-Attribute oder &amp;quot;innerring&amp;quot; (1), &amp;quot;noinnerring&amp;quot; (undef)&lt;br /&gt;
# &amp;lt;pointer&amp;gt;: Breite des Zeigers in Pixel, &amp;quot;nopointer&amp;quot; (undef)&lt;br /&gt;
# &amp;lt;mode&amp;gt;: &amp;quot;minmax&amp;quot; (undef), &amp;quot;negzeropos&amp;quot; (1), &amp;quot;zeronegpos&amp;quot; (2)&lt;br /&gt;
# alle Parameter sind optional, default keine Angaben: &#039;,,,,,,&#039;&lt;br /&gt;
Argumente für den zweiten Wert entsprechend den Argumenten des ersten Wertes&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Wird &#039;&#039;&#039;$colorFunc...&#039;&#039;&#039; nicht angegeben, so wird der Farbwert zwischen &#039;&#039;&#039;$minColor...&#039;&#039;&#039; und &#039;&#039;&#039;$maxColor...&#039;&#039;&#039; linear interpoliert.&lt;br /&gt;
&lt;br /&gt;
Bei der Farbangabe des Icons beim Übergabeparameter $icon wird mit &#039;&#039;&#039;\@colorVal2&#039;&#039;&#039; das Icon mit der Farbe des zweiten Wertes eingefärbt. Bei keiner Farbangabe oder &#039;&#039;&#039;\@colorVal1&#039;&#039;&#039; wird das Icon mit der Farbe des ersten Wertes eingefärbt. Ansonsten gilt die allgemeine FHEM-Syntax für Farbgebung von Icons angehängt mit &#039;&#039;&#039;\@&#039;&#039;&#039;.&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_icon_ring2 DOIF ##&lt;br /&gt;
attr di_icon_ring2 uiTable {package ui_Table;;\&lt;br /&gt;
\&lt;br /&gt;
sub himmelsrichtung {\&lt;br /&gt;
my ($richtung)=@_;;\&lt;br /&gt;
my $element=int($richtung/22.5);;\##/&lt;br /&gt;
my @h=(qw&amp;quot;N NNO NO ONO O OSO SO SSO S SSW SW WSW W WNW NW NNW&amp;quot;);;\&lt;br /&gt;
return($h[$element]);;\&lt;br /&gt;
}\&lt;br /&gt;
}\&lt;br /&gt;
&amp;quot;Wallbox&amp;quot;| icon_ring2(&amp;quot;car,1.5,0,-3&amp;quot;,[tesla:Leistung],0,3.6,120,0,&amp;quot;kW&amp;quot;,120,undef,&amp;quot;1,font-weight:normal&amp;quot;,[tesla:Kapazitaet],0,100,0,120,&amp;quot;%&amp;quot;,undef,&amp;quot;0,font-weight:normal&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
&amp;quot;Wind&amp;quot;|icon_ring2(([Wind:Geschwindigkeit]&amp;gt;0 ? &amp;quot;wind&amp;quot;:&amp;quot;no_wind&amp;quot;).&amp;quot;,1,0,0,&amp;quot;.[Wind:Richtung],[Wind:Geschwindigkeit],0,50,120,0,&amp;quot;km/h&amp;quot;,120,undef,1,[Wind:Richtung],361,361,220,220,([Wind:Geschwindigkeit]&amp;gt;0?himmelsrichtung([Wind:Richtung]):&amp;quot;--&amp;quot;),undef,0)\&lt;br /&gt;
\&lt;br /&gt;
&amp;quot;Strom&amp;quot;|icon_ring2([zaehler:l-Produktion] &amp;gt; 0 ? &amp;quot;sani_solar\@colorVal1&amp;quot;:&amp;quot;fa_bolt\@colorVal2&amp;quot;,[zaehler:l-Produktion],0,3.6,20,120,&amp;quot;PV kW&amp;quot;,150,undef,&amp;quot;1,,font-size:50%;fill:white&amp;quot;,[zaehler:l-Bezug,0],0,2,120,0,&amp;quot;Netz kW&amp;quot;,undef,&amp;quot;1,,font-size:50%;fill:white&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:icon_ring2.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;bar&#039;&#039;&#039;-Funktionen ====&lt;br /&gt;
===== Farbskalierte Anzeige der Temperatur in Balkenform mit Hilfe der SVG-Funktionen &#039;&#039;&#039;temp_bar/temp_mbar&#039;&#039;&#039; =====&lt;br /&gt;
Die Farbe der dargestellten Temperatur ist abhängig vom Temperaturwert. Die Helligkeit der Farbgebung ist einstellbar. Bei der &#039;&#039;&#039;temp_mbar&#039;&#039;&#039;-SVG-Funktion wird der Balken einfarbig dargestellt.&lt;br /&gt;
&lt;br /&gt;
Farbskalierung der &#039;&#039;&#039;temp_bar&#039;&#039;&#039;-SVG-Funktion:&lt;br /&gt;
[[Datei:Farbskalierung temp_bar_scaling.png|600px|ohne]]&lt;br /&gt;
&lt;br /&gt;
Farbskalierung der &#039;&#039;&#039;temp_mbar&#039;&#039;&#039;-SVG-Funktion:&lt;br /&gt;
[[Datei:Farbskalierung temp_mbar_scaling.png|600px|ohne]]&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;temp_bar/temp_mbar&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
temp_bar/temp_mbar ($temp_value,$temp_min,$temp_max, $header,$width,$height,$size, $light,$lightnumber,$decFont)&lt;br /&gt;
&lt;br /&gt;
$temp_value  # Temperaturwert&lt;br /&gt;
$temp_min    # minimale Temperatur, optional, default=-20&lt;br /&gt;
$temp_max    # maximale Temperatur, optional, default=60&lt;br /&gt;
$header      # Überschrift, optional, default= undef (keine)&lt;br /&gt;
$width       # Breite der Grafik, optional, default=63&lt;br /&gt;
$height      # Höhe der Grafik, optional, default=60&lt;br /&gt;
$size        # Größe der Grafik, optional, default=100&lt;br /&gt;
$light       # Helligkeit der Grafik (0-100), optional, default=50&lt;br /&gt;
$lightnumber # Helligkeit der Zahl (0-100), optional, default=50&lt;br /&gt;
$decFont     # &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional, default = 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_temp_bar DOIF ##&lt;br /&gt;
attr di_temp_bar uiTable {package ui_Table}\&lt;br /&gt;
&amp;quot;standard&amp;quot;|temp_bar([Aussensensor:temperature])\&lt;br /&gt;
&amp;quot;heller&amp;quot;|temp_bar([Aussensensor:temperature],undef,undef,undef,undef,undef,undef,80)\&lt;br /&gt;
&amp;quot;monochrom&amp;quot;|temp_mbar([Aussensensor:temperature])\&lt;br /&gt;
&amp;quot;kleiner&amp;quot;|temp_bar([Aussensensor:temperature],undef,undef,undef,undef,undef,80)\&lt;br /&gt;
&amp;quot;mit Überschrift&amp;quot;|temp_bar([Aussensensor:temperature],undef,undef,&amp;quot;Außen&amp;quot;)\&lt;br /&gt;
&amp;quot;hoch&amp;quot;|temp_bar([Aussensensor:temperature],undef,undef,undef,undef,100)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:temp_bar_bsp.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
===== Farbskalierte Anzeige der Feuchtigkeit in Balkenform mit Hilfe der SVG-Funktionen &#039;&#039;&#039;hum_bar/hum_mbar&#039;&#039;&#039; =====&lt;br /&gt;
Die Farbe der dargestellten Feuchtigkeit ist abhängig vom Feuchtigkeitswert. Die Helligkeit der Farbgebung ist einstellbar. Bei der &#039;&#039;&#039;hum_mbar&#039;&#039;&#039;-SVG-Funktion wird der Balken einfarbig dargestellt.&lt;br /&gt;
&lt;br /&gt;
Farbskalierung der &#039;&#039;&#039;hum_bar&#039;&#039;&#039;-SVG-Funktion:&lt;br /&gt;
[[Datei:Farbskalierung hum_bar_scaling.png|600px|ohne]]&lt;br /&gt;
&lt;br /&gt;
Farbskalierung der &#039;&#039;&#039;hum_mbar&#039;&#039;&#039;-SVG-Funktion:&lt;br /&gt;
[[Datei:Farbskalierung hum_mbar_scaling.png|600px|ohne]]&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;hum_bar/hum_mbar&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
hum_bar/hum_mbar ($hum_value,$header,$width,$height,$size, $light,$lightnumber,$decFont)&lt;br /&gt;
&lt;br /&gt;
$hum_value   # Feuchtigkeitswert&lt;br /&gt;
$header      # Überschrift, optional, default = undef (keine)&lt;br /&gt;
$width       # Breite der Grafik, optional, default=63&lt;br /&gt;
$height      # Höhe der Grafik, optional, default=80&lt;br /&gt;
$size        # Größe der Grafik, optional, default=100&lt;br /&gt;
$light       # Helligkeit des der Grafik (0-100), optional, default=50&lt;br /&gt;
$lightnumber # Helligkeit der Zahl (0-100), optional, default=50&lt;br /&gt;
$decFont     # &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional, default = 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_hum_bar DOIF ##&lt;br /&gt;
attr di_hum_bar uiTable {package ui_Table}\&lt;br /&gt;
&amp;quot;standard&amp;quot;|hum_bar([Aussensensor:humidity])\&lt;br /&gt;
&amp;quot;heller&amp;quot;|hum_bar([Aussensensor:humidity],undef,undef,undef,undef,80)\&lt;br /&gt;
&amp;quot;monochrom&amp;quot;|hum_mbar([Aussensensor:humidity])\&lt;br /&gt;
&amp;quot;kleiner&amp;quot;|hum_bar([Aussensensor:humidity],undef,undef,undef,80)\&lt;br /&gt;
&amp;quot;mit Überschrift&amp;quot;|hum_bar([Aussensensor:humidity],&amp;quot;Außen&amp;quot;)\&lt;br /&gt;
&amp;quot;hoch&amp;quot;|hum_bar([Aussensensor:humidity],undef,undef,100)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:hum_bar_bsp.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
===== Farbskalierte Anzeige eines Zahlenwertes mit Hilfe der universellen SVG-Funktion &#039;&#039;&#039;bar&#039;&#039;&#039; =====&lt;br /&gt;
Die Farbe des dargestellten Wertes kann abhängig vom Wert bestimmt werden.&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;bar&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
bar ($value,$min,$max,$header,$minColor,$maxColor,$unit,$width, $height,$size,$colorFunc,$decFont,$gradient,$light,$lightnumber)&lt;br /&gt;
&lt;br /&gt;
$value     # darzustellender Wert&lt;br /&gt;
$min       # minimaler Wert, optional, default=0&lt;br /&gt;
$max       # maximaler Wert, optional, default=100&lt;br /&gt;
$header    # Überschrift, optional, default = undef (keine)&lt;br /&gt;
$minColor  # Farbe (hue: 0-360) des kleinsten Wertes, optional, default = undef&lt;br /&gt;
$maxColor  # Farbe (hue: 0-360) des maximalen Wertes, optional, default = undef&lt;br /&gt;
$unit      # Einheit des Wertes, optional, default = undef&lt;br /&gt;
$width     # Breite der Grafik, optional, default = 63&lt;br /&gt;
$height    # Höhe der Grafik, optional, default = 60&lt;br /&gt;
$size      # Größe der Grafik, optional, default = 100&lt;br /&gt;
$colorFunc # Funktion, die zu einem Wert einen Farbwert (hue: 0-360) bestimmt, optional, default = undef&lt;br /&gt;
$decFont   # &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional, default = 1&lt;br /&gt;
$gradient  # Farbverlauf, optional, undef mit Farbverlauf, 1 ohne Farbverlauf, default = undef&lt;br /&gt;
$light     # Helligkeit der Grafik (light:0-100), optional, default=50&lt;br /&gt;
$lightnumber # Helligkeit der Zahl (light:0-100), optional, default=50&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Wird &#039;&#039;&#039;$colorFunc&#039;&#039;&#039; nicht angegeben, so wird der Farbwert zwischen &#039;&#039;&#039;$minColor&#039;&#039;&#039; und &#039;&#039;&#039;$maxColor&#039;&#039;&#039; linear interpoliert&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
{package ui_Table}&lt;br /&gt;
defmod di_bar DOIF ##&lt;br /&gt;
attr di_bar uiTable {package ui_Table}\&lt;br /&gt;
## von 0 bis 20 in Farben von grün (hue:120) bis rot (hue:0)\&lt;br /&gt;
&amp;quot;Umlaufmenge&amp;quot;|bar([heizung:Umlaufmenge],0,20,&amp;quot;Umlauf&amp;quot;,120,0,&amp;quot;l/min&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
## von 0 bis 3 in Farben von rot (hue:0) bis türkis (hue:180)\&lt;br /&gt;
&amp;quot;Wasserdruck&amp;quot;|bar([heizung:Wasserdruck],0,3,undef,0,180,&amp;quot;bar&amp;quot;undef,70,undef,undef,&amp;quot;1,font-size:130%;;font-weight:normal&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
## Temperaturdarstellung, entspricht dem Funktionsaufruf:\&lt;br /&gt;
## temp_bar ([Aussensensor:temperature],-20,60)\&lt;br /&gt;
&amp;quot;Temperatur&amp;quot;|bar([Aussensensor:temperature],-20,60,undef,undef,undef,&amp;quot;°C&amp;quot;,undef,undef,undef,\&amp;amp;temp_hue)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:bar_bsp.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;icon_bar&#039;&#039;&#039;-Funktionen ====&lt;br /&gt;
===== Farbskalierte Anzeige der Temperatur in Balkenform mit Hilfe der SVG-Funktion &#039;&#039;&#039;icon_temp_bar/icon_temp_mbar&#039;&#039;&#039; =====&lt;br /&gt;
Die Farbe der dargestellten Temperatur ist abhängig vom Temperaturwert. Die Helligkeit der Farbgebung ist einstellbar. Bei der &#039;&#039;&#039;icon_temp_mbar&#039;&#039;&#039;-SVG-Funktion wird der Balken einfarbig dargestellt.&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;icon_temp_bar/icon_temp_mbar&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
icon_temp_bar/icon_temp_mbar ($icon,$temp_value,$temp_min,$temp_max, $header,$width,$height,$size,$light,$lightnumber,$decFont)&lt;br /&gt;
&lt;br /&gt;
$icon        # &amp;quot;Iconname\@Farbe,Skalierungsfaktor,x-Position,y-Position&amp;quot;, \@Farbe, Skalierungsfaktor, x-Position, y-Position sind optional&lt;br /&gt;
$temp_value  # Temperaturwert&lt;br /&gt;
$temp_min    # minimale Temperatur, optional, default=-20&lt;br /&gt;
$temp_max    # maximale Temperatur, optional, default=60&lt;br /&gt;
$header      # Überschrift, optional, default= undef (keine)&lt;br /&gt;
$width       # Breite der Grafik, optional, default=63&lt;br /&gt;
$height      # Höhe der Grafik, optional, default=75&lt;br /&gt;
$size        # Größe der Grafik, optional, default=100&lt;br /&gt;
$light       # Helligkeit der Grafik (0-100), optional, default=50&lt;br /&gt;
$lightnumber # Helligkeit der Zahl (0-100), optional, default=50&lt;br /&gt;
$decFont     # &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional, default = 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_icon_temp_bar DOIF ##&lt;br /&gt;
attr di_icon_temp_bar room test10&lt;br /&gt;
attr di_icon_temp_bar uiTable {package ui_Table}\&lt;br /&gt;
&amp;quot;standard&amp;quot;|icon_temp_bar(&amp;quot;temp_outside&amp;quot;,[Aussensensor:temperature])\&lt;br /&gt;
&amp;quot;heller&amp;quot;|icon_temp_bar(&amp;quot;temp_outside&amp;quot;,[Aussensensor:temperature],undef,undef,undef,undef,undef,undef,80)\&lt;br /&gt;
&amp;quot;monochrom&amp;quot;|icon_temp_mbar(&amp;quot;temp_outside&amp;quot;,[Aussensensor:temperature])\&lt;br /&gt;
&amp;quot;kleiner&amp;quot;|icon_temp_bar(&amp;quot;temp_outside&amp;quot;,[Aussensensor:temperature],undef,undef,undef,undef,undef,80)\&lt;br /&gt;
&amp;quot;mit Überschrift&amp;quot;|icon_temp_bar(&amp;quot;temp_outside&amp;quot;,[Aussensensor:temperature],undef,undef,&amp;quot;Außen&amp;quot;)\&lt;br /&gt;
&amp;quot;hoch&amp;quot;|icon_temp_bar(&amp;quot;temp_outside&amp;quot;,[Aussensensor:temperature],undef,undef,undef,undef,100)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:icon_temp_bar_bsp.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
===== Farbskalierte Anzeige der Feuchtigkeit in Balkenform mit Hilfe der SVG-Funktionen &#039;&#039;&#039;icon_hum_bar/icon_hum_mbar&#039;&#039;&#039; =====&lt;br /&gt;
Die Farbe der dargestellten Feuchtigkeit ist abhängig vom Feuchtigkeitswert. Die Helligkeit der Farbgebung ist einstellbar. Bei der &#039;&#039;&#039;icon_hum_mbar&#039;&#039;&#039;-SVG-Funktion wird der Balken einfarbig dargestellt.&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;icon_hum_bar/icon_hum_mbar&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
icon_hum_bar/icon_hum_mbar ($icon,$hum_value,$header,$width,$height,$size, $light,$lightnumber,$decFont)&lt;br /&gt;
&lt;br /&gt;
$icon        # &amp;quot;Iconname\@Farbe,Skalierungsfaktor,x-Position,y-Position&amp;quot;, \@Farbe, Skalierungsfaktor, x-Position, y-Position sind optional&lt;br /&gt;
$hum_value   # Temperaturwert&lt;br /&gt;
$header      # Überschrift, optional, default = undef (keine)&lt;br /&gt;
$width       # Breite der Grafik, optional, default=63&lt;br /&gt;
$height      # Höhe der Grafik, optional, default=75&lt;br /&gt;
$size        # Größe der Grafik, optional, default=100&lt;br /&gt;
$light       # Helligkeit des der Grafik (0-100), optional, default=50&lt;br /&gt;
$lightnumber # Helligkeit der Zahl (0-100), optional, default=50&lt;br /&gt;
$decFont     # &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional, default = 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_icon_hum_bar DOIF ##&lt;br /&gt;
attr di_icon_hum_bar uiTable {package ui_Table}\&lt;br /&gt;
&amp;quot;standard&amp;quot;|icon_hum_bar(&amp;quot;temperature_humidity&amp;quot;,[Aussensensor:humidity])\&lt;br /&gt;
&amp;quot;heller&amp;quot;|icon_hum_bar(&amp;quot;temperature_humidity&amp;quot;,[Aussensensor:humidity],undef,undef,undef,undef,80)\&lt;br /&gt;
&amp;quot;monochrom&amp;quot;|icon_hum_mbar(&amp;quot;temperature_humidity&amp;quot;,[Aussensensor:humidity])\&lt;br /&gt;
&amp;quot;kleiner&amp;quot;|icon_hum_bar(&amp;quot;temperature_humidity&amp;quot;,[Aussensensor:humidity],undef,undef,undef,80)\&lt;br /&gt;
&amp;quot;mit Überschrift&amp;quot;|icon_hum_bar(&amp;quot;temperature_humidity&amp;quot;,[Aussensensor:humidity],&amp;quot;Außen&amp;quot;)\&lt;br /&gt;
&amp;quot;hoch&amp;quot;|icon_hum_bar(&amp;quot;temperature_humidity&amp;quot;,[Aussensensor:humidity],undef,undef,100)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:icon_hum_bar_bsp.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
===== Farbskalierte Anzeige eines Zahlenwertes mit Hilfe der universellen SVG-Funktionen &#039;&#039;&#039;icon_bar/icon_mbar&#039;&#039;&#039; =====&lt;br /&gt;
Die Farbe des dargestellten Wertes und des Icons kann abhängig vom Wert bestimmt werden. Bei der &#039;&#039;&#039;icon_mbar&#039;&#039;&#039;-SVG-Funktion wird der Balken einfarbig dargestellt.&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;icon_bar/icon_mbar&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
icon_bar ($icon,$value,$min,$max,$minColor,$maxColor,$unit,$decfont,$header,$width,$height,$size, $colorFunc,$light,$lightnumber)&lt;br /&gt;
&lt;br /&gt;
$icon      # &amp;quot;Iconname\@Farbe,Skalierungsfaktor,x-Position,y-Position,Rotation&amp;quot;, \@Farbe, Skalierungsfaktor, x-Position, y-Position, Rotation (0-360) sind optional&lt;br /&gt;
$value     # darzustellender Wert&lt;br /&gt;
$min       # minimaler Wert, optional, default=0&lt;br /&gt;
$max       # maximaler Wert, optional, default=100&lt;br /&gt;
$header    # Überschrift, optional, default = undef (keine)&lt;br /&gt;
$minColor  # Farbe (hue: 0-360) des kleinsten Wertes, optional, default = undef&lt;br /&gt;
$maxColor  # Farbe (hue: 0-360) des maximalen Wertes, optional, default = undef&lt;br /&gt;
$unit      # Einheit des Wertes, optional, default = undef&lt;br /&gt;
$decFont   # &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Schrift-SVG-Attribute Wert&amp;gt;,&amp;lt;Schrift-SVG-Attribute Einheit&amp;gt;&amp;quot;, optional, default = 1&lt;br /&gt;
$width     # Breite der Grafik, optional, default = 63&lt;br /&gt;
$height    # Höhe der Grafik, optional, default = 75&lt;br /&gt;
$size      # Größe der Grafik, optional, default = 100&lt;br /&gt;
$colorFunc # Funktion, die zu einem Wert einen Farbwert (hue: 0-360) bestimmt, optional, default = undef&lt;br /&gt;
$light     # Helligkeit der Grafik (light:0-100), optional, default=50&lt;br /&gt;
$lightnumber # Helligkeit der Zahl (light:0-100), optional, default=50&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Wird &#039;&#039;&#039;$colorFunc&#039;&#039;&#039; nicht angegeben, so wird der Farbwert zwischen &#039;&#039;&#039;$minColor&#039;&#039;&#039; und &#039;&#039;&#039;$maxColor&#039;&#039;&#039; linear interpoliert&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_icon_bar_bsp DOIF ##&lt;br /&gt;
attr di_icon_bar_bsp uiTable {package ui_Table;;\&lt;br /&gt;
}\&lt;br /&gt;
icon_bar (&amp;quot;fuel&amp;quot;,[Tankstelle:Diesel],1.10,1.30,120,0,&amp;quot;€&amp;quot;,2)|\&lt;br /&gt;
icon_bar (&amp;quot;air&amp;quot;,[ESPEasy_Eingang_CO2:PPM],400,1200,120,0,&amp;quot;ppm&amp;quot;,0)|\&lt;br /&gt;
icon_bar (&amp;quot;Zisterne&amp;quot;,([Wasserzisterne]/3.4),0,100,0,120,&amp;quot;%&amp;quot;,0)|\&lt;br /&gt;
icon_bar (([vaillant:Pumpenstatus] eq &amp;quot;off&amp;quot; ? &amp;quot;sani_buffer_temp_down\@Darkorange&amp;quot; : &amp;quot;sani_buffer_temp_down\@white&amp;quot;),[vaillant:Umlaufmenge],0,20,120,0,&amp;quot;l/min&amp;quot;)\&lt;br /&gt;
icon_bar (&amp;quot;measure_water_meter&amp;quot;,[Wasserverbrauch:heute],0,600,120,0,&amp;quot;l&amp;quot;,0)|\&lt;br /&gt;
icon_bar (&amp;quot;weather_barometric_pressure&amp;quot;,[vaillant:Wasserdruck],0,3,0,180,&amp;quot;bar&amp;quot;)|\&lt;br /&gt;
icon_bar (&amp;quot;sani_water_tap&amp;quot;,[vaillant:HwcHours_hoursum2_value],0,2000,120,0,&amp;quot;h&amp;quot;,0)|\&lt;br /&gt;
icon_bar (&amp;quot;sani_floor_heating_neutral&amp;quot;,[Heizenergie:Vortag_hc],0,150,120,0,&amp;quot;kWh&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:icon_bar_bsp.png|ohne|mini]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Anzeige eines Werteverlaufs und des aktuellen Wertes mit Hilfe der SVG-Funktion &#039;&#039;&#039;card&#039;&#039;&#039; ====&lt;br /&gt;
Es wird der aktuelle Wert eines Readings, sein zeitlicher Verlauf sowie der maximale und minimale Wert in Form einer Informationskarte visualisiert. Das Erscheinungsbild kann über zahlreiche Parameter individualisiert werden. Die Besonderheit ist das Argument &#039;&#039;&#039;&amp;lt;collect type&amp;gt;&#039;&#039;&#039; bei der Angabe des Readings der Form &#039;&#039;&#039;[&amp;lt;Device&amp;gt;:&amp;lt;Reading&amp;gt;:&amp;lt;collect type]&#039;&#039;&#039;. Dadurch werden Daten des Readings im DOIF-Modul gesammelt und für die Erzeugung eines Graphen zur Verfügung gestellt - es sind keine weiteren Definitionen erforderlich. Dabei wird besonders sparsam mit der Datensammlung umgegangen. Die gesammelten Daten werden über den FHEM-Befehl &#039;&#039;&#039;save&#039;&#039;&#039; in versteckten Readings des jeweiligen DOIF-Moduls gespeichert.&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;card&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
card ($collect,$header,$icon,$min,$max,$minColor,$maxColor, $desc,$colorRef,$decFontUnit,$prop,$ringModel,$lightness, $collect2,$min2,$max2,$minColor2,$maxColor2,$desc2,$func2,$decFontUnit2)&lt;br /&gt;
&lt;br /&gt;
$collect/$collect2  &lt;br /&gt;
# Angabe eines Readings oder eines Arrays mit mehreren Readings der Form [&amp;lt;Device&amp;gt;:&amp;lt;Reading&amp;gt;:&amp;lt;collect type&amp;gt;:&amp;lt;output&amp;gt;], mit Hilfe des Argumentes &amp;lt;collect type&amp;gt; wird das Modul angewiesen Daten des Readings über einen bestimmten Zeitraum zu sammeln. Sollen Werte aus einem Array nur im Ring angezeigt werden und nicht Diagramm visualisiert werden, so wird das &amp;lt;collect type&amp;gt; nicht angegeben. Dabei können pro Wert eigene ring-Formatierungen vorgenommen werden. Mindestens ein Reading muss mit &amp;lt;collect type&amp;gt; angegeben werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;collect type&amp;gt;&lt;br /&gt;
# Darstellung kontinuierlicher Daten als Linie&lt;br /&gt;
col&amp;lt;number&amp;gt;&amp;lt;timeFormat&amp;gt; &lt;br /&gt;
# &amp;lt;timeFormat&amp;gt;: d Tage, w Wochen, ohne Angabe des Zeitformates wird &amp;lt;Anzahl&amp;gt; in Stunden interpretiert. &lt;br /&gt;
# Beispiele: col (entspricht col24), col1, col12, col1d, col3d, col1w, col4w, col52w usw.&lt;br /&gt;
&lt;br /&gt;
# Darstellung eines Wertes als Säule eines bestimmten Zeitraum (Stunde, Tag, Monat, Jahr)&lt;br /&gt;
bar/barAvg&amp;lt;number&amp;gt;&amp;lt;period&amp;gt;&amp;lt;timeOffset&amp;gt;&lt;br /&gt;
# &amp;lt;number&amp;gt;: Anzahl der Perioden&lt;br /&gt;
# &amp;lt;period&amp;gt;: Art der Periode: day, week, month, year, decade&lt;br /&gt;
# bei day werden 24 Stunden als Balken dargestellt,&lt;br /&gt;
# bei week werden 7 Tage (Mo bis So) der Woche dargestellt,&lt;br /&gt;
# bei month werden bis 31 Tage des Monats dargestellt,&lt;br /&gt;
# bei year werden 12 Monate des Jahres dargestellt,&lt;br /&gt;
# bei decade werden 10 Jahre eines Jahrzehnts (Dekade) dargestellt.&lt;br /&gt;
# &amp;lt;timeOffset&amp;gt;: Zeitverschiebung in Sekunden (positive Zahlen in die Zukunft, neg. Zahlen in die Vergangenheit)&lt;br /&gt;
# Anmerkung: Im optimalen Fall wird im angegebenen Zeitraum (Stunde (Periode day), Tag (Periode week oder month), Monat (Periode year), Jahr (Periode decade)) nur ein Wert per Event geliefert, werden mehrere Events geliefert, so wird der letzte Wert des Zeitraum übernommen. Bei barAvg werden wird dagegen der Mittelwert der gelieferten Daten einer Periode gebildet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;output&amp;gt; &lt;br /&gt;
# Der Wert des Readings kann über den optionalen output-Parameter mit Hilfe von Perl verändert werden&lt;br /&gt;
# Beispiel, der Wert on des Readings soll auf 1 abgebildet werden, sonst auf 0: $_ eq &amp;quot;on&amp;quot; ? 1 : 0&lt;br /&gt;
 &lt;br /&gt;
$header    # &amp;quot;&amp;lt;Überschrifttext,&amp;lt;Style-SVG-Text-Attribute&amp;gt;&amp;quot;, optional&lt;br /&gt;
$icon      # &amp;quot;Iconname\@Farbe,Skalierungsfaktor,x-Position,y-Position,Rotation&amp;quot;, \@Farbe, Skalierungsfaktor, x-Position, y-Position, Rotation sind optional&lt;br /&gt;
$min       # minimaler Wert, optional, default=0&lt;br /&gt;
$max       # maximaler Wert, optional, default=100&lt;br /&gt;
$minColor  # Farbe (hue: 0-360) des kleinsten Wertes, optional, default = 0 (rot)&lt;br /&gt;
$maxColor  # Farbe (hue: 0-360) des maximalen Wertes, optional, default = 120 (grün)&lt;br /&gt;
$desc      &lt;br /&gt;
# Beschreibung des Wertes, optional, default = undef, falls unter $collect ein Array für mehrere Readings angegeben wurde, so werden hier als Array die entsprechenden Beschreibungen angegeben, zusätzlich kann kommagetrennt pro Einheit Farbe des Graphen angegeben werden&lt;br /&gt;
&lt;br /&gt;
$colorRef  &lt;br /&gt;
# Referenz auf eine Funktion, die zu einem Wert einen Farbwert (hue: 0-360) bestimmt, oder eine Referenz auf eine Arrayliste mit Grenzwerten und Farben, optional, default = undef&lt;br /&gt;
&lt;br /&gt;
$decFontUnit&lt;br /&gt;
# &amp;quot;&amp;lt;Anzahl der Nachkommastellen&amp;gt;,&amp;lt;Style-SVG-Attribute Wert&amp;gt;,&amp;lt;Style-SVG-Attribute Einheit&amp;gt;,&amp;lt;Einheit hinter dem Zahlenwert&amp;gt;&amp;quot;, optional&lt;br /&gt;
&lt;br /&gt;
$prop      &lt;br /&gt;
# Eigenschaft von card: &amp;quot;&amp;lt;size&amp;gt;,&amp;lt;y-scaling&amp;gt;,&amp;lt;steps&amp;gt;,&amp;lt;footer&amp;gt;,&amp;lt;color_y_scale&amp;gt;,&amp;lt;ring&amp;gt;,&amp;lt;width&amp;gt;&amp;quot;, optional&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;size&amp;gt;: Größe der der Karte, default = 130,&lt;br /&gt;
# &amp;lt;y-scaling&amp;gt;: &amp;quot;fixedscaling&amp;quot; (1), &amp;quot;autoscaling&amp;quot; (undef)&lt;br /&gt;
# &amp;lt;steps&amp;gt;: &amp;quot;steps&amp;quot; (1),&amp;quot;nosteps&amp;quot; (undef)&lt;br /&gt;
# &amp;lt;footer&amp;gt;: &amp;quot;footer&amp;quot; (undef),&amp;quot;nofooter&amp;quot; (1)&lt;br /&gt;
# &amp;lt;color_y_scale&amp;gt;: &amp;quot;ycolor&amp;quot; (undef), &amp;quot;noycolor&amp;quot; (1)&lt;br /&gt;
# &amp;lt;ring&amp;gt;: &amp;quot;ring&amp;quot; (undef), &amp;quot;noring&amp;quot; (0), &amp;quot;halfring&amp;quot; (1)&lt;br /&gt;
# &amp;lt;width&amp;gt;: Breite der Karte, default: 160&lt;br /&gt;
&lt;br /&gt;
$ringModel&lt;br /&gt;
# &#039;&amp;lt;color gradient&amp;gt;,&amp;lt;min/max&amp;gt;,&amp;lt;inner ring&amp;gt;,&amp;lt;pointer&amp;gt;,&amp;lt;mode&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;color gradient&amp;gt;: &amp;quot;gradient&amp;quot; (undef),&amp;quot;nogradient&amp;quot; (1)&lt;br /&gt;
# &amp;lt;min/max&amp;gt;: Style-SVG-Attribute oder &amp;quot;nominmaxvalue&amp;quot; (undef), &amp;quot;minmaxvalue&amp;quot; (1)&lt;br /&gt;
# &amp;lt;inner ring&amp;gt;: Style-SVG-Attribute oder &amp;quot;innerring&amp;quot; (1), &amp;quot;noinnerring&amp;quot; (undef)&lt;br /&gt;
# &amp;lt;pointer&amp;gt;: Breite des Zeigers in Pixel, &amp;quot;nopointer&amp;quot; (undef)&lt;br /&gt;
# &amp;lt;mode&amp;gt;: &amp;quot;minmax&amp;quot; (undef), &amp;quot;negzeropos&amp;quot; (1), &amp;quot;zeronegpos&amp;quot; (2)&lt;br /&gt;
# alle Parameter sind optional, default keine Angaben: &#039;,,,,,,&#039;&lt;br /&gt;
&lt;br /&gt;
$lightness &lt;br /&gt;
# Helligkeit einzelner Elemente (0-100) &amp;quot;&amp;lt;ring&amp;gt;,&amp;lt;inner ring&amp;gt;,&amp;lt;minMax&amp;gt;,&amp;lt;unit&amp;gt;,&amp;lt;value&amp;gt;,&amp;lt;icon&amp;gt;&amp;quot;, optional, default: &amp;quot;50,50,50,40,50,40&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$collect2  # optionale Angaben für ein zweites Reading&lt;br /&gt;
$min       # restliche Parameter&lt;br /&gt;
$max       # entsprechen der Syntax&lt;br /&gt;
...        # des ersten Sensors&lt;br /&gt;
$decFontUnit2 # &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Wird &#039;&#039;&#039;$colorRef&#039;&#039;&#039; nicht angegeben, so wird der Farbwert zwischen &#039;&#039;&#039;$minColor&#039;&#039;&#039; und &#039;&#039;&#039;$maxColor&#039;&#039;&#039; linear interpoliert&lt;br /&gt;
Werden mehrere Readings angegeben, so müssen sie alle die gleiche Zeitspanne besitzen (Zeitangabe bei col)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nützliche Links&#039;&#039;&#039;&lt;br /&gt;
* Anwendungsbeispiel [[DOIF/uiTable_Schnelleinstieg#Visualisierung:_Wetterstation|Wetterstation]]&lt;br /&gt;
* Anwendungsbeispiel [[DOIF/uiTable_Schnelleinstieg#Visualisierung:_aktueller_Spritpreis|Spritpreise]]&lt;br /&gt;
* Anwendungsbeispiel [[DOIF/uiTable_Schnelleinstieg#Visualisierung_und_Steuerung:_Heiztherme|Heiztherme]]&lt;br /&gt;
* svg-Funktion [[DOIF/uiTable_Schnelleinstieg#Farbskalierte_Anzeige_eines_Icons_mit_einem_Zahlenwert_mit_Hilfe_der_universellen_SVG-Funktion_icon_ring.2Ficon_mring.2Ficon_uring|icon_ring]] &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=====&amp;lt;big&amp;gt;Darstellung kontinuierlicher Daten als Linie&amp;lt;/big&amp;gt;=====&lt;br /&gt;
Es folgen einige Beispiele für die Darstellung von Readings mit Hilfe des Darstellungstyps &#039;&#039;&#039;col&#039;&#039;&#039;, deren Werte sich per Event kontinuierlich verändern.&lt;br /&gt;
&lt;br /&gt;
======&amp;lt;big&amp;gt;Darstellung eines Readingwertes&amp;lt;/big&amp;gt;======&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_collect DOIF ##&lt;br /&gt;
attr di_collect uiTable {package ui_Table;;}\&lt;br /&gt;
card([Aussensensor:temperature:col12],&amp;quot;Außen&amp;quot;,&amp;quot;temp_outside&amp;quot;,-10,45,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue,undef)|\&lt;br /&gt;
card([Tankstelle:Diesel:col12],&amp;quot;Sprit,fill:darkorange&amp;quot;,&amp;quot;fuel&amp;quot;,&amp;quot;1.00&amp;quot;,&amp;quot;1.40&amp;quot;,120,0,&amp;quot;Diesel €&amp;quot;,undef,&amp;quot;2&amp;quot;,&amp;quot;,,1&amp;quot;)\&lt;br /&gt;
card([zaehler:l-Produktion:col12],undef,[zaehler:l-Produktion] &amp;gt; 0 ? &amp;quot;sani_solar\@colorVal1&amp;quot;:&amp;quot;fa_bolt\@colorVal2&amp;quot;,0,3.6,30,60,&amp;quot;PV kW&amp;quot;,undef,&amp;quot;1,,font-size:50%&amp;quot;)|\&lt;br /&gt;
card([ESPEasy_Eingang_CO2:PPM:col12],undef,&amp;quot;air&amp;quot;,400,1200,120,0,&amp;quot;ppm&amp;quot;,[600,120,1000,60,1200,0],0,undef,&#039;0,1,1&#039;,&amp;quot;50,35,45,35,50,35&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:svgcard.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
======&amp;lt;big&amp;gt;Anpassung des Layouts&amp;lt;/big&amp;gt;======&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_cards DOIF {}&lt;br /&gt;
attr di_cards uiTable {package ui_Table;;}\&lt;br /&gt;
&amp;quot;Standard&amp;quot;|\&lt;br /&gt;
card([Aussensensor:temperature:col],undef,&amp;quot;temp_outside&amp;quot;,-10,50,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue,&amp;quot;1&amp;quot;,&amp;quot;130&amp;quot;)\&lt;br /&gt;
&amp;quot;mit Halbring&amp;quot;|\&lt;br /&gt;
card([Aussensensor:temperature:col],&amp;quot;Außen&amp;quot;,&amp;quot;temp_outside&amp;quot;,-10,50,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue,&amp;quot;1&amp;quot;,&amp;quot;130,,,,,1&amp;quot;)\&lt;br /&gt;
&amp;quot;mit Halbring&amp;quot;,&amp;quot;ohne Fußzeile&amp;quot;,&amp;quot;Breite 110&amp;quot;|\&lt;br /&gt;
card([Aussensensor:temperature:col],&amp;quot;Außen&amp;quot;,&amp;quot;temp_outside&amp;quot;,-10,50,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue,&amp;quot;1&amp;quot;,&amp;quot;130,,,1,,1,110&amp;quot;)\&lt;br /&gt;
&amp;quot;Standard&amp;quot;,&amp;quot;Breite 200&amp;quot;|\&lt;br /&gt;
card([Aussensensor:temperature:col],&amp;quot;Außen&amp;quot;,&amp;quot;temp_outside&amp;quot;,-10,50,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue,&amp;quot;1&amp;quot;,&amp;quot;130,,,,,,200&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:di_card_variations.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
======&amp;lt;big&amp;gt;Darstellung zwei Readingwerte mit unterschiedlichen Einheiten&amp;lt;/big&amp;gt;======&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_cards DOIF {}&lt;br /&gt;
attr di_cards uiTable {package ui_Table;;}\&lt;br /&gt;
&amp;quot;Standard&amp;quot;|\&lt;br /&gt;
card([Aussensensor:temperature:col],&amp;quot;Außen&amp;quot;,&amp;quot;temp_outside&amp;quot;,-10,60,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue,&amp;quot;1&amp;quot;,&amp;quot;130,,,,&amp;quot;,undef,undef,[outsensor:humidity:col],0,100,undef,undef,&amp;quot;%&amp;quot;,\&amp;amp;hum_hue,&amp;quot;0&amp;quot;)\&lt;br /&gt;
&amp;quot;ohne Header&amp;quot;|\&lt;br /&gt;
card([Aussensensor:temperature:col],undef,&amp;quot;temp_outside&amp;quot;,-10,60,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue,&amp;quot;1&amp;quot;,&amp;quot;130,,,,&amp;quot;,undef,undef,[outsensor:humidity:col],0,100,undef,undef,&amp;quot;%&amp;quot;,\&amp;amp;hum_hue,&amp;quot;0&amp;quot;)\&lt;br /&gt;
&amp;quot;ohne Header&amp;quot;,&amp;quot;ohne Fußzeile&amp;quot;|card([Aussensensor:temperature:col],undef,&amp;quot;temp_outside&amp;quot;,-10,60,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue,&amp;quot;1&amp;quot;,&amp;quot;130,,,1,&amp;quot;,undef,undef,[outsensor:humidity:col],0,100,undef,undef,&amp;quot;%&amp;quot;,\&amp;amp;hum_hue,&amp;quot;0&amp;quot;)\&lt;br /&gt;
&amp;quot;Als Halbring&amp;quot;|\&lt;br /&gt;
card([Aussensensor:temperature:col],&amp;quot;Außen&amp;quot;,&amp;quot;temp_outside&amp;quot;,-10,60,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue,&amp;quot;1&amp;quot;,&amp;quot;130,,,,,1&amp;quot;,undef,undef,[outsensor:humidity:col],0,100,undef,undef,&amp;quot;%&amp;quot;,\&amp;amp;hum_hue,&amp;quot;0&amp;quot;)\&lt;br /&gt;
&amp;quot;ohne Fußzeile&amp;quot;|\&lt;br /&gt;
card([Aussensensor:temperature:col],&amp;quot;Außen&amp;quot;,&amp;quot;temp_outside&amp;quot;,-10,60,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue,&amp;quot;1&amp;quot;,&amp;quot;130,,,1,,1&amp;quot;,undef,undef,[outsensor:humidity:col],0,100,undef,undef,&amp;quot;%&amp;quot;,\&amp;amp;hum_hue,&amp;quot;0&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:di_card_collect2.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
======&amp;lt;big&amp;gt;Darstellung mehrerer Readingwerte mit gleicher Einheit&amp;lt;/big&amp;gt;======&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod Sprit DOIF ##&lt;br /&gt;
attr Sprit uiTable {package ui_Table;;}\&lt;br /&gt;
card([[Tankstelle:SuperE5:col3d],[Tankstelle:Diesel:col3d]],undef,&amp;quot;fuel\@silver&amp;quot;,1.40,1.9,120,0,[&amp;quot;E10&amp;quot;,&amp;quot;Diesel&amp;quot;],undef,&amp;quot;2,,fill:silver, €&amp;quot;,&amp;quot;130,autoscaling,steps,footer,ycolor,ring,200&amp;quot;,undef,undef)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:di_Sprit2.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod PV DOIF {}&lt;br /&gt;
attr PV DOIF_Readings l_Eigenv: [zaehler:l-Produktion]-[zaehler:l-Lieferung],\&lt;br /&gt;
Eigenv:[zaehler:Produktion]-[zaehler:Lieferung],\&lt;br /&gt;
l_Verbrauch: [zaehler:l-Bezug,0]+[$SELF:l_Eigenv,0],\&lt;br /&gt;
Verbrauch:[zaehler:Bezug]+[$SELF:Eigenv],\&lt;br /&gt;
l_Bezug:-[zaehler:l-Bezug]&lt;br /&gt;
attr PV uiTable {\&lt;br /&gt;
 package ui_Table;;\&lt;br /&gt;
 $SHOWNOSTATE=1;;\&lt;br /&gt;
}\&lt;br /&gt;
card([[zaehler:l-Produktion:col],[$SELF:l_Eigenv:col],[$SELF:l_Bezug:col]],&amp;quot;kW&amp;quot;,&amp;quot;fa_bolt\@silver&amp;quot;,-3.6,3.6,0,90,[&amp;quot;Solar&amp;quot;,&amp;quot;Eigen.&amp;quot;,&amp;quot;Bezug&amp;quot;],[(-1,0,0,30,1,60,3.6,90)],&amp;quot;2&amp;quot;,&amp;quot;167,,1,,,1&amp;quot;,&amp;quot;,,1,6&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:di_card_energie.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
======&amp;lt;big&amp;gt;Darstellung mehrerer Readingwerte mit einfarbigen Graphen&amp;lt;/big&amp;gt;======&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_heating DOIF {}&lt;br /&gt;
attr di_heating uiTable {\&lt;br /&gt;
  package ui_Table;;\&lt;br /&gt;
}\&lt;br /&gt;
card([[ESPEasy_ESP_Temp_Vorlauf:Temperature:col],[ESPEasy_ESP_Temp_Keller_Ruecklauf:Temperature:col]],&amp;quot;Umwälzpumpe&amp;quot;,([vaillant:Pumpenstatus] eq &amp;quot;on&amp;quot; ? &amp;quot;sani_floor_heating\@Darkorange&amp;quot; : &amp;quot;sani_floor_heating_neutral\@white&amp;quot;),15,70,undef,undef,[&amp;quot;Vor. °C,red&amp;quot;,&amp;quot;Rück. °C,#287afc&amp;quot;],\&amp;amp;temp_hue,undef,&amp;quot;,,1,,1&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:di_card_pump.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
======&amp;lt;big&amp;gt;Darstellung mehrere Readingwerte mit und ohne Verlaufvisualisierung&amp;lt;/big&amp;gt;======&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;card mit Zusatzinformationen, die nicht im Plot erscheinen&#039;&#039;&#039;&lt;br /&gt;
*Die col-Angabe kann bei Readingsangaben ausgelassen werden, dann werden die Daten dieses Readings nicht gesammelt und erscheinen nur in den Ringen in der Kopfzeile, nicht aber im Hauptring, nicht im Plot und nicht in der Fußzeile. Mindestens ein Reading einer card muss col-Angaben beinhalten.&lt;br /&gt;
*Für collect bzw. collect2 können beliebig viele Werte angegeben werden.&lt;br /&gt;
*In card gibt es nur einen Hauptring mit einem Wert oder als Doppelring mit zwei Werten, alle weiteren Werte landen als Halbringe in der Kopfzeile. Wenn eine 1 beim Parameter hring angegeben wird, so werden alle Werte als Halbring in der Kopfzeile dargestellt, es gibt dann keinen Hauptring.&lt;br /&gt;
*Die ersten beiden Werte mit col-Angaben aus collect werden im Doppelring angezeigt, alle weiteren landen in Halbringen in der Kopfzeile; wenn collect nur einen Wert hat und collect2 mehrere, dann wird der erste Wert von collect und der erste Wert von collect2 im Doppelring angezeigt, die restlichen von collect2 landen in Halbringen der Kopfzeile.&lt;br /&gt;
*Bei einer Card mit Standardbreite können maximal 6 Werte angezeigt werden. Zwei im Doppelring und vier in Halbringen in der Kopfzeile. Möchte man mehr als 6 Werte anzeigen, dann muss man die Breite von card vergrößern, damit mehr als vier Halbringe in der Kopfzeile Platz finden.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_energie DOIF {}&lt;br /&gt;
attr di_energie uiTable {\&lt;br /&gt;
  package ui_Table;;\&lt;br /&gt;
}\&lt;br /&gt;
card([[$SELF:power_pv:144col1d],[$SELF:power_fc:144col1d]],&amp;quot;&amp;quot;,&amp;quot;fa_bolt\@silver&amp;quot;,-3.6,3.6,0,90,[&amp;quot;PV&amp;quot;,&amp;quot;Netz&amp;quot;],[(-1,0,-0.01,30,1,60,3.6,90)],&amp;quot;2,,fill:silver, kW&amp;quot;,&amp;quot;130,,1,0,1&amp;quot;,&amp;quot;1,,1,0,negzeropos&amp;quot;,undef, [[di_counter_new:MQTT2_DVES_C58DCB.total_pv.day],[di_counter_new:MQTT2_DVES_C58DCB.total_c.day],[di_counter_new:MQTT2_DVES_C58DCB.total_f.day]],-25,25,0,90,[&amp;quot;PV&amp;quot;,&amp;quot;Bezug&amp;quot;,&amp;quot;Einsp.&amp;quot;],[(-10,0,-0.01,30,10,60,25,90)],&amp;quot;1,,fill:silver, kWh&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:di_card_energie2.png|ohne|mini]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;card mit Zusatzinformationen, die nicht im Plot erscheinen mit eigenen Formatierungsangaben zum Ring&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sollen Zusatzinformationen, die nicht im Plot erscheinen, in der Kopfzeile mit eigenen Formatierungsangaben im Ring dargestellt werden, dann können sie beim $collect/$collec2-Parameter als Array mit zusätzlichen Parametern angegeben werden. Diese Angaben übersteuern die Formatierungsangaben, die für den Hauptring gelten. Die Bedeutung der Parameter entspricht der der card-Parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Syntax für $collect/$collect2&lt;br /&gt;
[...,[[&amp;lt;Device&amp;gt;:&amp;lt;Reading&amp;gt;],$min,$max,$minColor,$maxColor,$desc, $colorRef,$decFontUnit,$ringModel],...]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Beschreibung der Parameter siehe card-Funktion &lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_gas DOIF {}&lt;br /&gt;
attr di_gas uiTable {\&lt;br /&gt;
  package ui_Table;;\&lt;br /&gt;
}\&lt;br /&gt;
card([[di_counter:gas.day:col1w],[[di_counter:gas.month],0,250,90,0,&amp;quot;Monat&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;0,,fill:silver, m³&amp;quot;],[[di_counter:gas.year],0,1500,90,0,&amp;quot;Jahr&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;0,,fill:silver, m³&amp;quot;]],&amp;quot;Gas&amp;quot;, undef,0,10,90,0,&amp;quot;Tag&amp;quot;, undef,&amp;quot;1,,fill:silver, m³&amp;quot;,&amp;quot;130,1,1,0,1,halfring,180&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
card([[di_counter:gas.last_day:bar2month-300],[[di_counter:gas.last_month],0,250,90,0,&amp;quot;letzter&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;0,,fill:silver, m³&amp;quot;],[[di_counter:gas.month],0,250,90,0,&amp;quot;Monat&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;0,,fill:silver, m³&amp;quot;]],&amp;quot;Gasverbrauch&amp;quot;, undef,0,10,90,0,&amp;quot;Tag&amp;quot;, undef,&amp;quot;2,,fill:silver, m³&amp;quot;,&amp;quot;130,1,1,0,1,noring,180&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:di_card_gas.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_wetter DOIF {}&lt;br /&gt;
attr di_wetter uiTable {\&lt;br /&gt;
  package ui_Table;;\&lt;br /&gt;
}\&lt;br /&gt;
card([Aussen:temperature:col1d],&amp;quot;&amp;quot;,&amp;quot;temp_outside\@silver&amp;quot;,-10,50,undef,undef,&amp;quot;Temp.&amp;quot;,\&amp;amp;temp_hue,&amp;quot;1,,fill:silver,°C&amp;quot;,&amp;quot;130,autoscaling,nosteps,footer,ycolor,ring,200&amp;quot;,undef,undef,[[Aussen:humidity:col1d],[[Wetter:WindboeenKm],0,30,90,30,&amp;quot;Wind&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;1,,fill:silver, km/h&amp;quot;,&amp;quot;,,,0&amp;quot;],[[Wetter:LuftdruckHpa],980,1047,30,90,&amp;quot;Luftdr.&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;0,,fill:silver, hPa&amp;quot;,&amp;quot;,,,0&amp;quot;],[[Wetter:RegenGesamtMm],0,50,180,270,&amp;quot;Regen&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;1,,fill:silver, mm&amp;quot;,&amp;quot;,,,0&amp;quot;]],0,100,undef,undef,&amp;quot;Feuchte&amp;quot;,\&amp;amp;hum_hue,&amp;quot;0,,fill:silver, %&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:di_card_wetter.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
======&amp;lt;big&amp;gt;Anwendungsbeispiele mit card&amp;lt;/big&amp;gt;======&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod Aktuell DOIF {}&lt;br /&gt;
attr Aktuell alias Übersicht&lt;br /&gt;
attr Aktuell uiTable {package ui_Table;;\&lt;br /&gt;
\&lt;br /&gt;
 ## $TABLE=&#039;vertical-align:top&#039;;;\&lt;br /&gt;
  $TC{0..1} = &amp;quot;style=&#039;vertical-align:top&#039;&amp;quot;\&lt;br /&gt;
  $TABLE=&#039;text-align:center;;&#039;;;\&lt;br /&gt;
  ## $SHOWNOSTATE=1;;\&lt;br /&gt;
 }\&lt;br /&gt;
## $prop: &amp;quot;&amp;lt;size&amp;gt;,&amp;lt;y-scaling&amp;gt;,&amp;lt;steps&amp;gt;,&amp;lt;noFooter&amp;gt;,&amp;lt;noColor&amp;gt;,&amp;lt;hring&amp;gt;,&amp;lt;width&amp;gt;&amp;quot;\&lt;br /&gt;
::sunrise_abs(),::sunset_abs()|&amp;quot;&amp;lt;div class=&#039;doifclock&#039;style=&#039;font-size:25pt;;color:silver&#039;&amp;gt;wait&amp;lt;/div&amp;gt;&amp;quot;&amp;lt;\&lt;br /&gt;
style([wetter_com_broich:Ansage],[wetter_com_broich:Ansage] eq &amp;quot;Kein Niederschlag in Sicht&amp;quot; ? &amp;quot;silver&amp;quot;:&amp;quot;red&amp;quot;)&amp;lt;\&lt;br /&gt;
\&lt;br /&gt;
card([MQTT2_zigbee_0x048727fffee80c78:temperature:col1d],&amp;quot;&amp;quot;,&amp;quot;temp_outside\@silver&amp;quot;,-10,50,undef,undef,&amp;quot;Temp.&amp;quot;,\&amp;amp;temp_hue,&amp;quot;1,,fill:silver,°C&amp;quot;,&amp;quot;130,,,0,1,,200&amp;quot;,undef,undef,[[MQTT2_zigbee_0x048727fffee80c78:humidity:col1d],[[Wetter:WindboeenKm],0,30,90,30,&amp;quot;Wind&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;1,,fill:silver, km/h&amp;quot;,&amp;quot;,,,0&amp;quot;],[[Wetter:LuftdruckHpa],980,1047,30,90,&amp;quot;Luftdr.&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;0,,fill:silver, hPa&amp;quot;,&amp;quot;,,,0&amp;quot;],[[Wetter:RegenGesamtMm],0,10,180,270,&amp;quot;Regen&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;1,,fill:silver, mm&amp;quot;,&amp;quot;,,,0&amp;quot;]],0,100,undef,undef,&amp;quot;Feuchte&amp;quot;,\&amp;amp;hum_hue,&amp;quot;0,,fill:silver, %&amp;quot;)|\&lt;br /&gt;
\&lt;br /&gt;
card([[MQTT2_DVES_C58DCB:power_pv:144col1d],[MQTT2_DVES_C58DCB:power_fc:144col1d]],&amp;quot;&amp;quot;,&amp;quot;fa_bolt\@silver&amp;quot;,-3.6,3.6,0,90,[&amp;quot;PV&amp;quot;,&amp;quot;Netz&amp;quot;],[(-1,0,-0.01,30,1,60,3.6,90)],&amp;quot;2,,fill:silver, kW&amp;quot;,&amp;quot;130,,1,0,1,,200&amp;quot;,&amp;quot;1,,1,0,negzeropos&amp;quot;,undef, [[[di_counter_new:MQTT2_DVES_C58DCB.total_pv.day],0,30,60,90,&amp;quot;PV&amp;quot;,[(10,60,30,90)]],[[di_counter_new:MQTT2_DVES_C58DCB.total_f.day],0,30,60,90,&amp;quot;Einsp.&amp;quot;,[(10,60,30,90)]],[[di_counter_new:MQTT2_DVES_C58DCB.total_c_positiv.day],0,10,30,0,&amp;quot;Bezug&amp;quot;,[(3.3,30,10,0)]],[[di_counter_new:MQTT2_DVES_C58DCB.total_consum.day],0,15,30,0,&amp;quot;Verbr.&amp;quot;,[(5,30,15,0)]]],0,10,30,0,[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;],[(3,30,10,0)],&amp;quot;1,,fill:silver, kWh&amp;quot;) \&lt;br /&gt;
\&lt;br /&gt;
card([di_counter_new:MQTT2_DVES_C58DCB.total_w.last_day:col4w],undef,&amp;quot;measure_water_meter\@silver&amp;quot;,0,600,120,0,&amp;quot;Verbr.&amp;quot;,undef,&amp;quot;0,,fill:silver, l&amp;quot;,&amp;quot;130,autoscaling,1,0,1,,200&amp;quot;,undef,undef,[Wasserzisterne:Stand:col4w],0,100,240,180,&amp;quot;Zisterne&amp;quot;,undef,&amp;quot;0,,fill:silver, %&amp;quot;) |\&lt;br /&gt;
\&lt;br /&gt;
card([[Tankstelle:SuperE5:col3d],[Tankstelle:Diesel:col3d]],undef,&amp;quot;fuel\@silver&amp;quot;,1.40,1.9,120,0,[&amp;quot;E10&amp;quot;,&amp;quot;Diesel&amp;quot;],undef,&amp;quot;2,,fill:silver, €&amp;quot;,&amp;quot;130,autoscaling,1,0,1,,200&amp;quot;,undef,undef)\&lt;br /&gt;
\&lt;br /&gt;
\&lt;br /&gt;
card([[di_counter_new:MQTT2_DVES_C58DCB.total_pv.last_day:bar2month-300],[di_counter_new:MQTT2_DVES_C58DCB.total_c.last_day:bar2month-300]],&amp;quot;Strom&amp;quot;,undef,-25,25,0,90,[&amp;quot;PV&amp;quot;,&amp;quot;Bezug&amp;quot;],[(-10,0,-0.01,30,10,60,25,90)],&amp;quot;1,,fill:silver, kWh&amp;quot;,&amp;quot;130,autoscaling,steps,footer,noycolor,halfring,200&amp;quot;,&amp;quot;1,,1,0,1&amp;quot;,undef) |\&lt;br /&gt;
\&lt;br /&gt;
card([[di_counter_new:MQTT2_DVES_C58DCB.total_gas.last_day:bar2month-300],\&lt;br /&gt;
[[di_counter_new:MQTT2_DVES_C58DCB.total_gas.last_day],0,10,90,0,&amp;quot;gestern&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;2,,fill:silver, m³&amp;quot;],\&lt;br /&gt;
[[di_counter_new:MQTT2_DVES_C58DCB.total_gas.day],0,10,90,0,&amp;quot;heute&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;2,,fill:silver, m³&amp;quot;],[[di_counter_new:MQTT2_DVES_C58DCB.total_gas.month],0,250,90,0,&amp;quot;Monat&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;1,,fill:silver, m³&amp;quot;]],&amp;quot;Gas&amp;quot;,undef,0,10,90,0,&amp;quot;m³&amp;quot;,undef,&amp;quot;2,,fill:silver, m³&amp;quot;,&amp;quot;130,autoscaling,1,0,1,nohalfring,200&amp;quot;,undef,undef)\&lt;br /&gt;
\&lt;br /&gt;
card([di_tibber:tibber],&amp;quot;Tibber&amp;quot;,undef,0,40,90,0,&amp;quot;Cent&amp;quot;,undef,&amp;quot;1&amp;quot;,&amp;quot;,autoscaling,,,noycolor,halfring,200&amp;quot;)|\&lt;br /&gt;
\&lt;br /&gt;
card([[di_counter_new:di_tibber.costsSum.last_day:bar2month-300],[[di_counter_new:di_tibber.costsSum.last_day],0,3,90,0,&amp;quot;gestern&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;2,,, €&amp;quot;],[[di_counter_new:di_tibber.costsSum.day],0,3,90,0,&amp;quot;heute&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;2,,, €&amp;quot;],[[di_counter_new:di_tibber.costsSum.month],0,80,90,0,&amp;quot;Monat&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;2,,, €&amp;quot;]],&amp;quot;Tibber&amp;quot;,undef,0,3,90,0,&amp;quot;Euro&amp;quot;,undef,&amp;quot;2,,, €&amp;quot;,&amp;quot;130,autoscaling,,footer,noycolor,nohalfring,200&amp;quot;,&amp;quot;0,0,0,0,2&amp;quot;) \&lt;br /&gt;
\&lt;br /&gt;
\&lt;br /&gt;
card([[MQTT2_sbfspot:PDC1:144col1d],[MQTT2_sbfspot:PDC2:144col1d]],&amp;quot;PV Leistung&amp;quot;,undef,0,3300,40,100,[&amp;quot;PDC1,yellow&amp;quot;,&amp;quot;PDC2,#FF5F1F&amp;quot;],undef,&amp;quot;0,,fill:silver, W&amp;quot;,&amp;quot;130,autoscaling,steps,footer,noycolor,halfring,200&amp;quot;,&amp;quot;1,,1,0,1&amp;quot;,undef)|\&lt;br /&gt;
\&lt;br /&gt;
card([[MQTT2_sbfspot:IDC1:144col1d],[MQTT2_sbfspot:IDC2:144col1d]],&amp;quot;PV Strom&amp;quot;,undef,0,8.5,40,100,[&amp;quot;IDC1,yellow&amp;quot;,&amp;quot;IDC2,#FF5F1F&amp;quot;],undef,&amp;quot;3,,, A&amp;quot;,&amp;quot;130,autoscaling,steps,footer,noycolor,halfring,200&amp;quot;,&amp;quot;1,,1,0,1&amp;quot;,undef)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:di_card_uebersicht.png|ohne|500px]]&lt;br /&gt;
&lt;br /&gt;
=====&amp;lt;big&amp;gt;Darstellung fortlaufender Daten als Säulen&amp;lt;/big&amp;gt;=====&lt;br /&gt;
Die Darstellung von fortlaufenden Daten kann mit Hilfe von Säulendiagrammen über den Darstellungstyp &#039;&#039;&#039;bar&#039;&#039;&#039; oder &#039;&#039;&#039;barAvg&#039;&#039;&#039; erfolgen. Werden die Reading-Werte innerhalb der definierten Periode öfters geschrieben, so wird bei der Angabe &#039;&#039;&#039;bar&#039;&#039;&#039; der letzte Wert des jeweiligen Zeitraums übernommen, bei der Angabe &#039;&#039;&#039;barAvg&#039;&#039;&#039; wird dagegen der Mittelwert der Werte gebildet und als Säule dargestellt. Die Werte der aktuellen Periode werden in hellen Farben dargestellt, die der vorherigen Perioden sind abgedunkelt. Der aktuelle Tag wird im Diagramm gekennzeichnet. Ebenso wird der minimale, maximale und der durchschnittlicher Wert errechnet und im Diagramm per Symbol bzw. Linie gekennzeichnet.&lt;br /&gt;
======&amp;lt;big&amp;gt;Energieverbrauch verschiedener Zeiträume&amp;lt;/big&amp;gt;======&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;nützliche Links&#039;&#039;&#039;&lt;br /&gt;
* [https://wiki.fhem.de/wiki/DOIF/uiTable_Schnelleinstieg#Anzeige_eines_Werteverlaufs_und_des_aktuellen_Wertes_mit_Hilfe_der_SVG-Funktion_card siehe Syntax zu bar/barAvg beim card-Parameter &amp;lt;collect type&amp;gt;]&lt;br /&gt;
* [https://wiki.fhem.de/wiki/DOIF/Automatisierung#Tages-.2C_Monats-_und_Jahresstatistik_f.C3.BCr_Strom-.2C_Gas-.2C_Wasserz.C3.A4hler_und_andere_Z.C3.A4hler siehe Statistik zu Zählerdaten mit Visualisierung]&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_energie DOIF {}&lt;br /&gt;
attr di_energie uiTable {package ui_Table}\&lt;br /&gt;
&amp;quot;Darstellung eines Monats&amp;quot;|&amp;quot;Darstellung eines Jahres&amp;quot;|&amp;quot;Darstellung einer Dekade&amp;quot;\&lt;br /&gt;
card([di_counter_new:MQTT2_DVES_C58DCB.total_gas.last_day:bar1month],&amp;quot;Gas in m³ pro Tag&amp;quot;,undef,0,10,90,0,&amp;quot;m³&amp;quot;,undef,&amp;quot;1&amp;quot;,&amp;quot;130,1,1,0,1,0,200&amp;quot;)|\&lt;br /&gt;
card([di_counter_new:MQTT2_DVES_C58DCB.total_gas.last_month:bar1year],&amp;quot;Gas in m³ pro Monat&amp;quot;,undef,0,100,90,0,&amp;quot;m³&amp;quot;,undef,&amp;quot;0&amp;quot;,&amp;quot;130,1,1,0,1,0,200&amp;quot;)|\&lt;br /&gt;
card([di_counter_new:MQTT2_DVES_C58DCB.total_gas.last_year:bar1decade],&amp;quot;Gas in m³ pro Jahr&amp;quot;,undef,0,20000,90,0,&amp;quot;m³&amp;quot;,undef,&amp;quot;0&amp;quot;,&amp;quot;130,1,1,0,1,0,200&amp;quot;)\&lt;br /&gt;
&amp;quot;Darstellung einer Woche&amp;quot;|&amp;quot;Darstellung zwei Wochen&amp;quot;|&amp;quot;Darstellung vier Wochen&amp;quot;\&lt;br /&gt;
card([di_counter_new:MQTT2_DVES_C58DCB.total_gas.last_day:bar1week],&amp;quot;Gas in m³ pro Tag&amp;quot;,undef,0,10,90,0,&amp;quot;m³&amp;quot;,undef,&amp;quot;1&amp;quot;,&amp;quot;130,1,1,0,1,0,200&amp;quot;)|\&lt;br /&gt;
card([di_counter_new:MQTT2_DVES_C58DCB.total_gas.last_day:bar2week],&amp;quot;Gas in m³ pro Tag&amp;quot;,undef,0,10,90,0,&amp;quot;m³&amp;quot;,undef,&amp;quot;1&amp;quot;,&amp;quot;130,1,1,0,1,0,200&amp;quot;)|\&lt;br /&gt;
card([di_counter_new:MQTT2_DVES_C58DCB.total_gas.last_day:bar4week],&amp;quot;Gas in m³ pro Tag&amp;quot;,undef,0,10,90,0,&amp;quot;m³&amp;quot;,undef,&amp;quot;1&amp;quot;,&amp;quot;130,1,1,0,1,0,200&amp;quot;)\&lt;br /&gt;
&amp;quot;Darstellung von zwei Werten&amp;quot;|&amp;quot;Darstellung mit Halbringen&amp;quot;|&amp;quot;Darstellung von zwei Monaten&amp;quot;\&lt;br /&gt;
card([[di_counter_new:MQTT2_DVES_C58DCB.total_pv.last_day:bar1month],[di_counter_new:MQTT2_DVES_C58DCB.total_c.last_day:bar1month]],&amp;quot;Elektrizität in kWh pro Tag&amp;quot;,undef,-15,15,0,90,[&amp;quot;Ertrag&amp;quot;,&amp;quot;Bezug&amp;quot;],undef,&amp;quot;1&amp;quot;,&amp;quot;130,1,1,0,1,0,200&amp;quot;,&amp;quot;0,0,0,0,2&amp;quot;)|\&lt;br /&gt;
card([[di_counter_new:MQTT2_DVES_C58DCB.total_pv.last_day:bar1month],[di_counter_new:MQTT2_DVES_C58DCB.total_c.last_day:bar1month]],&amp;quot;kWh pro Tag&amp;quot;,undef,-15,15,0,90,[&amp;quot;Ertrag&amp;quot;,&amp;quot;Bezug&amp;quot;],undef,&amp;quot;1&amp;quot;,&amp;quot;130,1,1,0,1,halfring,200&amp;quot;)|\&lt;br /&gt;
card([[di_counter_new:MQTT2_DVES_C58DCB.total_pv.last_day:bar2month],[di_counter_new:MQTT2_DVES_C58DCB.total_c.last_day:bar2month]],&amp;quot;kWh pro Tag&amp;quot;,undef,-15,15,0,90,[&amp;quot;Ertrag&amp;quot;,&amp;quot;Bezug&amp;quot;],undef,&amp;quot;1&amp;quot;,&amp;quot;130,1,1,0,1,halfring,200&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:di_energie_bar.png|ohne|800px]]&lt;br /&gt;
&lt;br /&gt;
=====&amp;lt;big&amp;gt;Import, Änderung und Löschung von Diagrammdaten&amp;lt;/big&amp;gt;=====&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;card-data-Funktionen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Gesammelte card-Daten löschen.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
DOIF_delete_card_data (&amp;lt;card device&amp;gt;,&amp;lt;reading device&amp;gt;,&amp;lt;reading&amp;gt;,&amp;lt;col/bar specification&amp;gt;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Daten aus einer Logdatei oder einer Liste übernehmen. Vorhandene card-Daten werden zuvor gelöscht.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
DOIF_set_card_data (&amp;lt;card device&amp;gt;,&amp;lt;reading device&amp;gt;,&amp;lt;reading&amp;gt;,&amp;lt;col/bar specification&amp;gt;,&amp;lt;time offset&amp;gt;,&amp;lt;data list&amp;gt;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Daten aus einer Logdatei oder einer Liste übernehmen. Vorhandene card-Daten werden zuvor nicht gelöscht.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
DOIF_modify_card_data (&amp;lt;card device&amp;gt;,&amp;lt;reading device&amp;gt;,&amp;lt;reading&amp;gt;,&amp;lt;col/bar specification&amp;gt;,&amp;lt;time offset&amp;gt;,&amp;lt;data list&amp;gt;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#&amp;lt;card device&amp;gt; DOIF-Device, wo die Definition der zu sammelnden Daten vorgenommen wurde&lt;br /&gt;
#&amp;lt;reading device&amp;gt; Device des Readings&lt;br /&gt;
#&amp;lt;reading&amp;gt; Readingname&lt;br /&gt;
#&amp;lt;col/bar specification&amp;gt; die dazugehörige Spezifikation des collect Typs, z. B. &amp;quot;col1w&amp;quot;, &amp;quot;bar1month&amp;quot; usw.&lt;br /&gt;
#&amp;lt;time offset&amp;gt; Angabe in Sekunden.&lt;br /&gt;
Der Zeitstempel der Daten wird zeitlich (positiv - in die Zukunft, negativ - in die Vergangenheit) verschoben. Damit kann man erreichen, dass Daten, die nach Mitternacht entstanden sind, dem Tag zuvor zugeordnet werden (negative Sekundenangabe).&lt;br /&gt;
#&amp;lt;data list&amp;gt; Liste von Datensätzen, die importiert werden sollen&lt;br /&gt;
das Format eines Datensatzes ist:&lt;br /&gt;
#YYYY.MM.DD_HH:MM:SS&amp;lt;separator&amp;gt;&amp;lt;value&amp;gt;, mit&lt;br /&gt;
#&amp;lt;separator&amp;gt; Leerzeichen oder Semikolon&lt;br /&gt;
#&amp;lt;value&amp;gt; Zahl&lt;br /&gt;
#ebenfalls ist das deutsche Zeitformat erlaubt&lt;br /&gt;
#DD.MM.YYYY HH:MM:SS&lt;br /&gt;
Die Datensätze können durch Komma oder Zeilenumbruch (newline) voneinander getrennt werden. Werden Zahlen mit Komma statt mit Punkt angegeben, so müssen die Datensätze durch Zeilenumbrüche getrennt werden.&lt;br /&gt;
Bei Datumsangaben kann der Tag und der Monat weggelassen werden, ebenfalls können Zeitangaben weggelassen werden.&lt;br /&gt;
Beispiel: &amp;quot;2023.02.21_15:01 10,2023.02.21 20,2023 15&amp;quot; oder &amp;quot;15.02.2023 15:01 10,21.02.2023 20,2023 15&amp;quot;&lt;br /&gt;
Die Liste kann ebenfalls von einer Funktion geliefert werden, wie z. B. Filelog oder DOIF_get_file_data.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
Die Daten der zu visualisierenden Readings werden event-gesteuert im DOIF-Device gesammelt und in versteckten Readings gespeichert. Bei Neudefinition von card oder nach einem Systemcrash kann es sinnvoll sein, vorhandene Daten aus dem Log oder einer Liste für die Visualisierung zu übernehmen. Ebenfalls können gesammelte Daten gelöscht oder einzeln modifiziert werden. All das lässt sich mit den card-data-Funktionen umsetzen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiele&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Ausgangssituation: Im DOIF-Device &#039;&#039;&#039;di_pv&#039;&#039;&#039; werden Daten mit  Angabe &#039;&#039;&#039;[energie:pv:col4w]&#039;&#039;&#039; über card-Funktion visualisiert.&lt;br /&gt;
&lt;br /&gt;
Löschen der visualisierten Daten:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
DOIF_delete_card_data (&amp;quot;di_pv&amp;quot;,&amp;quot;energie&amp;quot;,&amp;quot;pv&amp;quot;,&amp;quot;col4w&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Übernehmen von Daten eines bestimmten Zeitraums aus dem Log namens &#039;&#039;&#039;pv.energie.log&#039;&#039;&#039;, dort wurden die Daten des Readings &#039;&#039;&#039;pv&#039;&#039;&#039; geloggt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
DOIF_set_card_data (&amp;quot;di_pv&amp;quot;,&amp;quot;energie&amp;quot;,&amp;quot;pv&amp;quot;,&amp;quot;col4w&amp;quot;,0,fhem(&amp;quot;get pv.energie.log - - 2022-11-01 2023-02-03 4:pv&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
get-Filelog-Syntax bitte in der Dokumentation zu Filelog entnehmen.&lt;br /&gt;
&lt;br /&gt;
Statt Log-Daten können ebenfalls Daten in einer kommagetrennten Liste angegeben übernommen werden.&lt;br /&gt;
&lt;br /&gt;
Es sollen zwei Datensätze übernommen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
DOIF_modify_card_data (&amp;quot;di_pv&amp;quot;,&amp;quot;energie&amp;quot;,&amp;quot;pv&amp;quot;,&amp;quot;col4w&amp;quot;,0,&amp;quot;2023.02.04_11:00 10,2023.02.04_11:02 5.6&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine Liste aus einer Datei, z. B. aus einer csv-Excel-Datei, kann mit der Funktion &#039;&#039;&#039;DOIF_get_file_data (&amp;lt;file&amp;gt;)&#039;&#039;&#039; übernommen werden. Dabei ist es unerheblich, ob die Daten im deutschen oder im internationalen Zeitformat vorliegen, ebenso wird das Kommazeichen statt Punkt bei Zahlen erkannt.&lt;br /&gt;
&lt;br /&gt;
Ausgangssituation: Die Datei &#039;&#039;gas_jan.csv&#039;&#039; wurde in das log-Verzeichnis kopiert. Sie beinhaltet u.a. folgende Datensätze (Nachkommastellen wurden mit Komma getrennt):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
2023;4,142&lt;br /&gt;
02.01.2023 00:01:00;5,159&lt;br /&gt;
03.01.2023 00:01;3,170&lt;br /&gt;
04.01.2023;5,420&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Import der Daten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
DOIF_set_card_data (&amp;quot;di_pv&amp;quot;,&amp;quot;energie&amp;quot;,&amp;quot;pv&amp;quot;,&amp;quot;col4w&amp;quot;,0,DOIF_get_file_data(&amp;quot;./log/gas_jan.csv&amp;quot;)))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====&amp;lt;big&amp;gt;card im Status des Originaldevices&amp;lt;/big&amp;gt;=====&lt;br /&gt;
Soll im Status des Originaldevices eine Visualisierung mit Hilfe der card-Funktion vorgenommen werden, so kann wie folgt vorgegangen werden.&lt;br /&gt;
&lt;br /&gt;
Definition eines DOIF-Devices mit dem Attribut DOIF_Readings zum Sammeln der zu visualisierenden Daten.&lt;br /&gt;
&lt;br /&gt;
Beispieldefintion für fünf Readings aus unterschiedlichen Devices:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_collect DOIF {}&lt;br /&gt;
attr di_collect DOIF_Readings temperature:[Aussen:temperature:col2d],\&lt;br /&gt;
humidity:[Aussen:humidity:col2d],\&lt;br /&gt;
co2:[MQTT2_DVES_D90D08:MHZ19B_CarbonDioxide:col2d],\&lt;br /&gt;
SuperE5:[Tankstelle:SuperE5:col3d],\&lt;br /&gt;
Diesel:[Tankstelle:Diesel:col3d],\&lt;br /&gt;
full:[GasInStorageDE:full:bar1month]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im ursprünglichen Device wird jeweils über das Attribut devStateIcon der Aufruf von card vorgenommen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod Aussen CUL_WS 5&lt;br /&gt;
attr Aussen alias Schuppen&lt;br /&gt;
attr Aussen devStateIcon {ui_Table::card(ReadingsVal(&amp;quot;di_collect&amp;quot;,&amp;quot;temperature&amp;quot;,&amp;quot;&amp;quot;),undef,&amp;quot;temp_outside\@silver&amp;quot;,-10,50,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;ui_Table::temp_hue,&amp;quot;1,,fill:silver&amp;quot;,&amp;quot;130,,,0,1,,&amp;quot;,undef,undef,ReadingsVal(&amp;quot;di_collect&amp;quot;,&amp;quot;humidity&amp;quot;,&amp;quot;&amp;quot;),0,100,undef,undef,&amp;quot;%&amp;quot;,\&amp;amp;ui_Table::hum_hue,&amp;quot;0,,fill:silver&amp;quot;)}&lt;br /&gt;
&lt;br /&gt;
defmod GasInStorageDE JsonMod https://agsi.gie.eu/api?country=de&amp;amp;date=now&lt;br /&gt;
attr GasInStorageDE comment Status: \&lt;br /&gt;
E - Estimated - Geschätzt\&lt;br /&gt;
C - Confirm - Bestätigt&lt;br /&gt;
attr GasInStorageDE devStateIcon {ui_Table::card(ReadingsVal(&amp;quot;di_collect&amp;quot;,&amp;quot;full&amp;quot;,&amp;quot;&amp;quot;),undef,&amp;quot;&amp;quot;,0,100,0,120,&amp;quot;full in %&amp;quot;,undef,&amp;quot;1&amp;quot;,&amp;quot;,fixedscaling,,,,halfring&amp;quot;)}&lt;br /&gt;
attr GasInStorageDE httpHeader x-key: 08154711&lt;br /&gt;
attr GasInStorageDE interval 0 6 * * *&lt;br /&gt;
attr GasInStorageDE readingList single(jsonPath(&#039;$.gas_day&#039;), &#039;gas_Day&#039;, &#039;N/A&#039;);;\&lt;br /&gt;
single(jsonPath(&#039;$.data.0.gasInStorage&#039;), &#039;gasInStorage&#039;, &#039;N/A&#039;);;\&lt;br /&gt;
single(jsonPath(&#039;$.data.0.consumption&#039;), &#039;consumption&#039;, &#039;N/A&#039;);;\&lt;br /&gt;
single(jsonPath(&#039;$.data.0.consumptionFull&#039;), &#039;consumptionFull&#039;, &#039;N/A&#039;);;\&lt;br /&gt;
single(jsonPath(&#039;$.data.0.injection&#039;), &#039;injection&#039;, &#039;N/A&#039;);;\&lt;br /&gt;
single(jsonPath(&#039;$.data.0.withdrawal&#039;), &#039;withdrawal&#039;, &#039;N/A&#039;);;\&lt;br /&gt;
single(jsonPath(&#039;$.data.0.workingGasVolume&#039;), &#039;workingGasVolume&#039;, &#039;N/A&#039;);;\&lt;br /&gt;
single(jsonPath(&#039;$.data.0.injectionCapacity&#039;), &#039;injectionCapacity&#039;, &#039;N/A&#039;);;\&lt;br /&gt;
single(jsonPath(&#039;$.data.0.withdrawalCapacity&#039;), &#039;withdrawalCapacity&#039;, &#039;N/A&#039;);;\&lt;br /&gt;
single(jsonPath(&#039;$.data.0.status&#039;), &#039;status&#039;, &#039;N/A&#039;);;\&lt;br /&gt;
single(jsonPath(&#039;$.data.0.trend&#039;), &#039;trend&#039;, &#039;N/A&#039;);;\&lt;br /&gt;
single(jsonPath(&#039;$.data.0.full&#039;), &#039;full&#039;, &#039;N/A&#039;);;&lt;br /&gt;
&lt;br /&gt;
defmod Tankstelle HTTPMOD http://www.clever-tanken.de/tankstelle_details/24198 300&lt;br /&gt;
attr Tankstelle devStateIcon {ui_Table::card([ReadingsVal(&amp;quot;di_collect&amp;quot;,&amp;quot;SuperE5&amp;quot;,&amp;quot;&amp;quot;),ReadingsVal(&amp;quot;di_collect&amp;quot;,&amp;quot;Diesel&amp;quot;,&amp;quot;&amp;quot;)],undef,&amp;quot;fuel\@silver&amp;quot;,&amp;quot;1.50&amp;quot;,&amp;quot;2.00&amp;quot;,120,0,[&amp;quot;E10&amp;quot;,&amp;quot;Diesel&amp;quot;],undef,&amp;quot;2,,fill:silver&amp;quot;,&amp;quot;130,1,1,0,1&amp;quot;,undef,undef)}&lt;br /&gt;
attr Tankstelle enableControlSet 1&lt;br /&gt;
attr Tankstelle event-on-change-reading .*&lt;br /&gt;
attr Tankstelle reading01Name Diesel&lt;br /&gt;
attr Tankstelle reading01Regex &amp;quot;current-price-1&amp;quot;&amp;gt;(\d.\d{2})&lt;br /&gt;
attr Tankstelle reading02Name SuperE5&lt;br /&gt;
attr Tankstelle reading02Regex &amp;quot;current-price-2&amp;quot;&amp;gt;(\d.\d{2})&lt;br /&gt;
attr Tankstelle timeout 10&lt;br /&gt;
&lt;br /&gt;
defmod MQTT2_DVES_D90D08 MQTT2_DEVICE DVES_D90D08&lt;br /&gt;
attr MQTT2_DVES_D90D08 devStateIcon {ui_Table::card(ReadingsVal(&amp;quot;di_collect&amp;quot;,&amp;quot;co2&amp;quot;,&amp;quot;&amp;quot;),undef,&amp;quot;air\@silver&amp;quot;,400,1200,120,0,&amp;quot;ppm&amp;quot;,[(600,120,1000,60,1200,0)],&amp;quot;0,,fill:silver&amp;quot;,&amp;quot;130,autoscaling,nosteps,footer,noycolor&amp;quot;,&#039;nogradient,nominmaxvalue,innerring,nopointer,minmax&#039;)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Visualisierung wird automatisch aktualisiert. Mit Hilfe dieser Vorgehensweise lassen sich cards über den Status des jeweiligen Devices oder den direkten Aufruf der card-Funktion auch in anderen Frontends wie z. B. Floorplan oder TabletUI darstellen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:card_im_Status.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
====&amp;lt;big&amp;gt;3d-Balkendarstellung mehrerer Zahlenwerten mit Hilfe der universellen SVG-Funktion &#039;&#039;&#039;cylinder/cylinder_s&#039;&#039;&#039; &amp;lt;/big&amp;gt; ====&lt;br /&gt;
Es können mehrere Zahlenwerte mit Legende farbig in Balkenform visualisiert werden. Negative Werte werden als Balken nach unten dargestellt, positive nach oben, der Nullpunkt wird automatisch berechnet. Bei cylinder_s werden die Balken aufeinander gestapelt.&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;cylinder/cylinder_s&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
cylinder/cylinder_s ($header,$min,$max,$unit,$width,$height,$size,$dec,($value1,$color1,$text1),($value2,$color2,$text2),...&lt;br /&gt;
&lt;br /&gt;
$header     # Überschrift&lt;br /&gt;
$min        # minimaler Wert, optional, default = 0&lt;br /&gt;
$max        # maximaler Wert, optional, default = 100&lt;br /&gt;
$unit       # Einheit des Wertes, optional, default = undef&lt;br /&gt;
$width      # Breite der Grafik, optional, default = wird bei Beschriftungen automatisch angepasst&lt;br /&gt;
$height     # Höhe der Grafik, optional, default = wird automatisch berechnet&lt;br /&gt;
$size       # Größe der Grafik, optional, default = 100&lt;br /&gt;
$dec        # Anzahl der Nachkommastellen, optional, default=1&lt;br /&gt;
$value1     # erster Zahlenwert&lt;br /&gt;
$color1     # HSL-Farbe des ersten Balkens: &amp;quot;&amp;lt;hue&amp;gt;.&amp;lt;saturation&amp;gt;.&amp;lt;lightness&amp;gt;&amp;quot; (hue:0-360,saturation:0-100,lightness:0-100), saturation (default:100) und lightness (default:50) sind optional&lt;br /&gt;
$text1      # Beschriftung des Zahlenwertes in der Legende, optional, default = undef&lt;br /&gt;
$value2     # zweiter Zahlenwert, optional&lt;br /&gt;
$color2     # HSL-Farbe des zweiten Balkens: &amp;quot;&amp;lt;hue&amp;gt;.&amp;lt;saturation&amp;gt;.&amp;lt;lightness&amp;gt;&amp;quot; (hue:0-360,saturation:0-100,lightness:0-100), saturation (default:100) und lightness (default:50) sind optional&lt;br /&gt;
$text2      # Beschriftung des Zahlenwertes in der Legende, optional, default = undef&lt;br /&gt;
...&lt;br /&gt;
Es können weitere Zahlenwerte jeweils mit Farbe und Beschriftung optional angegeben werden &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
=====&amp;lt;big&amp;gt;cylinder mit verschiedenen Layouts&amp;lt;/big&amp;gt;=====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_cylinder DOIF ##&lt;br /&gt;
attr di_cylinder room Test,wiki&lt;br /&gt;
attr di_cylinder uiTable {package ui_Table}\&lt;br /&gt;
&amp;quot;normal&amp;quot;|cylinder(&amp;quot;&amp;quot;,0,100,&amp;quot;%&amp;quot;,80,undef,undef,0,[Wasserzisterne:state],200,undef)\&lt;br /&gt;
\&lt;br /&gt;
&amp;quot;mit Überschrift&amp;quot;|cylinder(&amp;quot;Zisterne&amp;quot;,0,100,&amp;quot;%&amp;quot;,80,undef,undef,0,[Wasserzisterne:state],200,undef)\&lt;br /&gt;
\&lt;br /&gt;
&amp;quot;kleiner&amp;quot;|cylinder(&amp;quot;Zisterne&amp;quot;,0,100,&amp;quot;%&amp;quot;,80,undef,80,0,[Wasserzisterne:state],200,undef)\&lt;br /&gt;
\&lt;br /&gt;
&amp;quot;hoch&amp;quot;|cylinder(&amp;quot;Zisterne&amp;quot;,0,100,&amp;quot;%&amp;quot;,undef,100,undef,0,[Wasserzisterne:state],200,undef)\&lt;br /&gt;
\&lt;br /&gt;
&amp;quot;mit Beschriftung&amp;quot;|cylinder(&amp;quot;Zisterne&amp;quot;,0,100,&amp;quot;%&amp;quot;,undef,100,undef,0,[Wasserzisterne:state],200,&amp;quot;Wasserstand&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
&amp;quot;mit mehreren Informationen&amp;quot;|cylinder(&amp;quot;Energie&amp;quot;,-20,30,&amp;quot;kWh&amp;quot;,undef,undef,undef,1,[zaehler:Bezug],0,&amp;quot;Bezug&amp;quot;,[zaehler:Produktion],60,&amp;quot;Produktion&amp;quot;,[zaehler:Eigenverbrauch],30,&amp;quot;Eigenverbrauch&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
&amp;quot;mit hellen Farben&amp;quot;| cylinder(&amp;quot;Tag&amp;quot;,0,100,&amp;quot;kWh&amp;quot;,undef,undef,undef,1,[Heizenergie:Tagesverbrauch_hc]/100000,&amp;quot;30.100.70&amp;quot;,&amp;quot;letzter&amp;quot;,[Heizenergie:heute_hc]/100000,&amp;quot;60.100.70&amp;quot;,&amp;quot;aktuell&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:cylinder_bsp.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
=====&amp;lt;big&amp;gt;Gestapelte Werte mit cylinder_s&amp;lt;/big&amp;gt;=====&lt;br /&gt;
Gegenüberstellung cylinder und cylinder_s&lt;br /&gt;
[[Datei:cylinder_s.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
====&amp;lt;big&amp;gt;Balkendarstellung mehrerer Zahlenwerte mit Hilfe der universellen SVG-Funktion &#039;&#039;&#039;cylinder_bars&#039;&#039;&#039; &amp;lt;/big&amp;gt;====&lt;br /&gt;
Es können mehrere Zahlenwerte mit Legende farbig in Balkenform visualisiert werden. Negative Werte werden als Balken nach unten dargestellt, positive nach oben, der Nullpunkt wird automatisch berechnet. Die &#039;&#039;&#039;cylinder_bars&#039;&#039;&#039;-SVG-Funkton besitzt die gleichen Argumente, wie die obige &#039;&#039;&#039;cylinder&#039;&#039;&#039;-SVG-Funktion, mehrerer Balken werden jedoch nicht übereinander, sondern nebeneinander dargestellt.&lt;br /&gt;
{{Randnotiz|RNText=SVG-uiTable-Funktion &#039;&#039;&#039;cylinder_bars&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
cylinder_bars ($header,$min,$max,$unit,$width,$height,$size,$dec,($value1,$color1,$text1),($value2,$color2,$text2),...&lt;br /&gt;
&lt;br /&gt;
$header     # Überschrift&lt;br /&gt;
$min        # minimaler Wert, optional, default = 0&lt;br /&gt;
$max        # maximaler Wert, optional, default = 100&lt;br /&gt;
$unit       # Einheit des Wertes, optional, default = undef&lt;br /&gt;
$width      # Breite der Grafik, optional, default = wird bei Beschriftungen automatisch angepasst&lt;br /&gt;
$height     # Höhe der Grafik, optional, default = wird automatisch berechnet&lt;br /&gt;
$size       # Größe der Grafik, optional, default = 100&lt;br /&gt;
$dec        # Anzahl der Nachkommastellen, optional, default=1&lt;br /&gt;
$value1     # erster Zahlenwert&lt;br /&gt;
$color1     # HSL-Farbe des ersten Balkens: &amp;quot;&amp;lt;hue&amp;gt;.&amp;lt;saturation&amp;gt;.&amp;lt;lightness&amp;gt;&amp;quot; (hue:0-360,saturation:0-100,lightness:0-100), saturation (default:100) und lightness (default:50) sind optional&lt;br /&gt;
$text1      # Beschriftung des Zahlenwertes in der Legende, optional, default = undef&lt;br /&gt;
$value2     # zweiter Zahlenwert, optional&lt;br /&gt;
$color2     # HSL-Farbe des zweiten Balkens: &amp;quot;&amp;lt;hue&amp;gt;.&amp;lt;saturation&amp;gt;.&amp;lt;lightness&amp;gt;&amp;quot; (hue:0-360,saturation:0-100,lightness:0-100), saturation (default:100) und lightness (default:50) sind optional&lt;br /&gt;
$text2      # Beschriftung des Zahlenwertes in der Legende, optional, default = undef&lt;br /&gt;
...&lt;br /&gt;
Es können weitere Zahlenwerte jeweils mit Farbe und Beschriftung optional angegeben werden &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* [https://wiki.fhem.de/wiki/DOIF/uiTable_Schnelleinstieg#Darstellung_fortlaufender_Daten_als_S.C3.A4ulen siehe auch card bar]&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_wasserverbrauch DOIF ##&lt;br /&gt;
attr di_wasserverbrauch uiTable {package ui_Table;;}\&lt;br /&gt;
cylinder_bars(&amp;quot;Monat&amp;quot;,0,15,&amp;quot;m³&amp;quot;,undef,undef,undef,1,[Wasserverbrauch:monatsdurchschnitt],30,&amp;quot;Durchschnitt&amp;quot;,[Wasserverbrauch:monatsverbrauch]/1000,220,&amp;quot;letzter&amp;quot;,[Wasserverbrauch:monat]/1000,180,&amp;quot;aktuell&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
cylinder_bars(&amp;quot;Monat&amp;quot;,0,15,&amp;quot;m³&amp;quot;,undef,undef,undef,1,[Wasserverbrauch:jan],30,&amp;quot;Januar&amp;quot;,[Wasserverbrauch:feb],220,&amp;quot;Februar&amp;quot;,[Wasserverbrauch:mrz],180,&amp;quot;März&amp;quot;,[Wasserverbrauch:apr],30,&amp;quot;April&amp;quot;,[Wasserverbrauch:mai],220,&amp;quot;Mai&amp;quot;,[Wasserverbrauch:jun],180,&amp;quot;Juni&amp;quot;,[Wasserverbrauch:jul],30,&amp;quot;Juli&amp;quot;,[Wasserverbrauch:aug],220,&amp;quot;August&amp;quot;,[Wasserverbrauch:sep],180,&amp;quot;September&amp;quot;,[Wasserverbrauch:okt],30,&amp;quot;Oktober&amp;quot;,[Wasserverbrauch:nov],220,&amp;quot;November&amp;quot;,[Wasserverbrauch:dez],180,&amp;quot;Dezember&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:cylinder_bars_bsp.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
====&amp;lt;big&amp;gt;SVG-Grafiken beim Überstreichen mit dem Mauszeiger vergrößern&amp;lt;/big&amp;gt;====&lt;br /&gt;
Eine SVG-Grafik lässt sich beim Überstreichen mit dem Mauszeiger vergrößert darstellen. Dazu kann die hover-HTML-Eigenschaft genutzt werden.&lt;br /&gt;
&lt;br /&gt;
Im Css-Attribut des FHEMWEB-Devices wird für diesen Zweck folgende Zeile eingefügt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
svg:hover {transition: transform 0.3s ease; transform: scale(2.0); transform-origin: 0 0;z-index: 9999; position:relative}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollen nur bestimmte SVG-Grafiken vergrößert werden, so muss deren Klasse angegeben werden. Mögliche Klassen sind: DOIF_card, DOIF_ring, DOIF_bar, DOIF_cylinder.&lt;br /&gt;
&lt;br /&gt;
Es sollen nur Cards vergrößert werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
.DOIF_card:hover {transition: transform 0.3s ease; transform: scale(2.0); transform-origin: 0 0;z-index: 9999; position:relative}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es können ebenfalls mehrere Klassen mit Komma angegeben werden. Cards und Ringe sollen vergrößert werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
.DOIF_card:hover,.DOIF_ring:hover {transition: transform 0.3s ease; transform: scale(2.0); transform-origin: 0 0;z-index: 9999; position:relative}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es sich um eine allgemeingültige CSS-Definition handelt, können mit CSS-Kenntnissen durch Anpassung der Definition ebenfalls auch andere Transformationen der Grafiken vorgenommen werden. &lt;br /&gt;
&lt;br /&gt;
Auf Tablets und Smartphones wird im Browser die hover-Eigenschaft oft durch Antippen der Grafik ausgelöst.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht eines PCs:&#039;&#039;&lt;br /&gt;
[[Datei:hover.gif|ohne]]&lt;br /&gt;
&lt;br /&gt;
=== Einfache uiTable-Funktionen ===&lt;br /&gt;
==== Farbskalierte Temperaturanzeige mit Hilfe der Funktion &#039;&#039;&#039;temp&#039;&#039;&#039; ====&lt;br /&gt;
Die Farbe der dargestellten Temperatur ist abhängig vom Temperaturwert:&lt;br /&gt;
[[Datei:Farbskalierung temp.png|600px|ohne]]&lt;br /&gt;
{{Randnotiz|RNText=uiTable-Funktion &#039;&#039;&#039;temp&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
temp ($temp,$size,$icon)&lt;br /&gt;
&lt;br /&gt;
$temp # Temperatur&lt;br /&gt;
$size # Schriftgröße in Pixel (pt), optional&lt;br /&gt;
$icon # Icon, welches vorangestellt wird, optional&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_uiTable_temp DOIF ##&lt;br /&gt;
attr di_uiTable_temp uiTable {\&lt;br /&gt;
  package ui_Table;;           ## Package für uiTable-Funktionen\&lt;br /&gt;
  $TC{0..2}=&amp;quot;align=&#039;center&#039;&amp;quot;;; ## zentrierte Darstellung aller Tabellenspalten\&lt;br /&gt;
}\&lt;br /&gt;
## Tabellendefinition\&lt;br /&gt;
\&lt;br /&gt;
&amp;quot;Aussen&amp;quot;|&amp;quot;Bad&amp;quot;|&amp;quot;Warmwasser&amp;quot;                             ## mit | werden Tabellenzellen voneinander getrennt \&lt;br /&gt;
temp([Aussensensor:temperature])|                       ## Anzeige des Readings &#039;temperature&#039; des Gerätes &#039;Aussensensor&#039;  \&lt;br /&gt;
temp([TH_Bad_HM:measured-temp],24,&amp;quot;temp_temperature&amp;quot;)|  ## Schriftgröße 24pt, mit Icon namens temp_temperature\&lt;br /&gt;
temp([T_Warmwasserspeicher:temperature:d1],20)          ## Schriftgröße 20pt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:Temp.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
==== Farbskalierte Feuchtigkeitsanzeige mit Hilfe der Funktion &#039;&#039;&#039;hum&#039;&#039;&#039; ====&lt;br /&gt;
Die Farbe der dargestellten Feuchtigkeit ist abhängig vom Feuchtigkeitswert:&lt;br /&gt;
[[Datei:Farbskalierung hum.png|350px|ohne]]&lt;br /&gt;
{{Randnotiz|RNText=uiTable-Funktion &#039;&#039;&#039;hum&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
hum ($hum,$size,$icon)&lt;br /&gt;
&lt;br /&gt;
$hum  # Feuchtigkeit&lt;br /&gt;
$size # Schriftgröße in Pixel (pt), optional&lt;br /&gt;
$icon # Icon, welches vorangestellt wird, optional&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_uiTable_hum DOIF ##&lt;br /&gt;
attr di_uiTable_hum uiTable {\&lt;br /&gt;
package ui_Table;;\&lt;br /&gt;
$TC{1}=&amp;quot;align=&#039;center&#039;&amp;quot;;; ## zweite Spalte der Tabelle zentriert\&lt;br /&gt;
}\&lt;br /&gt;
## Tabellendefinition \&lt;br /&gt;
\&lt;br /&gt;
## Anzeige des Readings &#039;humidity&#039; des Thermostats &#039;TH_Bad_HM&#039;  \&lt;br /&gt;
&amp;quot;Bad&amp;quot;|hum ([TH_Bad_HM:humidity])\&lt;br /&gt;
\&lt;br /&gt;
## Feuchtigkeit in Größe 10pt mit Temperatur in einer Tabellenzelle\&lt;br /&gt;
&amp;quot;Aussen&amp;quot;|temp ([Aussensensor:temperature]),hum ([Aussensensor:humidity],10)\&lt;br /&gt;
\&lt;br /&gt;
## Feuchtigkeit in Größe 26pt mit Icon namens &#039;temperature_humidity&#039;\&lt;br /&gt;
&amp;quot;Keller&amp;quot;|hum ([TH_Keller_HM:humidity],26,&amp;quot;temperature_humidity&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable Funktion hum.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
==== Textformatierungen mit Hilfe der Funktion &#039;&#039;&#039;style&#039;&#039;&#039; ====&lt;br /&gt;
Texte werden in Farbe, Größe und Schriftart statisch oder dynamisch formatiert.&lt;br /&gt;
{{Randnotiz|RNText=uiTable-Funktion &#039;&#039;&#039;style&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
style ($text,$color,$font_size,$font_weight)&lt;br /&gt;
&lt;br /&gt;
$text        # anzuzeigender Text&lt;br /&gt;
$color       # CSS color, optional&lt;br /&gt;
$font_size   # Schriftgröße in Pixel (pt), optional&lt;br /&gt;
$font_weight # CSS Schriftart, optional&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Mögliche Werte für &#039;&#039;&#039;&#039;&#039;color&#039;&#039;&#039;&#039;&#039; und &#039;&#039;&#039;&#039;&#039;font_weight&#039;&#039;&#039;&#039;&#039; können in einschlägiger Dokumentation zu CSS nachgeschlagen werden&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_uiTable_style DOIF ##&lt;br /&gt;
attr di_uiTable_style uiTable {\&lt;br /&gt;
  package ui_Table;;\&lt;br /&gt;
}\&lt;br /&gt;
## Tabellendefinition\&lt;br /&gt;
\&lt;br /&gt;
## statische Farbgebung, Größe, Schriftart \&lt;br /&gt;
style(&amp;quot;Montag&amp;quot;,&amp;quot;orange&amp;quot;)\&lt;br /&gt;
style(&amp;quot;Dienstag&amp;quot;,&amp;quot;red&amp;quot;,14)\&lt;br /&gt;
style(&amp;quot;Mittwoch&amp;quot;,&amp;quot;#00FFFF&amp;quot;,20)\&lt;br /&gt;
style(&amp;quot;Donnerstag&amp;quot;,&amp;quot;blue&amp;quot;,23,&amp;quot;bold&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
## dynamische Farbgebung abhängig vom Zustand des Gerätes &#039;Alarm&#039;\&lt;br /&gt;
style(&amp;quot;Alarm&amp;quot;,([Alarm:state] eq &amp;quot;on&amp;quot; ? &amp;quot;red&amp;quot;:&amp;quot;green&amp;quot;))\&lt;br /&gt;
\&lt;br /&gt;
## dynamische Farbgebung des Zustands des Gerätes &#039;Alarm&#039;\&lt;br /&gt;
style([Alarm:state],([Alarm:state] eq &amp;quot;on&amp;quot; ? &amp;quot;red&amp;quot;:&amp;quot;green&amp;quot;))\&lt;br /&gt;
\&lt;br /&gt;
## variabler Text abhängig vom Zustand des Gerätes &#039;Alarm&#039;\&lt;br /&gt;
style(([Alarm:state] eq &amp;quot;on&amp;quot; ? &amp;quot;Alarm aktiv&amp;quot;:&amp;quot;Alarm deaktiviert&amp;quot;),&amp;quot;red&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:Style.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
==== Icon-Darstellung mit Hilfe der Funktion &#039;&#039;&#039;ICON&#039;&#039;&#039; ====&lt;br /&gt;
Mit Hilfe der Funktion &#039;&#039;&#039;ICON&#039;&#039;&#039; kann ein FHEM-Icon dargestellt werden&lt;br /&gt;
{{Randnotiz|RNText=uiTable-Funktion &#039;&#039;&#039;ICON&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
ICON ($icon)&lt;br /&gt;
&lt;br /&gt;
$icon        # Icon mit Farbgebung&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ICON&#039;&#039;&#039; benutzt die Funktion [[DevelopmentFHEMWEB-API#FW_makeImage|FW_makeImage]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nützliche Links&#039;&#039;&#039;&lt;br /&gt;
* [[DOIF/uiTable Schnelleinstieg#hsv-Funktion für Farbskalierungen|hsv-Funktion]]&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_Table_ICON DOIF ##&lt;br /&gt;
attr di_Table_ICON uiTable {\&lt;br /&gt;
package ui_Table;;\&lt;br /&gt;
}\&lt;br /&gt;
## Tabellendefinition\&lt;br /&gt;
ICON(&amp;quot;temp_frost&amp;quot;) |  ## Icon ohne Einfärbung\&lt;br /&gt;
ICON(&amp;quot;temp_frost\@blue&amp;quot;) | ## Icon in CSS-Farbe blau\&lt;br /&gt;
ICON(&amp;quot;temp_frost\@#8A2BE2&amp;quot;) | ## Icon in CSS-Farbe #8A2BE2\&lt;br /&gt;
ICON(&amp;quot;temp_frost\@&amp;quot;.([Aussensensor:temperature] &amp;gt; 0 ? &amp;quot;orange&amp;quot;:&amp;quot;blue&amp;quot;))| ## Icon in CSS-Farbe orange über Null Grad, sonst in CSS-Farbe blau\&lt;br /&gt;
ICON(&amp;quot;temp_frost\@&amp;quot;.hsv ([Aussensensor:temperature],-20,40,320,0)) ## Icon in Farbskalierung von violett (-20 °C) bis rot (40 °C) mit Hilfe der Funktion hsv&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable_IC.png|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
==== Icon-Darstellung mit Text mit Hilfe der Funktion &#039;&#039;&#039;icon_label&#039;&#039;&#039; ====&lt;br /&gt;
Mit Hilfe der Funktion &#039;&#039;&#039;icon_label&#039;&#039;&#039; kann ein FHEM-Icon mit einem angehängten Text/Wert dargestellt werden.&lt;br /&gt;
{{Randnotiz|RNText=uiTable-Funktion &#039;&#039;&#039;icon_label&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
icon_label ($icon,$text,$color,$color_bg,$pos_left,$pos_top)&lt;br /&gt;
$icon        # FHEM-Icon mit Farboption&lt;br /&gt;
$text        # dargestellter Text&lt;br /&gt;
$color       # Farbe des Textes, optional&lt;br /&gt;
$color       # Hintergrundfarbe des Textes, optional&lt;br /&gt;
$pos_left    # horizontale Position des Textes in px, default -5, optional&lt;br /&gt;
$pos_top     # vertikale Position des Textes in px, default -8, optional&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Anwendungsbeispiele&#039;&#039;&#039;&lt;br /&gt;
* [[DOIF/uiTable Schnelleinstieg#Anzahl der Tage bis zur Abfall-Entsorgung|Abfall]]&lt;br /&gt;
* [[DOIF/uiTable Schnelleinstieg#Visualisierung: aktueller Spritpreis|Sprit]]&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_uiTable_icon_label DOIF ##&lt;br /&gt;
attr di_uiTable_icon_label uiTable { package ui_Table;;\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
icon_label(&amp;quot;fuel&amp;quot;,[Tankstelle:Diesel])|\&lt;br /&gt;
icon_label(&amp;quot;fuel&amp;quot;,[Tankstelle:Diesel],&amp;quot;red&amp;quot;)|\&lt;br /&gt;
icon_label(&amp;quot;fuel\@blue&amp;quot;,[Tankstelle:Diesel],&amp;quot;blue&amp;quot;,&amp;quot;#999999&amp;quot;)|\&lt;br /&gt;
icon_label(&amp;quot;fuel\@red&amp;quot;,[Tankstelle:Diesel],&amp;quot;red&amp;quot;,&amp;quot;white&amp;quot;,-10)|\&lt;br /&gt;
icon_label(&amp;quot;fuel&amp;quot;,[Tankstelle:Diesel],&amp;quot;white&amp;quot;,&amp;quot;red&amp;quot;,-5,8)\&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable_icon_label.png|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
==== Visualisierung eines Gerätes mit Hilfe der Funktion &#039;&#039;&#039;icon&#039;&#039;&#039; ====&lt;br /&gt;
Der Zustand eines Gerätes/Readings wird mit Hilfe eines Icons dargestellt.&lt;br /&gt;
{{Randnotiz|RNText=uiTable-Funktion &#039;&#039;&#039;icon&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
icon ($value,$icon_off,$icon_on,$state_off,$state_on)&lt;br /&gt;
&lt;br /&gt;
$value       # Wert &lt;br /&gt;
$icon_off    # Icon für den Wert off, default &amp;quot;off&amp;quot;&lt;br /&gt;
$icon_on     # Icon für den Wert on, default Icon für Wert &#039;off&#039; in Farbe &#039;DarkOrange&#039;, sonst Icon &#039;on&#039;, wenn $icon_off nicht definiert ist&lt;br /&gt;
$state_off   # Wert zugehörig zum Icon off, default &amp;quot;off&amp;quot;&lt;br /&gt;
$state_on    # Wert zugehörig zum Icon on, default &amp;quot;on&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_uiTable_icon DOIF ##&lt;br /&gt;
attr di_uiTable_icon uiTable {\&lt;br /&gt;
  package ui_Table;;\&lt;br /&gt;
}\&lt;br /&gt;
## Tabellendefinition\&lt;br /&gt;
\&lt;br /&gt;
 ## Standard-Icon off/on für Standardwert off/on \&lt;br /&gt;
&amp;quot;Lampe&amp;quot;|icon([Lampe:state])    ## entspricht icon([Lampe:state],&amp;quot;off&amp;quot;,&amp;quot;on&amp;quot;,&amp;quot;off&amp;quot;,&amp;quot;on&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
## Icon für Zustand &#039;off&#039; ist &#039;hue_room_hallway&#039;, für Zustand &#039;on&#039; &#039;hue_room_hallway\@DarkOrange&#039;\&lt;br /&gt;
&amp;quot;Flur&amp;quot;|icon([Lampeflur:state],&amp;quot;hue_room_hallway&amp;quot;)    ## entspricht icon([Lampeflur:state],&amp;quot;hue_room_hallway&amp;quot;,&amp;quot;hue_room_hallway\DarkOrange&amp;quot;,&amp;quot;off&amp;quot;,&amp;quot;on&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
## Icon für Zustand &#039;off&#039; ist &#039;status_away_2&#039;, für Zustand &#039;on&#039; &#039;status_available\@DarkOrange&#039;\&lt;br /&gt;
&amp;quot;Anwesenheit&amp;quot;|icon([Anwesenheit:state],&amp;quot;status_away_2&amp;quot;,&amp;quot;status_available\@DarkOrange&amp;quot;) \&lt;br /&gt;
\&lt;br /&gt;
## Icon für Zustand &#039;closed&#039; ist &amp;quot;status_locked&amp;quot;, für Zustand &#039;open&#039; &#039;status_open\@DarkOrange&#039;\&lt;br /&gt;
&amp;quot;Haus&amp;quot;|icon([Schloss:state],&amp;quot;status_locked&amp;quot;,&amp;quot;status_open\@DarkOrange&amp;quot;,&amp;quot;closed&amp;quot;,&amp;quot;open&amp;quot;) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable icon.png|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
==== Schaltbares Icon mit Hilfe der Funktion &#039;&#039;&#039;switch&#039;&#039;&#039; ====&lt;br /&gt;
Der Zustand eines Gerätes/Readings wird mit Hilfe eines Icons dargestellt, er kann über die WEB-Oberfläche durch Anklicken geschaltet werden. Damit der Zustand des Gerätes geschaltet werden kann, muss das Gerät den set-Befehl unterstützen.&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=uiTable-Funktion &#039;&#039;&#039;switch&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
switch ($value,$icon_off,$icon_on,$state_off,$state_on)&lt;br /&gt;
&lt;br /&gt;
$value       # [&amp;lt;device&amp;gt;:&amp;lt;reading&amp;gt;] &lt;br /&gt;
$icon_off    # Icon für den Wert off, default &amp;quot;off&amp;quot;&lt;br /&gt;
$icon_on     # Icon für den Wert on, default Icon für Wert &#039;off&#039; in Farbe &#039;DarkOrange&#039;, sonst Icon &#039;on&#039;, wenn $icon_off nicht definiert ist&lt;br /&gt;
$state_off   # Wert zugehörig zum Icon off, default &amp;quot;off&amp;quot;&lt;br /&gt;
$state_on    # Wert zugehörig zum Icon on, default &amp;quot;on&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_uiTable_switch DOIF ##&lt;br /&gt;
attr di_uiTable_switch uiTable {\&lt;br /&gt;
  package ui_Table;;\&lt;br /&gt;
}\&lt;br /&gt;
## schaltbares Icons in der Webansicht \&lt;br /&gt;
switch([Lampe:state]) | \&lt;br /&gt;
switch([Lampeflur:state],&amp;quot;hue_room_hallway&amp;quot;) |\&lt;br /&gt;
switch([Anwesenheit:state],&amp;quot;status_away_2&amp;quot;,&amp;quot;status_available\@DarkOrange&amp;quot;)|\&lt;br /&gt;
switch([Haus:state],&amp;quot;status_locked&amp;quot;,&amp;quot;status_open\@DarkOrange&amp;quot;,&amp;quot;closed&amp;quot;,&amp;quot;open&amp;quot;)\&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable switch.png|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
==== Rollladen: Visualisierung und Steuerung mit Hilfe der Funktion &#039;&#039;&#039;shutter&#039;&#039;&#039; ====&lt;br /&gt;
Die aktuelle Position des Rollladens (0 % - 100 %) wird über Icons visualisiert. Das Anklicken eines Symbols steuert den Rollladen auf die entsprechende Position. Prozentwerte zwischen zwei Icon-Werten werden dem nächsthöheren Icon-Wert zugeordnet.&lt;br /&gt;
{{Randnotiz|RNText=uiTable-Funktion &#039;&#039;&#039;shutter&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
shutter ($value,$color,$type)&lt;br /&gt;
&lt;br /&gt;
$value       # [&amp;lt;device&amp;gt;:&amp;lt;reading&amp;gt;] &lt;br /&gt;
$color       # Farbe der aktuellen Rollladenposition, vorangestelltes @ verändert die Farbe des Icons, ohne @ wird der Hintergrund des Icons eingefärbt, default ist @DarkOrange&lt;br /&gt;
$type        # optional, Anzahl der Symbole 2 bis 6, 3 ist default&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* [[DOIF/uiTable Schnelleinstieg#Visualisierung und Steuerung von Rollläden|Anwendungsbeispiel]]&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod ui_Table_shutter DOIF ##&lt;br /&gt;
attr ui_Table_shutter uiTable {\&lt;br /&gt;
  package ui_Table;;\&lt;br /&gt;
}\&lt;br /&gt;
shutter([R_Keller:pct],&amp;quot;\@yellow&amp;quot;,2)     ## zwei Symbole für 0 % und 100 %\&lt;br /&gt;
shutter([R_Wohnzimmer_S:pct])            ## entspricht shutter ([R_Wohnzimmer_S:pct],&amp;quot;\@DarkOrange&amp;quot;,3) \&lt;br /&gt;
shutter([R_Wohnzimmer_W1:pct],&amp;quot;blue&amp;quot;,4)  ## vier Symbole \&lt;br /&gt;
shutter([R_Wohnzimmer_W2:pct],&amp;quot;\@red&amp;quot;,5) ## fünf Symbole\&lt;br /&gt;
shutter([R_Wohnzimmer_W3:pct],&amp;quot;red&amp;quot;,6    ## sechs Symbole)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable shutter.png|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
====  Helligkeit: Visualisierung und Steuerung mit Hilfe der Funktion &#039;&#039;&#039;dimmer&#039;&#039;&#039; ====&lt;br /&gt;
Die aktuelle Helligkeit (0 % - 100 %) wird über Icons visualisiert. Das Anklicken eines Icons bestimmt die Helligkeit der Leuchte. Prozentwerte zwischen zwei Icon-Werten werden dem nächsthöheren Icon-Wert zugeordnet.&lt;br /&gt;
{{Randnotiz|RNText=uiTable-Funktion &#039;&#039;&#039;dimmer&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
dimmer ($value,$color,$type)&lt;br /&gt;
&lt;br /&gt;
$value       # [&amp;lt;device&amp;gt;:&amp;lt;reading&amp;gt;] &lt;br /&gt;
$color       # Farbe der aktuellen Helligkeit, vorangestelltes @ verändert die Farbe des Icons, ohne @ wird der Hintergrund des Icons eingefärbt, default ist @DarkOrange&lt;br /&gt;
$type        # Anzahl der Symbole 2 bis 7, 3 ist default&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_uiTable_dimmer DOIF ##&lt;br /&gt;
attr di_uiTable_dimmer uiTable {\&lt;br /&gt;
  package ui_Table;;\&lt;br /&gt;
}\&lt;br /&gt;
dimmer([Strauch3:pct],&amp;quot;\@yellow&amp;quot;,2)\&lt;br /&gt;
dimmer([Strauch3:pct]) ## entspricht dimmer([Strauch3:pct],&amp;quot;\@DarkOrange&amp;quot;,3) \&lt;br /&gt;
dimmer([Strauch3:pct],&amp;quot;blue&amp;quot;,4)\&lt;br /&gt;
dimmer([Strauch3:pct],&amp;quot;\@red&amp;quot;,5)\&lt;br /&gt;
dimmer([Strauch3:pct],&amp;quot;red&amp;quot;,6)\&lt;br /&gt;
dimmer([Strauch3:pct],&amp;quot;DarkOrange&amp;quot;,7)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable dimmer.png|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
====  Vorgabetemperatur eines Thermostats mit Hilfe der Funktion &#039;&#039;&#039;temp_knob&#039;&#039;&#039; ====&lt;br /&gt;
Die aktuelle Vorgabetemperatur eines Thermostats wird über ein Icons visualisiert. Durch Anklicken des Ringes wird die Vorgabetemperatur verändert.&lt;br /&gt;
{{Randnotiz|RNText=uiTable-Funktion &#039;&#039;&#039;temp_knob&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
temp_knob ($value,$color,$set)&lt;br /&gt;
&lt;br /&gt;
$value       # [&amp;lt;device&amp;gt;:&amp;lt;reading&amp;gt;] &lt;br /&gt;
$color       # Farbe der voreingestellten Temperatur, default &amp;quot;Darkorange&amp;quot;&lt;br /&gt;
$set         # set-Befehl, default &amp;quot;set&amp;quot;, sonst muss &amp;quot;set &amp;lt;Readingname&amp;gt;&amp;quot; angegeben werden, falls sich das Reading vom set-Befehl vom angezeigten Reading unterscheidet, wie beim THRESHOLD-Modul&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod ui_Table_temp_knob DOIF ##&lt;br /&gt;
attr ui_Table_temp_knob uiTable {\&lt;br /&gt;
package ui_Table;;\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
## HM-EU-Thermostat, angezeigt wird das Reading &amp;quot;desired-temp&amp;quot;, geschaltet wird über &amp;quot;set desired-temp&amp;quot; \&lt;br /&gt;
&amp;quot;Dachgeschoss&amp;quot;|temp_knob([TH_DG_HM:desired-temp]) ## entspricht temp_knob([TH_DG_HM:desired-temp],&amp;quot;Darkorange&amp;quot;,&amp;quot;set&amp;quot;) \&lt;br /&gt;
\&lt;br /&gt;
## HM-EU-Thermostat Temperaturanzeige in gelb \ &lt;br /&gt;
&amp;quot;Wohnzimmer&amp;quot;|temp_knob([TH_WZ_HM:desired-temp],&amp;quot;yellow&amp;quot;) \&lt;br /&gt;
\&lt;br /&gt;
## Beim THRESHOLD-Modul wird das Reading &amp;quot;desired_value&amp;quot; angezeigt, geändert wird die Temperatur per &amp;quot;set desired&amp;quot; \&lt;br /&gt;
&amp;quot;Küche&amp;quot;|temp_knob([TH_Kueche:desired_value],&amp;quot;red&amp;quot;,&amp;quot;set desired&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable temp knob.png|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
==  uiTable-&#039;&#039;&#039;Templates&#039;&#039;&#039; ==&lt;br /&gt;
Die Definition einer oder mehrere Zellen kann zu einem Template zusammengefasst werden. Durch die Nutzung von Templates kann die Definition einer Tabelle erheblich vereinfacht werden. Insb. bei gleichartigen Zellen/Zeilen für verschiedene Geräte/Readings braucht eine aufwendige Definition nicht immer wieder wiederholt werden, sondern kann jeweils mit dem Aufruf eines zuvor definierten Templates realisiert werden.&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;Templates&#039;&#039;&#039;&lt;br /&gt;
* Die Definition von Templates muss vor der Tabellendefinition vorgenommen werden&lt;br /&gt;
* Eine Template-Definition beginnt mit dem Schlüsselwort &#039;&#039;&#039;DEF&#039;&#039;&#039;&lt;br /&gt;
* Der Template-Name muss mit &#039;&#039;&#039;TPL_&#039;&#039;&#039; beginnen&lt;br /&gt;
* &#039;&#039;&#039;Template-Definition&#039;&#039;&#039;-Syntax&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
DEF TPL_&amp;lt;Template-Name&amp;gt;(&amp;lt;Zellendefinition mit Platzhaltern: $1,$2,...&amp;gt;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Templates-Definitionen können in externe Dateien ausgelagert werden&lt;br /&gt;
* Templates-Definitionen können per IMPORT-Befehl aus externen Dateien importiert werden&lt;br /&gt;
* &#039;&#039;&#039;Template-Import&#039;&#039;&#039;-Syntax&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
IMPORT &amp;lt;Pfad mit Dateinamen&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Innerhalb einer Tabellendefinition können zuvor definierte oder importierte Templates mehrfach genutzt werden&lt;br /&gt;
* &#039;&#039;&#039;Template-Aufruf&#039;&#039;&#039;-Syntax&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
TPL_&amp;lt;Template-Name&amp;gt;(&amp;lt;Übergabeparameter für $1&amp;gt;,&amp;lt;Übergabeparameter für $2&amp;gt;,...)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod ui_Table_Template DOIF ##&lt;br /&gt;
attr ui_Table_Template uiTable {\&lt;br /&gt;
  package ui_Table;;\&lt;br /&gt;
  $TC{1..3}=&amp;quot;align=&#039;center&#039;&amp;quot;;; ## Spalten 1 bis 3 werden zentriert\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
## Template-Definitionen beginnen vor der Tabellendefinition\&lt;br /&gt;
\&lt;br /&gt;
## Das Template TPL_raum stellt eine Tabellenzeile dar, die mit Hilfe von uiTable-Funktionen mehrere Tabellenzellen definiert\&lt;br /&gt;
DEF TPL_raum (&amp;quot;$1&amp;quot; | temp([TH_$2_HM:measured-temp]),hum([TH_$2_HM:humidity]) | switch([H_$2:state],&amp;quot;fa_off&amp;quot;) | temp_knob([TH_$2_HM:desired-temp]))\&lt;br /&gt;
\&lt;br /&gt;
## Tabellendefinition\&lt;br /&gt;
\&lt;br /&gt;
## pro Tabellenzeile wird ein Raum mit Hilfe des oben definierten Templates &amp;quot;TPL_raum&amp;quot; dargestellt\&lt;br /&gt;
&amp;quot;Raum&amp;quot;|&amp;quot;Temp./Feuchte&amp;quot;|&amp;quot;Ventil&amp;quot;|&amp;quot;Vorgabetemp.&amp;quot;\&lt;br /&gt;
TPL_raum (Dachgeschoss,DG)  ## der Übergabeparameter &amp;quot;Dachgeschoss&amp;quot; wird im Template &amp;quot;TPL_raum&amp;quot; anstelle von $1 eingesetzt, &amp;quot;DG&amp;quot; wird anstelle von $2 eingesetzt\&lt;br /&gt;
TPL_raum (Bad,Bad)\&lt;br /&gt;
TPL_raum (Kinderzimmer ost,Kz_o)\&lt;br /&gt;
TPL_raum (Kinderzimmer west,Kz_w)\&lt;br /&gt;
TPL_raum (Wohnzimmer,WZ)\&lt;br /&gt;
TPL_raum (Keller,Keller)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable Templates.png|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
==  Eigene uiTable-Funktionen programmieren ==&lt;br /&gt;
Für die eigenen Bedürfnisse können eigene uiTable-Funktionen programmiert werden. In der Datei [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DOIF/uiTable.tpl contrib/DOIF/uiTable.tpl] befinden sich alle intern definierten uiTable-Funktion aus dem package ui_Table als Kopie. Diese Funktionen können als Inspiration für eigene Entwicklung dienen. &lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;uiTable-Funktionen&#039;&#039;&#039;&lt;br /&gt;
* Es gibt drei Arten von uiTable-Funktionen, sie werden intern anhand der Rückgabewerte unterschieden&lt;br /&gt;
* uiTable-Funktionen vom Typ 1: &#039;&#039;&#039;HTML&#039;&#039;&#039;, ein Rückgabewert&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
return(&amp;lt;HTML-code&amp;gt;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* uiTable-Funktionen vom Typ 2: &#039;&#039;&#039;Style&#039;&#039;&#039; (entspricht der &#039;&#039;&#039;STY&#039;&#039;&#039;-Funktion), zwei Rückgabewerte&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
return(&amp;lt;value&amp;gt;,&amp;lt;CSS-style&amp;gt;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* uiTable-Funktionen vom Typ 3: &#039;&#039;&#039;Widget&#039;&#039;&#039; (entspricht der &#039;&#039;&#039;WID&#039;&#039;&#039;-Funktion), vier Rückgabewerte&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
return (&amp;lt;value&amp;gt;,&amp;lt;&amp;gt;,&amp;lt;FHEM-widget&amp;gt;,&amp;lt;set-command: &amp;quot;&amp;quot; or &amp;quot;set&amp;quot; or &amp;quot;set &amp;lt;Readingname&amp;gt;&amp;quot;&amp;gt;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* uiTable-Funktionen sind reine Perlfunktionen&lt;br /&gt;
* uiTable-Funktionen sollten im eigenen Package definiert werden, sonst könnten bestehende Perlfunktionen im System überschrieben werden&lt;br /&gt;
* uiTable-Funktionen können in Template-Dateien ausgelagert werden und über IMPORT-Befehl importiert werden, siehe Templates&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_uiTable_function DOIF ##&lt;br /&gt;
attr di_uiTable_function uiTable {\&lt;br /&gt;
package my_uiTable;; ## eigenes Package mit selbstdefinierten Funktionen\&lt;br /&gt;
\&lt;br /&gt;
## uiTable-Funktion vom Typ &amp;quot;HTML&amp;quot;, Rückgabewert: (HTML-code)\&lt;br /&gt;
\&lt;br /&gt;
sub clock { ## Anzeige aktueller Uhrzeit mit Datum\&lt;br /&gt;
            ## Voraussetzung: contrib/DOIF/doifclock.js muss ins www/pgm2-Verzeichnis kopiert werden\&lt;br /&gt;
            ## Attribut setzen in der Webinstanz: attr &amp;lt;WEB-Instanz&amp;gt; JavaScripts pgm2/doifclock.js \&lt;br /&gt;
  my ($color,$size)=@_;;\&lt;br /&gt;
  $color=&amp;quot;darkorange&amp;quot; if (!defined ($color));; ## $color ist optional, default Darkorange\&lt;br /&gt;
  $size=&amp;quot;20&amp;quot; if (!defined ($size));;           ## $size ist optional, default 20pt\&lt;br /&gt;
  return(&amp;quot;&amp;lt;div class=&#039;doifclock&#039;style=&#039;font-weight:bold;;font-size:&amp;quot;.$size.&amp;quot;pt;;color:&amp;quot;.$color.&amp;quot;;;&#039;&amp;gt;error&amp;lt;/div&amp;gt;&amp;quot;)\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
## uiTable-Funktion vom Typ Style, Rückgabewerte (Wert,CSS-style)\&lt;br /&gt;
\&lt;br /&gt;
sub red_green { ## Farbige Skalierung von Zahlen mit Hilfe der DOIF_hsv-Funktion: von 0 - rot bis 10 - grün\&lt;br /&gt;
    my ($value)=@_;;\&lt;br /&gt;
    return ($value.&amp;quot; KW&amp;quot;,                                                   ## Wert/Text\&lt;br /&gt;
           &amp;quot;font-weight:bold;;color:&amp;quot;.::DOIF_hsv ($value,0,10,0,120,70,100) ## CSS-Style\&lt;br /&gt;
           );;\&lt;br /&gt;
} \&lt;br /&gt;
\&lt;br /&gt;
## uiTable-Funktion vom Typ Widget, Rückgabewerte (Wert,Leer,FHEM-Widget,set-Befehl)\&lt;br /&gt;
\&lt;br /&gt;
sub slider { ## FHEM-Widget Slider, weitere FHEM-Widgets siehe: https://wiki.fhem.de/wiki/FHEMWEB/Widgets\&lt;br /&gt;
    my ($value,$set)=@_;;\&lt;br /&gt;
    $set=&amp;quot;&amp;quot; if (!defined $set);;\&lt;br /&gt;
    return ($value,                   ## Zahlenwert\&lt;br /&gt;
            &amp;quot;&amp;quot;,                       ## leer\&lt;br /&gt;
            &amp;quot;slider,0,0.5,100,1&amp;quot;,     ## FHEM-Widget\&lt;br /&gt;
            $set                      ## set-Befehl des FHEM-Widgets\&lt;br /&gt;
            ) \&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
## Tabellendefinition\&lt;br /&gt;
\&lt;br /&gt;
&amp;quot;Uhrzeit/Datum&amp;quot;\&lt;br /&gt;
clock(&amp;quot;yellow&amp;quot;,30)          ## obige Funktion clock\&lt;br /&gt;
&amp;quot;Dimmer&amp;quot;\&lt;br /&gt;
slider([Wohnzimmer:pct])    ## obige Funktion slider\&lt;br /&gt;
&amp;quot;Leistung&amp;quot;\&lt;br /&gt;
red_green([Leistung:state]) ## obige Funktion red_green&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable-functions.png|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
== Package-Konzept, Auslagerung eigener Funktionen, der &#039;&#039;&#039;IMPORT&#039;&#039;&#039;-Befehl==&lt;br /&gt;
uiTable arbeitet mit Packages. In einem Package sind definierte Funktionen gekapselt, sie kollidieren nicht mit bereits definierten Funktionen in FHEM.&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;Package&#039;&#039;&#039;&lt;br /&gt;
* das für die Definition der Tabelle gültige Package wird im Perlblock des uiTable-Attributes angegeben&lt;br /&gt;
* interne uiTable-Funktionen befinden sich im Package &#039;&#039;&#039;ui_Table&#039;&#039;&#039;&lt;br /&gt;
* ohne eine Angabe eines Package befindet man sich im Package &#039;&#039;&#039;main&#039;&#039;&#039;&lt;br /&gt;
* Funktionen außerhalb des gültigen Package müssen mit &amp;lt;package-Name&amp;gt;::&amp;lt;Funktion&amp;gt; angegeben werden&lt;br /&gt;
* externe uiTable-Funktionen können per IMPORT-Befehl importiert werden&lt;br /&gt;
}} &lt;br /&gt;
=== Tabellendefinition im Package main ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod beispiel1 DOIF ##&lt;br /&gt;
attr beispiel1 uiTable ## keine Package-Definition im Perlblock\&lt;br /&gt;
\&lt;br /&gt;
## Tabellendefinition befindet sich im Package main\&lt;br /&gt;
\&lt;br /&gt;
## Funktionen aus dem main-Package können unmittelbar angegeben werden\&lt;br /&gt;
FW_makeImage(&amp;quot;scene_day&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
## Funktionen aus dem ui_Table-Package müssen mit vorangestelltem Package angegeben werden\&lt;br /&gt;
ui_Table::temp ([Aussensensor:tempaerature])&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tabellendefinition im Package ui_Table ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod beispiel2 DOIF ##&lt;br /&gt;
attr beispiel2 uiTable {\&lt;br /&gt;
  package ui_Table; ## Package-Angabe im Perlblock\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
## Tabellendefinition befindet sich im Package ui_Table\&lt;br /&gt;
\&lt;br /&gt;
## Funktionen aus dem main-Package müssen mit vorangestelltem package angegeben werden, der Name main kann weggelassen werden\&lt;br /&gt;
::FW_makeImage(&amp;quot;scene_day&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
## Funktionen aus dem ui_Table-Package können direkt angegeben werden\&lt;br /&gt;
temp ([Aussensensor:temperature])&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Eigene uiTable-Funktionen im eigenen Package ===&lt;br /&gt;
Diese Art der Definition bietet sich dann an, wenn man eine eigene uiTable-Funktion nur in einem DOIF nutzen möchte.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod beispiel3 DOIF ##&lt;br /&gt;
attr beispiel3 uiTable {\&lt;br /&gt;
  package $SELF;;  ## Package-Name ist der Name des DOIF-Moduls, dadurch ist der Package-Name eindeutig\&lt;br /&gt;
  sub scene_day {  ## eigene Funktion befindet sich im eigenen Package beispiel3\&lt;br /&gt;
    return (::FW_makeImage(&amp;quot;scene_day&amp;quot;));;\&lt;br /&gt;
  }\&lt;br /&gt;
}\&lt;br /&gt;
## Tabellendefinition befindet sich im Package beispiel3\&lt;br /&gt;
\&lt;br /&gt;
## Funktionen aus dem main-Package müssen mit vorangestelltem Package angegeben werden (der Name main kann weggelassen werden)\&lt;br /&gt;
::FW_makeImage(&amp;quot;scene_day&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
## interne Funktionen aus dem ui_Table-Package müssen mit vorangestelltem Package ui_Table angegeben werden\&lt;br /&gt;
ui_Table::temp ([Aussensensor:temperature])\&lt;br /&gt;
\&lt;br /&gt;
## eigene Funktionen können direkt angegeben werden\&lt;br /&gt;
scene_day()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Eigene ausgelagerte uiTable-Funktionen ===&lt;br /&gt;
Möchte man das ui_Table-Package um eigene Funktionen erweitern, die man in verschiedenen DOIFs nutzen möchte, so sollte man diese in eine eigene Datei auslagern, die man mit dem IMPORT-Befehl vor der Definition der Tabelle importieren kann.&lt;br /&gt;
&lt;br /&gt;
Ausgelagerte Funktion in einer eigenen Datei z. B. my_uiTable.tpl:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
{ ## Inhalt der Datei my_uiTable.tpl&lt;br /&gt;
  package ui_Table; ## das aktuelle Package  ist ui_Table&lt;br /&gt;
  sub scene_day {   ## eigene Funktion wird zum Package ui_Table hinzugefügt &lt;br /&gt;
    return (::FW_makeImage(&amp;quot;scene_day&amp;quot;));&lt;br /&gt;
  }&lt;br /&gt;
  ## die Datei kann alle Funktionen beinhalten, die man in diversen DOIFs nutzen möchte&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod beispiel4 DOIF ##&lt;br /&gt;
attr beispiel4 uiTable ##\&lt;br /&gt;
\&lt;br /&gt;
IMPORT ./contrib/DOIF/my_uiTable.tpl ## nach dem Import befindet man sich in Package ui_Table erweitert um eigene Funktionen\&lt;br /&gt;
\&lt;br /&gt;
## Tabellendefinition befindet sich im Package ui_Table\&lt;br /&gt;
\&lt;br /&gt;
## Funktionen aus dem main-Package müssen mit vorangestelltem Package angegeben werden (der Name main kann weggelassen werden)\&lt;br /&gt;
::FW_makeImage(&amp;quot;scene_day&amp;quot;)\&lt;br /&gt;
\&lt;br /&gt;
## interne uiTable-Funktionen aus dem ui_Table-Package können direkt angegeben werden\&lt;br /&gt;
temp ([Aussensensor:temperature])\&lt;br /&gt;
\&lt;br /&gt;
## eigene Funktionen können direkt angegeben werden, da man sich bereits im Package uiTable befinden\&lt;br /&gt;
scene_day()\&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==  &#039;&#039;&#039;hsv&#039;&#039;&#039;-Funktion für Farbskalierungen==&lt;br /&gt;
Mit Hilfe der hsv-Funktion können Texte, Werte oder Icons abhängig vom Wert eingefärbt werden. Es wird durch Vorgabe von Farbsättigung (saturation) und Helligkeit (lightness), linear ein Farbton für einen bestimmten Wert errechnet. Den Farbwert HUE (0 - 360) für den kleinsten sowie größten Wert kann man mit Hilfe eines Color-Pickers bestimmen. Der Rückgabewert ist ein Farbwert in der CSS-Notation.&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;hsv-Funktion für Farbskalierungen&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
hsv ($value,$min_value,$max_value,$min_hue,$max_hue,$saturation,$lightness)&lt;br /&gt;
$value      # Wert, Reading&lt;br /&gt;
$min_value  # der kleinste Wert, dieser entspricht dem Farbwert $min_hue&lt;br /&gt;
$max_value  # der größte Wert, dieser entspricht dem Farbwert $max_hue&lt;br /&gt;
$min_hue    # Farbwert für den kleinsten Wert $min_value&lt;br /&gt;
$max_hue    # Farbwert für den größten Wert $max_value&lt;br /&gt;
$saturation # Farbsättigung, default 100, optional&lt;br /&gt;
$lightness  # Farbhelligkeit, default 100, optional&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Die Funktion befindet sich im ui_Table-Package&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinition&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_uiTable_hsv DOIF ##&lt;br /&gt;
attr di_uiTable_hsv uiTable {\&lt;br /&gt;
  package ui_Table;;\&lt;br /&gt;
  ## eigene uiTable-Funktionen vom Typ 1 mit einem Rückgabewert als HTML-Code\&lt;br /&gt;
  \&lt;br /&gt;
  sub bat_icon { ## färbt das Icon &#039;measure_battery_100&#039; abhängig vom Wert mit Hilfe der Funktion hsv \&lt;br /&gt;
    my ($value)=@_;;\&lt;br /&gt;
    return(ICON(&amp;quot;measure_battery_100\@&amp;quot;.hsv($value,0,100,0,120,100,100)))\&lt;br /&gt;
  }\&lt;br /&gt;
   \&lt;br /&gt;
  sub bat_icon2 {## zusätzlich zum Farbwert wird ein entsprechendes Icon bestimmt\&lt;br /&gt;
    my($val)=@_;;\&lt;br /&gt;
	my $icon;;\&lt;br /&gt;
	if ($val==0) {\&lt;br /&gt;
	  $icon=&amp;quot;measure_battery_0&amp;quot;;;\&lt;br /&gt;
	} elsif ($val&amp;lt;=25) {\&lt;br /&gt;
	  $icon=&amp;quot;measure_battery_25&amp;quot;;;\&lt;br /&gt;
	} elsif ($val&amp;lt;=50) {\&lt;br /&gt;
	  $icon=&amp;quot;measure_battery_50&amp;quot;;;\&lt;br /&gt;
	} elsif ($val&amp;lt;=75) {\&lt;br /&gt;
	  $icon=&amp;quot;measure_battery_75&amp;quot;;;\&lt;br /&gt;
	} else {\&lt;br /&gt;
	  $icon=&amp;quot;measure_battery_100&amp;quot;;;\&lt;br /&gt;
	}\&lt;br /&gt;
	\&lt;br /&gt;
	my $output=ICON(&amp;quot;$icon\@&amp;quot;.hsv ($val,0,100,0,120,90,100));;\&lt;br /&gt;
    return($output);;\&lt;br /&gt;
  }\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
## Tabellendefinition\&lt;br /&gt;
\&lt;br /&gt;
## eingefärbtes Icon 0 % entspricht rot (HSV-Wert 0), 100 % entspricht grün (HSV-Wert 120) mit Direktangabe\&lt;br /&gt;
1|ICON(&amp;quot;measure_battery_100\@&amp;quot;.hsv([bat:level],0,100,0,120,100,100))\&lt;br /&gt;
\&lt;br /&gt;
## gleiche Funktionalität mit Hilfe der oben definierten Funktion bat_icon \&lt;br /&gt;
2|bat_icon([bat:level])\&lt;br /&gt;
\&lt;br /&gt;
## Icon mit Hilfe der oben definierten Funktion bat_icon2\&lt;br /&gt;
3|bat_icon2([bat:level])\&lt;br /&gt;
\&lt;br /&gt;
## Beispiel für die Farbskaliereung von 0 bis 100 % mit der obigen Funktion bat_icon\&lt;br /&gt;
4|bat_icon(0)|bat_icon(10)|bat_icon(20)|bat_icon(30)|bat_icon(40)|bat_icon(50)|bat_icon(60)|bat_icon(70)|bat_icon(80)|bat_icon(90)|bat_icon(100)\&lt;br /&gt;
\&lt;br /&gt;
## Beispiel für die Farbskaliereung von 0 bis 100 % mit der obigen Funktion bat_icon2\&lt;br /&gt;
5|bat_icon2(0)|bat_icon2(10)|bat_icon2(20)|bat_icon2(30)|bat_icon2(40)|bat_icon2(50)|bat_icon2(60)|bat_icon2(70)|bat_icon2(80)|bat_icon2(90)|bat_icon2(100)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable DOIF hsv.png|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
== Eine for-Schleife mit Hilfe des &#039;&#039;&#039;FOR&#039;&#039;&#039;-Befehls ==&lt;br /&gt;
Mit Hilfe des &#039;&#039;&#039;FOR&#039;&#039;&#039;-Befehls können über eine Schleife aus einer Liste mit Elementen mehrere Tabellenzellen definiert werden. Die Elementenliste (Array) kann über eine Funktion bestimmt werden. Auf diese Weise kann z. B. eine Tabelle für mehrere Geräte einfach definiert werden.&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;FOR-Befehl&#039;&#039;&#039;&lt;br /&gt;
* Der FOR-Befehl entspricht einer foreach-Schleife in Perl&lt;br /&gt;
* Syntax: &#039;&#039;&#039;FOR (&amp;lt;Array&amp;gt;,&amp;lt;Zellendefinitionen&amp;gt;)&#039;&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;lt;Array&amp;gt;&#039;&#039;&#039; eine gültige Angabe eines Arrays oder eine Perlfunktion, die ein Array liefert&amp;lt;br&amp;gt;&#039;&#039;&#039;&amp;lt;Zellendefinitionen&amp;gt;&#039;&#039;&#039; Definition einer oder mehrerer Zellen, die Angabe $_ wird durch das jeweilige Element des Arrays ersetzt&lt;br /&gt;
*&#039;&#039;&#039;nützliche Links&#039;&#039;&#039;&lt;br /&gt;
**{{Link2CmdRef|Anker=DOIF_aggregation|Lang=de|Label=DOIF Aggregationsfunktionen mit Perlfunktion AggrDoIf}}&lt;br /&gt;
**[[DevelopmentModuleAPI#devspec2array|devspec2array]]&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Beispieldefinitionen&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_for DOIF ##&lt;br /&gt;
attr di_for uiTable \&lt;br /&gt;
## Temperaturen aller Geräte, die mit &#039;T&#039; beginnen und ein Reading &#039;temperature&#039; haben, sollen in einer Tabelle visualisiert werden\&lt;br /&gt;
FOR(::AggrDoIf(&#039;@&#039;,&#039;^T_&#039;,&#039;temperature&#039;),&amp;quot;$_&amp;quot;|temp([$_:temperature:d2]))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable-FOR-temperature.png|200px|ohne]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_for DOIF ##&lt;br /&gt;
attr di_for uiTable \&lt;br /&gt;
## Anzeige des Batteriestatus aller Geräte, bei denen das Wort &#039;Fenster&#039; vorkommt, die das Readings &#039;battery&#039; haben\ &lt;br /&gt;
FOR(::AggrDoIf(&#039;@&#039;,&#039;Fenster&#039;,&#039;battery&#039;),&amp;quot;$_&amp;quot;|bat([$_:battery]))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable-FOR-battery.png|200px|ohne]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_for DOIF ##&lt;br /&gt;
attr di_for uiTable \&lt;br /&gt;
## Anzeige des Status aller Geräte im System vom Typ &#039;HMS&#039;\&lt;br /&gt;
FOR(::devspec2array(&amp;quot;TYPE=HMS&amp;quot;),&amp;quot;$_&amp;quot;|[$_])&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable-FOR-HMS.png|300px|ohne]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_for DOIF ##&lt;br /&gt;
attr di_for uiTable \&lt;br /&gt;
## Elemente einer kommagetrennten Liste sollen jeweils in einer Tabellenzelle in einer Tabellenzeile angezeigt werden\&lt;br /&gt;
FOR(split(&amp;quot;,&amp;quot;,&amp;quot;Mo,Di,Mi,Do,Fr,Sa,So&amp;quot;),ui_Table::style(&amp;quot;$_&amp;quot;,&amp;quot;Darkorange&amp;quot;)|)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable-FOR-split.png|300px|ohne]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_for DOIF ##&lt;br /&gt;
attr di_for uiTable \&lt;br /&gt;
## Durch Leerzeichen getrennte Zeichenketten sollen jeweils in einer Tabellenzelle in einer Tabellenzeile angezeigt werden\&lt;br /&gt;
FOR(qw/Montag Dienstag Mittwoch Donnerstag Freitag/,&amp;quot;$_&amp;quot;|)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable-FOR-qw.png|300px|ohne]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_for DOIF ##&lt;br /&gt;
attr di_for uiTable \&lt;br /&gt;
## das Templates TPL_raum, soll vier mal aufgerufen werden: TPL_raum(1), TPL_raum(2)...\&lt;br /&gt;
## das Templates TPL_raum muss vorher definiert worden sein\&lt;br /&gt;
FOR(1..4,TPL_raum($_))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable-FOR TPL raum.png|600px|ohne]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Anwendungsbeispiele&#039;&#039;&#039; ==&lt;br /&gt;
=== &#039;&#039; Visualisierung und Steuerung von &#039;&#039;&#039;Rollläden&#039;&#039;&#039;&#039;&#039; ===&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;nützliche Links&#039;&#039;&#039;&lt;br /&gt;
* {{Link2CmdRef|Anker=DOIF_Zeitsteuerung_mit_Zeitintervallen|Lang=de|Label=Zeitsteuerung}}&lt;br /&gt;
* uiTable-Funktion [[DOIF/uiTable Schnelleinstieg#Rollladen: Visualisierung und Steuerung mit Hilfe der Funktion shutter|shutter]]&lt;br /&gt;
* uiTable-Funktion [[DOIF/uiTable Schnelleinstieg#Textformatierungen mit Hilfe der Funktion style|style]]&lt;br /&gt;
* [[DOIF/uiTable Schnelleinstieg#uiTable-Templates|Templates]]&lt;br /&gt;
}}&lt;br /&gt;
Im folgenden Beispiel werden Rollläden morgens hochgefahren, ebenso wird die Position aller Rollläden visualisiert. Durch Anklicken eines Icons wird der Rollladen auf die entsprechende Position bewegt. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod DI_Rollladen DOIF (([Dunkelheit] eq &amp;quot;off&amp;quot; and [06:25-09:00|8]) or [09:00|7]) \&lt;br /&gt;
  ((set R_W_S,R_W_W[1-3] on)) ## Hochfahren der Rollläden im Erdgeschoss morgens\&lt;br /&gt;
DOELSEIF ([Dunkelheit] eq &amp;quot;on&amp;quot;)&lt;br /&gt;
attr DI_Rollladen cmdState oben|unten&lt;br /&gt;
attr DI_Rollladen devStateIcon unten:status_night oben:scene_day&lt;br /&gt;
attr DI_Rollladen icon fts_shutter_automatic&lt;br /&gt;
attr DI_Rollladen uiTable {\&lt;br /&gt;
   package ui_Table;;\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
## Template für ein Fenster\&lt;br /&gt;
DEF TPL_shutter(&amp;quot;$1&amp;quot;|shutter([$1:pct]))\&lt;br /&gt;
\&lt;br /&gt;
## Tabellendefinition\&lt;br /&gt;
\&lt;br /&gt;
style(&amp;quot;Dachgeschoss&amp;quot;,&amp;quot;Darkorange&amp;quot;)|&amp;quot;&amp;quot;\&lt;br /&gt;
TPL_shutter(R_Dachboden)\&lt;br /&gt;
style(&amp;quot;erstes Geschoss&amp;quot;,&amp;quot;Darkorange&amp;quot;)|&amp;quot;&amp;quot;\&lt;br /&gt;
TPL_shutter(R_Bad)\&lt;br /&gt;
TPL_shutter(R_Kinderzimmer1_O)\&lt;br /&gt;
TPL_shutter(R_Kinderzimmer1_S)\&lt;br /&gt;
TPL_shutter(R_Kinderzimmer2_S)\&lt;br /&gt;
TPL_shutter(R_Kinderzimmer2_W1)\&lt;br /&gt;
TPL_shutter(R_Kinderzimmer2_W2)\&lt;br /&gt;
style(&amp;quot;Erdgeschoss&amp;quot;,&amp;quot;Darkorange&amp;quot;)|&amp;quot;&amp;quot;\&lt;br /&gt;
TPL_shutter(R_Kueche)\&lt;br /&gt;
TPL_shutter(R_W_S)\&lt;br /&gt;
TPL_shutter(R_W_W1)\&lt;br /&gt;
TPL_shutter(R_W_W2)\&lt;br /&gt;
TPL_shutter(R_W_W3)\&lt;br /&gt;
style(&amp;quot;Keller&amp;quot;,&amp;quot;Darkorange&amp;quot;)|&amp;quot;&amp;quot;\&lt;br /&gt;
TPL_shutter(R_Keller)\&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Ergebnis des Anwendungsbeispiels in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable Rollladen.png|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;Anzahl der Tage bis zur &#039;&#039;&#039;Abfall-Entsorgung&#039;&#039;&#039;&#039;&#039; ===&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;nützliche Links&#039;&#039;&#039;&lt;br /&gt;
* FHEM-Modul [[Calendar]]&lt;br /&gt;
* ui_Table Funktion [[DOIF/uiTable Schnelleinstieg#Icon-Darstellung mit Text mit Hilfe der Funktion icon_label|icon_label]]&lt;br /&gt;
}}&lt;br /&gt;
Mit Hilfe des Kalender-Moduls werden die verbleibenden Tage bis zur Abfall-Entsorgung der jeweiligen Tonne berechnet und mit Hilfe von uiTable visualisiert. Wenn der Tag der Entsorgung bevorsteht, wird er farbig gekennzeichnet. Vorausgesetzt wird die Definition des Kalenders namens &#039;cal&#039; mit Hilfe des Moduls [[Calendar]]. Dieser muss die Termine der Abfallentsorgung der Tonnen beinhalten. Im Beispiel wird nach Stichwörtern: &amp;quot;Altpapier&amp;quot;, &amp;quot;Restmüll&amp;quot;, &amp;quot;Bio&amp;quot;, &amp;quot;Gelbe&amp;quot; und &amp;quot;Grünabfuhr&amp;quot; im Kalender gesucht. &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod Abfall DOIF subs {\&lt;br /&gt;
  ## Hier reicht es den Kalender-Eintrag anzupassen\&lt;br /&gt;
  ##            Kalender-Eintrag, Reading, icon \&lt;br /&gt;
  push @{$_sc},[&amp;quot;Altpapier&amp;quot;,&amp;quot;altpapier&amp;quot;,&amp;quot;Abfalltonne-Recycling-Logo\@blue&amp;quot;];;\&lt;br /&gt;
  push @{$_sc},[&amp;quot;Restmüll&amp;quot;,&amp;quot;restmuell&amp;quot;,&amp;quot;Abfalltonne\@gray&amp;quot;];;\&lt;br /&gt;
  push @{$_sc},[&amp;quot;Bio&amp;quot;,&amp;quot;bio&amp;quot;,&amp;quot;Abfalltonne-Recycling-Logo\@green&amp;quot;];;\&lt;br /&gt;
  push @{$_sc},[&amp;quot;Gelbe&amp;quot;,&amp;quot;gelbe_tonne&amp;quot;,&amp;quot;Abfalltonne-Recycling-Logo\@yellow&amp;quot;];;\&lt;br /&gt;
  push @{$_sc},[&amp;quot;Grünabfuhr&amp;quot;,&amp;quot;gruenschnitt&amp;quot;,&amp;quot;Gartenabfall\@green&amp;quot;];;\&lt;br /&gt;
  \&lt;br /&gt;
  sub days \&lt;br /&gt;
  {\&lt;br /&gt;
    my ($event,$reading)=@_;;\&lt;br /&gt;
	my $days=fhem(&#039;get cal events timeFormat:&amp;quot;%j&amp;quot; filter:field(summary)=~&amp;quot;&#039;.$event.&#039;&amp;quot; limit:count=1,from=0 format:custom=&amp;quot;$T1&amp;quot;&#039;,1);;\&lt;br /&gt;
	my $date=fhem(&#039;get cal events timeFormat:&amp;quot;%a. %d.%m.&amp;quot; filter:field(summary)=~&amp;quot;&#039;.$event.&#039;&amp;quot; limit:count=1,from=0 format:custom=&amp;quot;$T1&amp;quot;&#039;,1);;\&lt;br /&gt;
	my $diff;;\&lt;br /&gt;
	if (defined($days) and $days ne &amp;quot;&amp;quot;) {\&lt;br /&gt;
	  my $now=::strftime (&#039;%j&#039;, localtime());;\&lt;br /&gt;
	  my $year=::strftime (&#039;%Y&#039;, localtime());;\&lt;br /&gt;
	  $diff=$days-$now;;\&lt;br /&gt;
	  if ($diff &amp;lt; 0) {\&lt;br /&gt;
	    $diff+=(365+($year % 4 eq 0 and $year % 100 ne 0 or $year % 400 eq 0 ? 1: 0));;\&lt;br /&gt;
	  }\&lt;br /&gt;
	} else {\&lt;br /&gt;
	  $date=&amp;quot;&amp;quot;;;\&lt;br /&gt;
	  $diff=&amp;quot;N/A&amp;quot;\&lt;br /&gt;
	}\&lt;br /&gt;
	set_Reading($reading.&amp;quot;_date&amp;quot;,$date);;\&lt;br /&gt;
    set_Reading($reading,$diff,1);;\&lt;br /&gt;
  }\&lt;br /&gt;
  sub update\&lt;br /&gt;
  {\&lt;br /&gt;
    for (my $i=0;;$i &amp;lt; @{$_sc};;$i++) {\&lt;br /&gt;
      days($_sc[$i][0],$_sc[$i][1]);;\&lt;br /&gt;
    }\&lt;br /&gt;
  }\&lt;br /&gt;
}\&lt;br /&gt;
init{[00:00];;set_Exec(&amp;quot;Timer&amp;quot;,60,&#039;update()&#039;);;}\&lt;br /&gt;
update{update()}&lt;br /&gt;
attr Abfall room wiki-&amp;gt;abfall&lt;br /&gt;
attr Abfall uiTable {\&lt;br /&gt;
  package ui_Table;;\&lt;br /&gt;
  $TABLE=&amp;quot;text-align:center&amp;quot;;;\&lt;br /&gt;
  $SHOWNOSTATE=1;;\&lt;br /&gt;
  sub ic\&lt;br /&gt;
  {\&lt;br /&gt;
    my ($icon,$days)=@_;;\&lt;br /&gt;
    icon_label($icon,$days,&amp;quot;white&amp;quot;,$days eq &amp;quot;N/A&amp;quot; ? &amp;quot;blue&amp;quot; : $days &amp;gt; 1 ? &amp;quot;#606060&amp;quot; : &amp;quot;red&amp;quot;)\&lt;br /&gt;
  }\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
DEF TPL_Tonne (style([$SELF:$1_date],&amp;quot;&amp;quot;,8),ic (&#039;$2&#039;,[$SELF:$1]))\&lt;br /&gt;
\&lt;br /&gt;
FOR (@{$_sc},TPL_Tonne($_$2,$_$3)|)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:Anwendungsbeispiel Abfall.png|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;Visualisierung: &#039;&#039;&#039;offene Fenster&#039;&#039;&#039;&#039;&#039; ===&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;nützliche Links&#039;&#039;&#039;&lt;br /&gt;
* Attribut {{Link2CmdRef|Anker=DOIF_DOIF_Readings|Lang=de|Label=DOIF_Readings}}&lt;br /&gt;
* DOIF-{{Link2CmdRef|Anker=DOIF_aggregation|Lang=de|Label=Aggregationsfunktionen}}&lt;br /&gt;
* uiTable-Funktion [[DOIF/uiTable Schnelleinstieg#Icon-Darstellung mit Hilfe der Funktion icon|icon]]&lt;br /&gt;
}}&lt;br /&gt;
Alle offenen Fenster werden aufgelistet und mit entsprechendem Icon visualisiert.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_uiTable_windows DOIF ## Visualisierung offener Fenster, Fenster-Devices enden mit &amp;quot;Fenster&amp;quot; im Namen&lt;br /&gt;
attr di_uiTable_windows DOIF_Readings windows:[@as(&amp;lt;br&amp;gt;)&amp;quot;Fenster$&amp;quot;:state:&amp;quot;open&amp;quot;,&amp;quot;keine&amp;quot;]&lt;br /&gt;
attr di_uiTable_windows uiTable {package ui_Table;;}\&lt;br /&gt;
icon([$SELF:windows],&amp;quot;fts_window_1w_open\@DarkOrange&amp;quot;,&amp;quot;fts_window_1w&amp;quot;,&amp;quot;.*&amp;quot;,&amp;quot;keine&amp;quot;)|[$SELF:windows]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable windows closed.png|mini|ohne]]&lt;br /&gt;
[[Datei:UiTable windows open.png|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;Visualisierung: &#039;&#039;&#039;aktuelle Wetterlage&#039;&#039;&#039;&#039;&#039; ===&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;nützliche Links&#039;&#039;&#039;&lt;br /&gt;
* DWD [https://www.dwd.de/DE/Home/home_node.html Homepage]&lt;br /&gt;
* Regenradar [https://www.dwd.de/DE/wetter/wetterundklima_vorort/_node.html Radarfilm BRD]&lt;br /&gt;
* aktuelles Wetter [https://www.dwd.de/DE/wetter/wetterundklima_vorort/nordrhein-westfalen/nrw_node.html NRW]&lt;br /&gt;
* Wetteronline [https://www.wetteronline.de/wetter-widget eignes Widget]&lt;br /&gt;
}}&lt;br /&gt;
Regenrader animiert, aktuelle Temperatur und Feuchte vom Sensor, aktuelle Wetterlage sowie Wettervorhersage der nächsten Tage. Über entsprechende Weblinks werden Bilder aus dem WWW in der Tabelle visualisiert. Im Gegensatz zu lokalen Sensoren, muss für die Aktualisierung der WWW-Elemente in der jeweiligen Webinstanz (FHEMWEB) das refresh-Attribut gesetzt werden. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_uiTable_wetter DOIF ##&lt;br /&gt;
attr di_uiTable_wetter uiTable {\&lt;br /&gt;
 package ui_Table;;\&lt;br /&gt;
 $TC{1}=&amp;quot;align=&#039;center&#039;&amp;quot;;;\&lt;br /&gt;
}\&lt;br /&gt;
## das Attribut &#039;refresh&#039; der Webinstanz für ein Wandtablet wurde auf 900 gesetzt, damit die Bilder alle 15 Minuten aktualisiert werden \&lt;br /&gt;
## Tabellendefinition\&lt;br /&gt;
\&lt;br /&gt;
## Regenradar BRD\&lt;br /&gt;
&#039;&amp;lt;img src=&amp;quot;https://www.dwd.de/DWD/wetter/radar/radfilm_brd_akt.gif&amp;quot; height=&amp;quot;365px&amp;quot; width=&amp;quot;365px&amp;quot;&amp;gt;&#039;|\&lt;br /&gt;
\&lt;br /&gt;
## Aktuelle Temperatur und Feuchtigkeit vom lokalen sensor\&lt;br /&gt;
temp([Aussensensor:temperature],40),hum ([Aussensensor:humidity],30),\&lt;br /&gt;
\&lt;br /&gt;
## aktuelle Wetterlage NRW\&lt;br /&gt;
&amp;quot;&amp;lt;img src =&#039;https://www.dwd.de/DE/wetter/wetterundklima_vorort/nordrhein-westfalen/_functions/bildgalerie/wetter_aktuell.jpg?view=nasImage&amp;amp;nn=561200&#039; height=&#039;255px&#039; width=&#039;255px&#039;&amp;gt;&amp;quot;|\&lt;br /&gt;
\&lt;br /&gt;
## Wettervorhersage\&lt;br /&gt;
&amp;quot;&amp;lt;iframe marginheight=&#039;0&#039; marginwidth=&#039;0&#039; scrolling=&#039;no&#039; width=&#039;300&#039; height=&#039;365&#039; name=&#039;FC3&#039; style=&#039;border:1px solid;;border-color:#00537f;;&#039; src=&#039;https://api.wetteronline.de/wetterwidget?gid=x0677&amp;amp;modeid=FC3&amp;amp;seourl=juelich&amp;amp;locationname=Jülich&amp;amp;lang=de&#039;&amp;gt;&amp;lt;/iframe&amp;gt;&amp;quot;\&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable wetter.png|600px|links]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;Visualisierung: &#039;&#039;&#039;Wetterstation&#039;&#039;&#039;&#039;&#039; ===&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;nützliche Links&#039;&#039;&#039;&lt;br /&gt;
* Wunderground [https://wunderground.com/ Homepage]&lt;br /&gt;
* svg-Funktion [https://wiki.fhem.de/wiki/DOIF/uiTable_Schnelleinstieg#Anzeige_eines_Werteverlaufs_und_des_aktuellen_Wertes_mit_Hilfe_der_SVG-Funktion_card card]&lt;br /&gt;
* svg-Funktionen [https://wiki.fhem.de/wiki/DOIF/uiTable_Schnelleinstieg#icon_ring-Funktionen icon_ring]&lt;br /&gt;
}}&lt;br /&gt;
Die vorgestellte Lösung funktioniert ohne Anmeldung beim Wetterdienst und ohne Nutzung von API.&lt;br /&gt;
Über den Wetterdienst: https://www.wunderground.com/ werden sehr viele private Wifi-Wetterstationen eingebunden. Das kann man sich zunutze machen, indem man zunächst in seiner Umgebung nach Wetterstationen des Dienstes sucht - oft findet man im Umkreis von wenigen Kilometern schon einige Stationen, die rege Wetterdaten liefern. Danach definiert man über HTTPMOD seine Station und visualisiert diese anschließend.&lt;br /&gt;
&lt;br /&gt;
Definition einer Station in der Nachbarschaft. &amp;lt;StationsID&amp;gt; muss gegen die korrekte Stationsnummer ersetzt werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod Wetter HTTPMOD https://www.wunderground.com/dashboard/pws/&amp;lt;StationsID&amp;gt;&lt;br /&gt;
attr Wetter enableControlSet 1&lt;br /&gt;
attr Wetter reading01Name Wind&lt;br /&gt;
attr Wetter reading01Regex stationID(?!.*stationID).*windspeedAvg&amp;quot;:([\d+\.]+)&lt;br /&gt;
attr Wetter reading02Name Windboeen&lt;br /&gt;
attr Wetter reading02Regex stationID(?!.*stationID).*windgustAvg&amp;quot;:([\d+\.]+)&lt;br /&gt;
attr Wetter reading03Name Windrichtung&lt;br /&gt;
attr Wetter reading03Regex stationID(?!.*stationID).*winddirAvg&amp;quot;:([\d+\.]+)&lt;br /&gt;
attr Wetter reading04Name Regen&lt;br /&gt;
attr Wetter reading04Regex stationID(?!.*stationID).*precipRate&amp;quot;:([\d+\.]+)&lt;br /&gt;
attr Wetter reading05Name RegenGesamt&lt;br /&gt;
attr Wetter reading05Regex stationID(?!.*stationID).*precipTotal&amp;quot;:([\d+\.]+)&lt;br /&gt;
attr Wetter reading06Name Temperatur&lt;br /&gt;
attr Wetter reading06Regex stationID(?!.*stationID).*tempAvg&amp;quot;:([\d+\.]+)&lt;br /&gt;
attr Wetter reading07Name Feuchtigkeit&lt;br /&gt;
attr Wetter reading07Regex stationID(?!.*stationID).*humidityAvg&amp;quot;:([\d+\.]+)&lt;br /&gt;
attr Wetter reading08Name UV&lt;br /&gt;
attr Wetter reading08Regex stationID(?!.*stationID).*uvHigh&amp;quot;:([\d+\.]+)&lt;br /&gt;
attr Wetter reading09Name Luftdruck&lt;br /&gt;
attr Wetter reading09Regex stationID(?!.*stationID).*pressureMin&amp;quot;:([\d+\.]+)&lt;br /&gt;
attr Wetter reading10Name TemperaturGefuehlt&lt;br /&gt;
attr Wetter reading10Regex stationID(?!.*stationID).*windchillAvg&amp;quot;:([\d+\.]+)&lt;br /&gt;
attr Wetter reading11Name TaupunktTemp&lt;br /&gt;
attr Wetter reading11Regex stationID(?!.*stationID).*dewptAvg&amp;quot;:([\d+\.]+)&lt;br /&gt;
attr Wetter reading12Name Sonnenstrahlung&lt;br /&gt;
attr Wetter reading12Regex stationID(?!.*stationID).*solarRadiationHigh&amp;quot;:([\d+\.]+)&lt;br /&gt;
attr Wetter room Wetter&lt;br /&gt;
attr Wetter timeout 10&lt;br /&gt;
attr Wetter userReadings WindKm {sprintf(&amp;quot;%1.1f&amp;quot;,ReadingsVal($name,&amp;quot;Wind&amp;quot;,0)*1.60934)},\&lt;br /&gt;
WindboeenKm {sprintf(&amp;quot;%1.1f&amp;quot;,ReadingsVal($name,&amp;quot;Windboeen&amp;quot;,0)*1.60934)},\&lt;br /&gt;
WindrichtungGrad {ReadingsVal($name,&amp;quot;Windrichtung&amp;quot;,0)-180},\&lt;br /&gt;
RegenMm {ReadingsVal($name,&amp;quot;Regen&amp;quot;,0)*25.4},\&lt;br /&gt;
RegenGesamtMm {ReadingsVal($name,&amp;quot;RegenGesamt&amp;quot;,0)*25.4},\&lt;br /&gt;
TemperaturC {sprintf(&amp;quot;%1.1f&amp;quot;,(ReadingsVal($name,&amp;quot;Temperatur&amp;quot;,0)-32)*5/9)},\&lt;br /&gt;
TaupunktTempC {sprintf(&amp;quot;%1.1f&amp;quot;,(ReadingsVal($name,&amp;quot;TaupunktTemp&amp;quot;,0)-32)*5/9)},\&lt;br /&gt;
LuftdruckHpa {sprintf(&amp;quot;%d&amp;quot;,ReadingsVal($name,&amp;quot;Luftdruck&amp;quot;,0)*33.8639)},\&lt;br /&gt;
TemperaturGefuehltC {sprintf(&amp;quot;%1.1f&amp;quot;,(ReadingsVal($name,&amp;quot;TemperaturGefuehlt&amp;quot;,0)-32)*5/9)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun erfolgt die Visualisierung der Daten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_Wetter_ring DOIF ##&lt;br /&gt;
attr di_Wetter_ring uiTable {package ui_Table;;}\&lt;br /&gt;
\&lt;br /&gt;
icon_temp_hum_ring(&amp;quot;temp_outside&amp;quot;,[Wetter:TemperaturC],[Wetter:Feuchtigkeit],undef,undef,150)|\&lt;br /&gt;
icon_temp_ring (&amp;quot;temp_windchill&amp;quot;,[Wetter:TemperaturGefuehltC],undef,undef,150) |\&lt;br /&gt;
icon_temp_ring (&amp;quot;temperature_humidity&amp;quot;,[Wetter:TaupunktTempC],undef,undef,150) |\&lt;br /&gt;
icon_ring2([Wetter:WindKm] &amp;gt; 0 ? &amp;quot;wind&amp;quot;.&amp;quot;,1,0,0,&amp;quot;.[Wetter:WindrichtungGrad]:&amp;quot;no_wind&amp;quot;,[Wetter:WindKm],0,50,120,0,&amp;quot;km/h&amp;quot;,150,undef,1,[Wetter:WindboeenKm],0,50,120,0,&amp;quot;km/h&amp;quot;,undef,1) |\&lt;br /&gt;
icon_ring2(&amp;quot;weather_rain_gauge&amp;quot;,[Wetter:RegenMm],0,10,180,270,&amp;quot;mm/h&amp;quot;,150,undef,1,[Wetter:RegenGesamtMm],0,50,180,270,&amp;quot;mm&amp;quot;,undef,1)|\&lt;br /&gt;
icon_ring2(&amp;quot;sani_solar&amp;quot;,[Wetter:UV],0,10,100,30,&amp;quot;UV&amp;quot;,150,undef,0,[Wetter:Sonnenstrahlung],0,1000,100,30,&amp;quot;Watt/m²&amp;quot;,undef,0)|\&lt;br /&gt;
icon_ring (&amp;quot;weather_barometric_pressure&amp;quot;,[Wetter:LuftdruckHpa],980,1047,0,120,&amp;quot;hPa&amp;quot;,0,150)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable ringwetter.png|600px|links]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel der Visualisierung mit Verlauf der letzten drei Tage mit Hilfe der svg-Funktion &#039;&#039;&#039;card&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_Wetter DOIF ##&lt;br /&gt;
attr di_Wetter icon weather_wind&lt;br /&gt;
attr di_Wetter uiTable {package ui_Table;;}\&lt;br /&gt;
##  card ($collect,$header,$icon,$min,$max,$minColor,$maxColor,$unit,$func,$decfont,$size,$model,$lightness)\&lt;br /&gt;
\&lt;br /&gt;
card([Wetter:TemperaturC:col3d],&amp;quot;Außentemperatur&amp;quot;,&amp;quot;temp_outside&amp;quot;,-10,60,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue)|\&lt;br /&gt;
card([Wetter:TemperaturGefuehltC:col3d],&amp;quot;gefühlte Temperatur&amp;quot;,&amp;quot;temp_windchill&amp;quot;,-10,60,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue)|\&lt;br /&gt;
card([Wetter:TaupunktTempC:col3d],&amp;quot;Taupunkttemperatur&amp;quot;,&amp;quot;temperature_humidity&amp;quot;,-10,60,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue)|\&lt;br /&gt;
card([Wetter:Feuchtigkeit:col3d],&amp;quot;Außenfeuchtigkeit&amp;quot;,&amp;quot;temperature_humidity&amp;quot;,0,100,undef,undef,&amp;quot;%&amp;quot;,\&amp;amp;hum_hue)|\&lt;br /&gt;
card([Wetter:WindKm:col3d],&amp;quot;Wind&amp;quot;,[Wetter:WindKm] &amp;gt; 0 ? &amp;quot;wind&amp;quot;.&amp;quot;,1,0,0,&amp;quot;.[Wetter:WindrichtungGrad]:&amp;quot;no_wind&amp;quot;,0,30,90,30,&amp;quot;km/h&amp;quot;,undef,1)\&lt;br /&gt;
card([Wetter:WindboeenKm:col3d],&amp;quot;Windböen&amp;quot;,&amp;quot;weather_wind&amp;quot;,0,30,90,30,&amp;quot;km/h&amp;quot;,undef,1)|\&lt;br /&gt;
card([Wetter:RegenMm:col3d],&amp;quot;Regen&amp;quot;,&amp;quot;weather_rain_gauge&amp;quot;,0,10,180,270,&amp;quot;mm/h&amp;quot;)|\&lt;br /&gt;
card([Wetter:RegenGesamtMm:col3d],&amp;quot;Regengesamt&amp;quot;,&amp;quot;weather_rain_gauge&amp;quot;,0,50,180,270,&amp;quot;mm&amp;quot;)|\&lt;br /&gt;
##card([Wetter:UV:col3d],&amp;quot;UV-Strahlung&amp;quot;,&amp;quot;sani_solar&amp;quot;,0,7,100,30,&amp;quot;UV&amp;quot;,undef,0)|\&lt;br /&gt;
card([Wetter:Sonnenstrahlung:col3d],&amp;quot;Sonnenstrahlung&amp;quot;,&amp;quot;sani_solar&amp;quot;,0,1000,30,90,&amp;quot;Watt/m²&amp;quot;,undef,0)|\&lt;br /&gt;
card([Wetter:LuftdruckHpa:col3d],&amp;quot;Luftdruck&amp;quot;,&amp;quot;weather_barometric_pressure&amp;quot;,980,1047,30,90,&amp;quot;hPa&amp;quot;,undef,0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable svgwetter.png|800px|links]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ohne Angabe der Überschrift (undef für $header setzen) lässt sich eine kompaktere Darstellung erzielen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:UiTable svgwetteroh.png|800px|links]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;Visualisierung: &#039;&#039;&#039;aktueller Spritpreis&#039;&#039;&#039;&#039;&#039; ===&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;nützliche Links&#039;&#039;&#039;&lt;br /&gt;
* svg-Funktion [[DOIF/uiTable_Schnelleinstieg#ring-Funktionen|ring]]&lt;br /&gt;
* svg-Funktion [[DOIF/uiTable_Schnelleinstieg#Anzeige_eines_Werteverlaufs_und_des_aktuellen_Wertes_mit_Hilfe_der_SVG-Funktion_card|card]]&lt;br /&gt;
* Tankstelle bestimmen [https://www.clever-tanken.de/ Clever tanken]&lt;br /&gt;
* Modul [[HTTPMOD]]&lt;br /&gt;
}}&lt;br /&gt;
Der aktuelle Spritpreis einer Tankstelle wird ermittelt und mit seinem zeitlichen Verlauf visualisiert.&lt;br /&gt;
&lt;br /&gt;
Zunächst wird ein HTTPMOD-Modul für den aktuellen Spritpreis definiert, dabei ist &amp;lt;Stations-ID&amp;gt; durch die ID der Tankstelle zu ersetzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod Tankstelle HTTPMOD http://www.clever-tanken.de/tankstelle_details/&amp;lt;Stations-ID&amp;gt; 300&lt;br /&gt;
attr Tankstelle devStateIcon {ui_Table::ring(ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;Diesel&amp;quot;,0),1.00,1.40,120,0,&amp;quot;Diesel&amp;quot;,90,undef,2).&amp;quot; &amp;quot;.ui_Table::ring(ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;SuperE5&amp;quot;,0),1.10,1.60,120,0,&amp;quot;E5&amp;quot;,90,undef,2)}&lt;br /&gt;
attr Tankstelle enableControlSet 1&lt;br /&gt;
attr Tankstelle event-on-change-reading .*&lt;br /&gt;
attr Tankstelle group Spritpreise&lt;br /&gt;
attr Tankstelle reading01Name Diesel&lt;br /&gt;
attr Tankstelle reading01Regex &amp;quot;current-price-1&amp;quot;&amp;gt;(\d.\d{2})&lt;br /&gt;
attr Tankstelle reading02Name SuperE5&lt;br /&gt;
attr Tankstelle reading02Regex &amp;quot;current-price-2&amp;quot;&amp;gt;(\d.\d{2})&lt;br /&gt;
attr Tankstelle room Spritpreise&lt;br /&gt;
attr Tankstelle timeout 10&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:Di uiTable Tankstelle.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
Visualisierung der Preisentwicklung der letzten 24 Stunden: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod sprit DOIF ##&lt;br /&gt;
attr sprit uiTable {package ui_Table;;}\&lt;br /&gt;
card([[Tankstelle:SuperE5:col3d],[Tankstelle:Diesel:col3d]],undef,&amp;quot;fuel\@silver&amp;quot;,1.40,1.9,120,0,[&amp;quot;E10&amp;quot;,&amp;quot;Diesel&amp;quot;],undef,&amp;quot;2,,fill:silver, €&amp;quot;,&amp;quot;130,autoscaling,steps,footer,ycolor,ring,200&amp;quot;,undef,undef)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:Di uiTable sprit.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;Visualisierung: &#039;&#039;&#039;aktuelle Corona-7-Tage-Inzidenz&#039;&#039;&#039;&#039;&#039; ===&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;nützliche Links&#039;&#039;&#039;&lt;br /&gt;
* svg-Funktion [[DOIF/uiTable_Schnelleinstieg#ring-Funktionen|ring]]&lt;br /&gt;
* svg-Funktion [[DOIF/uiTable_Schnelleinstieg#Anzeige_eines_Werteverlaufs_und_des_aktuellen_Wertes_mit_Hilfe_der_SVG-Funktion_card|card]]&lt;br /&gt;
* Modul [[JsonMod]]&lt;br /&gt;
}}&lt;br /&gt;
Die aktuellen Inzidenzwerte werden vom RKI ausgelesen und deren Verlauf visualisiert.&lt;br /&gt;
&lt;br /&gt;
Zunächst wird ein JsonMod Device für das Auslesen der Inzidenzzahlen definiert. Die gewünschten Regionen müssen für eigene Bedürfnisse angepasst werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod RKI7 JsonMod https://services7.arcgis.com/mOBPykOjAyBO2ZKk/arcgis/rest/services/RKI_Landkreisdaten/FeatureServer/0/query?where=1%3D1&amp;amp;outFields=last_update,cases7_per_100k,BEZ,BEM,GEN,BL,county&amp;amp;returnGeometry=false&amp;amp;outSR=4326&amp;amp;f=json&lt;br /&gt;
attr RKI7 readingList multi(jsonPath(&amp;quot;\$.features[?(\@.attributes.GEN in [&#039;Städteregion Aachen&#039;, &#039;Düren&#039;, &#039;Heinsberg&#039;])]&amp;quot;), property(&#039;attributes.GEN&#039;), sprintf(&#039;%.1f&#039;, property(&#039;attributes.cases7_per_100k&#039;)));;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Visualisierung der Inzidenzzahlen der letzten sieben Tage: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_corona DOIF ##&lt;br /&gt;
attr di_corona uiTable {package ui_Table}\&lt;br /&gt;
card([RKI7:Duren:col1w],&amp;quot;Düren&amp;quot;,&amp;quot;coronavirus&amp;quot;,0,200,120,0,&amp;quot;Fälle&amp;quot;)|\&lt;br /&gt;
card([RKI7:Heinsberg:col1w],&amp;quot;Heinsberg&amp;quot;,&amp;quot;coronavirus&amp;quot;,0,200,120,0,&amp;quot;Fälle&amp;quot;)|\&lt;br /&gt;
card([RKI7:Stadteregion_Aachen:col1w],&amp;quot;Aachen&amp;quot;,&amp;quot;coronavirus&amp;quot;,0,200,120,0,&amp;quot;Fälle&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:uiTable_Inzidenz.png|600px|links]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039; Visualisierung und Steuerung: &#039;&#039;&#039;Heiztherme&#039;&#039;&#039;&#039;&#039; ===&lt;br /&gt;
Im folgenden Beispiel wurde eine Heiztherme über einen ebus-Adapter in FHEM eingebunden. Die Heizungsdaten werden über MQTT ausgelesen und anschließend visualisiert. Die vorgestellten Visualisierungsbeispiele können ebenso im funktionslosen DOIF mit Hilfe des uiTable-Attriutes auf bereits existierende Readings des eigenen Systems angewendet werden. &lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;nützliche Links&#039;&#039;&#039;&lt;br /&gt;
* svg-Funktion [[DOIF/uiTable_Schnelleinstieg#icon_ring-Funktionen|icon_ring]]&lt;br /&gt;
* svg-Funktion [[DOIF/uiTable_Schnelleinstieg#Anzeige_eines_Werteverlaufs_und_des_aktuellen_Wertes_mit_Hilfe_der_SVG-Funktion_card|card]]&lt;br /&gt;
* Commandref [https://fhem.de/commandref_DE.html#DOIF_Perl_Modus DOIF Perl-Modus]&lt;br /&gt;
* ebus-Adapter [https://ebusd.de/ ebusd]&lt;br /&gt;
* ebus-Wiki [[EBUS|ebus]]&lt;br /&gt;
}}&lt;br /&gt;
Definition eines DOIF-Devices zur Steuerung der Therme und Visualisierung der Daten. Es werden Readings und Befehle genutzt, die durch den MQTT2-Server zur Verfügung gestellt werden. Einzelne Heizungswerte werden in bestimmten Intervallen über den publish-Befehl ausgelesen. Die Temperaturen der Zirkulation, des Vorlaufs und des Rücklaufs werden außerhalb der Therme mit 1-wire-Temperatursensoren über WLAN-ESP-Easy ausgelesen. Die Definition des Layouts über das Attribut uiTable ist unabhängig vom Auslesen der Werte, sie bezieht sich lediglich auf vorhandene Readings, die visualisiert werden sollen. Das Layout kann ebenso auf Readings aus anderen Devices der eigenen FHEM-Umgebung anpasst werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod di_vaillant DOIF ##{[+00:01];;foreach (qw(FanSpeed Flame PumpPower Storageloadpump PrimaryCircuitFlowrate FlowTempDesired PumpHours HcHours HcPumpStarts)) {fhem_set(&amp;quot;MQTT2_FHEM_Server publish ebusd/bai/$_/get&amp;quot;)}}\&lt;br /&gt;
\&lt;br /&gt;
{[+[1]:01];;foreach (qw(PrEnergySumHc1 PrEnergySumHwc1 HcHours HwcHours z1OpMode WaterPressure z1NightTemp z1DayTemp Hc1HeatCurve HwcLockTime HolidayStartPeriod HolidayEndPeriod)) {fhem_set(&amp;quot;MQTT2_FHEM_Server publish ebusd/bai/$_/get&amp;quot;)}\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
{[+00:00:30];;foreach (qw(Flame PrimaryCircuitFlowrate)) {fhem_set(&amp;quot;MQTT2_FHEM_Server publish ebusd/bai/$_/get&amp;quot;)}}\&lt;br /&gt;
\&lt;br /&gt;
{[00:01];;foreach (qw(FanHours HcStarts HwcStarts )) {fhem_set(&amp;quot;MQTT2_FHEM_Server publish ebusd/bai/$_/get&amp;quot;)}\&lt;br /&gt;
  set_Reading(&amp;quot;gesamt_hc&amp;quot;,int([?vaillant:PrEnergySumHc1_0_value]/10000)/10,0);;\&lt;br /&gt;
  set_Reading(&amp;quot;gesamt_hwc&amp;quot;,int([?vaillant:PrEnergySumHwc1_0_value]/10000)/10,0);;\&lt;br /&gt;
  set_Reading(&amp;quot;diff_hc&amp;quot;,0,1);;\&lt;br /&gt;
  set_Reading(&amp;quot;diff_hwc&amp;quot;,0,1);;\&lt;br /&gt;
  set_Reading(&amp;quot;diff_h&amp;quot;,0,1)\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
{if ([00:05|WE]) {fhem_set(&amp;quot;MQTT2_FHEM_Server publish ebusd/700/BankHolidayStartPeriod/set $mday.$month.$year&amp;quot;);;fhem_set(&amp;quot;MQTT2_FHEM_Server publish ebusd/700/BankHolidayEndPeriod/set $mday.$month.$year&amp;quot;)}}\&lt;br /&gt;
\&lt;br /&gt;
Timer {\&lt;br /&gt;
fhem_set &amp;quot;MQTT2_FHEM_Server publish ebusd/700/z1Timer.Monday/set 04:00;;09:00;;13:00;;22:00;;-:-;;-:-&amp;quot;\&lt;br /&gt;
fhem_set &amp;quot;MQTT2_FHEM_Server publish ebusd/700/z1Timer.Tuesday/set 04:00;;09:00;;13:00;;22:00;;-:-;;-:-&amp;quot;\&lt;br /&gt;
fhem_set &amp;quot;MQTT2_FHEM_Server publish ebusd/700/z1Timer.Wednesday/set 04:00;;09:00;;13:00;;22:00;;-:-;;-:-&amp;quot;\&lt;br /&gt;
fhem_set &amp;quot;MQTT2_FHEM_Server publish ebusd/700/z1Timer.Thursday/set 04:00;;09:00;;13:00;;22:00;;-:-;;-:-&amp;quot;\&lt;br /&gt;
fhem_set &amp;quot;MQTT2_FHEM_Server publish ebusd/700/z1Timer.Friday/set 04:00;;09:00;;13:00;;22:00;;-:-;;-:-&amp;quot;\&lt;br /&gt;
fhem_set &amp;quot;MQTT2_FHEM_Server publish ebusd/700/z1Timer.Sunday/set 05:00;;10:00;;12:00;;22:30;;-:-;;-:-&amp;quot;\&lt;br /&gt;
fhem_set &amp;quot;MQTT2_FHEM_Server publish ebusd/700/z1Timer.Saturday/set 05:00;;10:00;;12:00;;22:30;;-:-;;-:-&amp;quot;\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
diff {\&lt;br /&gt;
 set_Reading(&amp;quot;diff_hc&amp;quot;,int(([vaillant:PrEnergySumHc1_0_value]/100000-get_Reading(&amp;quot;gesamt_hc&amp;quot;,0))*10)/10,1);;\&lt;br /&gt;
 set_Reading(&amp;quot;diff_hwc&amp;quot;,int(([vaillant:PrEnergySumHwc1_0_value]/100000-get_Reading(&amp;quot;gesamt_hwc&amp;quot;,0))*10)/10,1);;\&lt;br /&gt;
 set_Reading(&amp;quot;diff_h&amp;quot;,get_Reading(&amp;quot;diff_hc&amp;quot;)+get_Reading(&amp;quot;diff_hwc&amp;quot;),1);;\&lt;br /&gt;
}\&lt;br /&gt;
\&lt;br /&gt;
&lt;br /&gt;
attr di_vaillant event-on-change-reading .*&lt;br /&gt;
attr di_vaillant room Ebus&lt;br /&gt;
attr di_vaillant uiTable {\&lt;br /&gt;
  package ui_Table;;\&lt;br /&gt;
  $TABLE=&#039;text-align:center;;&#039;;;\&lt;br /&gt;
  $SHOWNODEVICELINE = &amp;quot;test9|Damian&amp;quot;;;\&lt;br /&gt;
}\&lt;br /&gt;
icon_temp_ring(&amp;quot;temp_outside&amp;quot;,[vaillant:Aussentemp],-15,40,130)|\&lt;br /&gt;
icon_temp_mring(([vaillant:Flame] eq &amp;quot;off&amp;quot;?&amp;quot;sani_boiler_temp\@white&amp;quot;:&amp;quot;sani_boiler_temp\@Darkorange&amp;quot;),[vaillant:Vorlauf],15,70,130)|\&lt;br /&gt;
icon_temp_mring(([vaillant:Pumpenstatus] eq &amp;quot;4&amp;quot; ? &amp;quot;sani_buffer_temp_down\@Darkorange&amp;quot; : &amp;quot;sani_buffer_temp_down\@white&amp;quot;),[vaillant:WWSpeicher],15,70,130)|\&lt;br /&gt;
icon_uring(&amp;quot;0,0,1&amp;quot;,&amp;quot;weather_barometric_pressure&amp;quot;,[vaillant:Wasserdruck],0,3,undef,undef,&amp;quot;bar&amp;quot;,1,130,[(0.8,0,1,60,1.5,120,1.7,60,3,0)],&amp;quot;50,35&amp;quot;)|\&lt;br /&gt;
icon_ring(&amp;quot;sani_floor_heating_neutral&amp;quot;,[vaillant:HcHours_hoursum2_value],0,10000,120,0,&amp;quot;h&amp;quot;,0,130)|\&lt;br /&gt;
icon_ring(&amp;quot;sani_water_tap&amp;quot;,[vaillant:HwcHours_hoursum2_value],0,2000,120,0,&amp;quot;h&amp;quot;,0,130)|\&lt;br /&gt;
\&lt;br /&gt;
icon_ring(&amp;quot;time_graph&amp;quot;,[vaillant:HeizKennlinie],0.4,1,120,0,&amp;quot;HK&amp;quot;,1,130)|\&lt;br /&gt;
icon_temp_mring(&amp;quot;scene_day\@yellow&amp;quot;,[vaillant:TagSolltemp],undef,undef,130)|\&lt;br /&gt;
icon_temp_mring(&amp;quot;scene_night\@#3464eb&amp;quot;,[vaillant:NachtSolltemp],undef,undef,130)\&lt;br /&gt;
&amp;quot;&amp;quot;|&amp;quot;&amp;quot;|&amp;quot;&amp;quot;|&amp;quot;&amp;quot;|&amp;quot;&amp;quot;|&amp;quot;&amp;quot;|widget([vaillant:HeizKennlinie],&amp;quot;selectnumbers,0.4,.1,1,1,lin&amp;quot;,&amp;quot;set&amp;quot;)|widget([vaillant:TagSolltemp],&amp;quot;selectnumbers,15,1,25,1,lin&amp;quot;,&amp;quot;set&amp;quot;)|widget([vaillant:NachtSolltemp],&amp;quot;selectnumbers,15,1,25,1,lin&amp;quot;,&amp;quot;set&amp;quot;)&amp;lt;\&lt;br /&gt;
\&lt;br /&gt;
card([vaillant:Aussentemp:col],&amp;quot;Außentemperatur&amp;quot;,&amp;quot;temp_outside&amp;quot;,-15,35,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue)|\&lt;br /&gt;
card([vaillant:WWSpeicher:col],&amp;quot;WW-Speicher&amp;quot;,([vaillant:Pumpenstatus] eq &amp;quot;4&amp;quot; ? &amp;quot;sani_buffer_temp_down\@Darkorange&amp;quot; : &amp;quot;sani_buffer_temp_down\@white&amp;quot;),15,70,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue)|\&lt;br /&gt;
card([ESPEasy_ESP_Temp_Vorlauf:Temperature:col],&amp;quot;Vorlauf&amp;quot;,([vaillant:Pumpenstatus] eq &amp;quot;on&amp;quot; ? &amp;quot;sani_floor_heating\@Darkorange&amp;quot; : &amp;quot;sani_floor_heating_neutral\@white&amp;quot;),15,70,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue)|\&lt;br /&gt;
card([$SELF:diff_hc:col],&amp;quot;Energie Heizung&amp;quot;,&amp;quot;sani_floor_heating_neutral&amp;quot;,0,100,120,0,&amp;quot;kWh&amp;quot;,undef,1)\&lt;br /&gt;
card([vaillant:Umlaufmenge:col],&amp;quot;Umlaufmenge&amp;quot;,&amp;quot;sani_pump&amp;quot;,0,20,120,0,&amp;quot;l/min&amp;quot;)|\&lt;br /&gt;
card([ESPEasy_ESP_Temp_Zirkulation:Temperature:col],&amp;quot;Zirkulation&amp;quot;,([Zirk] eq &amp;quot;off&amp;quot;?&amp;quot;sani_pump\@white&amp;quot;:&amp;quot;sani_pump\@Darkorange&amp;quot;),15,70,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue)|\&lt;br /&gt;
card([ESPEasy_ESP_Temp_Keller_Ruecklauf:Temperature:col],&amp;quot;Rücklauf&amp;quot;,&amp;quot;sani_floor_heating_neutral\@wite&amp;quot;,15,70,undef,undef,&amp;quot;°C&amp;quot;,\&amp;amp;temp_hue)|\&lt;br /&gt;
card([$SELF:diff_hwc:col],&amp;quot;Energie Warmwasser&amp;quot;,&amp;quot;sani_water_tap&amp;quot;,0,15,120,0,&amp;quot;kWh&amp;quot;,undef,1)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:Di uiTable Heizung.png|800px|links]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;Visualisierung: &#039;&#039;&#039;Anwesenheitsstatus&#039;&#039;&#039;&#039;&#039; ===&lt;br /&gt;
{{Randnotiz|RNText=&#039;&#039;&#039;nützliche Links&#039;&#039;&#039;&lt;br /&gt;
* [[FRITZBOX|FritzBox-Modul]]&lt;br /&gt;
* ui_Table Funktion [[DOIF/uiTable Schnelleinstieg#Icon-Darstellung mit Text mit Hilfe der Funktion icon_label|icon_label]]&lt;br /&gt;
*[[DOIF/uiTable Schnelleinstieg#uiTable-Templates|uiTable-Templates]]&lt;br /&gt;
}}&lt;br /&gt;
Die aktuelle Anwesenheit von Heimbewohnern wird visualisiert.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Zunächst wird mit Hilfe des Moduls [[FRITZBOX]] ein Device namens &#039;&#039;FritzBox&#039;&#039; erstellt. Dort werden die eingebuchten Smartphones der Bewohner mit Ihren MAC-Adressen in Readings abgelegt. Die folgende Definition wertet aus, ob die angegebenen MAC-Adressen als Readings vorhanden sind und erstellt für jeden Bewohner ein Reading mit den Zuständen on/off. Diese Readings werden dann über das Attribut uiTable visualisiert. Die anwesenden Personen werden farblich markiert. Die Namen der Personen sowie die MAC-Adressen sind fiktiv und müssen den eigenen Angaben entsprechend angepasst werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod myHome DOIF {\&lt;br /&gt;
 set_Reading_Begin;;\&lt;br /&gt;
  set_Reading_Update(&amp;quot;Ernie&amp;quot;,[FritzBox:mac_12_34_E0_00_CD_E4] ? &amp;quot;on&amp;quot;:&amp;quot;off&amp;quot;);;\&lt;br /&gt;
  set_Reading_Update(&amp;quot;Bert&amp;quot;, [FritzBox:mac_02_08_02_07_30_E3] ? &amp;quot;on&amp;quot;:&amp;quot;off&amp;quot;);;\&lt;br /&gt;
  set_Reading_Update(&amp;quot;Grobi&amp;quot;, [FritzBox:mac_00_08_01_0B_00_E7] ? &amp;quot;on&amp;quot;:&amp;quot;off&amp;quot;);; \&lt;br /&gt;
  set_Reading_Update(&amp;quot;Kermit&amp;quot;, [FritzBox:mac_01_30_A9_72_02_E3] ? &amp;quot;on&amp;quot;:&amp;quot;off&amp;quot;);; \&lt;br /&gt;
 set_Reading_End(1);;\&lt;br /&gt;
}&lt;br /&gt;
attr myHome checkReadingEvent 0&lt;br /&gt;
attr myHome uiTable {\&lt;br /&gt;
  package ui_Table;;\&lt;br /&gt;
  $SHOWNOSTATE=1;;\&lt;br /&gt;
  $TC{0..4}=&amp;quot;align=&#039;center&#039;&amp;quot;;;\&lt;br /&gt;
}\&lt;br /&gt;
## Template-Definition für die Visualisierung eines Bewohners mit Hilfe des Icons fa__508\&lt;br /&gt;
DEF TPL_person (icon_label([$SELF:$1] eq &amp;quot;on&amp;quot; ? &amp;quot;fa__508\@DarkOrange&amp;quot;:&amp;quot;fa__508&amp;quot;,&amp;quot;$1&amp;quot;,&amp;quot;#e67e00&amp;quot;,&amp;quot;white&amp;quot;,-10))\&lt;br /&gt;
\&lt;br /&gt;
## Darstellung der Bewohner mit Hilfe des obigen Templates\&lt;br /&gt;
TPL_person(Ernie)|TPL_person(Bert)|TPL_person(Grobi)|TPL_person(Kermit)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ergebnis der Beispieldefinition in der Webansicht:&#039;&#039;&lt;br /&gt;
[[Datei:UiTable myHome.png|ohne|mini]]&lt;br /&gt;
&lt;br /&gt;
=== Weiterführende Links ===&lt;br /&gt;
* [[DOIF/Perl-Modus]]&lt;br /&gt;
* [[DOIF/Automatisierung]]&lt;br /&gt;
&lt;br /&gt;
== Weiterführende Links ==&lt;br /&gt;
* Weitere Beispiele für Fortgeschrittene, siehe &amp;quot;[[DOIF/uiTable|uiTable mit FHEM-Widgets und Styles]]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Frontends]]&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>Ansgru</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mehrere_USB-Ger%C3%A4te_einbinden&amp;diff=39212</id>
		<title>Mehrere USB-Geräte einbinden</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mehrere_USB-Ger%C3%A4te_einbinden&amp;diff=39212"/>
		<updated>2024-03-31T08:47:38Z</updated>

		<summary type="html">&lt;p&gt;Ansgru: /* FreeBSD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Problembeschreibung ==&lt;br /&gt;
Nutzt man an einem FHEM-Server mehrere USB-Geräte, insbesondere als [[Interface|Interface]], ist es wichtig, diese so einzubinden, dass sie von FHEM jeweils korrekt angesprochen werden. Hierzu ist eine eindeutige Addressierung im USB-System erforderlich.&lt;br /&gt;
{{Hinweis|Sofern neben FHEM noch weitere Dienste auf der Server-Hardware aktiv sind, die auf Hardware an USB-Schnittstellen zugreift (z.B. ein HM-IP-USB-Stick für eine virtualisierte CCUx oder ConBee-Dongles für deconz bzw. USB-Dongles für zigbee2mqtt betr. ZigBee), empfiehlt es sich, auch bei diesen Diensten nach Möglichkeiten zu forschen, die von diesen angesprochenen USB-Geräte auch von deren Seite eindeutig zu adressieren.}}&lt;br /&gt;
&lt;br /&gt;
== Linux ==&lt;br /&gt;
=== Hintergrund ===&lt;br /&gt;
In einem Linux-System erfolgt die Einbindung zunächst häufig über allgemeine Standardpfade wie &#039;&#039;/dev/ttyUSB0&#039;&#039; oder &#039;&#039;/dev/ttyACM0&#039;&#039;. Steckt man im laufenden Betrieb ein weiteres Interface ein, erscheint dieses ohne Neustart des Rechners erst einmal unter dem nächsten freien Standardpfad, also z.B. &#039;&#039;/dev/ttyUSB1&#039;&#039;. Allerdings kann es sein, dass die Zuordnung beim nächsten Systemstart genau umgekehrt ist, sich also das Gerät, das unter &#039;&#039;/dev/ttyUSB1&#039;&#039; zu finden war, nunmehr unter &#039;&#039;/dev/ttyUSB0&#039;&#039; zu erreichen ist. Hierdurch funktionieren die Geräte nicht mehr, wenn sie in FHEM über diese allgemeinen Schnittstellenbezeichnungen in der DEF eingebunden waren. Dies gilt vor allem dann, wenn diese völlig unterschiedliche Funktionen haben, andere Baud-Raten verwenden oder andere Initialisierungscodes erwarten.&lt;br /&gt;
&lt;br /&gt;
Ensprechendes gilt, wenn die Geräte später entfernt werden und/oder danach ggf. an einem anderen USB-Port verwendet.&lt;br /&gt;
&lt;br /&gt;
Da die Geräte im Verlauf der Einbindung in das USB-System einige Informationen austauschen, gibt es mehrere Möglichkeiten, dieses unerwünschte Verhalten zu unterbinden.&lt;br /&gt;
&lt;br /&gt;
=== Nutzen der Serial ID ===&lt;br /&gt;
Um dies zu umgehen, kann man sie über ihre Serial-ID in FHEM einbinden.&lt;br /&gt;
&lt;br /&gt;
Dieser Befehl zeigt die Serial-ID:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;ls -l /dev/serial/by-id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier die Beispielausgabe eines CUL868, JeeLink, RFXtrx und eines CUL433&lt;br /&gt;
&lt;br /&gt;
 user@xxxx:~# ls -l /dev/serial/by-id&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jan  9 23:34 usb-busware.de_CUL868-if00 -&amp;gt; ../../ttyACM0&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jan  9 13:26 usb-FTDI_FT232R_USB_UART_A901RQ9F-if00-port0-&amp;gt; ../../ttyUSB0&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jan  9 13:26 usb-RFXCOM_RFXtrx433_A1WZWL5Y-if00-port0-&amp;gt; ../../ttyUSB1&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jan  9 21:29 usb-busware.de_CUL433-if00 -&amp;gt; ../../ttyACM1 &lt;br /&gt;
&lt;br /&gt;
Damit lässt sich folgende Definition erstellen:&lt;br /&gt;
&lt;br /&gt;
z.B. für einen CUL868&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;define CUL868 CUL /dev/serial/by-id/usb-busware.de_CUL868-if00@9600 1134&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder einen JeeLink&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;define Jeelink JeeLink /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A901RQ9F-if00-port0@57600&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Nutzt man die &amp;quot;by-id&amp;quot;-Methode, empfiehlt es sich, dies für alle USB-Geräte zu verwenden. Ist man gezwungen, &amp;quot;by-path&amp;quot; zu verwenden, sollte man letzteres auf die problematischen Geräte beschränken und eindeutige Geräte weiter mit &amp;quot;by-id&amp;quot; addressieren.}}&lt;br /&gt;
&lt;br /&gt;
=== Problemfälle: by-id ===&lt;br /&gt;
Bei CULs von Busware lassen sich nur CUL433 und CUL868 unterscheiden. Zwei CUL868 haben z.B. immer die gleiche Serial-ID. Entsprechendes gilt, wenn man mehrere Produkte mit gleicher &amp;quot;by-id&amp;quot;-Kennung nutzt. Dies betrifft z.B. Arduino-Nano-Klone mit CHG340/CHG341 USB-Serial-Wandler (/dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0), [[CP2102|CP2102-Wandler]] (10c4:ea60) oder Prolific-Produkte. &lt;br /&gt;
Lösungsansätze sind weiter unten aufgeführt, man kann in solchen Fällen jedoch auch die problematischen Geräte über die Angaben einbinden, welche man über :&amp;lt;code&amp;gt;ls -l /dev/serial/by-path&amp;lt;/code&amp;gt; erhält.&lt;br /&gt;
Das Vorgehen entspricht im Übrigen dem für &amp;quot;by-id&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== udev-Rules ===&lt;br /&gt;
Man kann mittels udev-Rules auch die Angaben zur Serial-ID und/oder der &#039;&#039;py-path&#039;&#039; dazu nutzen, den jeweiligen Geräten einen eindeutigen Namen zuzuweisen.&lt;br /&gt;
Detaillierte Erläuterungen zu udev:&lt;br /&gt;
* [https://wiki.debian.org/udev https://wiki.debian.org/udev]&lt;br /&gt;
* [https://wiki.ubuntuusers.de/udev/ https://wiki.ubuntuusers.de/udev/]&lt;br /&gt;
* [https://wiki.archlinux.de/title/Udev https://wiki.archlinux.de/title/Udev]&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
Links zur Anbindung von USB-COM-Port-Geräten&lt;br /&gt;
* [https://www.uhlenbrock.de/de_DE/service/faq/software/I23A3243-001.htm!ArcEntryInfo=0004.18.I23A3243&amp;amp;NewServerName=zeta COM-PORT Einstellungen unter Windows 10 ändern - bebilderte Anleitung]&lt;br /&gt;
* [http://heise.de/-2150736 Nicht angeschlossene Geräte unter Windows loswerden]&lt;br /&gt;
* [https://www.uwe-sieber.de/comportman.html ComPortMan - Windows-Dienst zur Kontrolle über die Zuordnung von COM-Ports]&lt;br /&gt;
* [https://www.ftdichip.com/Support/Documents/AppNotes/AN_132_Re-Assigning_COM_Port_Numbers_Using_Registry.pdf FTDI Application Note Re-Assigning COM Port Numbers Using the Windows Registry]&lt;br /&gt;
&lt;br /&gt;
== FreeBSD ==&lt;br /&gt;
=== Hintergrund ===&lt;br /&gt;
USB zu seriell Adapter (z.B. für RS485/Modbus, Arduinos etc) tauchen unter FreeBSD als &#039;&#039;/dev/cuaU*&#039;&#039; Geräte auf. Das macht es schwierig, sie in FHEM einzubinden da sich beim Umstecken etc. der Gerätename ändern kann und dann der Adapter z.B. nicht mehr unter &#039;&#039;cuaU0&#039;&#039; sondern unter &#039;&#039;cuaU1&#039;&#039; etc. zu finden ist.&lt;br /&gt;
=== Nutzen der Serial ID ===&lt;br /&gt;
Unter Linux haben die Adapter eine eindeutige Kennung (z.B. als &#039;&#039;/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A10KVD0Q-if00-port0&#039;&#039;). In FreeBSD kann man das wie folgt nachbauen:&lt;br /&gt;
&lt;br /&gt;
  &amp;gt; cat /usr/local/etc/devd/rs485.conf&lt;br /&gt;
  attach 1000 {&lt;br /&gt;
          match &amp;quot;sernum&amp;quot;          &amp;quot;AB0LHFXT|AB0MG4RO|A10KVD0Q&amp;quot;;&lt;br /&gt;
          action                  &amp;quot;ln -sf /dev/cua$ttyname /dev/waveshare_$sernum &amp;amp;&amp;amp; ln -sf /dev/cua$ttyname.lock /dev/waveshare_$sernum.lock &amp;amp;&amp;amp; ln -sf /dev/cua$ttyname.init /dev/waveshare_$sernum.init&amp;quot;;&lt;br /&gt;
  };&lt;br /&gt;
  &lt;br /&gt;
  notify 1000 {&lt;br /&gt;
          match &amp;quot;sernum&amp;quot;          &amp;quot;AB0LHFXT|AB0MG4RO|A10KVD0Q&amp;quot;;&lt;br /&gt;
          match &amp;quot;type&amp;quot;            &amp;quot;DETACH&amp;quot;;&lt;br /&gt;
          match &amp;quot;subsystem&amp;quot;       &amp;quot;DEVICE&amp;quot;;&lt;br /&gt;
          action                  &amp;quot;rm /dev/waveshare_$sernum &amp;amp;&amp;amp; rm /dev/waveshare_$sernum.init &amp;amp;&amp;amp; rm /dev/waveshare_$sernum.lock&amp;quot;;&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
In diesem Beispiel sind die Adapter mit Seriennummer AB0LHFXT, AB0MG4RO oder A10KVD0Q eindeutig als &#039;&#039;/dev/waveshare_&#039;&#039;&#039;Seriennummer&#039;&#039;&#039;&#039;&#039; ansprechbar und lassen sich entsprechend in FHEM einbinden.&lt;br /&gt;
&lt;br /&gt;
Die Seriennummer (oder zur Not auch der USB Pfad für Adapter, die keine Seriennummer haben (wie z.B. CH340 Chips)) lässt sich mit &lt;br /&gt;
:&amp;lt;code&amp;gt;usbconfig -d ugen1.11 dump_all_desc&amp;lt;/code&amp;gt;&lt;br /&gt;
herausfinden wenn das Gerät bereits eingesteckt ist oder aber mit einem laufenden &lt;br /&gt;
:&amp;lt;code&amp;gt;cat /var/run/devd.pipe &amp;lt;/code&amp;gt;&lt;br /&gt;
und dann einem anschliessen des Gerätes.&lt;br /&gt;
&lt;br /&gt;
=== ECMD ===&lt;br /&gt;
Regelmässiges Abfragen scheinen dazu zu führen, dass FHEM hängt.&lt;br /&gt;
&lt;br /&gt;
== Hilfsmittel ==&lt;br /&gt;
=== CUL-firmware modifizieren ===&lt;br /&gt;
Für Original CULs sowie Klone auf ATMega32U4-Basis kann man die Kennung im Quellcode der culfw ändern, unter der sich der Microkontroller später im USB-System anmeldet.&lt;br /&gt;
&lt;br /&gt;
=== FTDI-Chips ===&lt;br /&gt;
FTDI-Wandler sollten eigentlich von Hause aus mit einer eindeutigen Seriennummer versehen sein. Sollte dies nicht der Fall sein, kann man dies nachholen. FTDI bietet hierzu ein Tool an, unter Linux kann man hierfür [http://rtr.ca/ft232r/ ft232r_prog] verwenden. Allerdings kann es insbesondere bei der Windows-Software von FTDI zu Problemen kommen, wenn es sich um einen geklonten Chip handelt.&lt;br /&gt;
&lt;br /&gt;
=== CP2102 ===&lt;br /&gt;
Für Linux ist [http://cp210x-program.sourceforge.net/ hier] ein in Python-Tool verfügbar.&lt;br /&gt;
Beispiel für die gleichzeitige Nutzung von drei Modulen (eines davon mit bereits geänderter Kennung - dieses wird in &amp;quot;by-id&amp;quot; gelistet, das andere (noch) nicht):&lt;br /&gt;
&lt;br /&gt;
 lsusb&lt;br /&gt;
 Bus 002 Device 017: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP210x UART Bridge / myAVR mySmartUSB light&lt;br /&gt;
 Bus 002 Device 015: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP210x UART Bridge / myAVR mySmartUSB light&lt;br /&gt;
 Bus 002 Device 016: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP210x UART Bridge / myAVR mySmartUSB light&lt;br /&gt;
&lt;br /&gt;
 ls -l /dev/serial/by-path&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jun  9 16:33 pci-0000:00:1d.0-usb-0:1.1.2:1.0-port0 -&amp;gt; ../../ttyUSB2&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jun  9 16:33 pci-0000:00:1d.0-usb-0:1.1.3:1.0-port0 -&amp;gt; ../../ttyUSB0&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jun  9 16:33 pci-0000:00:1d.0-usb-0:1.1.4:1.0-port0 -&amp;gt; ../../ttyUSB1&lt;br /&gt;
 &lt;br /&gt;
 ls -l /dev/serial/by-id&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jun  9 16:33 usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 -&amp;gt; ../../ttyUSB2&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jun  9 16:33 usb-Silicon_Labs_Multi_TTL_RS485_0003-if00-port0 -&amp;gt; ../../ttyUSB0&lt;br /&gt;
{{Hinweis|Dabei sollte nicht die VID oder PID verändert werden, Änderungen der Seriennummer oder der Produktkennung (product-string) sind jedoch gefahrlos möglich, ebenso die der Herstellerkennung (vendor-string), die allerdings ein --force-eeprom erfordert (Linux).}}&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
[[Kategorie:FAQ]]&lt;br /&gt;
[[Kategorie:Other Components]]&lt;br /&gt;
[[Kategorie:FHEM-Verwendung]]&lt;/div&gt;</summary>
		<author><name>Ansgru</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mehrere_USB-Ger%C3%A4te_einbinden&amp;diff=39211</id>
		<title>Mehrere USB-Geräte einbinden</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mehrere_USB-Ger%C3%A4te_einbinden&amp;diff=39211"/>
		<updated>2024-03-31T08:42:33Z</updated>

		<summary type="html">&lt;p&gt;Ansgru: Hinzufügen FreeBSD&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Problembeschreibung ==&lt;br /&gt;
Nutzt man an einem FHEM-Server mehrere USB-Geräte, insbesondere als [[Interface|Interface]], ist es wichtig, diese so einzubinden, dass sie von FHEM jeweils korrekt angesprochen werden. Hierzu ist eine eindeutige Addressierung im USB-System erforderlich.&lt;br /&gt;
{{Hinweis|Sofern neben FHEM noch weitere Dienste auf der Server-Hardware aktiv sind, die auf Hardware an USB-Schnittstellen zugreift (z.B. ein HM-IP-USB-Stick für eine virtualisierte CCUx oder ConBee-Dongles für deconz bzw. USB-Dongles für zigbee2mqtt betr. ZigBee), empfiehlt es sich, auch bei diesen Diensten nach Möglichkeiten zu forschen, die von diesen angesprochenen USB-Geräte auch von deren Seite eindeutig zu adressieren.}}&lt;br /&gt;
&lt;br /&gt;
== Linux ==&lt;br /&gt;
=== Hintergrund ===&lt;br /&gt;
In einem Linux-System erfolgt die Einbindung zunächst häufig über allgemeine Standardpfade wie &#039;&#039;/dev/ttyUSB0&#039;&#039; oder &#039;&#039;/dev/ttyACM0&#039;&#039;. Steckt man im laufenden Betrieb ein weiteres Interface ein, erscheint dieses ohne Neustart des Rechners erst einmal unter dem nächsten freien Standardpfad, also z.B. &#039;&#039;/dev/ttyUSB1&#039;&#039;. Allerdings kann es sein, dass die Zuordnung beim nächsten Systemstart genau umgekehrt ist, sich also das Gerät, das unter &#039;&#039;/dev/ttyUSB1&#039;&#039; zu finden war, nunmehr unter &#039;&#039;/dev/ttyUSB0&#039;&#039; zu erreichen ist. Hierdurch funktionieren die Geräte nicht mehr, wenn sie in FHEM über diese allgemeinen Schnittstellenbezeichnungen in der DEF eingebunden waren. Dies gilt vor allem dann, wenn diese völlig unterschiedliche Funktionen haben, andere Baud-Raten verwenden oder andere Initialisierungscodes erwarten.&lt;br /&gt;
&lt;br /&gt;
Ensprechendes gilt, wenn die Geräte später entfernt werden und/oder danach ggf. an einem anderen USB-Port verwendet.&lt;br /&gt;
&lt;br /&gt;
Da die Geräte im Verlauf der Einbindung in das USB-System einige Informationen austauschen, gibt es mehrere Möglichkeiten, dieses unerwünschte Verhalten zu unterbinden.&lt;br /&gt;
&lt;br /&gt;
=== Nutzen der Serial ID ===&lt;br /&gt;
Um dies zu umgehen, kann man sie über ihre Serial-ID in FHEM einbinden.&lt;br /&gt;
&lt;br /&gt;
Dieser Befehl zeigt die Serial-ID:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;ls -l /dev/serial/by-id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier die Beispielausgabe eines CUL868, JeeLink, RFXtrx und eines CUL433&lt;br /&gt;
&lt;br /&gt;
 user@xxxx:~# ls -l /dev/serial/by-id&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jan  9 23:34 usb-busware.de_CUL868-if00 -&amp;gt; ../../ttyACM0&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jan  9 13:26 usb-FTDI_FT232R_USB_UART_A901RQ9F-if00-port0-&amp;gt; ../../ttyUSB0&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jan  9 13:26 usb-RFXCOM_RFXtrx433_A1WZWL5Y-if00-port0-&amp;gt; ../../ttyUSB1&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jan  9 21:29 usb-busware.de_CUL433-if00 -&amp;gt; ../../ttyACM1 &lt;br /&gt;
&lt;br /&gt;
Damit lässt sich folgende Definition erstellen:&lt;br /&gt;
&lt;br /&gt;
z.B. für einen CUL868&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;define CUL868 CUL /dev/serial/by-id/usb-busware.de_CUL868-if00@9600 1134&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder einen JeeLink&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;define Jeelink JeeLink /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A901RQ9F-if00-port0@57600&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Nutzt man die &amp;quot;by-id&amp;quot;-Methode, empfiehlt es sich, dies für alle USB-Geräte zu verwenden. Ist man gezwungen, &amp;quot;by-path&amp;quot; zu verwenden, sollte man letzteres auf die problematischen Geräte beschränken und eindeutige Geräte weiter mit &amp;quot;by-id&amp;quot; addressieren.}}&lt;br /&gt;
&lt;br /&gt;
=== Problemfälle: by-id ===&lt;br /&gt;
Bei CULs von Busware lassen sich nur CUL433 und CUL868 unterscheiden. Zwei CUL868 haben z.B. immer die gleiche Serial-ID. Entsprechendes gilt, wenn man mehrere Produkte mit gleicher &amp;quot;by-id&amp;quot;-Kennung nutzt. Dies betrifft z.B. Arduino-Nano-Klone mit CHG340/CHG341 USB-Serial-Wandler (/dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0), [[CP2102|CP2102-Wandler]] (10c4:ea60) oder Prolific-Produkte. &lt;br /&gt;
Lösungsansätze sind weiter unten aufgeführt, man kann in solchen Fällen jedoch auch die problematischen Geräte über die Angaben einbinden, welche man über :&amp;lt;code&amp;gt;ls -l /dev/serial/by-path&amp;lt;/code&amp;gt; erhält.&lt;br /&gt;
Das Vorgehen entspricht im Übrigen dem für &amp;quot;by-id&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== udev-Rules ===&lt;br /&gt;
Man kann mittels udev-Rules auch die Angaben zur Serial-ID und/oder der &#039;&#039;py-path&#039;&#039; dazu nutzen, den jeweiligen Geräten einen eindeutigen Namen zuzuweisen.&lt;br /&gt;
Detaillierte Erläuterungen zu udev:&lt;br /&gt;
* [https://wiki.debian.org/udev https://wiki.debian.org/udev]&lt;br /&gt;
* [https://wiki.ubuntuusers.de/udev/ https://wiki.ubuntuusers.de/udev/]&lt;br /&gt;
* [https://wiki.archlinux.de/title/Udev https://wiki.archlinux.de/title/Udev]&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
Links zur Anbindung von USB-COM-Port-Geräten&lt;br /&gt;
* [https://www.uhlenbrock.de/de_DE/service/faq/software/I23A3243-001.htm!ArcEntryInfo=0004.18.I23A3243&amp;amp;NewServerName=zeta COM-PORT Einstellungen unter Windows 10 ändern - bebilderte Anleitung]&lt;br /&gt;
* [http://heise.de/-2150736 Nicht angeschlossene Geräte unter Windows loswerden]&lt;br /&gt;
* [https://www.uwe-sieber.de/comportman.html ComPortMan - Windows-Dienst zur Kontrolle über die Zuordnung von COM-Ports]&lt;br /&gt;
* [https://www.ftdichip.com/Support/Documents/AppNotes/AN_132_Re-Assigning_COM_Port_Numbers_Using_Registry.pdf FTDI Application Note Re-Assigning COM Port Numbers Using the Windows Registry]&lt;br /&gt;
&lt;br /&gt;
== FreeBSD ==&lt;br /&gt;
=== Hintergrund ===&lt;br /&gt;
USB zu seriell Adapter (z.B. für RS485/Modbus, Arduinos etc) tauchen unter FreeBSD als &#039;&#039;/dev/cuaU*&#039;&#039; Geräte auf. Das macht es schwierig, sie in FHEM einzubinden da sich beim Umstecken etc. der Gerätename ändern kann und dann der Adapter z.B. nicht mehr unter &#039;&#039;cuaU0&#039;&#039; sondern unter &#039;&#039;cuaU1&#039;&#039; etc. zu finden ist.&lt;br /&gt;
=== Nutzen der Serial ID ===&lt;br /&gt;
Unter Linux haben die Adapter eine eindeutige Kennung (z.B. als &#039;&#039;/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A10KVD0Q-if00-port0&#039;&#039;). In FreeBSD kann man das wie folgt nachbauen:&lt;br /&gt;
&lt;br /&gt;
  &amp;gt; cat /usr/local/etc/devd/rs485.conf&lt;br /&gt;
  attach 1000 {&lt;br /&gt;
          match &amp;quot;sernum&amp;quot;          &amp;quot;AB0LHFXT|AB0MG4RO|A10KVD0Q&amp;quot;;&lt;br /&gt;
          action                  &amp;quot;ln -sf /dev/cua$ttyname /dev/waveshare_$sernum &amp;amp;&amp;amp; ln -sf /dev/cua$ttyname.lock /dev/waveshare_$sernum.lock &amp;amp;&amp;amp; ln -sf /dev/cua$ttyname.init /dev/waveshare_$sernum.init&amp;quot;;&lt;br /&gt;
  };&lt;br /&gt;
  &lt;br /&gt;
  notify 1000 {&lt;br /&gt;
          match &amp;quot;sernum&amp;quot;          &amp;quot;AB0LHFXT|AB0MG4RO|A10KVD0Q&amp;quot;;&lt;br /&gt;
          match &amp;quot;type&amp;quot;            &amp;quot;DETACH&amp;quot;;&lt;br /&gt;
          match &amp;quot;subsystem&amp;quot;       &amp;quot;DEVICE&amp;quot;;&lt;br /&gt;
          action                  &amp;quot;rm /dev/waveshare_$sernum &amp;amp;&amp;amp; rm /dev/waveshare_$sernum.init &amp;amp;&amp;amp; rm /dev/waveshare_$sernum.lock&amp;quot;;&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
In diesem Beispiel sind die Adapter mit Seriennummer AB0LHFXT, AB0MG4RO oder A10KVD0Q eindeutig als &#039;&#039;/dev/waveshare_&#039;&#039;&#039;Seriennummer&#039;&#039;&#039;&#039;&#039; ansprechbar und lassen sich entsprechend in FHEM einbinden.&lt;br /&gt;
&lt;br /&gt;
Die Seriennummer (oder zur Not auch der USB Pfad für Adapter, die keine Seriennummer haben (wie z.B. CH340 Chips)) lässt sich mit &lt;br /&gt;
:&amp;lt;code&amp;gt;usbconfig -d ugen1.11 dump_all_desc&amp;lt;/code&amp;gt;&lt;br /&gt;
herausfinden wenn das Gerät bereits eingesteckt ist oder aber mit einem laufenden &lt;br /&gt;
:&amp;lt;code&amp;gt;cat /var/run/devd.pipe &amp;lt;/code&amp;gt;&lt;br /&gt;
und dann einem anschliessen des Gerätes.&lt;br /&gt;
&lt;br /&gt;
== Hilfsmittel ==&lt;br /&gt;
=== CUL-firmware modifizieren ===&lt;br /&gt;
Für Original CULs sowie Klone auf ATMega32U4-Basis kann man die Kennung im Quellcode der culfw ändern, unter der sich der Microkontroller später im USB-System anmeldet.&lt;br /&gt;
&lt;br /&gt;
=== FTDI-Chips ===&lt;br /&gt;
FTDI-Wandler sollten eigentlich von Hause aus mit einer eindeutigen Seriennummer versehen sein. Sollte dies nicht der Fall sein, kann man dies nachholen. FTDI bietet hierzu ein Tool an, unter Linux kann man hierfür [http://rtr.ca/ft232r/ ft232r_prog] verwenden. Allerdings kann es insbesondere bei der Windows-Software von FTDI zu Problemen kommen, wenn es sich um einen geklonten Chip handelt.&lt;br /&gt;
&lt;br /&gt;
=== CP2102 ===&lt;br /&gt;
Für Linux ist [http://cp210x-program.sourceforge.net/ hier] ein in Python-Tool verfügbar.&lt;br /&gt;
Beispiel für die gleichzeitige Nutzung von drei Modulen (eines davon mit bereits geänderter Kennung - dieses wird in &amp;quot;by-id&amp;quot; gelistet, das andere (noch) nicht):&lt;br /&gt;
&lt;br /&gt;
 lsusb&lt;br /&gt;
 Bus 002 Device 017: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP210x UART Bridge / myAVR mySmartUSB light&lt;br /&gt;
 Bus 002 Device 015: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP210x UART Bridge / myAVR mySmartUSB light&lt;br /&gt;
 Bus 002 Device 016: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP210x UART Bridge / myAVR mySmartUSB light&lt;br /&gt;
&lt;br /&gt;
 ls -l /dev/serial/by-path&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jun  9 16:33 pci-0000:00:1d.0-usb-0:1.1.2:1.0-port0 -&amp;gt; ../../ttyUSB2&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jun  9 16:33 pci-0000:00:1d.0-usb-0:1.1.3:1.0-port0 -&amp;gt; ../../ttyUSB0&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jun  9 16:33 pci-0000:00:1d.0-usb-0:1.1.4:1.0-port0 -&amp;gt; ../../ttyUSB1&lt;br /&gt;
 &lt;br /&gt;
 ls -l /dev/serial/by-id&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jun  9 16:33 usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 -&amp;gt; ../../ttyUSB2&lt;br /&gt;
 lrwxrwxrwx 1 root root 13 Jun  9 16:33 usb-Silicon_Labs_Multi_TTL_RS485_0003-if00-port0 -&amp;gt; ../../ttyUSB0&lt;br /&gt;
{{Hinweis|Dabei sollte nicht die VID oder PID verändert werden, Änderungen der Seriennummer oder der Produktkennung (product-string) sind jedoch gefahrlos möglich, ebenso die der Herstellerkennung (vendor-string), die allerdings ein --force-eeprom erfordert (Linux).}}&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
[[Kategorie:FAQ]]&lt;br /&gt;
[[Kategorie:Other Components]]&lt;br /&gt;
[[Kategorie:FHEM-Verwendung]]&lt;/div&gt;</summary>
		<author><name>Ansgru</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Gleitende_Mittelwerte_berechnen_und_loggen&amp;diff=37505</id>
		<title>Gleitende Mittelwerte berechnen und loggen</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Gleitende_Mittelwerte_berechnen_und_loggen&amp;diff=37505"/>
		<updated>2022-07-19T07:13:13Z</updated>

		<summary type="html">&lt;p&gt;Ansgru: Formatierung&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Für verschiedene Wettersensoren ist es oftmals wünschenswert, gleitende Mittelwerte (fälschlich auch als &amp;quot;relative&amp;quot; Mittelwerte bezeichnet) über ein bestimmtes Zeitfenster auszugeben oder in den Logs zu speichern und zu plotten. Beispiele:&lt;br /&gt;
* Die momentanen Winddaten eines KS300 sind oft stark schwankend. Hier wäre ein Mittelwert z.B. der letzten 2-3 Stunden interessant. &lt;br /&gt;
* Für die Außentemperatur ist anhand eines Mittelwertes der letzten 24 Stunden evtl. ein gewisser Trend der generellen Entwicklung der Temperatur ableitbar.&lt;br /&gt;
&lt;br /&gt;
Mit Modulen wie &#039;&#039;rain&#039;&#039; oder &#039;&#039;average&#039;&#039; ist konzeptbedingt nur ein Mittelwert von fixen Zeiträumen (aktueller Tag, Monat, etc.) möglich. &lt;br /&gt;
&lt;br /&gt;
Im Nachfolgenden werden deshalb zwei Programme vorgestellt, die solche gleitenden Mittelwerte bereitstellen. Beide Programme werden in die Datei [[99 myUtils anlegen|99_MyUtils.pm]] eingetragen und dann von FHEM aufgerufen. Das erste Programm macht dies für beliebige Readings beliebiger Devices, das zweite Programm greift auf beliebige [[FileLog|File-]] oder [[DbLog|DbLogs]] zurück.&lt;br /&gt;
&lt;br /&gt;
== Gleitender Mittelwert für beliebige Readings ==&lt;br /&gt;
=== Subroutine movingAverage in 99_MyUtils anlegen ===&lt;br /&gt;
Zuerst muss die Subroutine &#039;&#039;movingAverage&#039;&#039; in die 99_MyUtils übernommen werden. Wenn noch nicht vorhanden, sollte die Datei dann so aussehen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;package main;&lt;br /&gt;
  use strict;&lt;br /&gt;
  use warnings;&lt;br /&gt;
  sub&lt;br /&gt;
  MyUtils_Initialize($$)&lt;br /&gt;
  {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
  }&lt;br /&gt;
  ###############################################################################&lt;br /&gt;
  #&lt;br /&gt;
  #  Moving average &lt;br /&gt;
  #&lt;br /&gt;
  #  Aufruf: movingAverage(devicename,readingname,zeitspanne in s)&lt;br /&gt;
  #&lt;br /&gt;
  ###############################################################################&lt;br /&gt;
  &lt;br /&gt;
  sub movingAverage($$$){&lt;br /&gt;
     my ($name,$reading,$avtime) = @_;&lt;br /&gt;
     my $hash = $defs{$name};&lt;br /&gt;
     my @new = my ($val,$time) = ($hash-&amp;gt;{READINGS}{$reading}{VAL},$hash-&amp;gt;{READINGS}{$reading}{TIME});&lt;br /&gt;
     my ($cyear, $cmonth, $cday, $chour, $cmin, $csec) = $time =~ /(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/;&lt;br /&gt;
     my $ctime = $csec+60*$cmin+3600*$chour;&lt;br /&gt;
     my $num;&lt;br /&gt;
     my $arr;&lt;br /&gt;
     #-- initialize if requested&lt;br /&gt;
     if( ($avtime eq &amp;quot;-1&amp;quot;) ){&lt;br /&gt;
       $hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}=undef;&lt;br /&gt;
     }&lt;br /&gt;
     #-- test for existence&lt;br /&gt;
     if( !$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}){&lt;br /&gt;
        #Log 1,&amp;quot;ARRAY CREATED&amp;quot;;&lt;br /&gt;
        push(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}},\@new);&lt;br /&gt;
        $num = 1;&lt;br /&gt;
        $arr=\@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}};&lt;br /&gt;
     } else {&lt;br /&gt;
        $num = int(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}});&lt;br /&gt;
        $arr=\@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}};&lt;br /&gt;
        my $starttime = $arr-&amp;gt;[0][1];&lt;br /&gt;
        my ($syear, $smonth, $sday, $shour, $smin, $ssec) = $starttime =~ /(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/;&lt;br /&gt;
        my $stime = $ssec+60*$smin+3600*$shour;&lt;br /&gt;
        #-- correct for daybreak&lt;br /&gt;
        $stime-=86400 &lt;br /&gt;
          if( $stime &amp;gt; $ctime);&lt;br /&gt;
        if( ($num &amp;lt; 25)&amp;amp;&amp;amp;( ($ctime-$stime)&amp;lt;$avtime) ){&lt;br /&gt;
          #Log 1,&amp;quot;ARRAY has $num elements, adding another one&amp;quot;;&lt;br /&gt;
          push(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}},\@new);&lt;br /&gt;
        }else{&lt;br /&gt;
          shift(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}});&lt;br /&gt;
          push(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}},\@new);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      #-- output and average&lt;br /&gt;
      my $average = 0;&lt;br /&gt;
      for(my $i=0;$i&amp;lt;$num;$i++){&lt;br /&gt;
        $average+=$arr-&amp;gt;[$i][0];&lt;br /&gt;
        Log 4,&amp;quot;[$name moving average] Value = &amp;quot;.$arr-&amp;gt;[$i][0].&amp;quot; Time = &amp;quot;.$arr-&amp;gt;[$i][1]; &lt;br /&gt;
      }&lt;br /&gt;
      $average=sprintf( &amp;quot;%5.3f&amp;quot;, $average/$num);&lt;br /&gt;
      #--average&lt;br /&gt;
      Log 4,&amp;quot;[$name moving average] calculated over $num values is $average&amp;quot;;  &lt;br /&gt;
      return $average;&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  1;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Funktion movingAverage() aufrufen und nutzen ===&lt;br /&gt;
Bei jedem Aufruf schiebt die obige Funktion den gegenwärtigen Wert sowie den Zeitpunkt eines Readings (zweiter Parameter) ans Ende eines Arrays (maximal 25 Einträge) und wirft dafür den ersten Eintrag heraus. Die Anzahl der Einträge im Array wird so gewählt, dass die Zeitpunkte der Readings größer oder gleich der gewünschten Zeitspanne für die Mittelung sind. Über diese Werte wird dann gemittelt und der Wert zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
Zur Anwendung empfiehlt sich, dem gewünschten Device ein userReading zu geben:&lt;br /&gt;
:&amp;lt;code&amp;gt;attr devicename userReadings readingname.av {movingAverage(&amp;quot;devicename&amp;quot;,&amp;quot;readingname&amp;quot;,zeitspanne)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieses wird dann automatisch bei jedem neuen Wert des Readings mit dem neuen gleitenden Mittelwert über die vergangene Zeitspanne gefüllt.&lt;br /&gt;
&lt;br /&gt;
Beispiel: Das Reading &amp;quot;pressure&amp;quot; des Devices &amp;quot;A.OWB&amp;quot; wird alle 5 Minuten aktualisiert. Das Device bekommt nun ein userReading:&lt;br /&gt;
:&amp;lt;code&amp;gt;attr A.OWB userReadings pressure.av {movingAverage(&amp;quot;A.OWB&amp;quot;,&amp;quot;pressure&amp;quot;,1800)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieses schreibt bei jeder Aktualisierung von &amp;quot;pressure&amp;quot; einen neuen Eintrag in sein Array - allerdings maximal sechs Werte, dann wird immer der älteste Eintrag gelöscht. Damit ist sichergestellt, dass diese mindestens 1800 Sekunden abdecken - also sechs Einträge.&lt;br /&gt;
&lt;br /&gt;
== Gleitender Mittelwert aus Log-Dateien ==&lt;br /&gt;
=== Subroutine myAverage() in 99_MyUtils anlegen ===&lt;br /&gt;
Zuerst muss die Subroutine myAverage in die 99_MyUtils übernommen werden. Wenn noch nicht vorhanden, sollte die Datei dann so aussehen:&lt;br /&gt;
&lt;br /&gt;
 package main;&lt;br /&gt;
  use strict;&lt;br /&gt;
  use warnings;&lt;br /&gt;
  sub&lt;br /&gt;
  MyUtils_Initialize($$)&lt;br /&gt;
  {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
  }&lt;br /&gt;
  ##########################################################&lt;br /&gt;
  # myAverage&lt;br /&gt;
  # berechnet den Mittelwert aus LogFiles über einen beliebigen Zeitraum&lt;br /&gt;
  sub&lt;br /&gt;
  myAverage($$$)&lt;br /&gt;
  {&lt;br /&gt;
   my ($offset,$logfile,$cspec) = @_;&lt;br /&gt;
   my $period_s = strftime &amp;amp;quot;%Y-%m-%d\x5f%H:%M:%S&amp;amp;quot;, localtime(time-$offset);&lt;br /&gt;
   my $period_e = strftime &amp;amp;quot;%Y-%m-%d\x5f%H:%M:%S&amp;amp;quot;, localtime;&lt;br /&gt;
   my $oll = $attr{global}{verbose};&lt;br /&gt;
   $attr{global}{verbose} = 0; &lt;br /&gt;
   my @logdata = split(&amp;amp;quot;\n&amp;amp;quot;, fhem(&amp;amp;quot;get $logfile - - $period_s $period_e $cspec&amp;amp;quot;));&lt;br /&gt;
   $attr{global}{verbose} = $oll; &lt;br /&gt;
   my ($cnt, $cum, $avg) = (0)x3;&lt;br /&gt;
   foreach (@logdata){&lt;br /&gt;
    my @line = split(&amp;amp;quot; &amp;amp;quot;, $_);&lt;br /&gt;
    if(defined $line[1] &amp;amp;amp;&amp;amp;amp; $line[1] ne &amp;amp;quot;&amp;amp;quot;){&lt;br /&gt;
     $cnt += 1;&lt;br /&gt;
     $cum += $line[1];&lt;br /&gt;
    }&lt;br /&gt;
   }&lt;br /&gt;
   if(&amp;amp;quot;$cnt&amp;amp;quot; &amp;amp;gt; 0){$avg = sprintf(&amp;amp;quot;%0.1f&amp;amp;quot;, $cum/$cnt)};&lt;br /&gt;
   Log 4, (&amp;amp;quot;myAverage: File: $logfile, Field: $cspec, Period: $period_s bis $period_e, Count: $cnt, Cum: $cum, Average: $avg&amp;amp;quot;);&lt;br /&gt;
   return $avg;&lt;br /&gt;
  }&lt;br /&gt;
  ##########################################################&lt;br /&gt;
  1;&lt;br /&gt;
&lt;br /&gt;
=== Funktion myAverage() aufrufen und nutzen ===&lt;br /&gt;
Jetzt kann die Funktion &amp;lt;code&amp;gt;myAverage(&amp;amp;lt;offset&amp;amp;gt;, &amp;amp;lt;logfile&amp;amp;gt;, &amp;amp;lt;column-spec&amp;amp;gt;)&amp;lt;/code&amp;gt; ganz normal auf der FHEM-Konsole (telnet localhost 7072) genutzt werden. Hier z.B. die Ausgabe des Mittelwertes des Windsensors, eines KS300, über die letzten drei Stunden (Angabe in 3*3600s) oder der Temperaturmittelwert der letzten 24 Stunden.&lt;br /&gt;
&lt;br /&gt;
Mit FileLog:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;fhem&amp;amp;gt; {myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;8:::&amp;amp;quot;)}&lt;br /&gt;
  6.3&lt;br /&gt;
  fhem&amp;amp;gt; {myAverage(&amp;amp;quot;86400&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;4:::&amp;amp;quot;)}&lt;br /&gt;
  -2.7&lt;br /&gt;
  fhem&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit DbLog:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;fhem&amp;amp;gt; {myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;myDbLog&amp;amp;quot;, &amp;amp;quot;KS300:wind::&amp;amp;quot;)}&lt;br /&gt;
  5.9&lt;br /&gt;
  fhem&amp;amp;gt; {myAverage(&amp;amp;quot;86400&amp;amp;quot;, &amp;amp;quot;myDbLog&amp;amp;quot;, &amp;amp;quot;KS300:temperature::&amp;amp;quot;)}&lt;br /&gt;
  -2.7&lt;br /&gt;
  fhem&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ähnlich ist die Verwendung in perl-Code in der [[Konfiguration|fhem.cfg]]:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;my $avg = myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;8:::&amp;amp;quot;);;\&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Ein [[notify]], welches bei jedem neuen Sensorwert die Mitteltemperatur der letzten 24 Stunden als Event &amp;quot;average-temp xy&amp;quot; ins Logfile schreibt, sieht dann wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define KS300_T_notify notify KS300:temperature.* {\&lt;br /&gt;
   fhem(&#039;trigger KS300 average-temp: &#039;.myAverage(&amp;amp;quot;86400&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;4:::&amp;amp;quot;));;\&lt;br /&gt;
  }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;!-- korrigiert lt. http://forum.fhem.de/index.php/topic,11622.msg170331.html#msg170331 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analog dazu wäre mit den Winddaten zu verfahren.&lt;br /&gt;
&lt;br /&gt;
== Gleitender Mittelwert und Minimum und Maximum aus Log-Dateien ==&lt;br /&gt;
&lt;br /&gt;
Manchmal interessieren einem auch Minimum und Maximum Werte über einen bestimmten Zeitraum, die Funktion &#039;&#039;myAverage&#039;&#039; kann einfach entsprechend abgeändert werden:&lt;br /&gt;
&lt;br /&gt;
=== Subroutine avgMinMaxAusLog() in 99_MyUtils anlegen ===&lt;br /&gt;
&lt;br /&gt;
  # Berechnet den Mittelwert, Minimum und Maximum aus LogFiles über einen beliebigen Zeitraum&lt;br /&gt;
  # Args: $offset = Offset in Sekunden&lt;br /&gt;
  #		$logfile = LogFile, z.B. DbLog Device&lt;br /&gt;
  #		$cspec = column-spec, siehe https://fhem.de/commandref_DE.html#DbLog -&amp;gt; get&lt;br /&gt;
  sub avgMinMaxAusLog($$$) {&lt;br /&gt;
  	my($offset, $logfile, $cspec) = @_;&lt;br /&gt;
  	my $period_s = strftime &amp;quot;%Y-%m-%d\x5f%H:%M:%S&amp;quot;, localtime(time - $offset);&lt;br /&gt;
  	my $period_e = strftime &amp;quot;%Y-%m-%d\x5f%H:%M:%S&amp;quot;, localtime;&lt;br /&gt;
  	my $oll = $attr { global } { verbose };&lt;br /&gt;
  	$attr { global } { verbose } = 0;&lt;br /&gt;
  	my @logdata = split(&amp;quot;\n&amp;quot;, fhem(&amp;quot;get $logfile - - $period_s $period_e $cspec&amp;quot;));&lt;br /&gt;
  	$attr { global } { verbose } = $oll;&lt;br /&gt;
  	my ($cnt, $cum, $avg, $min, $max) = (0)x5;&lt;br /&gt;
  	foreach(@logdata) {&lt;br /&gt;
  		my @line = split(&amp;quot; &amp;quot;, $_);&lt;br /&gt;
  		if (defined $line[1] &amp;amp;&amp;amp; $line[1] ne &amp;quot;&amp;quot;) {&lt;br /&gt;
  			$cnt += 1;&lt;br /&gt;
  			$cum += $line[1];&lt;br /&gt;
  			# Beim ersten Eintrag min/max setzen&lt;br /&gt;
  			if ($cnt == 1) {&lt;br /&gt;
  				$min = $line[1];&lt;br /&gt;
  				$max = $line[1];&lt;br /&gt;
  			# Bei den darauffolgenden Einträgen $min/max ermitteln&lt;br /&gt;
  			} else {&lt;br /&gt;
  				if ($line[1] &amp;lt; $min) { $min = $line[1]; }&lt;br /&gt;
  				if ($line[1] &amp;gt; $max) { $max = $line[1]; }&lt;br /&gt;
  			}&lt;br /&gt;
  		}&lt;br /&gt;
  	}&lt;br /&gt;
  	if (&amp;quot;$cnt&amp;quot; &amp;gt; 0) {&lt;br /&gt;
  		$avg = sprintf(&amp;quot;%0.1f&amp;quot;, $cum / $cnt)&lt;br /&gt;
  	};&lt;br /&gt;
  	Log 4, (&amp;quot;avgMinMaxAusLog: File: $logfile, Field: $cspec, Period: $period_s bis $period_e, Count: $cnt, Cum: $cum, Average: $avg, Minimum: $min, Maximum: $max&amp;quot;);&lt;br /&gt;
  	return ($avg, $min, $max);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Anwendung wie oben. Statt nur dem Mittelwert wird eine Liste zurückgeliefert mit Mittelwert, Minimum und Maximum. Verwendung z.B. wie folgt:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;my ($avg, $min, $max) = myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;8:::&amp;amp;quot;);;\&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Eigenes Filelog und Plot ==&lt;br /&gt;
==== Definitionen ====&lt;br /&gt;
Ich schreibe ein komplett eigenes Logfile und lasse über eine spezielle gplot-Definition die Temperatur- und Winddaten loggen und plotten.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define KS300_W dummy&lt;br /&gt;
  define KS300_W_notify notify KS300:wind.* {\&lt;br /&gt;
   my $avg = myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;8:::&amp;amp;quot;);;\&lt;br /&gt;
   my $event = sprintf(&amp;amp;quot;Wc:&amp;amp;#160;%0.1f Wd:&amp;amp;#160;%0.1f Wm:&amp;amp;#160;%0.1f Wlh:&amp;amp;#160;%0.1f&amp;amp;quot;, ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;wind&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;W_avg_day&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;W_avg_month&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), $avg);;\&lt;br /&gt;
   Log 2, (&amp;amp;quot;K300_W: Event: $event&amp;amp;quot;);;\&lt;br /&gt;
   fhem(&amp;amp;quot;trigger KS300_W data: $event&amp;amp;quot;);;\&lt;br /&gt;
   fhem(&amp;amp;quot;trigger KS300 average-wind: $avg&amp;amp;quot;);;\&lt;br /&gt;
  }&lt;br /&gt;
  define FileLog_KS300_W FileLog ./log/KS300_W-%Y.log KS300_W.*&lt;br /&gt;
  attr FileLog_KS300_W logtype text&lt;br /&gt;
  attr FileLog_KS300_W room Logs&lt;br /&gt;
  define KS300_TH dummy&lt;br /&gt;
  define KS300_TH_notify notify KS300:temperature.* {\&lt;br /&gt;
   my $avg = myAverage(&amp;amp;quot;86400&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;4:::&amp;amp;quot;);;\&lt;br /&gt;
   my $event = sprintf(&amp;amp;quot;Tc:&amp;amp;#160;%0.1f Hc:&amp;amp;#160;%0.1f Tavg:&amp;amp;#160;%0.1f&amp;amp;quot;, ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;temperature&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;humidity&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), $avg);;\&lt;br /&gt;
   Log 2, (&amp;amp;quot;K300_TH: Event: $event&amp;amp;quot;);;\&lt;br /&gt;
   fhem(&amp;amp;quot;trigger KS300_TH data: $event&amp;amp;quot;);;\&lt;br /&gt;
   fhem(&#039;trigger KS300 average-temp: &#039;.$avg);;\&lt;br /&gt;
  }&lt;br /&gt;
  define FileLog_KS300_TH FileLog ./log/KS300_TH-%Y.log KS300_TH.*&lt;br /&gt;
  attr FileLog_KS300_TH logtype text&lt;br /&gt;
  attr FileLog_KS300_TH room Logs&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Die Definitionen für die Plots schauen so aus:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define weblink_KS300_W weblink fileplot FileLog_KS300_W:ks300_wind:CURRENT&lt;br /&gt;
  attr weblink_KS300_W label &amp;amp;quot;Wind - Min: $data{min1}, Max: $data{max1}, Last: $data{currval1}&amp;amp;quot;&lt;br /&gt;
  attr weblink_KS300_W room Dachterasse&lt;br /&gt;
  define weblink_KS300_TH weblink fileplot FileLog_KS300_TH:ks300_temphum:CURRENT&lt;br /&gt;
  attr weblink_KS300_TH label &amp;amp;quot;Temperatur/Feuchte - Min: $data{min1}, Max: $data{max1}, Last: $data{currval1}&amp;amp;quot;&lt;br /&gt;
  attr weblink_KS300_TH room Dachterasse&lt;br /&gt;
  define weblink_KS300_R weblink fileplot FileLog_KS300:ks300_rain10:CURRENT&lt;br /&gt;
  attr weblink_KS300_R label &amp;amp;quot;Regen - Min: $data{min1}, Max: $data{max1}, Last: $data{currval1}&amp;amp;quot;&lt;br /&gt;
  attr weblink_KS300_R room Dachterasse&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Angepasste gplot-Dateien ====&lt;br /&gt;
Nun noch die speziellen gplot-Dateien.&lt;br /&gt;
ks300_wind.gplot&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;############################&lt;br /&gt;
  # Display the wind values of a KS300.&lt;br /&gt;
  # Corresponding FileLog definition:&lt;br /&gt;
  # define &amp;amp;lt;filelogname&amp;amp;gt; FileLog ./log/KS300_W-%Y.log KS300_W.*&lt;br /&gt;
  set terminal png transparent size &amp;amp;lt;SIZE&amp;amp;gt; crop&lt;br /&gt;
  set output &#039;&amp;amp;lt;OUT&amp;amp;gt;.png&#039;&lt;br /&gt;
  set xdata time&lt;br /&gt;
  set timefmt &amp;amp;quot;%Y-%m-%d_%H:%M:%S&amp;amp;quot;&lt;br /&gt;
  set xlabel &amp;amp;quot; &amp;amp;quot;&lt;br /&gt;
  set ytics nomirror&lt;br /&gt;
  #set y2tics&lt;br /&gt;
  set ytics&lt;br /&gt;
  set title &#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&lt;br /&gt;
  set grid xtics ytics&lt;br /&gt;
  set yrange [0:]&lt;br /&gt;
  set y2range [0:]&lt;br /&gt;
  set ylabel &amp;amp;quot;Wind (aktuell) [km/h]&amp;amp;quot;&lt;br /&gt;
  set y2label &amp;amp;quot;Wind (gemittelt) [km/h]&amp;amp;quot;&lt;br /&gt;
  set format y2 &amp;amp;quot;%0.1f&amp;amp;quot;&lt;br /&gt;
  #FileLog 5:Wc\x3a:0:&lt;br /&gt;
  #FileLog 11:Wlh\x3a:0:&lt;br /&gt;
  plot &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:5 ls l7fill axes x1y1 title &#039;Wind (aktuell)&#039; with lines,\&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:11 ls l5 axes x1y2 title &#039;Wind (3h-Mittel)&#039; with steps,\&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ks300_temphum.gplot&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;############################&lt;br /&gt;
  # Display the Temperature und Humidity values of a KS300.&lt;br /&gt;
  # Corresponding FileLog definition:&lt;br /&gt;
  # define &amp;amp;lt;filelogname&amp;amp;gt; FileLog ./log/KS300_TH-%Y.log KS300_TH.*&lt;br /&gt;
  set terminal png transparent size &amp;amp;lt;SIZE&amp;amp;gt; crop&lt;br /&gt;
  set output &#039;&amp;amp;lt;OUT&amp;amp;gt;.png&#039;&lt;br /&gt;
  set xdata time&lt;br /&gt;
  set timefmt &amp;amp;quot;%Y-%m-%d_%H:%M:%S&amp;amp;quot;&lt;br /&gt;
  set xlabel &amp;amp;quot; &amp;amp;quot;&lt;br /&gt;
  set ytics nomirror&lt;br /&gt;
  set y2tics&lt;br /&gt;
  #set ytics&lt;br /&gt;
  set title &#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&lt;br /&gt;
  set grid xtics y2tics&lt;br /&gt;
  set y2label &amp;amp;quot;Temperatur [°C]&amp;amp;quot;&lt;br /&gt;
  set ylabel &amp;amp;quot;Luftfeuchte [%]&amp;amp;quot;&lt;br /&gt;
  #FileLog 5:Tc\x3a:0:&lt;br /&gt;
  #FileLog 9:Tavg\x3a:0:&lt;br /&gt;
  #FileLog 7:Hc\x3a:0:&lt;br /&gt;
  plot &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:5 axes x1y2 ls l0 title &#039;Temperatur&#039; with lines,\&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:9 axes x1y2 ls l10 title &#039;Temperatur (24h-Mittel)&#039; with lines,\&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:7 axes x1y1 ls l2fill title &#039;Luftfeuchte&#039; with lines&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Den Plot für den Regen habe ich noch um Punkt-Plots für den israining-Status erweitert, so dass Punkte bei &amp;quot;yes&amp;quot; geplottet werden.&lt;br /&gt;
&lt;br /&gt;
ks300_rain10.gplot&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;############################&lt;br /&gt;
  # Display the Rain values of a KS300.&lt;br /&gt;
  # Corresponding FileLog definition:&lt;br /&gt;
  # define &amp;amp;lt;filelogname&amp;amp;gt; FileLog ./log/KS300-%Y.log KS300:T:.*&lt;br /&gt;
  set terminal png transparent size &amp;amp;lt;SIZE&amp;amp;gt; crop&lt;br /&gt;
  set output &#039;&amp;amp;lt;OUT&amp;amp;gt;.png&#039;&lt;br /&gt;
  set xdata time&lt;br /&gt;
  set timefmt &amp;amp;quot;%Y-%m-%d_%H:%M:%S&amp;amp;quot;&lt;br /&gt;
  set xlabel &amp;amp;quot; &amp;amp;quot;&lt;br /&gt;
  set ytics nomirror&lt;br /&gt;
  #set y2tics&lt;br /&gt;
  set ytics&lt;br /&gt;
  set title &#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&lt;br /&gt;
  set grid xtics ytics&lt;br /&gt;
  set y2range [0.5:1.5]&lt;br /&gt;
  set y2tics (&amp;amp;quot;&amp;amp;quot; 0, &amp;amp;quot;Regen&amp;amp;quot; 1)&lt;br /&gt;
  set pointsize 7&lt;br /&gt;
  set ylabel &amp;amp;quot;Regen (l/m²)&amp;amp;quot;&lt;br /&gt;
  set yrange [0:]&lt;br /&gt;
  # Computing Rain/h and Rain/d values by accumulating the changes.&lt;br /&gt;
  #FileLog 10:IR\x3a:0:delta-h&lt;br /&gt;
  #FileLog 10:IR\x3a:0:delta-d&lt;br /&gt;
  #FileLog 12:IR:0:$fld[11]=~&amp;amp;quot;yes&amp;amp;quot;?1:0&lt;br /&gt;
  plot &amp;amp;quot;&amp;amp;lt;grep -v avg_ &amp;amp;lt;IN&amp;amp;gt; | perl -ane &#039;\&lt;br /&gt;
      @a = split(\&amp;amp;quot;[_:]\&amp;amp;quot;, $F[0]);\&lt;br /&gt;
      if(defined($lh) &amp;amp;amp;&amp;amp;amp; $lh ne $a[1])\&lt;br /&gt;
       { printf(\&amp;amp;quot;${ld}_$lh:30:00&amp;amp;#160;%f\n\&amp;amp;quot;, $hv); $hv = 0; }\&lt;br /&gt;
      if($lv) { $hv += ($F[9]-$lv); }\&lt;br /&gt;
      $lh = $a[1]; $ld = $a[0]; $lv = $F[9];\&lt;br /&gt;
      END { printf(\&amp;amp;quot;${ld}_$lh:30:00&amp;amp;#160;%f\n\&amp;amp;quot;, $hv) }&#039;&amp;amp;quot;\&lt;br /&gt;
     using 1:2 axes x1y1 ls l1fill title &#039;Regen pro Stunde&#039; with histeps,\&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;grep -v avg_ &amp;amp;lt;IN&amp;amp;gt; | perl -ane &#039;\&lt;br /&gt;
      @a = split(\&amp;amp;quot;[_]\&amp;amp;quot;, $F[0]);\&lt;br /&gt;
      if(defined($ld) &amp;amp;amp;&amp;amp;amp; $ld ne $a[0]) {\&lt;br /&gt;
       printf(\&amp;amp;quot;${ld}_12:00:00&amp;amp;#160;%f\n\&amp;amp;quot;, $dv); $dv = 0; }\&lt;br /&gt;
       if($lv) { $dv += ($F[9]-$lv); }\&lt;br /&gt;
       $ld = $a[0]; $lv = $F[9];\&lt;br /&gt;
       END {printf(\&amp;amp;quot;${ld}_12:00:00&amp;amp;#160;%f\n\&amp;amp;quot;, $dv)}&#039;&amp;amp;quot;\&lt;br /&gt;
     using 1:2 axes x1y1 ls l7 title &#039;Regen pro Tag&#039; with histeps&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;grep -v avg_ &amp;amp;lt;IN&amp;amp;gt; | awk &#039;{print $1, $12==\&amp;amp;quot;yes\&amp;amp;quot;? 1&amp;amp;#160;: 0; }&#039;&amp;amp;quot;\&lt;br /&gt;
     using 1:2 axes x1y2 ls l11fill title &#039;Regen aktuell&#039; with points&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Eventuell müssen in den gplots noch die Linienstile/Farben den eigenen Bedürfnissen angepasst werden. Ich verwende hier eigene Farben und Füllungen.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;br /&gt;
[[Kategorie:Logging]]&lt;/div&gt;</summary>
		<author><name>Ansgru</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Gleitende_Mittelwerte_berechnen_und_loggen&amp;diff=37504</id>
		<title>Gleitende Mittelwerte berechnen und loggen</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Gleitende_Mittelwerte_berechnen_und_loggen&amp;diff=37504"/>
		<updated>2022-07-19T07:11:40Z</updated>

		<summary type="html">&lt;p&gt;Ansgru: Ergänzt um erweiterte Funktion mit Min/Max Werten&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Für verschiedene Wettersensoren ist es oftmals wünschenswert, gleitende Mittelwerte (fälschlich auch als &amp;quot;relative&amp;quot; Mittelwerte bezeichnet) über ein bestimmtes Zeitfenster auszugeben oder in den Logs zu speichern und zu plotten. Beispiele:&lt;br /&gt;
* Die momentanen Winddaten eines KS300 sind oft stark schwankend. Hier wäre ein Mittelwert z.B. der letzten 2-3 Stunden interessant. &lt;br /&gt;
* Für die Außentemperatur ist anhand eines Mittelwertes der letzten 24 Stunden evtl. ein gewisser Trend der generellen Entwicklung der Temperatur ableitbar.&lt;br /&gt;
&lt;br /&gt;
Mit Modulen wie &#039;&#039;rain&#039;&#039; oder &#039;&#039;average&#039;&#039; ist konzeptbedingt nur ein Mittelwert von fixen Zeiträumen (aktueller Tag, Monat, etc.) möglich. &lt;br /&gt;
&lt;br /&gt;
Im Nachfolgenden werden deshalb zwei Programme vorgestellt, die solche gleitenden Mittelwerte bereitstellen. Beide Programme werden in die Datei [[99 myUtils anlegen|99_MyUtils.pm]] eingetragen und dann von FHEM aufgerufen. Das erste Programm macht dies für beliebige Readings beliebiger Devices, das zweite Programm greift auf beliebige [[FileLog|File-]] oder [[DbLog|DbLogs]] zurück.&lt;br /&gt;
&lt;br /&gt;
== Gleitender Mittelwert für beliebige Readings ==&lt;br /&gt;
=== Subroutine movingAverage in 99_MyUtils anlegen ===&lt;br /&gt;
Zuerst muss die Subroutine &#039;&#039;movingAverage&#039;&#039; in die 99_MyUtils übernommen werden. Wenn noch nicht vorhanden, sollte die Datei dann so aussehen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;package main;&lt;br /&gt;
  use strict;&lt;br /&gt;
  use warnings;&lt;br /&gt;
  sub&lt;br /&gt;
  MyUtils_Initialize($$)&lt;br /&gt;
  {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
  }&lt;br /&gt;
  ###############################################################################&lt;br /&gt;
  #&lt;br /&gt;
  #  Moving average &lt;br /&gt;
  #&lt;br /&gt;
  #  Aufruf: movingAverage(devicename,readingname,zeitspanne in s)&lt;br /&gt;
  #&lt;br /&gt;
  ###############################################################################&lt;br /&gt;
  &lt;br /&gt;
  sub movingAverage($$$){&lt;br /&gt;
     my ($name,$reading,$avtime) = @_;&lt;br /&gt;
     my $hash = $defs{$name};&lt;br /&gt;
     my @new = my ($val,$time) = ($hash-&amp;gt;{READINGS}{$reading}{VAL},$hash-&amp;gt;{READINGS}{$reading}{TIME});&lt;br /&gt;
     my ($cyear, $cmonth, $cday, $chour, $cmin, $csec) = $time =~ /(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/;&lt;br /&gt;
     my $ctime = $csec+60*$cmin+3600*$chour;&lt;br /&gt;
     my $num;&lt;br /&gt;
     my $arr;&lt;br /&gt;
     #-- initialize if requested&lt;br /&gt;
     if( ($avtime eq &amp;quot;-1&amp;quot;) ){&lt;br /&gt;
       $hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}=undef;&lt;br /&gt;
     }&lt;br /&gt;
     #-- test for existence&lt;br /&gt;
     if( !$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}){&lt;br /&gt;
        #Log 1,&amp;quot;ARRAY CREATED&amp;quot;;&lt;br /&gt;
        push(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}},\@new);&lt;br /&gt;
        $num = 1;&lt;br /&gt;
        $arr=\@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}};&lt;br /&gt;
     } else {&lt;br /&gt;
        $num = int(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}});&lt;br /&gt;
        $arr=\@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}};&lt;br /&gt;
        my $starttime = $arr-&amp;gt;[0][1];&lt;br /&gt;
        my ($syear, $smonth, $sday, $shour, $smin, $ssec) = $starttime =~ /(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/;&lt;br /&gt;
        my $stime = $ssec+60*$smin+3600*$shour;&lt;br /&gt;
        #-- correct for daybreak&lt;br /&gt;
        $stime-=86400 &lt;br /&gt;
          if( $stime &amp;gt; $ctime);&lt;br /&gt;
        if( ($num &amp;lt; 25)&amp;amp;&amp;amp;( ($ctime-$stime)&amp;lt;$avtime) ){&lt;br /&gt;
          #Log 1,&amp;quot;ARRAY has $num elements, adding another one&amp;quot;;&lt;br /&gt;
          push(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}},\@new);&lt;br /&gt;
        }else{&lt;br /&gt;
          shift(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}});&lt;br /&gt;
          push(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}},\@new);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      #-- output and average&lt;br /&gt;
      my $average = 0;&lt;br /&gt;
      for(my $i=0;$i&amp;lt;$num;$i++){&lt;br /&gt;
        $average+=$arr-&amp;gt;[$i][0];&lt;br /&gt;
        Log 4,&amp;quot;[$name moving average] Value = &amp;quot;.$arr-&amp;gt;[$i][0].&amp;quot; Time = &amp;quot;.$arr-&amp;gt;[$i][1]; &lt;br /&gt;
      }&lt;br /&gt;
      $average=sprintf( &amp;quot;%5.3f&amp;quot;, $average/$num);&lt;br /&gt;
      #--average&lt;br /&gt;
      Log 4,&amp;quot;[$name moving average] calculated over $num values is $average&amp;quot;;  &lt;br /&gt;
      return $average;&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  1;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Funktion movingAverage() aufrufen und nutzen ===&lt;br /&gt;
Bei jedem Aufruf schiebt die obige Funktion den gegenwärtigen Wert sowie den Zeitpunkt eines Readings (zweiter Parameter) ans Ende eines Arrays (maximal 25 Einträge) und wirft dafür den ersten Eintrag heraus. Die Anzahl der Einträge im Array wird so gewählt, dass die Zeitpunkte der Readings größer oder gleich der gewünschten Zeitspanne für die Mittelung sind. Über diese Werte wird dann gemittelt und der Wert zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
Zur Anwendung empfiehlt sich, dem gewünschten Device ein userReading zu geben:&lt;br /&gt;
:&amp;lt;code&amp;gt;attr devicename userReadings readingname.av {movingAverage(&amp;quot;devicename&amp;quot;,&amp;quot;readingname&amp;quot;,zeitspanne)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieses wird dann automatisch bei jedem neuen Wert des Readings mit dem neuen gleitenden Mittelwert über die vergangene Zeitspanne gefüllt.&lt;br /&gt;
&lt;br /&gt;
Beispiel: Das Reading &amp;quot;pressure&amp;quot; des Devices &amp;quot;A.OWB&amp;quot; wird alle 5 Minuten aktualisiert. Das Device bekommt nun ein userReading:&lt;br /&gt;
:&amp;lt;code&amp;gt;attr A.OWB userReadings pressure.av {movingAverage(&amp;quot;A.OWB&amp;quot;,&amp;quot;pressure&amp;quot;,1800)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieses schreibt bei jeder Aktualisierung von &amp;quot;pressure&amp;quot; einen neuen Eintrag in sein Array - allerdings maximal sechs Werte, dann wird immer der älteste Eintrag gelöscht. Damit ist sichergestellt, dass diese mindestens 1800 Sekunden abdecken - also sechs Einträge.&lt;br /&gt;
&lt;br /&gt;
== Gleitender Mittelwert aus Log-Dateien ==&lt;br /&gt;
=== Subroutine myAverage() in 99_MyUtils anlegen ===&lt;br /&gt;
Zuerst muss die Subroutine myAverage in die 99_MyUtils übernommen werden. Wenn noch nicht vorhanden, sollte die Datei dann so aussehen:&lt;br /&gt;
&lt;br /&gt;
 package main;&lt;br /&gt;
  use strict;&lt;br /&gt;
  use warnings;&lt;br /&gt;
  sub&lt;br /&gt;
  MyUtils_Initialize($$)&lt;br /&gt;
  {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
  }&lt;br /&gt;
  ##########################################################&lt;br /&gt;
  # myAverage&lt;br /&gt;
  # berechnet den Mittelwert aus LogFiles über einen beliebigen Zeitraum&lt;br /&gt;
  sub&lt;br /&gt;
  myAverage($$$)&lt;br /&gt;
  {&lt;br /&gt;
   my ($offset,$logfile,$cspec) = @_;&lt;br /&gt;
   my $period_s = strftime &amp;amp;quot;%Y-%m-%d\x5f%H:%M:%S&amp;amp;quot;, localtime(time-$offset);&lt;br /&gt;
   my $period_e = strftime &amp;amp;quot;%Y-%m-%d\x5f%H:%M:%S&amp;amp;quot;, localtime;&lt;br /&gt;
   my $oll = $attr{global}{verbose};&lt;br /&gt;
   $attr{global}{verbose} = 0; &lt;br /&gt;
   my @logdata = split(&amp;amp;quot;\n&amp;amp;quot;, fhem(&amp;amp;quot;get $logfile - - $period_s $period_e $cspec&amp;amp;quot;));&lt;br /&gt;
   $attr{global}{verbose} = $oll; &lt;br /&gt;
   my ($cnt, $cum, $avg) = (0)x3;&lt;br /&gt;
   foreach (@logdata){&lt;br /&gt;
    my @line = split(&amp;amp;quot; &amp;amp;quot;, $_);&lt;br /&gt;
    if(defined $line[1] &amp;amp;amp;&amp;amp;amp; $line[1] ne &amp;amp;quot;&amp;amp;quot;){&lt;br /&gt;
     $cnt += 1;&lt;br /&gt;
     $cum += $line[1];&lt;br /&gt;
    }&lt;br /&gt;
   }&lt;br /&gt;
   if(&amp;amp;quot;$cnt&amp;amp;quot; &amp;amp;gt; 0){$avg = sprintf(&amp;amp;quot;%0.1f&amp;amp;quot;, $cum/$cnt)};&lt;br /&gt;
   Log 4, (&amp;amp;quot;myAverage: File: $logfile, Field: $cspec, Period: $period_s bis $period_e, Count: $cnt, Cum: $cum, Average: $avg&amp;amp;quot;);&lt;br /&gt;
   return $avg;&lt;br /&gt;
  }&lt;br /&gt;
  ##########################################################&lt;br /&gt;
  1;&lt;br /&gt;
&lt;br /&gt;
=== Funktion myAverage() aufrufen und nutzen ===&lt;br /&gt;
Jetzt kann die Funktion &amp;lt;code&amp;gt;myAverage(&amp;amp;lt;offset&amp;amp;gt;, &amp;amp;lt;logfile&amp;amp;gt;, &amp;amp;lt;column-spec&amp;amp;gt;)&amp;lt;/code&amp;gt; ganz normal auf der FHEM-Konsole (telnet localhost 7072) genutzt werden. Hier z.B. die Ausgabe des Mittelwertes des Windsensors, eines KS300, über die letzten drei Stunden (Angabe in 3*3600s) oder der Temperaturmittelwert der letzten 24 Stunden.&lt;br /&gt;
&lt;br /&gt;
Mit FileLog:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;fhem&amp;amp;gt; {myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;8:::&amp;amp;quot;)}&lt;br /&gt;
  6.3&lt;br /&gt;
  fhem&amp;amp;gt; {myAverage(&amp;amp;quot;86400&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;4:::&amp;amp;quot;)}&lt;br /&gt;
  -2.7&lt;br /&gt;
  fhem&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit DbLog:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;fhem&amp;amp;gt; {myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;myDbLog&amp;amp;quot;, &amp;amp;quot;KS300:wind::&amp;amp;quot;)}&lt;br /&gt;
  5.9&lt;br /&gt;
  fhem&amp;amp;gt; {myAverage(&amp;amp;quot;86400&amp;amp;quot;, &amp;amp;quot;myDbLog&amp;amp;quot;, &amp;amp;quot;KS300:temperature::&amp;amp;quot;)}&lt;br /&gt;
  -2.7&lt;br /&gt;
  fhem&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ähnlich ist die Verwendung in perl-Code in der [[Konfiguration|fhem.cfg]]:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;my $avg = myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;8:::&amp;amp;quot;);;\&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Ein [[notify]], welches bei jedem neuen Sensorwert die Mitteltemperatur der letzten 24 Stunden als Event &amp;quot;average-temp xy&amp;quot; ins Logfile schreibt, sieht dann wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define KS300_T_notify notify KS300:temperature.* {\&lt;br /&gt;
   fhem(&#039;trigger KS300 average-temp: &#039;.myAverage(&amp;amp;quot;86400&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;4:::&amp;amp;quot;));;\&lt;br /&gt;
  }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;!-- korrigiert lt. http://forum.fhem.de/index.php/topic,11622.msg170331.html#msg170331 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analog dazu wäre mit den Winddaten zu verfahren.&lt;br /&gt;
&lt;br /&gt;
== Gleitender Mittelwert und Minimum und Maximum aus Log-Dateien ==&lt;br /&gt;
&lt;br /&gt;
Manchmal interessieren einem auch Minimum und Maximum Werte über einen bestimmten Zeitraum, die Funktion &#039;&#039;myAverage&#039;&#039; kann einfach entsprechend abgeändert werden:&lt;br /&gt;
&lt;br /&gt;
	# Berechnet den Mittelwert, Minimum und Maximum aus LogFiles über einen beliebigen Zeitraum&lt;br /&gt;
	# Args: $offset = Offset in Sekunden&lt;br /&gt;
	#		$logfile = LogFile, z.B. DbLog Device&lt;br /&gt;
	#		$cspec = column-spec, siehe https://fhem.de/commandref_DE.html#DbLog -&amp;gt; get&lt;br /&gt;
	sub avgMinMaxAusLog($$$) {&lt;br /&gt;
		my($offset, $logfile, $cspec) = @_;&lt;br /&gt;
		my $period_s = strftime &amp;quot;%Y-%m-%d\x5f%H:%M:%S&amp;quot;, localtime(time - $offset);&lt;br /&gt;
		my $period_e = strftime &amp;quot;%Y-%m-%d\x5f%H:%M:%S&amp;quot;, localtime;&lt;br /&gt;
		my $oll = $attr { global } { verbose };&lt;br /&gt;
		$attr { global } { verbose } = 0;&lt;br /&gt;
		my @logdata = split(&amp;quot;\n&amp;quot;, fhem(&amp;quot;get $logfile - - $period_s $period_e $cspec&amp;quot;));&lt;br /&gt;
		$attr { global } { verbose } = $oll;&lt;br /&gt;
		my ($cnt, $cum, $avg, $min, $max) = (0)x5;&lt;br /&gt;
		foreach(@logdata) {&lt;br /&gt;
			my @line = split(&amp;quot; &amp;quot;, $_);&lt;br /&gt;
			if (defined $line[1] &amp;amp;&amp;amp; $line[1] ne &amp;quot;&amp;quot;) {&lt;br /&gt;
				$cnt += 1;&lt;br /&gt;
				$cum += $line[1];&lt;br /&gt;
				# Beim ersten Eintrag min/max setzen&lt;br /&gt;
				if ($cnt == 1) {&lt;br /&gt;
					$min = $line[1];&lt;br /&gt;
					$max = $line[1];&lt;br /&gt;
				# Bei den darauffolgenden Einträgen $min/max ermitteln&lt;br /&gt;
				} else {&lt;br /&gt;
					if ($line[1] &amp;lt; $min) { $min = $line[1]; }&lt;br /&gt;
					if ($line[1] &amp;gt; $max) { $max = $line[1]; }&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		if (&amp;quot;$cnt&amp;quot; &amp;gt; 0) {&lt;br /&gt;
			$avg = sprintf(&amp;quot;%0.1f&amp;quot;, $cum / $cnt)&lt;br /&gt;
		};&lt;br /&gt;
		Log 4, (&amp;quot;avgMinMaxAusLog: File: $logfile, Field: $cspec, Period: $period_s bis $period_e, Count: $cnt, Cum: $cum, Average: $avg, Minimum: $min, Maximum: $max&amp;quot;);&lt;br /&gt;
		return ($avg, $min, $max);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
Anwendung wie oben. Statt nur dem Mittelwert wird eine Liste zurückgeliefert mit Mittelwert, Minimum und Maximum. Verwendung z.B. wie folgt:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;my ($avg, $min, $max) = myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;8:::&amp;amp;quot;);;\&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subroutine avgMinMaxAusLog() in 99_MyUtils anlegen ===&lt;br /&gt;
&lt;br /&gt;
=== Eigenes Filelog und Plot ===&lt;br /&gt;
==== Definitionen ====&lt;br /&gt;
Ich schreibe ein komplett eigenes Logfile und lasse über eine spezielle gplot-Definition die Temperatur- und Winddaten loggen und plotten.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define KS300_W dummy&lt;br /&gt;
  define KS300_W_notify notify KS300:wind.* {\&lt;br /&gt;
   my $avg = myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;8:::&amp;amp;quot;);;\&lt;br /&gt;
   my $event = sprintf(&amp;amp;quot;Wc:&amp;amp;#160;%0.1f Wd:&amp;amp;#160;%0.1f Wm:&amp;amp;#160;%0.1f Wlh:&amp;amp;#160;%0.1f&amp;amp;quot;, ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;wind&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;W_avg_day&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;W_avg_month&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), $avg);;\&lt;br /&gt;
   Log 2, (&amp;amp;quot;K300_W: Event: $event&amp;amp;quot;);;\&lt;br /&gt;
   fhem(&amp;amp;quot;trigger KS300_W data: $event&amp;amp;quot;);;\&lt;br /&gt;
   fhem(&amp;amp;quot;trigger KS300 average-wind: $avg&amp;amp;quot;);;\&lt;br /&gt;
  }&lt;br /&gt;
  define FileLog_KS300_W FileLog ./log/KS300_W-%Y.log KS300_W.*&lt;br /&gt;
  attr FileLog_KS300_W logtype text&lt;br /&gt;
  attr FileLog_KS300_W room Logs&lt;br /&gt;
  define KS300_TH dummy&lt;br /&gt;
  define KS300_TH_notify notify KS300:temperature.* {\&lt;br /&gt;
   my $avg = myAverage(&amp;amp;quot;86400&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;4:::&amp;amp;quot;);;\&lt;br /&gt;
   my $event = sprintf(&amp;amp;quot;Tc:&amp;amp;#160;%0.1f Hc:&amp;amp;#160;%0.1f Tavg:&amp;amp;#160;%0.1f&amp;amp;quot;, ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;temperature&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;humidity&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), $avg);;\&lt;br /&gt;
   Log 2, (&amp;amp;quot;K300_TH: Event: $event&amp;amp;quot;);;\&lt;br /&gt;
   fhem(&amp;amp;quot;trigger KS300_TH data: $event&amp;amp;quot;);;\&lt;br /&gt;
   fhem(&#039;trigger KS300 average-temp: &#039;.$avg);;\&lt;br /&gt;
  }&lt;br /&gt;
  define FileLog_KS300_TH FileLog ./log/KS300_TH-%Y.log KS300_TH.*&lt;br /&gt;
  attr FileLog_KS300_TH logtype text&lt;br /&gt;
  attr FileLog_KS300_TH room Logs&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Die Definitionen für die Plots schauen so aus:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define weblink_KS300_W weblink fileplot FileLog_KS300_W:ks300_wind:CURRENT&lt;br /&gt;
  attr weblink_KS300_W label &amp;amp;quot;Wind - Min: $data{min1}, Max: $data{max1}, Last: $data{currval1}&amp;amp;quot;&lt;br /&gt;
  attr weblink_KS300_W room Dachterasse&lt;br /&gt;
  define weblink_KS300_TH weblink fileplot FileLog_KS300_TH:ks300_temphum:CURRENT&lt;br /&gt;
  attr weblink_KS300_TH label &amp;amp;quot;Temperatur/Feuchte - Min: $data{min1}, Max: $data{max1}, Last: $data{currval1}&amp;amp;quot;&lt;br /&gt;
  attr weblink_KS300_TH room Dachterasse&lt;br /&gt;
  define weblink_KS300_R weblink fileplot FileLog_KS300:ks300_rain10:CURRENT&lt;br /&gt;
  attr weblink_KS300_R label &amp;amp;quot;Regen - Min: $data{min1}, Max: $data{max1}, Last: $data{currval1}&amp;amp;quot;&lt;br /&gt;
  attr weblink_KS300_R room Dachterasse&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Angepasste gplot-Dateien ====&lt;br /&gt;
Nun noch die speziellen gplot-Dateien.&lt;br /&gt;
ks300_wind.gplot&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;############################&lt;br /&gt;
  # Display the wind values of a KS300.&lt;br /&gt;
  # Corresponding FileLog definition:&lt;br /&gt;
  # define &amp;amp;lt;filelogname&amp;amp;gt; FileLog ./log/KS300_W-%Y.log KS300_W.*&lt;br /&gt;
  set terminal png transparent size &amp;amp;lt;SIZE&amp;amp;gt; crop&lt;br /&gt;
  set output &#039;&amp;amp;lt;OUT&amp;amp;gt;.png&#039;&lt;br /&gt;
  set xdata time&lt;br /&gt;
  set timefmt &amp;amp;quot;%Y-%m-%d_%H:%M:%S&amp;amp;quot;&lt;br /&gt;
  set xlabel &amp;amp;quot; &amp;amp;quot;&lt;br /&gt;
  set ytics nomirror&lt;br /&gt;
  #set y2tics&lt;br /&gt;
  set ytics&lt;br /&gt;
  set title &#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&lt;br /&gt;
  set grid xtics ytics&lt;br /&gt;
  set yrange [0:]&lt;br /&gt;
  set y2range [0:]&lt;br /&gt;
  set ylabel &amp;amp;quot;Wind (aktuell) [km/h]&amp;amp;quot;&lt;br /&gt;
  set y2label &amp;amp;quot;Wind (gemittelt) [km/h]&amp;amp;quot;&lt;br /&gt;
  set format y2 &amp;amp;quot;%0.1f&amp;amp;quot;&lt;br /&gt;
  #FileLog 5:Wc\x3a:0:&lt;br /&gt;
  #FileLog 11:Wlh\x3a:0:&lt;br /&gt;
  plot &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:5 ls l7fill axes x1y1 title &#039;Wind (aktuell)&#039; with lines,\&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:11 ls l5 axes x1y2 title &#039;Wind (3h-Mittel)&#039; with steps,\&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ks300_temphum.gplot&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;############################&lt;br /&gt;
  # Display the Temperature und Humidity values of a KS300.&lt;br /&gt;
  # Corresponding FileLog definition:&lt;br /&gt;
  # define &amp;amp;lt;filelogname&amp;amp;gt; FileLog ./log/KS300_TH-%Y.log KS300_TH.*&lt;br /&gt;
  set terminal png transparent size &amp;amp;lt;SIZE&amp;amp;gt; crop&lt;br /&gt;
  set output &#039;&amp;amp;lt;OUT&amp;amp;gt;.png&#039;&lt;br /&gt;
  set xdata time&lt;br /&gt;
  set timefmt &amp;amp;quot;%Y-%m-%d_%H:%M:%S&amp;amp;quot;&lt;br /&gt;
  set xlabel &amp;amp;quot; &amp;amp;quot;&lt;br /&gt;
  set ytics nomirror&lt;br /&gt;
  set y2tics&lt;br /&gt;
  #set ytics&lt;br /&gt;
  set title &#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&lt;br /&gt;
  set grid xtics y2tics&lt;br /&gt;
  set y2label &amp;amp;quot;Temperatur [°C]&amp;amp;quot;&lt;br /&gt;
  set ylabel &amp;amp;quot;Luftfeuchte [%]&amp;amp;quot;&lt;br /&gt;
  #FileLog 5:Tc\x3a:0:&lt;br /&gt;
  #FileLog 9:Tavg\x3a:0:&lt;br /&gt;
  #FileLog 7:Hc\x3a:0:&lt;br /&gt;
  plot &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:5 axes x1y2 ls l0 title &#039;Temperatur&#039; with lines,\&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:9 axes x1y2 ls l10 title &#039;Temperatur (24h-Mittel)&#039; with lines,\&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:7 axes x1y1 ls l2fill title &#039;Luftfeuchte&#039; with lines&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Den Plot für den Regen habe ich noch um Punkt-Plots für den israining-Status erweitert, so dass Punkte bei &amp;quot;yes&amp;quot; geplottet werden.&lt;br /&gt;
&lt;br /&gt;
ks300_rain10.gplot&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;############################&lt;br /&gt;
  # Display the Rain values of a KS300.&lt;br /&gt;
  # Corresponding FileLog definition:&lt;br /&gt;
  # define &amp;amp;lt;filelogname&amp;amp;gt; FileLog ./log/KS300-%Y.log KS300:T:.*&lt;br /&gt;
  set terminal png transparent size &amp;amp;lt;SIZE&amp;amp;gt; crop&lt;br /&gt;
  set output &#039;&amp;amp;lt;OUT&amp;amp;gt;.png&#039;&lt;br /&gt;
  set xdata time&lt;br /&gt;
  set timefmt &amp;amp;quot;%Y-%m-%d_%H:%M:%S&amp;amp;quot;&lt;br /&gt;
  set xlabel &amp;amp;quot; &amp;amp;quot;&lt;br /&gt;
  set ytics nomirror&lt;br /&gt;
  #set y2tics&lt;br /&gt;
  set ytics&lt;br /&gt;
  set title &#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&lt;br /&gt;
  set grid xtics ytics&lt;br /&gt;
  set y2range [0.5:1.5]&lt;br /&gt;
  set y2tics (&amp;amp;quot;&amp;amp;quot; 0, &amp;amp;quot;Regen&amp;amp;quot; 1)&lt;br /&gt;
  set pointsize 7&lt;br /&gt;
  set ylabel &amp;amp;quot;Regen (l/m²)&amp;amp;quot;&lt;br /&gt;
  set yrange [0:]&lt;br /&gt;
  # Computing Rain/h and Rain/d values by accumulating the changes.&lt;br /&gt;
  #FileLog 10:IR\x3a:0:delta-h&lt;br /&gt;
  #FileLog 10:IR\x3a:0:delta-d&lt;br /&gt;
  #FileLog 12:IR:0:$fld[11]=~&amp;amp;quot;yes&amp;amp;quot;?1:0&lt;br /&gt;
  plot &amp;amp;quot;&amp;amp;lt;grep -v avg_ &amp;amp;lt;IN&amp;amp;gt; | perl -ane &#039;\&lt;br /&gt;
      @a = split(\&amp;amp;quot;[_:]\&amp;amp;quot;, $F[0]);\&lt;br /&gt;
      if(defined($lh) &amp;amp;amp;&amp;amp;amp; $lh ne $a[1])\&lt;br /&gt;
       { printf(\&amp;amp;quot;${ld}_$lh:30:00&amp;amp;#160;%f\n\&amp;amp;quot;, $hv); $hv = 0; }\&lt;br /&gt;
      if($lv) { $hv += ($F[9]-$lv); }\&lt;br /&gt;
      $lh = $a[1]; $ld = $a[0]; $lv = $F[9];\&lt;br /&gt;
      END { printf(\&amp;amp;quot;${ld}_$lh:30:00&amp;amp;#160;%f\n\&amp;amp;quot;, $hv) }&#039;&amp;amp;quot;\&lt;br /&gt;
     using 1:2 axes x1y1 ls l1fill title &#039;Regen pro Stunde&#039; with histeps,\&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;grep -v avg_ &amp;amp;lt;IN&amp;amp;gt; | perl -ane &#039;\&lt;br /&gt;
      @a = split(\&amp;amp;quot;[_]\&amp;amp;quot;, $F[0]);\&lt;br /&gt;
      if(defined($ld) &amp;amp;amp;&amp;amp;amp; $ld ne $a[0]) {\&lt;br /&gt;
       printf(\&amp;amp;quot;${ld}_12:00:00&amp;amp;#160;%f\n\&amp;amp;quot;, $dv); $dv = 0; }\&lt;br /&gt;
       if($lv) { $dv += ($F[9]-$lv); }\&lt;br /&gt;
       $ld = $a[0]; $lv = $F[9];\&lt;br /&gt;
       END {printf(\&amp;amp;quot;${ld}_12:00:00&amp;amp;#160;%f\n\&amp;amp;quot;, $dv)}&#039;&amp;amp;quot;\&lt;br /&gt;
     using 1:2 axes x1y1 ls l7 title &#039;Regen pro Tag&#039; with histeps&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;grep -v avg_ &amp;amp;lt;IN&amp;amp;gt; | awk &#039;{print $1, $12==\&amp;amp;quot;yes\&amp;amp;quot;? 1&amp;amp;#160;: 0; }&#039;&amp;amp;quot;\&lt;br /&gt;
     using 1:2 axes x1y2 ls l11fill title &#039;Regen aktuell&#039; with points&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Eventuell müssen in den gplots noch die Linienstile/Farben den eigenen Bedürfnissen angepasst werden. Ich verwende hier eigene Farben und Füllungen.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;br /&gt;
[[Kategorie:Logging]]&lt;/div&gt;</summary>
		<author><name>Ansgru</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Gleitende_Mittelwerte_berechnen_und_loggen&amp;diff=37503</id>
		<title>Gleitende Mittelwerte berechnen und loggen</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Gleitende_Mittelwerte_berechnen_und_loggen&amp;diff=37503"/>
		<updated>2022-07-19T07:07:50Z</updated>

		<summary type="html">&lt;p&gt;Ansgru: Hochkomma um &amp;quot;$line[1]&amp;quot; entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Für verschiedene Wettersensoren ist es oftmals wünschenswert, gleitende Mittelwerte (fälschlich auch als &amp;quot;relative&amp;quot; Mittelwerte bezeichnet) über ein bestimmtes Zeitfenster auszugeben oder in den Logs zu speichern und zu plotten. Beispiele:&lt;br /&gt;
* Die momentanen Winddaten eines KS300 sind oft stark schwankend. Hier wäre ein Mittelwert z.B. der letzten 2-3 Stunden interessant. &lt;br /&gt;
* Für die Außentemperatur ist anhand eines Mittelwertes der letzten 24 Stunden evtl. ein gewisser Trend der generellen Entwicklung der Temperatur ableitbar.&lt;br /&gt;
&lt;br /&gt;
Mit Modulen wie &#039;&#039;rain&#039;&#039; oder &#039;&#039;average&#039;&#039; ist konzeptbedingt nur ein Mittelwert von fixen Zeiträumen (aktueller Tag, Monat, etc.) möglich. &lt;br /&gt;
&lt;br /&gt;
Im Nachfolgenden werden deshalb zwei Programme vorgestellt, die solche gleitenden Mittelwerte bereitstellen. Beide Programme werden in die Datei [[99 myUtils anlegen|99_MyUtils.pm]] eingetragen und dann von FHEM aufgerufen. Das erste Programm macht dies für beliebige Readings beliebiger Devices, das zweite Programm greift auf beliebige [[FileLog|File-]] oder [[DbLog|DbLogs]] zurück.&lt;br /&gt;
&lt;br /&gt;
== Gleitender Mittelwert für beliebige Readings ==&lt;br /&gt;
=== Subroutine movingAverage in 99_MyUtils anlegen ===&lt;br /&gt;
Zuerst muss die Subroutine &#039;&#039;movingAverage&#039;&#039; in die 99_MyUtils übernommen werden. Wenn noch nicht vorhanden, sollte die Datei dann so aussehen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;package main;&lt;br /&gt;
  use strict;&lt;br /&gt;
  use warnings;&lt;br /&gt;
  sub&lt;br /&gt;
  MyUtils_Initialize($$)&lt;br /&gt;
  {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
  }&lt;br /&gt;
  ###############################################################################&lt;br /&gt;
  #&lt;br /&gt;
  #  Moving average &lt;br /&gt;
  #&lt;br /&gt;
  #  Aufruf: movingAverage(devicename,readingname,zeitspanne in s)&lt;br /&gt;
  #&lt;br /&gt;
  ###############################################################################&lt;br /&gt;
  &lt;br /&gt;
  sub movingAverage($$$){&lt;br /&gt;
     my ($name,$reading,$avtime) = @_;&lt;br /&gt;
     my $hash = $defs{$name};&lt;br /&gt;
     my @new = my ($val,$time) = ($hash-&amp;gt;{READINGS}{$reading}{VAL},$hash-&amp;gt;{READINGS}{$reading}{TIME});&lt;br /&gt;
     my ($cyear, $cmonth, $cday, $chour, $cmin, $csec) = $time =~ /(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/;&lt;br /&gt;
     my $ctime = $csec+60*$cmin+3600*$chour;&lt;br /&gt;
     my $num;&lt;br /&gt;
     my $arr;&lt;br /&gt;
     #-- initialize if requested&lt;br /&gt;
     if( ($avtime eq &amp;quot;-1&amp;quot;) ){&lt;br /&gt;
       $hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}=undef;&lt;br /&gt;
     }&lt;br /&gt;
     #-- test for existence&lt;br /&gt;
     if( !$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}){&lt;br /&gt;
        #Log 1,&amp;quot;ARRAY CREATED&amp;quot;;&lt;br /&gt;
        push(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}},\@new);&lt;br /&gt;
        $num = 1;&lt;br /&gt;
        $arr=\@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}};&lt;br /&gt;
     } else {&lt;br /&gt;
        $num = int(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}});&lt;br /&gt;
        $arr=\@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}};&lt;br /&gt;
        my $starttime = $arr-&amp;gt;[0][1];&lt;br /&gt;
        my ($syear, $smonth, $sday, $shour, $smin, $ssec) = $starttime =~ /(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/;&lt;br /&gt;
        my $stime = $ssec+60*$smin+3600*$shour;&lt;br /&gt;
        #-- correct for daybreak&lt;br /&gt;
        $stime-=86400 &lt;br /&gt;
          if( $stime &amp;gt; $ctime);&lt;br /&gt;
        if( ($num &amp;lt; 25)&amp;amp;&amp;amp;( ($ctime-$stime)&amp;lt;$avtime) ){&lt;br /&gt;
          #Log 1,&amp;quot;ARRAY has $num elements, adding another one&amp;quot;;&lt;br /&gt;
          push(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}},\@new);&lt;br /&gt;
        }else{&lt;br /&gt;
          shift(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}});&lt;br /&gt;
          push(@{$hash-&amp;gt;{READINGS}{$reading}{&amp;quot;history&amp;quot;}},\@new);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      #-- output and average&lt;br /&gt;
      my $average = 0;&lt;br /&gt;
      for(my $i=0;$i&amp;lt;$num;$i++){&lt;br /&gt;
        $average+=$arr-&amp;gt;[$i][0];&lt;br /&gt;
        Log 4,&amp;quot;[$name moving average] Value = &amp;quot;.$arr-&amp;gt;[$i][0].&amp;quot; Time = &amp;quot;.$arr-&amp;gt;[$i][1]; &lt;br /&gt;
      }&lt;br /&gt;
      $average=sprintf( &amp;quot;%5.3f&amp;quot;, $average/$num);&lt;br /&gt;
      #--average&lt;br /&gt;
      Log 4,&amp;quot;[$name moving average] calculated over $num values is $average&amp;quot;;  &lt;br /&gt;
      return $average;&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  1;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Funktion movingAverage() aufrufen und nutzen ===&lt;br /&gt;
Bei jedem Aufruf schiebt die obige Funktion den gegenwärtigen Wert sowie den Zeitpunkt eines Readings (zweiter Parameter) ans Ende eines Arrays (maximal 25 Einträge) und wirft dafür den ersten Eintrag heraus. Die Anzahl der Einträge im Array wird so gewählt, dass die Zeitpunkte der Readings größer oder gleich der gewünschten Zeitspanne für die Mittelung sind. Über diese Werte wird dann gemittelt und der Wert zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
Zur Anwendung empfiehlt sich, dem gewünschten Device ein userReading zu geben:&lt;br /&gt;
:&amp;lt;code&amp;gt;attr devicename userReadings readingname.av {movingAverage(&amp;quot;devicename&amp;quot;,&amp;quot;readingname&amp;quot;,zeitspanne)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieses wird dann automatisch bei jedem neuen Wert des Readings mit dem neuen gleitenden Mittelwert über die vergangene Zeitspanne gefüllt.&lt;br /&gt;
&lt;br /&gt;
Beispiel: Das Reading &amp;quot;pressure&amp;quot; des Devices &amp;quot;A.OWB&amp;quot; wird alle 5 Minuten aktualisiert. Das Device bekommt nun ein userReading:&lt;br /&gt;
:&amp;lt;code&amp;gt;attr A.OWB userReadings pressure.av {movingAverage(&amp;quot;A.OWB&amp;quot;,&amp;quot;pressure&amp;quot;,1800)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieses schreibt bei jeder Aktualisierung von &amp;quot;pressure&amp;quot; einen neuen Eintrag in sein Array - allerdings maximal sechs Werte, dann wird immer der älteste Eintrag gelöscht. Damit ist sichergestellt, dass diese mindestens 1800 Sekunden abdecken - also sechs Einträge.&lt;br /&gt;
&lt;br /&gt;
== Gleitender Mittelwert aus Log-Dateien ==&lt;br /&gt;
=== Subroutine myAverage() in 99_MyUtils anlegen ===&lt;br /&gt;
Zuerst muss die Subroutine myAverage in die 99_MyUtils übernommen werden. Wenn noch nicht vorhanden, sollte die Datei dann so aussehen:&lt;br /&gt;
&lt;br /&gt;
 package main;&lt;br /&gt;
  use strict;&lt;br /&gt;
  use warnings;&lt;br /&gt;
  sub&lt;br /&gt;
  MyUtils_Initialize($$)&lt;br /&gt;
  {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
  }&lt;br /&gt;
  ##########################################################&lt;br /&gt;
  # myAverage&lt;br /&gt;
  # berechnet den Mittelwert aus LogFiles über einen beliebigen Zeitraum&lt;br /&gt;
  sub&lt;br /&gt;
  myAverage($$$)&lt;br /&gt;
  {&lt;br /&gt;
   my ($offset,$logfile,$cspec) = @_;&lt;br /&gt;
   my $period_s = strftime &amp;amp;quot;%Y-%m-%d\x5f%H:%M:%S&amp;amp;quot;, localtime(time-$offset);&lt;br /&gt;
   my $period_e = strftime &amp;amp;quot;%Y-%m-%d\x5f%H:%M:%S&amp;amp;quot;, localtime;&lt;br /&gt;
   my $oll = $attr{global}{verbose};&lt;br /&gt;
   $attr{global}{verbose} = 0; &lt;br /&gt;
   my @logdata = split(&amp;amp;quot;\n&amp;amp;quot;, fhem(&amp;amp;quot;get $logfile - - $period_s $period_e $cspec&amp;amp;quot;));&lt;br /&gt;
   $attr{global}{verbose} = $oll; &lt;br /&gt;
   my ($cnt, $cum, $avg) = (0)x3;&lt;br /&gt;
   foreach (@logdata){&lt;br /&gt;
    my @line = split(&amp;amp;quot; &amp;amp;quot;, $_);&lt;br /&gt;
    if(defined $line[1] &amp;amp;amp;&amp;amp;amp; $line[1] ne &amp;amp;quot;&amp;amp;quot;){&lt;br /&gt;
     $cnt += 1;&lt;br /&gt;
     $cum += $line[1];&lt;br /&gt;
    }&lt;br /&gt;
   }&lt;br /&gt;
   if(&amp;amp;quot;$cnt&amp;amp;quot; &amp;amp;gt; 0){$avg = sprintf(&amp;amp;quot;%0.1f&amp;amp;quot;, $cum/$cnt)};&lt;br /&gt;
   Log 4, (&amp;amp;quot;myAverage: File: $logfile, Field: $cspec, Period: $period_s bis $period_e, Count: $cnt, Cum: $cum, Average: $avg&amp;amp;quot;);&lt;br /&gt;
   return $avg;&lt;br /&gt;
  }&lt;br /&gt;
  ##########################################################&lt;br /&gt;
  1;&lt;br /&gt;
&lt;br /&gt;
=== Funktion myAverage() aufrufen und nutzen ===&lt;br /&gt;
Jetzt kann die Funktion &amp;lt;code&amp;gt;myAverage(&amp;amp;lt;offset&amp;amp;gt;, &amp;amp;lt;logfile&amp;amp;gt;, &amp;amp;lt;column-spec&amp;amp;gt;)&amp;lt;/code&amp;gt; ganz normal auf der FHEM-Konsole (telnet localhost 7072) genutzt werden. Hier z.B. die Ausgabe des Mittelwertes des Windsensors, eines KS300, über die letzten drei Stunden (Angabe in 3*3600s) oder der Temperaturmittelwert der letzten 24 Stunden.&lt;br /&gt;
&lt;br /&gt;
Mit FileLog:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;fhem&amp;amp;gt; {myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;8:::&amp;amp;quot;)}&lt;br /&gt;
  6.3&lt;br /&gt;
  fhem&amp;amp;gt; {myAverage(&amp;amp;quot;86400&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;4:::&amp;amp;quot;)}&lt;br /&gt;
  -2.7&lt;br /&gt;
  fhem&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit DbLog:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;fhem&amp;amp;gt; {myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;myDbLog&amp;amp;quot;, &amp;amp;quot;KS300:wind::&amp;amp;quot;)}&lt;br /&gt;
  5.9&lt;br /&gt;
  fhem&amp;amp;gt; {myAverage(&amp;amp;quot;86400&amp;amp;quot;, &amp;amp;quot;myDbLog&amp;amp;quot;, &amp;amp;quot;KS300:temperature::&amp;amp;quot;)}&lt;br /&gt;
  -2.7&lt;br /&gt;
  fhem&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ähnlich ist die Verwendung in perl-Code in der [[Konfiguration|fhem.cfg]]:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;my $avg = myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;8:::&amp;amp;quot;);;\&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Ein [[notify]], welches bei jedem neuen Sensorwert die Mitteltemperatur der letzten 24 Stunden als Event &amp;quot;average-temp xy&amp;quot; ins Logfile schreibt, sieht dann wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define KS300_T_notify notify KS300:temperature.* {\&lt;br /&gt;
   fhem(&#039;trigger KS300 average-temp: &#039;.myAverage(&amp;amp;quot;86400&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;4:::&amp;amp;quot;));;\&lt;br /&gt;
  }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;!-- korrigiert lt. http://forum.fhem.de/index.php/topic,11622.msg170331.html#msg170331 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analog dazu wäre mit den Winddaten zu verfahren.&lt;br /&gt;
&lt;br /&gt;
=== Eigenes Filelog und Plot ===&lt;br /&gt;
==== Definitionen ====&lt;br /&gt;
Ich schreibe ein komplett eigenes Logfile und lasse über eine spezielle gplot-Definition die Temperatur- und Winddaten loggen und plotten.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define KS300_W dummy&lt;br /&gt;
  define KS300_W_notify notify KS300:wind.* {\&lt;br /&gt;
   my $avg = myAverage(&amp;amp;quot;10800&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;8:::&amp;amp;quot;);;\&lt;br /&gt;
   my $event = sprintf(&amp;amp;quot;Wc:&amp;amp;#160;%0.1f Wd:&amp;amp;#160;%0.1f Wm:&amp;amp;#160;%0.1f Wlh:&amp;amp;#160;%0.1f&amp;amp;quot;, ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;wind&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;W_avg_day&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;W_avg_month&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), $avg);;\&lt;br /&gt;
   Log 2, (&amp;amp;quot;K300_W: Event: $event&amp;amp;quot;);;\&lt;br /&gt;
   fhem(&amp;amp;quot;trigger KS300_W data: $event&amp;amp;quot;);;\&lt;br /&gt;
   fhem(&amp;amp;quot;trigger KS300 average-wind: $avg&amp;amp;quot;);;\&lt;br /&gt;
  }&lt;br /&gt;
  define FileLog_KS300_W FileLog ./log/KS300_W-%Y.log KS300_W.*&lt;br /&gt;
  attr FileLog_KS300_W logtype text&lt;br /&gt;
  attr FileLog_KS300_W room Logs&lt;br /&gt;
  define KS300_TH dummy&lt;br /&gt;
  define KS300_TH_notify notify KS300:temperature.* {\&lt;br /&gt;
   my $avg = myAverage(&amp;amp;quot;86400&amp;amp;quot;, &amp;amp;quot;FileLog_KS300&amp;amp;quot;, &amp;amp;quot;4:::&amp;amp;quot;);;\&lt;br /&gt;
   my $event = sprintf(&amp;amp;quot;Tc:&amp;amp;#160;%0.1f Hc:&amp;amp;#160;%0.1f Tavg:&amp;amp;#160;%0.1f&amp;amp;quot;, ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;temperature&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), ReadingsVal(&amp;amp;quot;KS300&amp;amp;quot;,&amp;amp;quot;humidity&amp;amp;quot;,&amp;amp;quot;0&amp;amp;quot;), $avg);;\&lt;br /&gt;
   Log 2, (&amp;amp;quot;K300_TH: Event: $event&amp;amp;quot;);;\&lt;br /&gt;
   fhem(&amp;amp;quot;trigger KS300_TH data: $event&amp;amp;quot;);;\&lt;br /&gt;
   fhem(&#039;trigger KS300 average-temp: &#039;.$avg);;\&lt;br /&gt;
  }&lt;br /&gt;
  define FileLog_KS300_TH FileLog ./log/KS300_TH-%Y.log KS300_TH.*&lt;br /&gt;
  attr FileLog_KS300_TH logtype text&lt;br /&gt;
  attr FileLog_KS300_TH room Logs&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Die Definitionen für die Plots schauen so aus:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define weblink_KS300_W weblink fileplot FileLog_KS300_W:ks300_wind:CURRENT&lt;br /&gt;
  attr weblink_KS300_W label &amp;amp;quot;Wind - Min: $data{min1}, Max: $data{max1}, Last: $data{currval1}&amp;amp;quot;&lt;br /&gt;
  attr weblink_KS300_W room Dachterasse&lt;br /&gt;
  define weblink_KS300_TH weblink fileplot FileLog_KS300_TH:ks300_temphum:CURRENT&lt;br /&gt;
  attr weblink_KS300_TH label &amp;amp;quot;Temperatur/Feuchte - Min: $data{min1}, Max: $data{max1}, Last: $data{currval1}&amp;amp;quot;&lt;br /&gt;
  attr weblink_KS300_TH room Dachterasse&lt;br /&gt;
  define weblink_KS300_R weblink fileplot FileLog_KS300:ks300_rain10:CURRENT&lt;br /&gt;
  attr weblink_KS300_R label &amp;amp;quot;Regen - Min: $data{min1}, Max: $data{max1}, Last: $data{currval1}&amp;amp;quot;&lt;br /&gt;
  attr weblink_KS300_R room Dachterasse&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Angepasste gplot-Dateien ====&lt;br /&gt;
Nun noch die speziellen gplot-Dateien.&lt;br /&gt;
ks300_wind.gplot&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;############################&lt;br /&gt;
  # Display the wind values of a KS300.&lt;br /&gt;
  # Corresponding FileLog definition:&lt;br /&gt;
  # define &amp;amp;lt;filelogname&amp;amp;gt; FileLog ./log/KS300_W-%Y.log KS300_W.*&lt;br /&gt;
  set terminal png transparent size &amp;amp;lt;SIZE&amp;amp;gt; crop&lt;br /&gt;
  set output &#039;&amp;amp;lt;OUT&amp;amp;gt;.png&#039;&lt;br /&gt;
  set xdata time&lt;br /&gt;
  set timefmt &amp;amp;quot;%Y-%m-%d_%H:%M:%S&amp;amp;quot;&lt;br /&gt;
  set xlabel &amp;amp;quot; &amp;amp;quot;&lt;br /&gt;
  set ytics nomirror&lt;br /&gt;
  #set y2tics&lt;br /&gt;
  set ytics&lt;br /&gt;
  set title &#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&lt;br /&gt;
  set grid xtics ytics&lt;br /&gt;
  set yrange [0:]&lt;br /&gt;
  set y2range [0:]&lt;br /&gt;
  set ylabel &amp;amp;quot;Wind (aktuell) [km/h]&amp;amp;quot;&lt;br /&gt;
  set y2label &amp;amp;quot;Wind (gemittelt) [km/h]&amp;amp;quot;&lt;br /&gt;
  set format y2 &amp;amp;quot;%0.1f&amp;amp;quot;&lt;br /&gt;
  #FileLog 5:Wc\x3a:0:&lt;br /&gt;
  #FileLog 11:Wlh\x3a:0:&lt;br /&gt;
  plot &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:5 ls l7fill axes x1y1 title &#039;Wind (aktuell)&#039; with lines,\&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:11 ls l5 axes x1y2 title &#039;Wind (3h-Mittel)&#039; with steps,\&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ks300_temphum.gplot&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;############################&lt;br /&gt;
  # Display the Temperature und Humidity values of a KS300.&lt;br /&gt;
  # Corresponding FileLog definition:&lt;br /&gt;
  # define &amp;amp;lt;filelogname&amp;amp;gt; FileLog ./log/KS300_TH-%Y.log KS300_TH.*&lt;br /&gt;
  set terminal png transparent size &amp;amp;lt;SIZE&amp;amp;gt; crop&lt;br /&gt;
  set output &#039;&amp;amp;lt;OUT&amp;amp;gt;.png&#039;&lt;br /&gt;
  set xdata time&lt;br /&gt;
  set timefmt &amp;amp;quot;%Y-%m-%d_%H:%M:%S&amp;amp;quot;&lt;br /&gt;
  set xlabel &amp;amp;quot; &amp;amp;quot;&lt;br /&gt;
  set ytics nomirror&lt;br /&gt;
  set y2tics&lt;br /&gt;
  #set ytics&lt;br /&gt;
  set title &#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&lt;br /&gt;
  set grid xtics y2tics&lt;br /&gt;
  set y2label &amp;amp;quot;Temperatur [°C]&amp;amp;quot;&lt;br /&gt;
  set ylabel &amp;amp;quot;Luftfeuchte [%]&amp;amp;quot;&lt;br /&gt;
  #FileLog 5:Tc\x3a:0:&lt;br /&gt;
  #FileLog 9:Tavg\x3a:0:&lt;br /&gt;
  #FileLog 7:Hc\x3a:0:&lt;br /&gt;
  plot &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:5 axes x1y2 ls l0 title &#039;Temperatur&#039; with lines,\&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:9 axes x1y2 ls l10 title &#039;Temperatur (24h-Mittel)&#039; with lines,\&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;IN&amp;amp;gt;&amp;amp;quot; using 1:7 axes x1y1 ls l2fill title &#039;Luftfeuchte&#039; with lines&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Den Plot für den Regen habe ich noch um Punkt-Plots für den israining-Status erweitert, so dass Punkte bei &amp;quot;yes&amp;quot; geplottet werden.&lt;br /&gt;
&lt;br /&gt;
ks300_rain10.gplot&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;############################&lt;br /&gt;
  # Display the Rain values of a KS300.&lt;br /&gt;
  # Corresponding FileLog definition:&lt;br /&gt;
  # define &amp;amp;lt;filelogname&amp;amp;gt; FileLog ./log/KS300-%Y.log KS300:T:.*&lt;br /&gt;
  set terminal png transparent size &amp;amp;lt;SIZE&amp;amp;gt; crop&lt;br /&gt;
  set output &#039;&amp;amp;lt;OUT&amp;amp;gt;.png&#039;&lt;br /&gt;
  set xdata time&lt;br /&gt;
  set timefmt &amp;amp;quot;%Y-%m-%d_%H:%M:%S&amp;amp;quot;&lt;br /&gt;
  set xlabel &amp;amp;quot; &amp;amp;quot;&lt;br /&gt;
  set ytics nomirror&lt;br /&gt;
  #set y2tics&lt;br /&gt;
  set ytics&lt;br /&gt;
  set title &#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&lt;br /&gt;
  set grid xtics ytics&lt;br /&gt;
  set y2range [0.5:1.5]&lt;br /&gt;
  set y2tics (&amp;amp;quot;&amp;amp;quot; 0, &amp;amp;quot;Regen&amp;amp;quot; 1)&lt;br /&gt;
  set pointsize 7&lt;br /&gt;
  set ylabel &amp;amp;quot;Regen (l/m²)&amp;amp;quot;&lt;br /&gt;
  set yrange [0:]&lt;br /&gt;
  # Computing Rain/h and Rain/d values by accumulating the changes.&lt;br /&gt;
  #FileLog 10:IR\x3a:0:delta-h&lt;br /&gt;
  #FileLog 10:IR\x3a:0:delta-d&lt;br /&gt;
  #FileLog 12:IR:0:$fld[11]=~&amp;amp;quot;yes&amp;amp;quot;?1:0&lt;br /&gt;
  plot &amp;amp;quot;&amp;amp;lt;grep -v avg_ &amp;amp;lt;IN&amp;amp;gt; | perl -ane &#039;\&lt;br /&gt;
      @a = split(\&amp;amp;quot;[_:]\&amp;amp;quot;, $F[0]);\&lt;br /&gt;
      if(defined($lh) &amp;amp;amp;&amp;amp;amp; $lh ne $a[1])\&lt;br /&gt;
       { printf(\&amp;amp;quot;${ld}_$lh:30:00&amp;amp;#160;%f\n\&amp;amp;quot;, $hv); $hv = 0; }\&lt;br /&gt;
      if($lv) { $hv += ($F[9]-$lv); }\&lt;br /&gt;
      $lh = $a[1]; $ld = $a[0]; $lv = $F[9];\&lt;br /&gt;
      END { printf(\&amp;amp;quot;${ld}_$lh:30:00&amp;amp;#160;%f\n\&amp;amp;quot;, $hv) }&#039;&amp;amp;quot;\&lt;br /&gt;
     using 1:2 axes x1y1 ls l1fill title &#039;Regen pro Stunde&#039; with histeps,\&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;grep -v avg_ &amp;amp;lt;IN&amp;amp;gt; | perl -ane &#039;\&lt;br /&gt;
      @a = split(\&amp;amp;quot;[_]\&amp;amp;quot;, $F[0]);\&lt;br /&gt;
      if(defined($ld) &amp;amp;amp;&amp;amp;amp; $ld ne $a[0]) {\&lt;br /&gt;
       printf(\&amp;amp;quot;${ld}_12:00:00&amp;amp;#160;%f\n\&amp;amp;quot;, $dv); $dv = 0; }\&lt;br /&gt;
       if($lv) { $dv += ($F[9]-$lv); }\&lt;br /&gt;
       $ld = $a[0]; $lv = $F[9];\&lt;br /&gt;
       END {printf(\&amp;amp;quot;${ld}_12:00:00&amp;amp;#160;%f\n\&amp;amp;quot;, $dv)}&#039;&amp;amp;quot;\&lt;br /&gt;
     using 1:2 axes x1y1 ls l7 title &#039;Regen pro Tag&#039; with histeps&lt;br /&gt;
     &amp;amp;quot;&amp;amp;lt;grep -v avg_ &amp;amp;lt;IN&amp;amp;gt; | awk &#039;{print $1, $12==\&amp;amp;quot;yes\&amp;amp;quot;? 1&amp;amp;#160;: 0; }&#039;&amp;amp;quot;\&lt;br /&gt;
     using 1:2 axes x1y2 ls l11fill title &#039;Regen aktuell&#039; with points&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Eventuell müssen in den gplots noch die Linienstile/Farben den eigenen Bedürfnissen angepasst werden. Ich verwende hier eigene Farben und Füllungen.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;br /&gt;
[[Kategorie:Logging]]&lt;/div&gt;</summary>
		<author><name>Ansgru</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Modbus&amp;diff=37154</id>
		<title>Modbus</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Modbus&amp;diff=37154"/>
		<updated>2022-01-25T07:28:18Z</updated>

		<summary type="html">&lt;p&gt;Ansgru: /* Set-Commands */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Library or physical device to extract information from devices with a Modbus interface or send information to such devices &lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModCmdRef=Modbus&lt;br /&gt;
|ModForumArea=Sonstiges&lt;br /&gt;
|ModTechName=98_Modbus.pm&lt;br /&gt;
|ModOwner=StefanStrobel ({{Link2FU|3960|Forum}} / [[Benutzer:StefanStrobel|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Modbus defines a physical modbus interface and library functions to be called from other logical modules / devices.&lt;br /&gt;
This low level module takes care of the communication with modbus devices and provides Get, Set and cyclic polling of Readings as well as formatting and input validation functions.&lt;br /&gt;
&lt;br /&gt;
The logical device modules for individual machines only need to define the supported modbus function codes and objects of the machine with the modbus interface in data structures. These data structures are then used by this low level module to implement Set, Get and automatic updating of readings in a given interval.&lt;br /&gt;
&lt;br /&gt;
The Modbus module supports Modbus RTU over serial / RS485 lines as well as Modbus TCP and Modbus RTU over TCP. It defines read / write functions for Modbus holding registers, input registers, coils and discrete inputs.&lt;br /&gt;
&lt;br /&gt;
See [[ModbusAttr]] if you don&#039;t want to use a library to develop your own module and if you are looking for a generic Modbus Module instead that can be configured with attributes.&lt;br /&gt;
&lt;br /&gt;
== Availability == &lt;br /&gt;
The module has been checked in.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
This module requires the Device::SerialPort or Win32::SerialPort module if you want to communicate with modbus devices over a serial line.&lt;br /&gt;
&lt;br /&gt;
== Define of a modbus interface device for serial communication ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define &amp;lt;name&amp;gt; Modbus &amp;lt;device&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A define of a physical device based on this module is only necessary if a shared physical device like a RS485 USB adapter is used. &lt;br /&gt;
In the case of Modbus TCP this module will be used as a library for other modules that define all the data objects and no define of the base module is needed.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define ModBusLine Modbus /dev/ttyUSB1@9600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example the module opens the given serial interface and other logical modules like [[ModbusAttr]] or [[ModbusSET]] can access several Modbus devices connected to this bus concurrently.&lt;br /&gt;
&lt;br /&gt;
== Set-Commands ==&lt;br /&gt;
this low level device module doesn&#039;t provide set commands for itself but implements set &lt;br /&gt;
for logical device modules that make use of this module as a library. See [[ModbusSET]] for example.&lt;br /&gt;
&lt;br /&gt;
== Get-Commands ==&lt;br /&gt;
this low level device module doesn&#039;t provide get commands for itself but implements get &lt;br /&gt;
for logical device modules that make use of this module as a library.&lt;br /&gt;
&lt;br /&gt;
== Attributes ==&lt;br /&gt;
;do_not_notify&lt;br /&gt;
;readingFnAttributes&lt;br /&gt;
&lt;br /&gt;
;queueDelay&lt;br /&gt;
:modify the delay used when sending requests to the device from the internal queue, defaults to 1 second&lt;br /&gt;
&lt;br /&gt;
;queueMax&lt;br /&gt;
:max length of the send queue, defaults to 100&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;clientSwitchDelay&lt;br /&gt;
:defines a delay that is always enforced between the last read from the bus and the next send to the bus &lt;br /&gt;
:for all connected devices, but only if the next send goes to a different device than the last one&lt;br /&gt;
&lt;br /&gt;
;dropQueueDoubles&lt;br /&gt;
:prevents new request to be queued if the same request is already in the send queue&lt;br /&gt;
&lt;br /&gt;
;skipGarbage&lt;br /&gt;
:if set to 1 this attribute will enhance the way the module treats Modbus response frames (RTU over serial lines) &lt;br /&gt;
:that look as if they have a wrong Modbus id as their first byte. &lt;br /&gt;
:If skipGarbage is set to 1 then the module will skip all bytes until a byte with the expected modbus id is seen. &lt;br /&gt;
:Under normal circumstances this behavior should not do any harm and lead to more robustness. &lt;br /&gt;
:However since it changes the original behavior of this module it has to be turned on explicitely.&lt;br /&gt;
:For Modbus ASCII it skips bytes until the expected starting byte &amp;quot;:&amp;quot; is seen.&lt;br /&gt;
 &lt;br /&gt;
;profileInterval&lt;br /&gt;
:if set to something non zero it is the time period in seconds for which the module will create bus usage statistics. &lt;br /&gt;
:Please note that this number should be at least twice as big as the interval used for requesting values in logical devices &lt;br /&gt;
:that use this physical device&lt;br /&gt;
:The bus usage statistics create the following readings:&lt;br /&gt;
:* Profiler_Delay_sum&lt;br /&gt;
::seconds used as delays to implement the defined sendDelay and commDelay&lt;br /&gt;
:*Profiler_Fhem_sum&lt;br /&gt;
::seconds spend processing in the module&lt;br /&gt;
:*Profiler_Idle_sum&lt;br /&gt;
::idle time &lt;br /&gt;
:*Profiler_Read_sum&lt;br /&gt;
::seconds spent reading and validating the data read&lt;br /&gt;
:*Profiler_Send_sum&lt;br /&gt;
::seconds spent preparing and sending data&lt;br /&gt;
:*Profiler_Wait_sum&lt;br /&gt;
::seconds waiting for a response to a request&lt;br /&gt;
:*Statistics_Requests&lt;br /&gt;
::number of requests sent&lt;br /&gt;
:*Statistics_Timeouts&lt;br /&gt;
::timeouts encountered&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Writing modules for devices using this module as a library ==&lt;br /&gt;
&lt;br /&gt;
Writing a module for a physical device with modbus interface is easy when you use the 98_Modbus.pm module as a library. &lt;br /&gt;
To use this module as a library for other fhem modules you only have to define a data structure that defines the mapping between modbus data objects (holding registers, input registers, coils or discrete inputs) and fhem readings.&lt;br /&gt;
Additionally the module needs to contain a few &amp;lt;code&amp;gt;package&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;use&amp;lt;/code&amp;gt; statements and an initialize function at the beginning, that assigns a few special variables to point to functions of the Modbus base module. &lt;br /&gt;
&lt;br /&gt;
The most easy way to start is to use [[ModbusAttr]] to define all objects and data types and then issue a set saveAsModule command which creates a new module automatically.&lt;br /&gt;
&lt;br /&gt;
Example for a module that is called ModbusSET:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
package main;&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
&lt;br /&gt;
sub ModbusSET_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
    my ($modHash) = @_;&lt;br /&gt;
    LoadModule &amp;quot;Modbus&amp;quot;;&lt;br /&gt;
    require &amp;quot;$attr{global}{modpath}/FHEM/DevIo.pm&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    $modHash-&amp;gt;{parseInfo}  = \%SET10parseInfo;              # defines registers, inputs, coils etc. for this Modbus Device&lt;br /&gt;
    $modHash-&amp;gt;{deviceInfo} = \%SET10deviceInfo;             # defines properties of the device, defaults and supported function codes&lt;br /&gt;
&lt;br /&gt;
    ModbusLD_Initialize($modHash);                          # Generic function of the Modbus module does the rest&lt;br /&gt;
    &lt;br /&gt;
    $modHash-&amp;gt;{AttrList} = $modHash-&amp;gt;{AttrList} . &amp;quot; &amp;quot; .     # Standard Attributes like IODEv etc &lt;br /&gt;
        $modHash-&amp;gt;{ObjAttrList} . &amp;quot; &amp;quot; .                     # Attributes to add or overwrite parseInfo definitions&lt;br /&gt;
        $modHash-&amp;gt;{DevAttrList};                            # Attributes to add or overwrite devInfo definitions&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The name of the initialize-Function has to match the name of the module. In the above example this is &amp;lt;code&amp;gt;ModbusSET_Initialize&amp;lt;/code&amp;gt;. Most of the steps needed in an initialize function are provided by the library function &amp;lt;code&amp;gt;ModbusLD_Initialize&amp;lt;/code&amp;gt;. This function tells fhem to use the library functions for &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt; and other typical functions in a module. See [[DevelopmentModuleIntro]] for more background information on writing fhem modules if you are curious.&lt;br /&gt;
&lt;br /&gt;
=== Introduction to the parseInfo structure ===&lt;br /&gt;
&lt;br /&gt;
Typically the data structure to map between data objects of the modbus device and fhem readings is named &amp;lt;code&amp;gt;parseInfo&amp;lt;/code&amp;gt; with a part of the name of the module itself as prefix. In the example of the module 98_ModbusSET.pm which uses Modbus.pm to implement a module for SET Silent 10 heat pumps, the structure is called &amp;lt;code&amp;gt;SET10parseInfo&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This strucure contains keys with values that directly correspond to attributes which can be used with the module ModbusAttr so it is advisable to prototype a new module with ModbusAttr and then translate the attributes to entries in the parseInfo structure. The values in the parseInfo structure can later still be overwritten / extended with the attributes documented in ModbusAttr.&lt;br /&gt;
&lt;br /&gt;
As an example a very simple definition of a parseInfo structure for a heat pump could look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
my %XYparseInfo = (&lt;br /&gt;
    &amp;quot;h256&amp;quot;  =&amp;gt;  {   reading =&amp;gt; &amp;quot;Temp_Wasser_Ein&amp;quot;,   # name of the reading for this value&lt;br /&gt;
                },&lt;br /&gt;
    &amp;quot;h258&amp;quot;  =&amp;gt;  {   reading =&amp;gt; &amp;quot;Temp_Wasser_Aus&amp;quot;,&lt;br /&gt;
                },&lt;br /&gt;
    &amp;quot;h770&amp;quot;  =&amp;gt;  {   reading =&amp;gt; &amp;quot;Temp_Soll&amp;quot;, &lt;br /&gt;
                    min     =&amp;gt; 10,                  # input validation for set: min value&lt;br /&gt;
                    max     =&amp;gt; 32,                  # input validation for set: max value&lt;br /&gt;
                    set     =&amp;gt; 1,                   # this value can be set&lt;br /&gt;
                }&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the corresponding attributes for ModbusAttr for prototyping or overwriting values would be obj-h256-reading, obj-h258-reading, obj-h770-reading, obj-h770-min and so on.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This parseInfo structure would be the main part of the module and map from holding register 256 to a fhem reading named Temp_Wasser_Ein, holding register 258 to Temp_Wasser_Aus and 770 to Temp_Soll. &lt;br /&gt;
&lt;br /&gt;
All readings will be read from the device in an interval that the user can specify when he issues the define command for your module.&lt;br /&gt;
The meaning of &amp;lt;code&amp;gt;set =&amp;gt; 1&amp;lt;/code&amp;gt; is that the holding register 770 can also be written to with a set command. FHEM will check that the value written is not smaller than 10 and not bigger than 32 as specified above.&lt;br /&gt;
&lt;br /&gt;
More complex example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
my %SET10parseInfo = (&lt;br /&gt;
    &amp;quot;h256&amp;quot;  =&amp;gt;  {   reading =&amp;gt; &amp;quot;Temp_Wasser_Ein&amp;quot;,   # name of the reading for this value&lt;br /&gt;
                    name    =&amp;gt; &amp;quot;Pb1&amp;quot;,               # internal name of this register in the hardware doc&lt;br /&gt;
                    expr    =&amp;gt; &#039;$val / 10&#039;,         # conversion of raw value to visible value &lt;br /&gt;
                    len     =&amp;gt; 1,&lt;br /&gt;
                },&lt;br /&gt;
    &amp;quot;h770&amp;quot;  =&amp;gt;  {   reading =&amp;gt; &amp;quot;Temp_Soll&amp;quot;, &lt;br /&gt;
                    name    =&amp;gt; &amp;quot;ST03&amp;quot;,&lt;br /&gt;
                    expr    =&amp;gt; &#039;$val / 10&#039;,         # convert raw value to readable temp&lt;br /&gt;
                    setexpr =&amp;gt; &#039;$val * 10&#039;,         # expression to convert a set value to the internal value &lt;br /&gt;
                    min     =&amp;gt; 10,                  # input validation for set: min value&lt;br /&gt;
                    max     =&amp;gt; 32,                  # input validation for set: max value&lt;br /&gt;
                    hint    =&amp;gt; &amp;quot;8,10,20,25,28,29,30,30.5,31,31.5,32&amp;quot;,&lt;br /&gt;
                    set     =&amp;gt; 1,                   # this value can be set&lt;br /&gt;
                },&lt;br /&gt;
    &amp;quot;h771&amp;quot;  =&amp;gt;  {   reading =&amp;gt; &amp;quot;Hysterese&amp;quot;,         # Hex Adr 303&lt;br /&gt;
                    name    =&amp;gt; &amp;quot;ST04&amp;quot;,&lt;br /&gt;
                    expr    =&amp;gt; &#039;$val / 10&#039;,&lt;br /&gt;
                    setexpr =&amp;gt; &#039;$val * 10&#039;,&lt;br /&gt;
                    poll    =&amp;gt; &amp;quot;x10&amp;quot;,               # only poll every 10th iteration.&lt;br /&gt;
                    min     =&amp;gt; 0.5,&lt;br /&gt;
                    max     =&amp;gt; 3,&lt;br /&gt;
                    set     =&amp;gt; 1,&lt;br /&gt;
                },&lt;br /&gt;
    &amp;quot;h777&amp;quot;  =&amp;gt;  {   reading =&amp;gt; &amp;quot;Hyst_Mode&amp;quot;,         # Hex Adr 0309&lt;br /&gt;
                    name    =&amp;gt; &amp;quot;ST10&amp;quot;,&lt;br /&gt;
                    map     =&amp;gt; &amp;quot;0:mittig, 1:oberhalb, 2:unterhalb&amp;quot;, &lt;br /&gt;
                    poll    =&amp;gt; &amp;quot;once&amp;quot;,              # only poll once (or after a set)&lt;br /&gt;
                    set     =&amp;gt; 1,&lt;br /&gt;
                },&lt;br /&gt;
    &amp;quot;i800&amp;quot;  =&amp;gt;  {   reading =&amp;gt; &amp;quot;Voltage&amp;quot;,           # Input register &lt;br /&gt;
                    unpack  =&amp;gt; &amp;quot;f&amp;gt;&amp;quot;,                # this value is a float&lt;br /&gt;
                    len     =&amp;gt; 2,                   # the float occupies two input registers, 800 and 801&lt;br /&gt;
                },&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are many more options that can be specified for each data object / reading. If these options are not specified, the base module assumes defaults that typically make sense. However if you want to modify the defaults, you can either define explicit values in the parseInfo structure or you can define another data structure typically called deviceInfo. &lt;br /&gt;
&lt;br /&gt;
=== Introduction to the deviceInfo structure ===&lt;br /&gt;
&lt;br /&gt;
The deviceInfo structure is completely optional. If you don&#039;t define it in your module, the base module takes default values that work in ost cases. If you only want to override a few of the defaults, you can just define them and leave other options or sections out.&lt;br /&gt;
A simple device info structure that modifies some defaults could look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
my %SET10deviceInfo = (&lt;br /&gt;
    &amp;quot;timing&amp;quot;    =&amp;gt; {&lt;br /&gt;
            timeout     =&amp;gt;  3,      # timeout is 3 seconds /default would be 2&lt;br /&gt;
            commDelay   =&amp;gt;  0.7,    # wait 0.7 seconds before sending after receiving&lt;br /&gt;
            sendDelay   =&amp;gt;  0.7,    # wait at least 0.7 seconds for another send&lt;br /&gt;
            }, &lt;br /&gt;
    &amp;quot;c&amp;quot;     =&amp;gt;  {               &lt;br /&gt;
            read        =&amp;gt;  1,      # function code 1 to read coils (this could be omitted because it is the default anyways&lt;br /&gt;
            write       =&amp;gt;  5,      # dito&lt;br /&gt;
            },&lt;br /&gt;
    &amp;quot;h&amp;quot;     =&amp;gt;  {               &lt;br /&gt;
            read        =&amp;gt;  3,      &lt;br /&gt;
            write       =&amp;gt;  6,      &lt;br /&gt;
            defLen      =&amp;gt;  1,      # default legth is 1 object&lt;br /&gt;
            combine     =&amp;gt;  5,      &lt;br /&gt;
            defShowGet  =&amp;gt;  1,      &lt;br /&gt;
            defUnpack   =&amp;gt;  &amp;quot;s&amp;gt;&amp;quot;,   # default data format is a signed 16 bit integer for holding registers &lt;br /&gt;
            },&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The deviceInfo structure contains five optional parts. Timing defines timing values and the remaining parts define settings or defaults for coils (c), discrete inputs (d), input registers (i) and holding registers (h). &lt;br /&gt;
&lt;br /&gt;
for each modbus object type you can change what function code should be used to read or write to the object. This is completely optional and if nothing is specified, the base module assumes function codes 1,2,3 and 4 for reading as well as 5 and 6 for writing which works for many modbus devices. If you prefer to use function code 16 for writing to holding registers, you can specify &amp;quot;write =&amp;gt; 16&amp;quot; in the &amp;quot;h&amp;quot; part.&lt;br /&gt;
&lt;br /&gt;
=== usage of a module created this way ===&lt;br /&gt;
&lt;br /&gt;
a logical module written this way will have a define command that can work in two ways. &lt;br /&gt;
If your module would be called ModbusSET and it is using a serial line connection (Modbus RTU over RS485 oer over RS232):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define &amp;lt;iodevice&amp;gt; Modbus /dev/device@baudrate&lt;br /&gt;
define &amp;lt;name&amp;gt; ModbusSET &amp;lt;Id&amp;gt; &amp;lt;Interval&amp;gt; &amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, a physical serial interface device is defined first using the Modbus module. Then a device based on your module (ModbusSET in the example) is defined for each physical modbus device connected to the serial line. For a RS485 bus, several devices with different Ids can be connected to the same bus.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define ModbusRS485 Modbus /dev/rs485@9600&lt;br /&gt;
define PWP ModbusAttr 5 60&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
this defines the device and it will use the readings that you coded in the parseInfo data structure.&lt;br /&gt;
&lt;br /&gt;
Alternatively your module would also support Modbus TCP or Modbus RTU over TCP with the following define syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define &amp;lt;name&amp;gt; ModbusAttr &amp;lt;Id&amp;gt; &amp;lt;Interval&amp;gt; &amp;lt;Address:Port&amp;gt; &amp;lt;RTU|TCP&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In this case no serial interface device is necessary and your module connects to the modbus device directly via TCP using either Modbus TCP or Modbus RTU over TCP.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define PWP ModbusAttr 1 30 192.168.1.115:502 TCP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== General information about data objects ===&lt;br /&gt;
&lt;br /&gt;
Modbus devices can use many different ways to encode values in their data objects. A temperature might be stored multiplied with 10 as a 16 bit integer value in one holding register so you have to read the integer and divide it by 10 to get the real temperature value back. It might also be stored as a 32 bit float data type that spans two adjacent input registers.&lt;br /&gt;
The modbus base module implements a very generic way to handle different encodings without real programming: It lets you define the Perl unpack code to convert a raw data string to a Perl value, a Perl expression to do further computation and a length in data objects. &lt;br /&gt;
&lt;br /&gt;
This way a temperature stored in a 16 bit signed integer as the value multiplied by 10 can be described with the unpack code &amp;quot;s&amp;gt;&amp;quot; and the expression &amp;quot;$val / 10&amp;quot;. A float value spanning 2 registers would be described with an unpack code &amp;quot;f&amp;gt;&amp;quot; and a len of 2. No expression is needed in this case. See Perldoc on the pack function for a detailed explation of pack and unpack codes.&lt;br /&gt;
&lt;br /&gt;
The idea here is that you should be able to define any mapping, encoding, transformation or formatting of data objects without programming by simpy describing them.&lt;br /&gt;
&lt;br /&gt;
=== most important options in parseInfo ===&lt;br /&gt;
&lt;br /&gt;
Most options here are optional and can be used if there is a need but they can also be omitted. If most readings require the same options and the option is different from the default, it is also possible to define a different default per modbus data object type in another data structure (see deviceInfo).&lt;br /&gt;
For a list of all options please refer to the attributes documentation of the module ModbusAttr. The attributes there can be translated to parseInfo or deviceInfo keys as shown above.&lt;br /&gt;
&lt;br /&gt;
;reading &lt;br /&gt;
:name of the reading to be used in FHEM e.g. Temp_Wasser_ein&lt;br /&gt;
&lt;br /&gt;
;expr           &lt;br /&gt;
:perl expression to convert a string after it has been read. The original value is in $val e.g. $val / 10&lt;br /&gt;
&lt;br /&gt;
;map            &lt;br /&gt;
:a map string to convert an value from the device to a more readable output string or to convert a user input to the machine representation e.g. &amp;quot;0:mittig, 1:oberhalb, 2:unterhalb&amp;quot;                &lt;br /&gt;
&lt;br /&gt;
;format     &lt;br /&gt;
:a format string for sprintf to format a value read, e.g. %.1f&lt;br /&gt;
&lt;br /&gt;
;len            &lt;br /&gt;
:number of Registers this value spans, can be 2 for a 32 bit float which is stored in 2 registers&lt;br /&gt;
&lt;br /&gt;
;unpack     &lt;br /&gt;
:defines the translation between data in the module and in the communication frame see the documentation of the perl pack function for details. example: &amp;quot;n&amp;quot; for an unsigned 16 bit value or &amp;quot;f&amp;gt;&amp;quot; for a float that is stored in two registers or &amp;quot;s&amp;gt;&amp;quot; for signed 16 bit integer in big endian format&lt;br /&gt;
&lt;br /&gt;
;showget        &lt;br /&gt;
:can be set to 1 to allow a FHEM get command to read this value from the device. All defined objects can be used in a get command that is issued on the command line. This parameter only controls if fhemweb will offer a get command for the object.&lt;br /&gt;
&lt;br /&gt;
;poll           &lt;br /&gt;
:defines if this value is included in the read that the module does every defined interval this can be changed by a user with an attribute&lt;br /&gt;
&lt;br /&gt;
;polldelay  &lt;br /&gt;
:if a value should not be read in each iteration (after interval has passed), this value can be set to an explicit time in seconds. The update function will then verify if this delay  has elapsed since the last read of this object. If not, the read is skipped.&lt;br /&gt;
&lt;br /&gt;
;set            &lt;br /&gt;
:can be set to 1 to allow writing this value with a FHEM set-command&lt;br /&gt;
&lt;br /&gt;
;min            &lt;br /&gt;
:min value for input validation in a set command. If the user issues e.g. set Device Temp_Soll 10, FHEM will check if the given value 10 is bigger or equal the defined min and smaller or equal the defined max.&lt;br /&gt;
&lt;br /&gt;
;max            &lt;br /&gt;
:max value for input validation in a set command&lt;br /&gt;
&lt;br /&gt;
;hint           &lt;br /&gt;
:string for fhemweb to create a selection or slider&lt;br /&gt;
&lt;br /&gt;
;setexpr        &lt;br /&gt;
:per expression to convert an input string to the machine format before writing this is typically the reverse of the above expr, e.g. $val * 10&lt;br /&gt;
&lt;br /&gt;
;name&lt;br /&gt;
:optional internal name of the value in the modbus documentation of the physical device, e.g. pb1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== most important options in deviceInfo ===&lt;br /&gt;
&lt;br /&gt;
Keys in the timing section:&lt;br /&gt;
&lt;br /&gt;
;timeout            &lt;br /&gt;
:how long to wait for a response from the device, can be overwritten by attribute timeout in logical device. Defaults to two seconds if this is not specified&lt;br /&gt;
&lt;br /&gt;
;commDelay      &lt;br /&gt;
:minimal delay in secounds between two communications e.g. a read a the next write, can be overwritten with attribute commDelay if added to AttrList in _Initialize below defaults to 0.1 seconds if not specified&lt;br /&gt;
&lt;br /&gt;
;sendDelay      &lt;br /&gt;
:minimal delay in seconds between two sends, can be overwritten with the attribute sendDelay if added to AttrList in _Initialize function below. Defaults to 0.1 seconds if not specified&lt;br /&gt;
&lt;br /&gt;
Keys per object type (c = coil, d = discrete input, i = input register, h = holding register)&lt;br /&gt;
&lt;br /&gt;
;read           &lt;br /&gt;
:function code to use for reading this object type (e.g. 3 for holding registers) defaults to function codes 1-4 depending on the object types if nothing else is specified (3 to read holding register, 1 to read coils and so on)&lt;br /&gt;
&lt;br /&gt;
;write          &lt;br /&gt;
:function code to use for writing this object type (e.g. 6 or 16 for holding registers) defaults to function codes 5 and 6 depending on the object types if nothing else is specified (6 to read holding register, 5 to write coils and so on)&lt;br /&gt;
&lt;br /&gt;
;defLen         &lt;br /&gt;
:default len for objects using this type (e.g. can be set to 2 if the device mainly provides float values that span 2 registers (2 times 16 Bit) can be overwritten in parseInfo per reading by specifying the key &amp;quot;len&amp;quot; defaults to 1 if not specified&lt;br /&gt;
&lt;br /&gt;
;defFormat      &lt;br /&gt;
:format string to do sprintf with the value can be overwritten in parseInfo per reading by specifying the key &amp;quot;format&amp;quot; if no format is specified here and none in parseInfo, the the reading is set without further formatting (which is typically fine)&lt;br /&gt;
&lt;br /&gt;
;defUnpack      &lt;br /&gt;
:default pack / unpack code to convert raw values, e.g. &amp;quot;n&amp;quot; for a 16 bit integer or &amp;quot;f&amp;gt;&amp;quot; for a big endian float can be overwritten in parseInfo per reading by specifying the key &amp;quot;unpack&amp;quot; if not specified here and not in parseInfo, then the raw value is interpreted as &amp;quot;n&amp;quot; which is 16 bit unsigned integer in big endian format&lt;br /&gt;
&lt;br /&gt;
;defPoll            &lt;br /&gt;
:defines that objects of this type should be polled by default unless specified otherwise in parseInfo or by attributes can be overwritten in parseInfo per reading by specifying the key defaultpoll if not specified here or in parseInfo, the object is not polled&lt;br /&gt;
&lt;br /&gt;
;defShowGet     &lt;br /&gt;
:defines that FHEMweb shows a Get option (by returning it as reslut to get ?) for objects of this type can be overwritten in parseInfo per reading by specifying the key showget defaults to 0.&lt;br /&gt;
&lt;br /&gt;
;combine            &lt;br /&gt;
:max number of registers that the device is willing to deliver in one read request. The modbus application layer protocol specification allows for more than 100 but most devices limit this to 5, 10 or some other number. This option defaults to 1 if not specified.&lt;br /&gt;
&lt;br /&gt;
For an example of a full module that is based on the mechanisms described here see 98_ModbusSET.pm.&lt;br /&gt;
&lt;br /&gt;
=== Attributes of your module ===&lt;br /&gt;
&lt;br /&gt;
a module based on the base module / library 98_Modbus.pm can also allow the end user to modify properties of each reading if you want to allow it. All you have to do is to offer an attribute by adding its name to the variable $modHash-&amp;gt;{AttrList} in your initialize function.&lt;br /&gt;
&lt;br /&gt;
If for example you want to allow the user to modify the maximum value for the reading Temp_Soll, you can add &amp;quot;Temp_Soll-max &amp;quot; to this variable and the user can then set this attribute. The attribute takes precedence over the max potentially already defined in your parseInfo structure.&lt;br /&gt;
&lt;br /&gt;
There are two ways that the base module accepts such readings. One is the reading name followed by &amp;quot;-&amp;quot; and the option to override, the alternative syntax is &amp;quot;obj-&amp;quot; followed by the first letter of an object type (c/d/h/i) and a decimal address just like the main key of an object in the parseInfo structure. &lt;br /&gt;
&lt;br /&gt;
Instead of allowing the attribute Temp_Soll-max for the max value of reading Temp_Soll which corresponds to holding register 770, you can alternatively add the attribute name &amp;quot;obj-h770-min &amp;quot; to $modHash-&amp;gt;{AttrList}.&lt;br /&gt;
&lt;br /&gt;
If the user is allowd to specify such attributes solely depends on the contents of the $modHash-&amp;gt;{AttrList} variable. All the processing is already built into the base module.&lt;br /&gt;
&lt;br /&gt;
If you want to allow the user the override the formatting of readings then you can add &amp;quot;obj-[cdih][1-9][0-9]*-format &amp;quot; as a regular expression that allows format specifications for all possible data objects.&lt;br /&gt;
&lt;br /&gt;
The module 98_ModbusAttr for example is also based on 98_Modbus.pm and allows all possible attributes so the user can completely define his device with attributes and without a parseInfo or deviceInfo structure.&lt;br /&gt;
&lt;br /&gt;
In the same way you can allow the user to override the device specific options and defaults with attributes that start with &amp;quot;dev-&amp;quot;, followed by the section of the deviceInfo and the name of the option. If you want to allow the user to modify the function code to be used for writing holding registers, you can add the attribute &amp;quot;obj-h-write &amp;quot; and the user can then set this attribute to 6 or 16 as he prefers.&lt;br /&gt;
It is up to the module author to decide if this makes sense.&lt;br /&gt;
&lt;br /&gt;
An assignment that allows most options to the user could be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $modHash-&amp;gt;{AttrList} = $modHash-&amp;gt;{AttrList} . &amp;quot; &amp;quot; .&lt;br /&gt;
        &amp;quot;obj-[cdih][1-9][0-9]*-reading &amp;quot; .&lt;br /&gt;
        &amp;quot;obj-[cdih][1-9][0-9]*-name &amp;quot; .&lt;br /&gt;
        &amp;quot;obj-[cdih][1-9][0-9]*-set &amp;quot; .&lt;br /&gt;
        &amp;quot;obj-[cdih][1-9][0-9]*-min &amp;quot; .&lt;br /&gt;
        &amp;quot;obj-[cdih][1-9][0-9]*-max &amp;quot; .&lt;br /&gt;
        &amp;quot;obj-[cdih][1-9][0-9]*-hint &amp;quot; .&lt;br /&gt;
        &amp;quot;obj-[cdih][1-9][0-9]*-expr &amp;quot; .&lt;br /&gt;
        &amp;quot;obj-[cdih][1-9][0-9]*-map &amp;quot; .&lt;br /&gt;
        &amp;quot;obj-[cdih][1-9][0-9]*-setexpr &amp;quot; .&lt;br /&gt;
        &amp;quot;obj-[cdih][1-9][0-9]*-format &amp;quot; .&lt;br /&gt;
        &amp;quot;obj-[cdih][1-9][0-9]*-len &amp;quot; .&lt;br /&gt;
        &amp;quot;obj-[cdih][1-9][0-9]*-unpack &amp;quot; .&lt;br /&gt;
        &amp;quot;obj-[cdih][1-9][0-9]*-showget &amp;quot; .&lt;br /&gt;
        &lt;br /&gt;
        &amp;quot;obj-[cdih][1-9][0-9]*-poll &amp;quot; .&lt;br /&gt;
        &amp;quot;obj-[cdih][1-9][0-9]*-polldelay &amp;quot; .&lt;br /&gt;
        &amp;quot;poll-.* &amp;quot; .&lt;br /&gt;
        &amp;quot;polldelay-.* &amp;quot; .&lt;br /&gt;
        &lt;br /&gt;
        &amp;quot;dev-([cdih]-)*read &amp;quot; .&lt;br /&gt;
        &amp;quot;dev-([cdih]-)*write &amp;quot; .&lt;br /&gt;
        &amp;quot;dev-([cdih]-)*combine &amp;quot; .&lt;br /&gt;
        &amp;quot;dev-([cdih]-)*defLen &amp;quot; .&lt;br /&gt;
        &amp;quot;dev-([cdih]-)*defFormat &amp;quot; .&lt;br /&gt;
        &amp;quot;dev-([cdih]-)*defUnpack &amp;quot; .&lt;br /&gt;
        &amp;quot;dev-([cdih]-)*defPoll &amp;quot; .&lt;br /&gt;
        &amp;quot;dev-([cdih]-)*defShowGet &amp;quot; .&lt;br /&gt;
        &amp;quot;dev-timing-timeout &amp;quot; .&lt;br /&gt;
        &amp;quot;dev-timing-sendDelay &amp;quot; .&lt;br /&gt;
        &amp;quot;dev-timing-commDelay &amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Examples for logical device modules that use this base module ==&lt;br /&gt;
;[http://forum.fhem.de/index.php/topic,25315.60.html SDM220M]&lt;br /&gt;
;[http://forum.fhem.de/index.php/topic,25315.60.html SDM630M]&lt;br /&gt;
:modules for energy meters from B+G E-Tech &amp;amp; EASTON written by Roger&lt;br /&gt;
;[http://forum.fhem.de/index.php/topic,25315.45.html UMG103]&lt;br /&gt;
;[http://forum.fhem.de/index.php/topic,25315.45.html UMG604]&lt;br /&gt;
:modules for the UMG103 and UMG604 meters from Janitza&lt;br /&gt;
;[[ModbusSET]]&lt;br /&gt;
:module for the set silent heat pumps from Schmidt Energie Technik&lt;br /&gt;
;[[ModbusAttr]]&lt;br /&gt;
:generic modbus device module where the data objects, addresses, display formats, function codes and other things can be configured using FHEM attributes similar to HTTPMOD  [[Kategorie:Interfaces]]&lt;/div&gt;</summary>
		<author><name>Ansgru</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=ArduCounter&amp;diff=36081</id>
		<title>ArduCounter</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=ArduCounter&amp;diff=36081"/>
		<updated>2021-09-29T19:44:24Z</updated>

		<summary type="html">&lt;p&gt;Ansgru: /* Text zu Intervallen angepasst (siehe https://forum.fhem.de/index.php/topic,19285.msg1175877.html#msg1175877)*/&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Count pulses, measure time between pulses and convert this to readings for e.g. power consumption of Energy meters or water meters&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModCmdRef=ArduCounter&lt;br /&gt;
|ModForumArea=Sonstiges&lt;br /&gt;
|ModFTopic=19285&lt;br /&gt;
|ModTechName=98_ArduCounter.pm&lt;br /&gt;
|ModOwner=StefanStrobel ({{Link2FU|3960|Forum}} / [[Benutzer:StefanStrobel|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
This module implements an Interface to an Arduino, ESP8266 or ESP32 based counter for pulses on any input pin of an Arduino Uno, Nano, Jeenode, &lt;br /&gt;
NodeMCU, Wemos D1, TTGO T-Display or similar device. &lt;br /&gt;
[[Datei:Wasserzaehler.jpg|mini|Wasserzähler mit Laserabtastung auf Basis ArduCounter mit ESP32]]&lt;br /&gt;
[[Datei:TTGO.png|mini|ArduCounter auf einem ESP32]]&lt;br /&gt;
[[Datei:ArduCounter_ESP_i.jpg|mini|ArduCounter mit Reflexlichtschranke auf einem ESP8266]]&lt;br /&gt;
[[Datei:ArduCounter_ESP2.jpg|mini|ArduCounter mit Reflexlichtschranke auf einem ESP8266]]&lt;br /&gt;
[[Datei:ArduCounter_Wifi.PNG|mini|ArduCounter Wifi-Konfiguration per WifiManager]]&lt;br /&gt;
&lt;br /&gt;
The device connects to Fhem either through USB / serial or via Wifi / TCP if an ESP board is used.&lt;br /&gt;
ArduCounter does not only count pulses but also measure pulse lenghts and the time between pulses so it can filter noise / bounces&lt;br /&gt;
and gives better power/flow (Watts or liters/second) readings than systems that just count in fixed time intervals.&lt;br /&gt;
The number of pulses per kWh or liter is defineable and counters continue even when Fhem or the device restarts&lt;br /&gt;
so you don&#039;t need additional user readings to make such calculations&lt;br /&gt;
The typical use case is an S0-Interface on an energy meter or water meter, but also reflection light barriers &lt;br /&gt;
to monitor old ferraris counters or analog water meters are supported&lt;br /&gt;
Counters are configured with attributes that define which GPIO pins should count pulses and in which intervals the board should report the current counts.&lt;br /&gt;
The sketch that works with this module uses pin change interrupts so it can efficiently count pulses on all available input pins.&lt;br /&gt;
The module has been tested with 14 inputs of an Arduino Uno counting in parallel and pulses as short as 3 milliseconds.&lt;br /&gt;
The module creates readings for pulse counts, consumption and optionally also a pin history with pulse lengths and gaps of the last pulses.&lt;br /&gt;
If an ESP8266 or ESP32 is used, the device can be flashed and configured over Wifi (it opens its own temporary Hotspot / SSID for configuration &lt;br /&gt;
so you can set which existing SSID to connect to and which password to use). For TTGO T-Display boards (ESP32 with TFT display) &lt;br /&gt;
the local display on the device itself can also display Wifi status and current consumption.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
&lt;br /&gt;
This module requires an Arduino Uno, Nano, Jeenode, NodeMCU, Wemos D1, TTGO T-Display or similar device based on an Atmel 328p, ESP8266 or ESP32 &lt;br /&gt;
running the ArduCounter sketch provided with this module&lt;br /&gt;
In order to flash an arduino board with the corresponding ArduCounter firmware from within Fhem, avrdude needs to be installed.&lt;br /&gt;
To flash ESP32 or ESP8266 boards form within Fhem, Python and the scripts esptool.py / espota.py need to be installed.&lt;br /&gt;
For old ferraris counters a reflection light barrier which in the simpest case can consist of a photo transistor (connected to an anlalog input of the Arduino / ESP)  &lt;br /&gt;
and an led or a laser module (connected to a digital output), both with a resistor in line are needed. &lt;br /&gt;
To drive a laser module with 5V, another transistor is typically needed to switch 5V from a 3.3V GPIO output.&lt;br /&gt;
&lt;br /&gt;
== Define ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define &amp;lt;name&amp;gt; ArduCounter &amp;lt;device&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;code&amp;gt;define &amp;lt;name&amp;gt; ArduCounter &amp;lt;ip:port&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;device&amp;gt; specifies the serial port to communicate with the Arduino.&lt;br /&gt;
&amp;lt;ip:port&amp;gt; specifies the ip address and tcp port to communicate with an esp8266 / ESP32 where port is typically 80.&lt;br /&gt;
&lt;br /&gt;
The name of the serial device depends on your distribution and serial adapter.&lt;br /&gt;
You can also specify a baudrate for serial connections if the device name contains the @ character, e.g.: /dev/ttyUSB0@115200&lt;br /&gt;
The default baudrate of the ArduCounter firmware is 115200 since sketch version 4 and used to be 38400 since sketch version 1.4&lt;br /&gt;
The latest version of this module will however try different baudrates automatically if communication with the counting device seems not possible.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define AC ArduCounter /dev/ttyUSB2@115200&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;define AC ArduCounter 192.168.1.134:80&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configuration of ArduCounter digital counters ==&lt;br /&gt;
&lt;br /&gt;
Specify the pins where impulses should be counted e.g. as &amp;lt;code&amp;gt;attr AC pinX falling pullup min 25&amp;lt;/code&amp;gt; &lt;br /&gt;
The X in pinX can be an Arduino / ESP GPIO pin number with or without the letter D e.g. pin4, pinD5, pin6, pinD7 ...&lt;br /&gt;
After the pin you can use the keywords falling or rising to define if a logical one / 5V (rising) or a logical zero / 0V (falling) should be treated as pulse.&lt;br /&gt;
The optional keyword pullup activates the pullup resistor for the given Pin. &lt;br /&gt;
The last argument is also optional but recommended and specifies a minimal pulse length in milliseconds.&lt;br /&gt;
An energy meter with S0 interface is typically connected to GND and an input pin like D4. &lt;br /&gt;
The S0 pulse then pulls the input down to 0V.&lt;br /&gt;
Since the minimal pulse lenght of an S0 interface is specified to be 30ms, the typical configuration for an s0 interface is &lt;br /&gt;
&amp;lt;code&amp;gt;attr AC pinX falling pullup min 25&amp;lt;/code&amp;gt;&lt;br /&gt;
Specifying a minimal pulse length is recommended since it filters bouncing of reed contacts or other noise. &lt;br /&gt;
The keyword &amp;lt;code&amp;gt;min&amp;lt;/code&amp;gt; before &amp;lt;code&amp;gt;25&amp;lt;/code&amp;gt; is optional.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define AC ArduCounter /dev/ttyUSB2&lt;br /&gt;
attr AC pulsesPerUnit 1000&lt;br /&gt;
attr AC interval 60 300&lt;br /&gt;
attr AC pinD4 falling pullup min 5&lt;br /&gt;
attr AC pinD5 falling pullup min 25&lt;br /&gt;
attr AC pinD6 rising&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This defines a counter that is connected to Fhem via serial line ttyUSB2 with three counters connected to the GPIO pins D4, D5 and D5. &lt;br /&gt;
D4 and D5 have their pullup resistors activated and the impulses draw the pins to zero.&lt;br /&gt;
For D4 and D5 the board measures the time in milliseconds between the falling edge and the rising edge. &lt;br /&gt;
If this time is longer than the specified 5 (or 25 for pin D5) milliseconds then the impulse is counted. &lt;br /&gt;
If the time is shorter then this impulse is regarded as noise and added to a separate reject counter.&lt;br /&gt;
For pin D6 the board uses a default minimal length of 2ms and counts every time when the signal changes from 1 (rising pulse) back to 0.&lt;br /&gt;
&lt;br /&gt;
== Configuration of ArduCounter analog counters ==&lt;br /&gt;
&lt;br /&gt;
This module and the corresponding ArduCounter sketch can be used to read water meters or old analog ferraris energy counters. &lt;br /&gt;
Therefore a reflection light barrier needs to be connected to the board. This might simply consist of an infra red photo transistor &lt;br /&gt;
(connected to an analog input) and an infra red led (connected to a digital output), both with a resistor in line. &lt;br /&gt;
The idea comes from Martin Kompf (https://www.kompf.de/tech/emeir.html) and has been adopted for ArduCounter to support &lt;br /&gt;
old ferraris energy counters or water meters.&lt;br /&gt;
The configuration is then similar to the one for digital counters:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define WaterMeter ArduCounter 192.168.1.110:80&lt;br /&gt;
attr ACF pinA0 rising pullup min 4 analog out 27 threshold 120,220&lt;br /&gt;
attr ACF interval 5,60,2,15,10,3&lt;br /&gt;
attr ACF pulsesPerUnit 35&lt;br /&gt;
attr ACF stateFormat {sprintf(&amp;quot;%.3f l/min&amp;quot;, ReadingsVal($name,&amp;quot;powerA0&amp;quot;,0))}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In this case an analog GPIO pin is used as input and the normal configuration parameters are followed by the keyword &lt;br /&gt;
&amp;lt;code&amp;gt;analog out&amp;lt;/code&amp;gt; or simply &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt;, the gpio number of a GPIO output that connects a light source and the thresholds &lt;br /&gt;
that decide when an analog input value is regarded as &amp;quot;low&amp;quot; or &amp;quot;high&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
In the example an ESP32 is used via Wifi connection. GPIO pin A0 is used as analog input and is connected to a photo transistor that senses the intensity of light.&lt;br /&gt;
GPIO 27 is used as LED output and switched on/off in a high frequency. On GPIO A0 the reflected light is measured &lt;br /&gt;
and the difference in a measurement between when the LED is off and when the LED is on is compared to the thresholds defined in the pinA0-attribute. &lt;br /&gt;
When the measured light difference is above &amp;lt;code&amp;gt;220&amp;lt;/code&amp;gt;, then a pulse starts (since &amp;lt;code&amp;gt;rising&amp;lt;/code&amp;gt; is specified). &lt;br /&gt;
When the measured difference is below &amp;lt;code&amp;gt;120&amp;lt;/code&amp;gt; then the pulse ends.&lt;br /&gt;
&lt;br /&gt;
The attribute &amp;lt;code&amp;gt;interval&amp;lt;/code&amp;gt; has the following meaning in the above example: &lt;br /&gt;
The device reports the current counts and the time difference beween the first and the last pulse if at least 2 pulses have been counted &lt;br /&gt;
and if they are more than 15 milliseconds apart form each other. If not, then the device continues counting. &lt;br /&gt;
If after 60 seconds these conditions are stil not met, then the device will report the current count anyways and use the current time as the end of the interval.&lt;br /&gt;
The last two numbers of the &amp;lt;code&amp;gt;interval&amp;lt;/code&amp;gt; attribute define that the device will read the analog input 3 times and then work with the average. &lt;br /&gt;
Between each analog measurement series there will be a delay of 10 milliseconds.&lt;br /&gt;
&lt;br /&gt;
The attribute &amp;lt;code&amp;gt;pulsesPerUnit 35&amp;lt;/code&amp;gt; defines that 35 pulses correspond to one unit (e.g. liter) and the reading &amp;lt;code&amp;gt;calcCounterA0&amp;lt;/code&amp;gt; &lt;br /&gt;
is increased by the reported raw counts divided by 35.&lt;br /&gt;
To find out the right analog thresholds you can set the attribute &amp;lt;code&amp;gt;enableHistory&amp;lt;/code&amp;gt; to 1 which will ask the firmware of your counting board &lt;br /&gt;
to report the average difference measurements before they are compared to a threshold. &lt;br /&gt;
The ArduCounter module will count how often each value is reported and you can then query these analog level counts with &amp;lt;code&amp;gt;get levels&amp;lt;/code&amp;gt;. &lt;br /&gt;
After a few measuremets the result of &amp;lt;code&amp;gt;get levels&amp;lt;/code&amp;gt; might look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
observed levels from analog input:&lt;br /&gt;
94: 21&lt;br /&gt;
95: 79&lt;br /&gt;
96: 6&lt;br /&gt;
97: 2&lt;br /&gt;
98: 3&lt;br /&gt;
99: 2&lt;br /&gt;
100: 2&lt;br /&gt;
101: 1&lt;br /&gt;
102: 3&lt;br /&gt;
105: 2&lt;br /&gt;
106: 1&lt;br /&gt;
108: 2&lt;br /&gt;
109: 1&lt;br /&gt;
110: 1&lt;br /&gt;
112: 1&lt;br /&gt;
113: 3&lt;br /&gt;
115: 4&lt;br /&gt;
116: 9&lt;br /&gt;
117: 14&lt;br /&gt;
118: 71&lt;br /&gt;
119: 103&lt;br /&gt;
120: 118&lt;br /&gt;
121: 155&lt;br /&gt;
122: 159&lt;br /&gt;
123: 143&lt;br /&gt;
124: 147&lt;br /&gt;
125: 158&lt;br /&gt;
126: 198&lt;br /&gt;
127: 249&lt;br /&gt;
128: 220&lt;br /&gt;
129: 230&lt;br /&gt;
130: 201&lt;br /&gt;
131: 140&lt;br /&gt;
132: 147&lt;br /&gt;
133: 153&lt;br /&gt;
134: 141&lt;br /&gt;
135: 119&lt;br /&gt;
136: 105&lt;br /&gt;
137: 109&lt;br /&gt;
138: 114&lt;br /&gt;
139: 83&lt;br /&gt;
140: 33&lt;br /&gt;
141: 14&lt;br /&gt;
142: 1  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This shows the measured values together with the frequency how often the individual value has been measured. &lt;br /&gt;
It is obvious that most measurements result in values between 120 and 135, very few values are betweem 96 and 115 &lt;br /&gt;
and another peak is around the value 95. &lt;br /&gt;
It means that in the example of a ferraris energy counter, when the red mark of the ferraris disc is under the sensor, &lt;br /&gt;
the value is around 95 and while when the blank disc is under the sensor, the value is typically between 120 and 135. &lt;br /&gt;
So a good upper threshold would be 120 and a good lower threshold would be for example 96.&lt;br /&gt;
&lt;br /&gt;
== Set-Commands ==&lt;br /&gt;
&lt;br /&gt;
;raw&lt;br /&gt;
:send the value to the board so you can directly talk to the sketch using its commands.&lt;br /&gt;
:This is not needed for normal operation but might be useful sometimes for debugging&lt;br /&gt;
&lt;br /&gt;
;flash [&amp;lt;file&amp;gt;]&lt;br /&gt;
:flashes the ArduCounter firmware from the subdirectory FHEM/firmware onto the device.&lt;br /&gt;
:Normally you can just specify &amp;lt;code&amp;gt;set myDevice flash&amp;lt;/code&amp;gt;. The parameter &amp;lt;file&amp;gt; is optional and allows specifying an alternative firmware file.&lt;br /&gt;
:The attribute flashCommand can be used to override which command is executed. &lt;br /&gt;
:If the attribute flashCommand is not specified then the module selects an appropriate command depending on the board type &lt;br /&gt;
:(set with the attribute &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt;) and depending on the connection (serial or Wifi).&lt;br /&gt;
:For an arduino NANO for example the module would execute avrdude (which has to be installed of course) &lt;br /&gt;
:and flash the connected arduino with the updated hex file &lt;br /&gt;
:(by default it looks for ArduCounter.hex in the FHEM/firmware subdirectory).&lt;br /&gt;
:For an Arduino UNO for example the default is &amp;lt;code&amp;gt;avrdude -p atmega328P -c arduino -P [PORT] -D -U flash:w:[HEXFILE] 2&amp;gt;[LOGFILE]&amp;lt;/code&amp;gt;&lt;br /&gt;
:For an Arduino Nano based counter &amp;lt;code&amp;gt;-b 57600&amp;lt;/code&amp;gt; is added.&lt;br /&gt;
:For an ESP32 connected via Wifi, the module would call espota.py which will upload the firmware over the air.&lt;br /&gt;
:If the attribute flashCommand is not specified for an ESP32 based board connected via serial line, then the module uses the command &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
esptool.py --chip esp32 --port [PORT] --baud 460800 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect&lt;br /&gt;
0x1000 FHEM/firmware/ArduCounter_ESP32_bootloader_dio_40m.bin 0x8000 FHEM/firmware/ArduCounter_ESP32_partitions.bin 0xe000  FHEM/firmware/ArduCounter_ESP32_boot_app0.bin&lt;br /&gt;
0x10000 FHEM/firmware/ArduCounter_ESP32_firmware.bin &amp;gt;[LOGFILE] 2&amp;gt;&amp;amp;1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
:for example which flashes the whole ESP32 with all the partitions. For over the air flashing it would use &lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
espota.py -i[IP] -p [NETPORT] -f [BINFILE] 2&amp;gt;[LOGFILE]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
:Of course esptool.py or espota.py as well as python would need to be installed on the system.&lt;br /&gt;
&lt;br /&gt;
;resetWifi&lt;br /&gt;
:reset Wifi settings of the counting device so the Wifi Manager will come up after the next reset to select a wireless network and enter the Wifi passphrase.&lt;br /&gt;
&lt;br /&gt;
;reset &lt;br /&gt;
:sends a command to the device which causes a hardware reset or reinitialize and reset of the internal counters of the board. &lt;br /&gt;
:The module then reopens the counting device and resends the attribute configuration / definition of the pins.&lt;br /&gt;
&lt;br /&gt;
;saveConfig &lt;br /&gt;
:stores the current interval, analog threshold and pin configuration in the EEPROM of the counter device so it will automatically be retrieved after a reset.&lt;br /&gt;
&lt;br /&gt;
;enable &lt;br /&gt;
:sets the attribute disable to 0&lt;br /&gt;
&lt;br /&gt;
;disable &lt;br /&gt;
sets the attribute disable to 1&lt;br /&gt;
&lt;br /&gt;
;reconnect &lt;br /&gt;
:closes the tcp connection to an ESP based counter board that is conected via TCP/IP and reopen the connection&lt;br /&gt;
&lt;br /&gt;
;clearLevels &lt;br /&gt;
:clears the statistics for analog levels. This is only relevant if you use the board to read via a reflective light barrier &lt;br /&gt;
:and you want to set the thresholds according to the statistics.&lt;br /&gt;
&lt;br /&gt;
;clearCounters &amp;lt;pin&amp;gt; &lt;br /&gt;
:resets all the counter readings for the specified pin to 0&lt;br /&gt;
&lt;br /&gt;
;counter &amp;lt;pin&amp;gt;, &amp;lt;value&amp;gt; &lt;br /&gt;
:set the calcCounter reading for the specified pin to the given value&lt;br /&gt;
&lt;br /&gt;
;clearHistory &lt;br /&gt;
:deletes all the cached pin history entries&lt;br /&gt;
&lt;br /&gt;
== Get-Commands ==&lt;br /&gt;
&lt;br /&gt;
;info &lt;br /&gt;
:send a command to the Arduino board to get current counts.&lt;br /&gt;
:This is not needed for normal operation but might be useful sometimes for debugging&lt;br /&gt;
&lt;br /&gt;
;levels &lt;br /&gt;
:show the count for the measured levels if an analog pin is used to measure e.g. the red mark of a ferraris counter disc. This is useful for setting the thresholds for analog :measurements.  &lt;br /&gt;
&lt;br /&gt;
;history &amp;lt;pin&amp;gt; &lt;br /&gt;
:shows details regarding all the level changes that the counter device (Arduino or ESP) has detected and how they were used (counted or rejected)&lt;br /&gt;
:If get history is issued with a pin name (e.g. get history D5) then only the history entries concerning D5 will be shown.&lt;br /&gt;
:This information is sent from the device to Fhem if the attribute &amp;lt;code&amp;gt;enableHistory&amp;lt;/code&amp;gt; is set to 1.&lt;br /&gt;
:The maximum number of lines that the Arducounter module stores in a ring buffer is defined by the attribute maxHist and defaults to 1000.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Attributes ==&lt;br /&gt;
&lt;br /&gt;
;do_not_notify&lt;br /&gt;
;readingFnAttributes&lt;br /&gt;
&lt;br /&gt;
;pin[AD]?[0-9]+&amp;lt;rising|falling&amp;gt; [&amp;lt;pullup&amp;gt;] [min] &amp;lt;min length&amp;gt; [[analog] out &amp;lt;out pin&amp;gt; [threshold] &amp;lt;min, max&amp;gt;] &lt;br /&gt;
:Define a GPIO pin of the Arduino or ESP board as input. This attribute expects for digital inputs either &lt;br /&gt;
:&amp;lt;code&amp;gt;rising&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;falling&amp;lt;/code&amp;gt;, followed by an optional &amp;lt;code&amp;gt;pullup&amp;lt;/code&amp;gt; and the optional keyword &amp;lt;code&amp;gt;min&amp;lt;/code&amp;gt; &lt;br /&gt;
:and an optional number as minimal length of pulses and gaps between pulses.&lt;br /&gt;
:The counter device will track rising and falling edges of each impulse and measure the length of a pulse in milliseconds.&lt;br /&gt;
:The minimal length specified here is the minimal duration of a pulse and a pause before a pulse. If one is too small, &lt;br /&gt;
:the pulse is not counted but added to a separate reject counter.&lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr MyCounter pinD4 falling pullup 25&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
:For analog inputs with connected reflective light barries, you have to add &amp;lt;code&amp;gt;analog out&amp;lt;/code&amp;gt; &lt;br /&gt;
:and the GPIO pin number of the pin where the light source (LED or laser) is connected, the keyword &amp;lt;code&amp;gt;threshold&amp;lt;/code&amp;gt; &lt;br /&gt;
:followed by the lower and upper threshold separated by a komma.&lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr MyCounter pinA0 rising pullup min 3 analog out 27 threshold 120,220&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;interval &amp;lt;normal&amp;gt; &amp;lt;max&amp;gt; [&amp;lt;min&amp;gt; &amp;lt;min count&amp;gt; [&amp;lt;analog interval&amp;gt; &amp;lt;analog samples&amp;gt;]] &lt;br /&gt;
:Defines the parameters that affect the way counting and reporting works. This Attribute expects at least two and a maximum of six numbers as value. The first is the normal interval, the second the maximal interval, the third is a minimal interval and the fourth is a minimal pulse count. The last two numbers are only needed for counting with reflective light barriers. They specify the delay between the measurements and the number of samples for each measurement.  The normal use case (where the normal interval is smaller than the maximum interval) would be where the Arduino board just counts and remembers the time between the first impulse and the last impulse for each pin.After the normal interval has elapsed the Arduino board reports the count and time for those pins where impulses were encountered.This means that even though the normal interval might be 10 seconds, the reported time difference can be different because impulses are observed by start and end point. The Power (e.g. for energy meters) is then calculated based of the counted impulses and the time difference between the first and the last impulse.For the next interval, the starting time will be the time of the last impulse in the previous reporting period and the time difference will be taken up to the last impulse before the reporting interval has elapsed.  The second, third and fourth numbers (maximum, minimal interval and minimal count) exist for edge cases where the pulse frequency is very low and the reporting time is comparatively short:  For example if the normal interval (first number) is 60 seconds but there is only one impulse every 90 seconds you will have spikes in your power readings (where there should be none).This can be avoided by choosing the max/min/min count numbers wisely: If impulses occur less frequently than the normal interval readings will be prolonged until max interval is reached. If however the last max interval has had no pulses, a new max interval has just started and right after it started an impuls occurs this would again cause spikes the way Arducounter works. To prevent those spikes from happening use &amp;lt;min&amp;gt; / &amp;lt;min count&amp;gt;. They make sure, that more than &amp;lt;min count&amp;gt; impulses and less than &amp;lt;min&amp;gt; time between impulses must have occured for the impulses to be considered as part of a normal interval (=a steady flow of impulses). If however it&#039;s just a single impulse which comes at an &amp;quot;akward&amp;quot; moment as mentioned before it won&#039;t be considered during a normal interval unless other impulses follow. Instead the normal interval will be prolonged until max interval is reached.&lt;br /&gt;
:A reasonable example would be:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter interval 60 600 5 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;If this is seems too complicated and you prefer a simple and constant reporting interval, then you can set the normal interval and the mximum interval to the same number.This changes the operation mode of the counter to just count during this normal and maximum interval and report the count. In this case the reported time difference is always the reporting interval and not the measured time between the real impulses.&lt;br /&gt;
:For analog sampling the last two numbers define the delay in milliseconds between analog measurements and the number of samples that will be taken as one mesurement.&lt;br /&gt;
&lt;br /&gt;
;pulsesPerUnit &amp;lt;number&amp;gt; &lt;br /&gt;
:specify the number of pulses that the meter is giving out per unit that sould be displayed (e.g. per kWh energy consumed). &lt;br /&gt;
:For many S0 counters this is 1000, for old ferraris counters this is 75 (rounds per kWh).&lt;br /&gt;
:This attribute used to be called pulsesPerKWh and this name still works but the new name should be used preferably since the old one could be removed in future versions.&lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter pulsesPerUnit 75&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;readingPulsesPerUnit[AD]?[0-9]+ &amp;lt;number&amp;gt; &lt;br /&gt;
:is the same as pulsesPerUnit but specified per GPIO pin individually in case you have multiple counters with different settings at the same time&lt;br /&gt;
:This attribute used to be called readingPulsesPerKWh[AD]?[0-9]+ and this name still works but the new name should be used preferably &lt;br /&gt;
:since the old one could be removed in future versions.&lt;br /&gt;
:&lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter readingPulsesPerUnitA7 75&lt;br /&gt;
attr myCounter readingPulsesPerUnitD4 1000&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;readingFlowUnitTime[AD]?[0-9]+ &amp;lt;time&amp;gt; &lt;br /&gt;
:specified the time period in seconds which is used as the basis for calculating the current flow or power for the given pin.&lt;br /&gt;
:If the counter e.g. counts liters and you want to see the flow in liters per minute, then you have to set this attribute to 60.&lt;br /&gt;
:If you count kWh and you want to see the current power in kW, then specify 3600 (one hour).&lt;br /&gt;
:Since this attribute is just used for multiplying the consumption per second, you can also use it to get watts &lt;br /&gt;
:instead of kW by using 3600000 instead of 3600.&lt;br /&gt;
&lt;br /&gt;
;flowUnitTime &amp;lt;time&amp;gt; &lt;br /&gt;
:like readingFlowUnitTimeXX but applies to all pins that have no explicit readingFlowUnitTimeXX attribute.&lt;br /&gt;
&lt;br /&gt;
;readingNameCount[AD]?[0-9]+ &amp;lt;new name&amp;gt; &lt;br /&gt;
:Change the name of the counter reading pinX to something more meaningful. &lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter readingNameCountD4 CounterHaus_internal&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;readingNameLongCount[AD]?[0-9]+ &amp;lt;new name&amp;gt; &lt;br /&gt;
:Change the name of the long counter reading longX to something more meaningful.&lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter readingNameLongCountD4 CounterHaus_long&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;readingNameInterpolatedCount[AD]?[0-9]+ &amp;lt;new name&amp;gt; &lt;br /&gt;
:Change the name of the interpolated long counter reading InterpolatedlongX to something more meaningful.&lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter readingNameInterpolatedCountD4 CounterHaus_interpolated&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;readingNameCalcCount[AD]?[0-9]+ &amp;lt;new name&amp;gt; &lt;br /&gt;
:Change the name of the real unit counter reading CalcCounterX to something more meaningful.&lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter readingNameCalcCountD4 CounterHaus_kWh&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;readingNamePower[AD]?[0-9]+ &amp;lt;new name&amp;gt; &lt;br /&gt;
:Change the name of the power reading powerX to something more meaningful.&lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter readingNamePowerD4 PowerHaus_kW&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;readingStartTime[AD]?[0-9]+ [0|1] &lt;br /&gt;
:Allow the reading time stamp to be set to the beginning of measuring intervals. &lt;br /&gt;
:This is a hack where the timestamp of readings is artificially set to a past time and may have side effects &lt;br /&gt;
:so avoid it unless you fully understand how Fhem works with readings and their time.&lt;br /&gt;
&lt;br /&gt;
;verboseReadings[AD]?[0-9]+ [0|1] &lt;br /&gt;
:create the additional readings lastMsg and pinHistory for each pin&lt;br /&gt;
:if verboseReafings is set to 1 for the specified pin.&lt;br /&gt;
:If set to -1 then the internal counter, the long counter and interpolated long counter readings will be hidden.&lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter verboseReadingsD4 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;enableHistory [0|1]&lt;br /&gt;
:tells the counting device to record the individual time of each change at each GPIO pin and send it to Fhem. &lt;br /&gt;
:This information is cached on the Fhem side and can be viewed with the command &amp;lt;code&amp;gt;get history&amp;lt;/code&amp;gt;&lt;br /&gt;
:The optput of &amp;lt;code&amp;gt;get history&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
seq  12627 2020-03-22 20:39:54 Pin D5   0.080 seconds at 0 -&amp;gt; pulse counted&lt;br /&gt;
seq  12628 2020-03-22 20:39:55 Pin D5   1.697 seconds at 1 -&amp;gt; gap&lt;br /&gt;
seq  12629 2020-03-22 20:39:56 Pin D5   0.080 seconds at 0 -&amp;gt; pulse counted&lt;br /&gt;
seq  12630 2020-03-22 20:39:56 Pin D5   1.694 seconds at 1 -&amp;gt; gap&lt;br /&gt;
seq  12631 2020-03-22 20:39:58 Pin D5   0.081 seconds at 0 -&amp;gt; pulse counted&lt;br /&gt;
seq  12632 2020-03-22 20:39:58 Pin D5   1.693 seconds at 1 -&amp;gt; gap&lt;br /&gt;
seq  12633 2020-03-22 20:40:00 Pin D5   0.081 seconds at 0 -&amp;gt; pulse counted&lt;br /&gt;
seq  12634 2020-03-22 20:40:00 Pin D5   1.696 seconds at 1 -&amp;gt; gap&lt;br /&gt;
seq  12635 2020-03-22 20:40:02 Pin D5   0.081 seconds at 0 -&amp;gt; pulse counted&lt;br /&gt;
seq  12636 2020-03-22 20:40:02 Pin D5   1.699 seconds at 1 -&amp;gt; gap&lt;br /&gt;
seq  12637 2020-03-22 20:40:03 Pin D5   0.079 seconds at 0 -&amp;gt; pulse counted&lt;br /&gt;
seq  12638 2020-03-22 20:40:03 Pin D5   1.700 seconds at 1 -&amp;gt; gap&lt;br /&gt;
seq  12639 2020-03-22 20:40:05 Pin D5   0.080 seconds at 0 -&amp;gt; pulse counted&lt;br /&gt;
seq  12642 2020-03-22 20:40:05 Pin D5   1.699 seconds at 1 -&amp;gt; gap&lt;br /&gt;
seq  12643 2020-03-22 20:40:07 Pin D5   0.080 seconds at 0 -&amp;gt; pulse counted&lt;br /&gt;
seq  12644 2020-03-22 20:40:07 Pin D5   1.698 seconds at 1 -&amp;gt; gap&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;enableSerialEcho [0|1] &lt;br /&gt;
:tells the counting device to show diagnostic data over the serial line when connected via TCP&lt;br /&gt;
&lt;br /&gt;
;enablePinDebug [0|1] &lt;br /&gt;
:tells the counting device to show every level change of the defined input pins over the serial line or via TCP&lt;br /&gt;
&lt;br /&gt;
;enableAnalogDebug [0|1] &lt;br /&gt;
:tells the counting device to show every analog measurement of the defined analog input pins over the serial line or via TCP&lt;br /&gt;
&lt;br /&gt;
;enableDevTime [0|1] &lt;br /&gt;
:tells the counting device to show its internal millis timer so a drift between the devices time and fhem time can be calculated and logged&lt;br /&gt;
&lt;br /&gt;
;maxHist &amp;lt;max entries&amp;gt; &lt;br /&gt;
:specifies how many pin history lines hould be buffered for &amp;quot;get history&amp;quot;.&lt;br /&gt;
:This attribute defaults to 1000.&lt;br /&gt;
&lt;br /&gt;
;analogThresholds &lt;br /&gt;
:this Attribute is outdated. Please specify the analog thresholds for reflective light barrier input with the attribute &amp;quot;pin...&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;flashCommand &amp;lt;new shell command&amp;gt; &lt;br /&gt;
:overrides the default command to flash the firmware via Wifi (OTA) or serial line. It is recommended to not define this attribute. &lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter flashCommand avrdude -p atmega328P -c arduino -b 57600 -P [PORT] -D -U flash:w:[HEXFILE] 2&amp;gt;[LOGFILE]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
:&amp;lt;code&amp;gt; [PORT]&amp;lt;/code&amp;gt; is automatically replaced with the serial port for this device as it is specified in the &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt; command.&lt;br /&gt;
:&amp;lt;code&amp;gt; [HEXFILE]&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;[BINFILE]&amp;lt;/code&amp;gt; are synonyms and are both automatically replaced with the firmware file appropriate for the device. &lt;br /&gt;
:For ESP32 boards &amp;lt;code&amp;gt;[HEXFILE]&amp;lt;/code&amp;gt; would be replaced by ArduCounter-8266.bin for example.&lt;br /&gt;
:&amp;lt;code&amp;gt; [LOGFILE]&amp;lt;/code&amp;gt; is automatically replaced ArduCounterFlash.log in the fhem log subdirectory.&lt;br /&gt;
:&amp;lt;code&amp;gt; [NETPORT]&amp;lt;/code&amp;gt; is automatically replaced by the tcp port number used for OTA flashing. &lt;br /&gt;
:For ESP32 this usually is 3232 and for 8266 Bords it is 8266.&lt;br /&gt;
&lt;br /&gt;
;keepAliveDelay &amp;lt;delay&amp;gt; &lt;br /&gt;
:defines an interval in which the module sends keepalive messages to a counter device that is conected via tcp.&lt;br /&gt;
:This attribute is ignored if the device is connected via serial port.&lt;br /&gt;
:If the device doesn&#039;t reply within a defined timeout then the module closes and tries to reopen the connection.&lt;br /&gt;
:The module tells the device when to expect the next keepalive message and the device will also close the tcp connection if it doesn&#039;t see a keepalive message within the delay :multiplied by 3&lt;br /&gt;
:The delay defaults to 10 seconds.&lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter keepAliveDelay 30&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;keepAliveTimeout &amp;lt;seconds&amp;gt; &lt;br /&gt;
:defines the timeout when wainting for a keealive reply (see keepAliveDelay)&lt;br /&gt;
:The timeout defaults to 2 seconds.&lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter keepAliveTimeout 3&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;keepAliveRetries &amp;lt;max number of retries&amp;gt; &lt;br /&gt;
:defines how often sending a keepalive is retried before the connection is closed and reopened.&lt;br /&gt;
:It defaults to 2.&lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter keepAliveRetries 3&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;nextOpenDelay &amp;lt;delay&amp;gt; &lt;br /&gt;
:defines the time in seconds that the module waits before retrying to open a disconnected tcp connection. &lt;br /&gt;
:This defaults to 60 seconds.&lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter nextOpenDelay 20&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;openTimeout &amp;lt;timeout&amp;gt; &lt;br /&gt;
:defines the timeout in seconds after which tcp open gives up trying to establish a connection to the counter device.&lt;br /&gt;
:This timeout defaults to 3 seconds.&lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter openTimeout 5&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;silentReconnect [0|1] &lt;br /&gt;
:if set to 1, then it will set the loglevel for &amp;quot;disconnected&amp;quot; and &amp;quot;reappeared&amp;quot; messages to 4 instead of 3&lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter silentReconnect 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;deviceDisplay &amp;lt;pin&amp;gt; &amp;lt;unit&amp;gt; &amp;lt;flowUnit&amp;gt; &lt;br /&gt;
:controls the unit strings that a local display on the counting device will show.  &lt;br /&gt;
:Example:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&lt;br /&gt;
attr myCounter deviceDisplay 36,l,l/m&lt;br /&gt;
attr myCounter deviceDisplay 36,kWh,kW&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;   &lt;br /&gt;
&lt;br /&gt;
;disable [0|1] &lt;br /&gt;
:if set to 1 then the module is disabled and closes the connection to a counter device.&lt;br /&gt;
&lt;br /&gt;
;factor &lt;br /&gt;
:Define a multiplicator for calculating the power from the impulse count and the time between the first and the last impulse. &lt;br /&gt;
:This attribute is outdated and unintuitive so you should avoid it. &lt;br /&gt;
:Instead you should specify the attribute pulsesPerUnit or readingPulsesPerUnit[0-9]+ (where [0-9]+ stands for the pin number).&lt;br /&gt;
&lt;br /&gt;
;readingFactor[AD]?[0-9]+ &lt;br /&gt;
:Override the factor attribute for this individual pin. &lt;br /&gt;
:Just like the attribute factor, this is a rather cumbersome way to specify the pulses per kWh. &lt;br /&gt;
:Instead it is advised to use the attribute pulsesPerUnit or readingPulsesPerUnit[0-9]+ (where [0-9]+ stands for the pin number).&lt;br /&gt;
&lt;br /&gt;
;devVerbose &lt;br /&gt;
:this attribute is outdated and has been replaced with the attributes &lt;br /&gt;
:&amp;lt;nowiki&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;enableHistory, enableSerialEcho, enablePinDebug, enableAnalogDebug, enableDevTime&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; xstyle=&amp;quot;width:80%;&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Readings / Events ==&lt;br /&gt;
&lt;br /&gt;
The module creates at least the following readings and events for each defined pin:&lt;br /&gt;
&lt;br /&gt;
;calcCounter.*  &lt;br /&gt;
:This is recommended reading for counting units based on the pulses and the attribute pulsesPerUnit. It is similar to interpolated long count &lt;br /&gt;
:which keeps on counting up after fhem restarts but this counter will take the pulses per Unit attribute into the calculation und thus does not &lt;br /&gt;
:count pulses but real Units (kWh, liters or some other unit that is applicable)&lt;br /&gt;
:The name of this reading can be changed with the attribute readingNameCalcCount[AD]?[0-9]+ where [AD]?[0-9]+ stands for the pin description e.g. D4.&lt;br /&gt;
:			Another reading with the same name but ending in _i (e.g. calcCounterD4_i) will show how many kWh (or other units) of the above value is interpolated.&lt;br /&gt;
&lt;br /&gt;
;pin.* e.g. pinD4 &lt;br /&gt;
:the current internal count at this pin (internal to the Arduino / ESP device, starts at 0 when the device restarts). &lt;br /&gt;
:The name of this reading can be changed with the attribute readingNameCount[AD]?[0-9]+ where [AD]?[0-9]+ stands for the pin description e.g. D4&lt;br /&gt;
&lt;br /&gt;
;long.* e.g. longD5  &lt;br /&gt;
:long count which keeps on counting up after fhem restarts whereas the pin.* count is only a temporary internal count that starts at 0 when the arduino board starts.&lt;br /&gt;
:The name of this reading can be changed with the attribute readingNameLongCount[AD]?[0-9]+ where [AD]?[0-9]+ stands for the pin description e.g. D4&lt;br /&gt;
&lt;br /&gt;
;interpolatedLong.*  &lt;br /&gt;
:like long.* but when the Arduino restarts the potentially missed pulses are interpolated based on the pulse rate before the restart and after the restart.&lt;br /&gt;
:The name of this reading can be changed with the attribute readingNameInterpolatedCount[AD]?[0-9]+ where [AD]?[0-9]+ stands for the pin description e.g. D4&lt;br /&gt;
&lt;br /&gt;
;reject.*&lt;br /&gt;
:counts rejected pulses that are shorter than the specified minimal pulse length. &lt;br /&gt;
&lt;br /&gt;
;power.* &lt;br /&gt;
:the current calculated power / flow at this pin.&lt;br /&gt;
:The name of this reading can be changed with the attribute readingNamePower[AD]?[0-9]+ where [AD]?[0-9]+ stands for the pin description e.g. D4.&lt;br /&gt;
:This reading depends on the attributes pulsesPerUnit as well as readingFlowUnitTime or flowUnitTime for calculation &lt;br /&gt;
&lt;br /&gt;
;pinHistory.* &lt;br /&gt;
:shows detailed information of the last pulses. This is only available when a minimal pulse length is specified for this pin. Also the total number of impulses recorded here is :limited to 20 for all pins together. The output looks like -36/7:0C, -29/7:1G, -22/8:0C, -14/7:1G, -7/7:0C, 0/7:1G&lt;br /&gt;
:The first number is the relative time in milliseconds when the input level changed, followed by the length in milliseconds, the level and the internal action.&lt;br /&gt;
:-36/7:0C for example means that 36 milliseconds before the reporting started, the input changed to 0V, stayed there for 7 milliseconds and this was counted.&lt;br /&gt;
&lt;br /&gt;
;countDiff.* &lt;br /&gt;
:delta of the current count to the last reported one. This is used together with timeDiff.* to calculate the power consumption.&lt;br /&gt;
&lt;br /&gt;
;timeDiff.* &lt;br /&gt;
:time difference between the first pulse in the current observation interval and the last one. Used togehter with countDiff to calculate the power consumption.&lt;br /&gt;
&lt;br /&gt;
;seq.* &lt;br /&gt;
:internal sequence number of the last report from the board to Fhem.&lt;br /&gt;
&lt;br /&gt;
;runTime.* &lt;br /&gt;
:this reading will only be created when the attribute runTime[AD]?[0-9]+ is set for a given pin.&lt;br /&gt;
:It contains the time in seconds that the consumption / flow observed at the specified pin has not ben zero.&lt;br /&gt;
:If a water meter which outputs 10 impulses per liter on its digital output is for example connected to GPIO pin D6, &lt;br /&gt;
:then if the attribute runTimeD6 is set to 1, the reading runTimeD6 will show for how many seconds the water has been flowing without a stop longer than the &lt;br /&gt;
:observation interval specifie in the interval-attribute. This is helpful when you want to create alerts in case someone forgot to close a water tap.  [[Kategorie:Other Components]] [[Kategorie:Energieverbrauchsmessung]]&lt;/div&gt;</summary>
		<author><name>Ansgru</name></author>
	</entry>
</feed>