FTUI Widget Chart: Unterschied zwischen den Versionen

Aus FHEMWiki
(→‎Beispiele: "Fensterstatus offen/geschlossen" hinzugefügt.)
Keine Bearbeitungszusammenfassung
 
(51 dazwischenliegende Versionen von 12 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
Das [[{{PAGENAME}}|Chart Widget]] ist ein Widget für [[FHEM Tablet UI]], mit dem sich verschiedenste Diagramme darstellen lassen. Die Aneinanderreihung mehrerer Werte eines Device-Readings zu einem zeitlichen Verlauf wird dabei als Graph bezeichnet.
Das [[{{PAGENAME}}|Chart Widget]] ist ein Widget für [[FHEM Tablet UI V2]], mit dem sich verschiedenste Diagramme darstellen lassen. Die Aneinanderreihung mehrerer Werte eines Device-Readings zu einem zeitlichen Verlauf wird dabei als Graph bezeichnet.


Es können beliebige Werte dargestellt und entsprechend der Sinnhaftigkeit, oder persönlichem Geschmack, formatiert werden. Farbe und Form der Linien sind je Graph einstellbar, auch wenn mehrere gleichzeitig in einem Diagramm angezeigt werden.
Es können beliebige Werte dargestellt und entsprechend der Sinnhaftigkeit, oder persönlichem Geschmack, formatiert werden. Farbe und Form der Linien sind je Graph einstellbar, auch wenn mehrere gleichzeitig in einem Diagramm angezeigt werden.
Zeile 7: Zeile 7:
<gallery>
<gallery>
File:Chart_tabletUI.png
File:Chart_tabletUI.png
Datei:FTUI Widget Chart Stacked.png
Datei:FTUI Widget Chart-fc-Proplanta.png
Datei:Wetterchart2.png
Datei:PieChart.png
</gallery>
</gallery>


==Attribute==
==Attribute==
{|class="wikitable"
{| class="wikitable"
! style="width:150px"|Attribut
! style="width:150px" |Attribut
!Beschreibung
!Beschreibung
!Standard-Wert
!Standard-Wert
!Beispiel
!Beispiel
|-
|'''data-device'''||Name des FHEM-Device, das die Aktualisierung des Charts triggert||||data-device="WohnzimmerHeizung"
|-
|'''data-get'''||Reading, das das Update des Diagramms triggert||'STATE'||
|-
|-
|'''data-logdevice'''||Name des Log-Device, das dargestellt werden soll, oder ein Array, um mehrere Werte in einem Diagramm darzustellen||||data-logdevice="FileLog_WohnzimmerHeizung"
|'''data-logdevice'''||Name des Log-Device, das dargestellt werden soll, oder ein Array, um mehrere Werte in einem Diagramm darzustellen||||data-logdevice="FileLog_WohnzimmerHeizung"
|-
|-
|'''data-logfile'''|| Name des Log-Files, aus dem die Daten entnommen werden sollen (oder Array)||'-' = aktuelle Datei||data-logfine="WohnzimmerHeizung-2015.log"
|'''data-logfile'''|| Name des Log-Files, aus dem die Daten entnommen werden sollen (oder Array)||'-' = aktuelle Datei||data-logfile="WohnzimmerHeizung-2015.log"<br>Beachte: Der Wert "CURRENT" ermöglicht die Navigation auch zu älterne Logfiles (Jahreswechsel)
|-
|-
|'''data-columnspec'''||Ermittelt den Wert aus dem Log-File, der angezeigt werden soll (oder Array)||||data-columnspec="4:meas.*"
|'''data-columnspec'''||Ermittelt den Wert aus dem Log-File, der angezeigt werden soll (oder Array)||||data-columnspec="4:meas.*"
|-
|-
|'''data-style'''||Stil, wie die Graph-Linien dargestellt werden sollen (z.B. 'SVGplot l0' oder 'ftui l0dash'), oder ein Array, wenn mehrere Linien unterschiedlich dargestellt werden sollen||||
|'''data-style'''||Stil, wie die Graph-Linien dargestellt werden sollen (z.B. 'SVGplot l0' oder 'ftui l0dash'), oder ein Array, wenn mehrere Linien unterschiedlich dargestellt werden sollen (siehe [[#Aussehen_der_Linien|Hinweise]])||||
|-
|-
|'''data-ptype'''||Form, wie die Graphen dargestellt werden sollen (z.B. 'lines', 'cubic' oder 'fa-cog'), oder ein Array||'lines'||
|'''data-ptype'''||Form, wie die Graphen dargestellt werden sollen (z.B. 'lines', 'cubic' oder 'fa-cog'), oder ein Array (siehe [[#Form_der_Linien|Hinweise]])||'lines'||
|-
|-
|'''data-uaxis'''||Name der Achse, die verwendet werden soll ('primary' = links, oder 'secondary' = rechts), oder ein Array||'primary'||
|'''data-uaxis'''||Name der Achse, die verwendet werden soll ('primary' = links, oder 'secondary' = rechts), oder ein Array||'primary'||
Zeile 37: Zeile 45:
|-
|-
|'''data-maxvalue_sec'''||Maximaler Wert, der auf der rechten Y-Achse ('secondary') angezeigt werden soll. 'auto' = automatische Berechnung||'auto'||
|'''data-maxvalue_sec'''||Maximaler Wert, der auf der rechten Y-Achse ('secondary') angezeigt werden soll. 'auto' = automatische Berechnung||'auto'||
|-
|'''data-xticks'''||Abstand zwischen den vertikalen Hilfslinien (bezogen auf die X-Achse) in Minuten. 'auto' = automatische Berechnung||'auto'||
|-
|-
|'''data-yticks'''||Abstand zwischen den horizontalen Hilfslinien (bezogen auf die linke Y-Achse). Kann auch ein Array mit Werte-Paaren enthalten, um die Linien mit Text zu beschriften.||'auto'||data-yticks='[[0,"open"],[1,"closed"]]'
|'''data-yticks'''||Abstand zwischen den horizontalen Hilfslinien (bezogen auf die linke Y-Achse). Kann auch ein Array mit Werte-Paaren enthalten, um die Linien mit Text zu beschriften.||'auto'||data-yticks='[[0,"open"],[1,"closed"]]'
|-
|'''data-yticks_format'''||Dient zur Formatierung der Ticks der Y-Achse. Die Formatierung geschieht über Platzhalter, Trenner und einen beliebigen durch ' ' getrennten Text. Als Platzhalter dient ein oder mehrere '#', als Trenner können '.', ',' und ':' verwendet werden. Ist ein Trenner enthalten (z.B. '#.##') dann bedeutet das in dem Beispiel, dass der Ytick mit 2 Nachkommastellen versehen wird und vorne Platz für eine Stelle vor dem Komma vorgehalten wird (führende Nullen werden nicht dargestellt, aber de Platz wird reserviert so dass das ganze rechtsbündig immer passt). Ist kein Trenner vorhanden, dann wird der Ytick auf die Summe der Platzhalter mit einer festen Gesamtbreite gesetzt (#### würde also bedeuten, dass immer 4 Stellen (ohne Trenner) verwendet werden. aus 0.4 würde 0.400 aus 10.437 würde 10.44). Als Trenner kann man z.B. für Zeiten auch einen ':' verwenden und dadurch auch so etwas wie "12:00 Uhr" realisieren (in dem Beispiel wäre data-yticks_format="##:## Uhr" und kein data-yunit oder data-yticks="##:##" und data-yunit="Uhr").||||data-yticks_format="#.##"
|-
|-
|'''data-yticks_sec'''||Abstand zwischen den horizontalen Hilfslinien (bezogen auf die rechte Y-Achse). Kann auch ein Array mit Werte-Paaren enthalten, um die Linien mit Text zu beschriften.||'auto'||data-yticks='[[0,"open"],[1,"closed"]]'
|'''data-yticks_sec'''||Abstand zwischen den horizontalen Hilfslinien (bezogen auf die rechte Y-Achse). Kann auch ein Array mit Werte-Paaren enthalten, um die Linien mit Text zu beschriften.||'auto'||data-yticks='[[0,"open"],[1,"closed"]]'
|-
|-
|'''data-xticks'''||Abstand zwischen den vertikalen Hilfslinien (bezogen auf die X-Achse) in Minuten. 'auto' = automatische Berechnung||'auto'||
|'''data-yticks_format_sec'''||Dient zur Formatierung der Ticks der Y-Achse. Die Formatierung geschieht über Platzhalter, Trenner und einen beliebigen durch ' ' getrennten Text. Als Platzhalter dient ein oder mehrere '#', als Trenner können '.', ',' und ':' verwendet werden. Ist ein Trenner enthalten (z.B. '#.##') dann bedeutet das in dem Beispiel, dass der Ytick mit 2 Nachkommastellen versehen wird und vorne Platz für eine Stelle vor dem Komma vorgehalten wird (führende Nullen werden nicht dargestellt, aber de Platz wird reserviert so dass das ganze rechtsbündig immer passt). Ist kein Trenner vorhanden, dann wird der Ytick auf die Summe der Platzhalter mit einer festen Gesamtbreite gesetzt (#### würde also bedeuten, dass immer 4 Stellen (ohne Trenner) verwendet werden. aus 0.4 würde 0.400 aus 10.437 würde 10.44). Als Trenner kann man z.B. für Zeiten auch einen ':' verwenden und dadurch auch so etwas wie "12:00 Uhr" realisieren (in dem Beispiel wäre data-yticks_format="##:## Uhr" und kein data-yunit oder data-yticks="##:##" und data-yunit="Uhr").||||data-yticks_format_sec="#.##"
|-
|'''data-yticks_prio'''||Legt fest, ob die horizontalen Hilfslinien der linken (primary) oder der rechten (secondary) Y-Achse zugeordnet werden sollen||||data-yticks_prio='secondary'
|-
|'''data-ytype'''||Legt fest, ob die primäre y Achse logarithmisch sein soll (wert "log")||||data-ytype="log"
|-
|'''data-ytype_sec'''||Legt fest, ob die sekundäre y Achse logarithmisch sein soll (wert "log")||||data-ytype_sec="log"
|-
|'''data-margin'''|||Abstand zwischen Buttons und Chart (Einheit Pixel). ||"0"|||data-margin="10"
|-
|'''data-y_margin'''|||Gibt die Möglichkeit, Abstände zwischen den Graphen und dem oberen Rand des Plots zu definieren (Einheit Pixel). Falls der Wert skalar ist, werden oben und unten die gleichen Abstände eingehalten. Falls ein 2D Array angegeben wird, können die Werte unten (erster Wert im Array) und oben (zweiter Wert im Array) getrennt festgelegt werden||"0"|||data-y_margin='["10","20"]'
|-
|'''data-y_margin_sec'''|||Gibt die Möglichkeit, Abstände zwischen den Graphen und dem oberen Rand des Plots zu definieren (Einheit Pixel). Falls der Wert skalar ist, werden oben und unten die gleichen Abstände eingehalten. Falls ein 2D Array angegeben wird, können die Werte unten (erster Wert im Array) und oben (zweiter Wert im Array) getrennt festgelegt werden||"0"|||data-y_margin='["10","20"]'
|-
|'''data-daysago_start'''||Anzahl der vergangenen Tage, wo das Diagramm beginnen soll. '0' = Beginn heute 0:00 Uhr. (siehe [[#Zeitstrahl_.2F_Start_.26_Ende_auf_der_X-Achse|Hinweise]])||'0'||
|-
|-
|'''data-daysago_start'''||Anzahl der vergangenen Tage, wo das Diagramm beginnen soll. '0' = Beginn heute 0:00 Uhr. Es kann auch ein fixes Datum (z.B. '2013-10-23') angegeben werden. Uhrzeitangaben werden nur berücksichtigt, wenn '''data-nofulldays='true' ''' verwendet wird.||'0'||
|'''data-daysago_end'''||Anzahl der vergangenen Tage, wo das Diagramm enden soll. '-1' = Ende heute 24:00 Uhr. (siehe [[#Zeitstrahl_.2F_Start_.26_Ende_auf_der_X-Achse|Hinweise]])||'-1'||
|-
|-
|'''data-daysago_end'''||Anzahl der vergangenen Tage, wo das Diagramm enden soll. '-1' = Ende heute 24:00 Uhr. Es kann auch ein fixes Datum (z.B. '2013-10-24') angegeben werden. Uhrzeitangaben werden nur berücksichtigt, wenn '''data-nofulldays='true' ''' verwendet wird.||'-1'||
|'''data-xticks_round'''||Wenn vorhanden und entweder 'h', 'd', 'w', wird auf Stunde, Tag oder Woche bei den xticks gerundet (also die Tickmarks und die Gridlines bei den entsprechend gerundeten Zeiten gesetzt). Es kann auch 'auto' angegeben werden, um eine autmoatische Rundung durchzuführen||||
|-
|-
|'''data-nofulldays'''||Aktiviert/deaktiviert die Rundung der X-Achse auf ganze Tage. Binärwert ('true' oder 'false')||'false'||
|'''data-nofulldays'''||Aktiviert/deaktiviert die Rundung der X-Achse auf ganze Tage. Binärwert ('true' oder 'false')||'false'||
|-
|-
|'''data-timeformat'''||Zeitformat für die Anzeige an der X-Achse (siehe Hinweise)||||
|'''data-timeformat'''||Zeitformat für die Anzeige an der X-Achse (siehe [[#Zeitformat_der_X-Achse|Hinweise]])||||
|-
|'''data-timeranges'''||Hierdurch können vordefinierte Zeiträume für die X-Achse festgelegt werden, die dann durch eine pulldown menu (neuer Button oben neben dem "-" Button) direkt ausgewählt werden können. Der Parameter ist ein Array aus Array Einträgen, welche jeweils [<Name>,<daysago_start>,<daysago_end>] enthalten)||
||data-timeranges='[<br>
["Actual Year","0Y","-1Y"],<br>
["Last Year","1Y","0Y"],<br>
["Actual Month","0M","-1M"],<br>
["Last Month","1M","0M"],<br>
["Actual Week","0W","-1W"],<br>
["Last Week","1W","0W"],<br>
["Today","0D","-1D"],<br>
["Yesterday","1D","0D"]<br>
]'
|-
|-
|'''data-ytext'''||Text, der neben der linken Y-Achse angezeigt wird||||
|'''data-ytext'''||Text, der neben der linken Y-Achse angezeigt wird||||
Zeile 59: Zeile 97:
|-
|-
|'''data-yunit_sec'''||Einheit, die an der rechten Y-Achse angezeigt wird||||
|'''data-yunit_sec'''||Einheit, die an der rechten Y-Achse angezeigt wird||||
|-
|'''data-show_both_axes'''||Legt fest ob beide Y-Achsen Linien gezeichnet werden sollen||false||
|-
|-
|'''data-crosshair'''||Aktiviert/deaktiviert den Fadenkreuz-Cursor. Binärwert ('true' oder 'false')||'false'||
|'''data-crosshair'''||Aktiviert/deaktiviert den Fadenkreuz-Cursor. Binärwert ('true' oder 'false')||'false'||
|-
|-
|'''data-cursorgroup'''||Zahl zur Gruppierung der Werte am Fadenkreuz-Cursor (siehe Hinweise)||||
|'''data-cursorgroup'''||Zahl zur Gruppierung der Werte am Fadenkreuz-Cursor ([[#Fadenkreuz-Cursor|Hinweise]])||||
|-
|-
|'''data-scrollgroup'''||Zahl zur Gruppierung der Graphen beim Bewegen und Zoomen. Alle Linien mit der selben Zahl werden miteinander gekoppelt und bewegen sich gemeinsam.||||
|'''data-scrollgroup'''||Zahl zur Gruppierung der Graphen beim Bewegen und Zoomen. Alle Linien mit der selben Zahl werden miteinander gekoppelt und bewegen sich gemeinsam.||||
Zeile 68: Zeile 108:
|'''data-showlegend'''||Aktiviert/deaktiviert die Anzeige der Legene. Binärwert ('true' oder 'false')||'false'||
|'''data-showlegend'''||Aktiviert/deaktiviert die Anzeige der Legene. Binärwert ('true' oder 'false')||'false'||
|-
|-
|'''data-legendpos'''||Array von zwei Werten, die die horizontale und vertikale Position der Legende festlegen (siehe Hinweise)||'["top","right"]'||
|'''data-legendpos'''||Array von zwei Werten, die die horizontale und vertikale Position der Legende festlegen ([[#Legende|Hinweise]])||'["right","top"]'||
|-
|'''data-legend_horiz'''||legt fest, dass die Legendeneinträge horizontal angeordnet sind (anstatt vertikal wie im default Fall)||false||data-legend_horiz="true"
|-
|-
|'''data-width'''||Breite des Diagramms (in % oder px)||||
|'''data-width'''||Breite des Diagramms (in % oder px)||||
Zeile 74: Zeile 116:
|'''data-height'''||Höhe des Diagramms (in % oder px)||||
|'''data-height'''||Höhe des Diagramms (in % oder px)||||
|-
|-
|'''data-graphsshown'''||Aktiviert/deaktiviert die initiale Anzeige von Graphen. Binärwert ('true' oder 'false'). Array, wenn mehrere Linien angezeigt werden sollen.||||
|'''data-graphsshown'''||Aktiviert/deaktiviert die initiale Anzeige von Graphen. Binärwert ('true' oder 'false'). Array, wenn mehrere Linien angezeigt werden sollen.||||data-graphsshown='[true,false,true]'
|-
|-
|'''data-ddd'''||Einstellung für die 3D-Drehung (siehe Hinweise)||||data-ddd='["40","60","0"]'
|'''data-ddd'''||Einstellung für die 3D-Drehung ([[#3-dimensionale_Drehung|Hinweise]])||||data-ddd='["40","60","0"]'
|-
|-
|'''data-dddspace'''||Abstand zwischen zwei Graphen, wenn die 3D-Anzeige aktiviert wurde (px)||'15'||
|'''data-dddspace'''||Abstand zwischen zwei Graphen, wenn die 3D-Anzeige aktiviert wurde (px)||'15'||
Zeile 82: Zeile 124:
|'''data-dddwidth'''||Breite, bzw. Tiefe der Graphen, wenn diese 3-dimensional angezeigt werden (px)||'10'||
|'''data-dddwidth'''||Breite, bzw. Tiefe der Graphen, wenn diese 3-dimensional angezeigt werden (px)||'10'||
|-
|-
|'''data-title'''||Titel, der über dem Diagramm angezeigt werden soll. Der Inhalt kann auch dynamisch erzeugt werden (siehe Hinweise)||||
|'''data-title'''||Titel, der über dem Diagramm angezeigt werden soll. Der Inhalt kann auch dynamisch erzeugt werden ([[#Diagrammtitel|Hinweise]])||||
|-
|'''data-title_class'''||Klassenname für die Formatierung des Titels. Die Eigenschaften müssen dann entsprechend in einem CSS File angegeben werden (z.B. in fhem-tablet-ui-user.css)||||
|-
|'''data-prefetch'''||Legt fest, ob zusätzliche Daten rechts und links des Plots im Hintergrund vom Server geholt werden sollen||false||data-prefetch="true"
|-
|'''data-xtext_offset'''
|Verschiebt den Text auf der x-Achse um die angegebene Anzahl in Minuten.
|
|
|}
|}
Einige Parameter (style, maxvalue, minvalue, maxvalue_sec, minvalue_sec) können auch aus Readings dynamisch gesetzt werden wenn "<device>:<reading>" als Parameter gesetzt wird. Damit kann man z.B. in FHEM über notify etc. die Linientypen dynamisch anpassen (z.B. wenn der Wert eines Devices in einem bestimmten Bereich liegt, ändert sich die Farbe des Graphen).


==CSS Klassen==
==CSS Klassen==
{|class="wikitable"
{| class="wikitable"
!Klasse!!Beschreibung
!Klasse!!Beschreibung
{{FTUI Klasse|fullsize}}{{FTUI Klasse|noticks}}{{FTUI Klasse|nobuttons}}{{FTUI Klasse|small}}{{FTUI Klasse|normal}}{{FTUI Klasse|big}}
{{FTUI Klasse|fullsize}}{{FTUI Klasse|noticks}}{{FTUI Klasse|nobuttons}}{{FTUI Klasse|small}}{{FTUI Klasse|normal}}{{FTUI Klasse|big}}
|}
|}


Folgende Widget-spezifsche Klassen können zusätzlich in einer eigenen CSS-Datei definiert werden:
Folgende Widget-spezifsche Klassen können zusätzlich in einer eigenen CSS-Datei definiert werden:


{|class="wikitable"
{| class="wikitable"
!Klasse
!Klasse
!Beschreibung
!Beschreibung
Zeile 120: Zeile 171:
|'''legend'''||Schriftart, Größe und Farbe der Legende
|'''legend'''||Schriftart, Größe und Farbe der Legende
|}
|}
Die Standardwerte sind in der Datei <code>css/ftui_chart.css</code> zu finden.


==Datenquellen==
==Datenquellen==
Zeile 132: Zeile 185:
Für ein Heizungsthermostat von Homematic mit dem Namen ''DG.wz.HZ.Heizungsventil'' ergibt sich somit beispielhaft folgende Definition, um gemessene Temperatur, Sollwert und Ventilstellung im Diagramm darzustellen:
Für ein Heizungsthermostat von Homematic mit dem Namen ''DG.wz.HZ.Heizungsventil'' ergibt sich somit beispielhaft folgende Definition, um gemessene Temperatur, Sollwert und Ventilstellung im Diagramm darzustellen:


<source lang="html">
<syntaxhighlight lang="html">
<div data-type="chart"
<div data-type="chart"
data-device="DG.wz.HZ.Heizungsventil"
data-logdevice="FileLog_DG.wz.HZ.Heizungsventil"
data-logdevice="FileLog_DG.wz.HZ.Heizungsventil"
data-logfile="-"
data-logfile="-"
Zeile 139: Zeile 193:
...>
...>
</div>
</div>
</source>
</syntaxhighlight>


Sollen Daten von unterschiedlichen Geräten in einem Diagramm angezeigt werden, muss '''data-logdevice''' als Array nach dem Schema <code>data-logdevice='["<Logdatei_1>","<Logdatei_2>","<Logdatei_3>"]'</code> definiert werden. Für jeden Eintrag in '''data-columnspec''' muss es auch den passenden Eintrag in '''data-logdevice''' geben (auch die Reihenfolge ist relevant).
Sollen Daten von unterschiedlichen Geräten in einem Diagramm angezeigt werden, muss '''data-logdevice''' als Array nach dem Schema <code>data-logdevice='["<Logdatei_1>","<Logdatei_2>","<Logdatei_3>"]'</code> definiert werden. Für jeden Eintrag in '''data-columnspec''' muss es auch den passenden Eintrag in '''data-logdevice''' geben (auch die Reihenfolge ist relevant).
Zeile 148: Zeile 202:
Für das oben beschriebene Homematic-Heizungsthermostat ergibt sich dann folgende Definition, um die gleichen Daten aus einer Datenbank, statt einem LogFile zu lesen:
Für das oben beschriebene Homematic-Heizungsthermostat ergibt sich dann folgende Definition, um die gleichen Daten aus einer Datenbank, statt einem LogFile zu lesen:


<source lang="html">
<syntaxhighlight lang="html">
<div data-type="chart"
<div data-type="chart"
data-device="DG.wz.HZ.Heizungsventil"
        data-get="measured-temp"
        data-style='["ftui l0"]'
data-logdevice="logdb"
data-logdevice="logdb"
data-logfile="HISTORY"
data-logfile="HISTORY"
Zeile 155: Zeile 212:
...>
...>
</div>
</div>
</source>
</syntaxhighlight>


Für die Anzeige von unterschiedlichen Geräten in einem Diagramm, muss nur '''data-columnspec''' entsprechend angepasst werden, solange sich alle Daten in der Datenbank befinden.
Für die Anzeige von unterschiedlichen Geräten in einem Diagramm, muss nur '''data-columnspec''' entsprechend angepasst werden, solange sich alle Daten in der Datenbank befinden.
Zeile 174: Zeile 231:
Das nachfolgende Beispiel zeigt, wie Vorhersagewerte aus einem FHEM-Device vom Typ Proplanta (Name hier <code>AU.xx.WE.Proplanta</code>) angezeigt werden können.
Das nachfolgende Beispiel zeigt, wie Vorhersagewerte aus einem FHEM-Device vom Typ Proplanta (Name hier <code>AU.xx.WE.Proplanta</code>) angezeigt werden können.


<source lang="html">
<syntaxhighlight lang="html">
<div data-type="chart"
<div data-type="chart"
data-device="AU.xx.WE.Proplanta"
data-logdevice='[
data-logdevice='[
"myLogProxy",
"myLogProxy",
Zeile 190: Zeile 248:
...>
...>
</div>
</div>
</source>
</syntaxhighlight>


'''Auch alle anderen Funktionen, die [[LogProxy]] bietet, können hier angewendet werden.'''
'''Auch alle anderen Funktionen, die [[LogProxy]] bietet, können hier angewendet werden.'''


==Hinweise==
==Hinweise==
===Aktualisierung des Charts===
Damit der Refresh des Charts funktioniert, muss auch ein Device angegeben werden, der das Refresh triggert. Das Diagramm wird immer dann aktualisiert, wenn sich der Inhalt von '''data-get''' ändert.
<syntaxhighlight lang="html">
<div data-type="chart"
data-device="WohnzimmerHeizung"
data-logdevice="FileLog_WohnzimmerHeizung"
...>
</div>
</syntaxhighlight>
===Aussehen der Linien===
===Aussehen der Linien===
Mit dem Attribut '''data-style''' kann das Aussehen der Linien des jeweiligen Graphen verändert werden. Hierfür können die Standard-FHEM-Styles verwendet werden. Dazu wird das Attribut mit <code>SVGplot</code>, gefolgt von einem Leerzeichen und der gewünschten Farbe/Stil befüllt. Es existieren jedoch auch noch weitere, an FTUI angepasste Styles, zu finden in der CSS-Datei <code>css/ftui_chart.css</code>. Um diese zu verwenden, wird das Attribut mit <code>ftui</code>, gefolgt von einem Leerzeichen und der gewünschten Farbe/Stil befüllt. Eigene Styles können zum Beispiel in der Datei <code>css/fhem-table-ui-user.css</code> definiert werden.
Mit dem Attribut '''data-style''' kann das Aussehen der Linien des jeweiligen Graphen verändert werden. Hierfür können die Standard-FHEM-Styles verwendet werden. Dazu wird das Attribut mit <code>SVGplot</code>, gefolgt von einem Leerzeichen und der gewünschten Farbe/Stil befüllt. Es existieren jedoch auch noch weitere, an FTUI angepasste Styles, zu finden in der CSS-Datei <code>css/ftui_chart.css</code>. Um diese zu verwenden, wird das Attribut mit <code>ftui</code>, gefolgt von einem Leerzeichen und der gewünschten Farbe/Stil befüllt. Eigene Styles können zum Beispiel in der Datei <code>css/fhem-table-ui-user.css</code> definiert werden.
Zeile 230: Zeile 299:


'''Hinweis:''' Der Stil ''sym'' ist speziell dafür geeignet, Symbole statt Linien zu zeichnen. Dazu kann beim Attribut '''data-ptype''' als Linienform ein beliebiges Font-Awsome-, oder Open Automation-Icon angegeben werden. Alle in diesem Abschnitt enthaltenen Abbildungen sind mit <code>data-ptype="lines"</code> entstanden.
'''Hinweis:''' Der Stil ''sym'' ist speziell dafür geeignet, Symbole statt Linien zu zeichnen. Dazu kann beim Attribut '''data-ptype''' als Linienform ein beliebiges Font-Awsome-, oder Open Automation-Icon angegeben werden. Alle in diesem Abschnitt enthaltenen Abbildungen sind mit <code>data-ptype="lines"</code> entstanden.
'''Übergänge mit datenabhängigen Grenzen:''' Plotstile (data-style) können auch direkt als Gradienten auf Basis von Plot-Datenwerten definiert werden. Dazu muss der Plotstil als Array angegeben werden. Der erste Wert des Arrays gibt an, ob nur die Linie gezeichnet werden soll (Zahl angeben, die die Dicke der Linie definiert) oder gefüllt ("fill" eintragen). Alle danach folgenden Array Elemente sind beliebig viele Stopp Punkte für die Farbübergänge, welche wiederum aus Arrays mit 3 Parametern bestehen. Für jeden Stopp Punkt werden der Datenwert, die Farbe und die Durchsichtigkeit gesetzt. Hierdurch lassen sich z.B. Einfärbungen setzen, die für Temperaturplots immer negative Werte blau einfärben und positive Werte rot. Zwischen den Stop Punkten wird die Farbe interpoliert, also ein weicher Übergang generiert. Will man harte Übergänge muss man Zwei Stopp Punkte mit unterschiedlichen Farbwerten aber dem gleichen Datenwert erzeugen.<br>
Beispiel 1 für einen weichen Gradienten, der bei 0 von blau nach rot übergeht, bei diesem Übergang durchsichtig ist und von dort nach negativen bzw. positiven Werden immer deckender wird:<br>
<code>data-style='["fill",["-20","#0000ff","0.7"],["0","#0000ff","0"],["0","#ff0000","0"],["302","#ff0000","0.7"]]'</code><br>
Beispiel 2 mit einem harten Übergang von blau nach rot bei 0:<br>
<code>data-style='["fill",["-20","#0000ff","0.7"],["0","#0000ff","0.7"],["0","#ff0000","0.7"],["50","#ff0000","0.7"]]'</code>
Es gibt auch die Möglichkeit den Bereich zwischen zwei Graphen einzufärben. Dazu muss ein Wert in Columnspec als Array angegeben werden. Ist dies der Fall, dann wird der zweite Graph umgekehrt an den ersten angehängt.<br>
Beispiel:
<syntaxhighlight lang="html">
data-columnspec='[
    "Func:logProxy_proplanta2Plot(\\x22AgroWeather\\x22,\\x22weatherIcon\\x22,$from,$to,12)",
    [
        "Func:logProxy_proplanta2Plot(\\x22AgroWeather\\x22,\\x22tempMax\\x22,$from,$to,12)",
        "Func:logProxy_proplanta2Plot(\\x22AgroWeather\\x22,\\x22tempMin\\x22,$from,$to,12)"
    ],
    "Func:logProxy_proplanta2Plot(\\x22AgroWeather\\x22,\\x22rain\\x22,$from,$to,0,\\x22day\\x22)"
]'
</syntaxhighlight>
[[Datei:FTUI Widget Chart DynamicStyles.png|thumb|none|500px|dynamischer Übergang]]


===Form der Linien===
===Form der Linien===
Das Attribut '''data-ptype''' beeinflusst die Form der Linien. Hier sind folgende Werte möglich:
Das Attribut '''data-ptype''' beeinflusst die Form der Linien. Hier sind folgende Werte möglich (in den Bildern sind zur Info zusätzlich auch immer points dargestellt):
 
<div><ul>
* <code>lines</code>
<li style="display: inline-block;"> [[File:Llines.png|thumb|none|350px|Darstellung in 2D: Stil "lines"]] </li>
* <code>steps</code>
<li style="display: inline-block;"> [[File:Points.png|thumb|none|350px|Darstellung in 2D: Stil "points"]] </li>
* <code>fsteps</code>
<li style="display: inline-block;"> [[File:Steps.png|thumb|none|350px|Darstellung in 2D: Stil "steps"]] </li>
* <code>histeps</code>
<li style="display: inline-block;"> [[File:Fsteps.png|thumb|none|350px|Darstellung in 2D: Stil "fsteps"]] </li>
* <code>bars</code>
<li style="display: inline-block;"> [[File:Histeps.png|thumb|none|350px|Darstellung in 2D: Stil "histeps"]] </li>
* <code>ibars</code>
<li style="display: inline-block;"> [[File:Bars.png|thumb|none|350px|Darstellung in 2D: Stil "bars"]] </li>
* <code>cubic</code>
<li style="display: inline-block;"> [[File:Ibars.png|thumb|none|350px|Darstellung in 2D: Stil "ibars"]] </li>
* <code>quadratic</code>
<li style="display: inline-block;"> [[File:Cubic.png|thumb|none|350px|Darstellung in 2D: Stil "cubic"]] </li>
* <code>quadraticSmooth</code>
<li style="display: inline-block;"> [[File:Quadratic.png|thumb|none|350px|Darstellung in 2D: Stil "quadratic"]] </li>
<li style="display: inline-block;"> [[File:QuadraticSmooth.png|thumb|none|350px|Darstellung in 2D: Stil "quadraticSmooth"]] </li>
</div>


Zusätzlich ist es möglich, Symbole anzeigen zu lassen. Unterstützt werden Font-Awesome ('fa-...'), Open Automation ('oa-...') und FHEM-Symbole ('fs-...')). Damit die Symbole korrekt angezeigt werden, muss  im Attribut '''data-style''' der Stil <code>sym</code> gewählt werden, da sonst nur Punkte, statt der Symbole gezeichnet werden.
Zusätzlich ist es möglich, Symbole anzeigen zu lassen. Unterstützt werden Font-Awesome ('fa-...'), Open Automation ('oa-...') und FHEM-Symbole ('fs-...')). Damit die Symbole korrekt angezeigt werden, muss  im Attribut '''data-style''' der Stil <code>sym</code> gewählt werden, da sonst nur Punkte, statt der Symbole gezeichnet werden.


<source lang="html">
<syntaxhighlight lang="html">
<div data-logdevice="FileLog_DG.wz.HZ.Heizungsventil"
<div data-type="chart"
data-device="DG.wz.HZ.Heizungsventil"
data-logdevice="FileLog_DG.wz.HZ.Heizungsventil"
...
...
data-style="ftui l1sym"
data-style="ftui l1sym"
data-ptype="fa-cog"
data-ptype="fa-cloud"
...>
...>
</div>
</div>
</source>
</syntaxhighlight>
<li style="display: inline-block;"> [[File:Ssymbols.png|thumb|none|500px|Darstellung in 2D: Stil "symbol fa-cloud"]] </li>


Die Größe der Symbole ist in der Datei <code>css/ftui_chart.css</code> auf 12px festgelegt. Dieser Wert kann in einer eigenen CSS-Datei durch Anpassung von <code>stroke-width</code> überschrieben werden.
Die Größe der Symbole ist in der Datei <code>css/ftui_chart.css</code> auf 12px festgelegt. Dieser Wert kann in einer eigenen CSS-Datei durch Anpassung von <code>stroke-width</code> überschrieben werden.


<source lang="css">
<syntaxhighlight lang="css">
.ftui.l0sym { stroke:#DDA400; stroke-width:12px; fill:none; }
.ftui.l0sym { stroke:#DDA400; stroke-width:12px; fill:none; }
.ftui.l1sym { stroke:#BBBBBB; stroke-width:12px; fill:none; }
.ftui.l1sym { stroke:#BBBBBB; stroke-width:12px; fill:none; }
Zeile 265: Zeile 358:
.ftui.l5sym { stroke:#33CCCC; stroke-width:12px; fill:none; }
.ftui.l5sym { stroke:#33CCCC; stroke-width:12px; fill:none; }
.ftui.l6sym { stroke:#3333CC; stroke-width:12px; fill:none; }
.ftui.l6sym { stroke:#3333CC; stroke-width:12px; fill:none; }
</source>
</syntaxhighlight>
 
'''data-ptype''' kann auch Inhalt im Format <code>'icon:1'</code> verarbeiten. Dann muss der zugehörige Wert in '''data-columnspec''' den Pfad zu einem Icon (z.B. für Wettervorhersagen) beinhalten. Der Y-Wert wird dann vom ersten Graphen übernommen. Weitere Ausführungen hierzu im Beispiel [[#Darstellung der Wetter Icons im Diagramm]].
<li style="display: inline-block;"> [[File:Wetterchart2.png|thumb|none|500px|Darstellung in 2D: Stil "Beispiel mit icons aus Readings"]] </li>
 
 
===Stapeln von Linien===
Über '''data-ptype''' kann zusätzlich festgelegt werden, ob Graphen übereinander gestapelt werden sollen. <code>data-ptype='lines:1'</code> bedeutet, dass der zugehörige Graph auf den Graph mit der Nummer 1 gestapelt werden soll. So etwas kann z.B. Sinn machen, wenn man den Stromverbrauch einzelner Devices darstellen und zusätzlich sehen will, wie hoch die Summe ist. Beispiel siehe unten.
 
[[Datei:FTUI Widget Chart Stacked.png]]
 
===Zeitstrahl / Start & Ende auf der X-Achse===
Die Attribute '''data-daysago_start''' und '''data-daysago_end''' dienen der Definition von Anfang und Ende der X-Achse. Im einfachsten Fall wird eine Anzahl an Tagen eingegeben, die sich auf das aktuelle Datum beziehen. Dabei gilt es zu beachten, dass es sich um ''vergangene Tage'' handelt. Das bedeutet, dass Tage in der Vergangenheit als positive Zahl angegeben werden, Tage in der Zukunft hingegen als negative Zahl. Es kann jeweils  auch ein fixes Datum (z.B. '2013-10-23') angegeben werden. Uhrzeitangaben werden nur berücksichtigt, wenn '''data-nofulldays='true' ''' verwendet wird.
 
'''Relative Zeitangabe in Stunden/Tagen/Wochen/Monaten/Jahren'''<br />
Zur Ausgabe einer Anzahl an zurückliegenden Stunden bis zum aktuellen Zeitpunkt wird als Startzeitpunkt die Anzahl der Stunden/Tage/Wochen/Monate/Jahre angegeben, die angezeigt werden sollen, gefolgt vom Kleinbuchstaben '''h''' für Stunden, '''d''' für Tage, '''w''' für Wochen, '''m''' für Monate, '''y''' für Jahre, . Als Endzeitpunkt wird '''now''' gewählt.<br />
Das nachfolgende Beispiel zeigt die Werte der vergangenen 3 Stunden an:
<syntaxhighlight lang="html">
data-nofulldays="true"
data-daysago_start="3h"
data-daysago_end="now"
</syntaxhighlight>
 
'''Fester Zeitbereich des heutigen Tages (Stunden/Tage/Wochen/Monate/Jahre)'''<br />
Um ein festes Stunden/Tages/Wochen/Monats/Jahresfenster anzuzeigen, werden die absoluten Stunden/Tages/Wochen/Monats/Jahreszahlen mit negativem Vorzeichen, gefolgt vom Großbuchstaben '''H''' (entsprechend D/W/M/Y für Tage/Wochen/Monate/Jahre) angegeben. Wird '''data-daysago_start''' als positiver Wert angegeben, wird die Anzahl der Stunden/Tage/Wochen/Monate/Jahre von heute 0:00 Uhr subtrahiert (siehe Rechenweg weiter unten).<br />
Das Beispiel zeigt den Zeitbereich von heute 5:00 Uhr bis heute 22:00 Uhr:
<syntaxhighlight lang="html">
data-nofulldays="true"
data-daysago_start="-5H"
data-daysago_end="-22H"
</syntaxhighlight>
 
'''Fester Zeitbereich Tage-übergreifend'''<br />
Die Zeit in Tagen kann als Gleitkommazahl angegeben werden. Damit ist es möglich, Tage und Uhrzeiten zu kombinieren. Die Werte sind dann als Teil eines ganzen Tages, bezogen auf heute 0:00 Uhr zu errechnen und mit <code>.</code> als Teiler anzugeben.<br />
Das nachfolgende Beispiel zeigt einen Zeitbereich von '''gestern 15:00 Uhr''' bis '''morgen 3:00 Uhr'''.
<syntaxhighlight lang="html">
data-nofulldays="true"
data-daysago_start="0.375"
data-daysago_end="-1.125"
</syntaxhighlight>
 
Für die nachfolgenden Rechenwege sind die Einheiten nur zur Verdeutlichung angegeben. Die Einheiten werden im Attribut nicht angegeben.
 
Der Wert für '''GESTERN''' wird wie folgt ermittelt:<br />
Ausgangspunkt ist heute 0:00 Uhr, gestern 15:00 Uhr liegt also 9 Stunden davor. Diese 9 Stunden sind ein <code>9/24 Tag</code> und errechnet sich so:
<pre>
1d / 24h = 0.0416666...d/h
0.0416d/h * 9h = 0.375d
</pre>
 
Der Wert für '''MORGEN''' wird wie folgt ermittelt:<br />
Ausgangspunkt ist wieder heute 0:00 Uhr, morgen 3:00 Uhr liegt dann 27 Stunden dahinter. Der Einfachheit halber werden hier nur die 3 Stunden errechnet und dann ein ganzer Tag addiert:
<pre>
1d / 24h = 0.0416666...d/h
0.0416d/h * 3h = 0.125d


'''data-ptype''' kann auch Inhalt im Format <code>'icon:1'</code> verarbeiten. Dann muss der zugehörige Wert in '''data-columnspec''' den Pfad zu einem Icon (z.B. für Wettervorhersagen) beinhalten. Der Y-Wert wird dann vom ersten Graphen übernommen.
0.125d + 1d = 1.125d
</pre>
Da das Attribut Tage in der Vergangenheit erwartet, muss für einen Wert in der Zukunft wieder eine negative Zahl angegeben werden.


===Zeitformat der X-Achse===
===Zeitformat der X-Achse===
Zeile 289: Zeile 438:


===Fadenkreuz-Cursor===
===Fadenkreuz-Cursor===
Der Fadenkreuz-Cursor zeigt die Momentanwerte, indem man ihn über die Graphen bewegt. In Desktop-Browsern reicht einfaches Bewegen des Maus. Unter iOS und Android kann der Cursor wird der Cursor durch einfaches Tippen auf die neue Position bewegt.
Der Fadenkreuz-Cursor zeigt die Momentanwerte, indem man ihn über die Graphen bewegt. In Desktop-Browsern reicht einfaches Bewegen der Maus. Unter iOS und Android wird der Cursor durch einfaches Tippen auf die neue Position bewegt.


Mit dem Attribut '''data-cursorgroup''' können Graphen gruppiert werden. Am Cursor werden dann die Momentanwerte aller Graphen gleichzeitig angezeigt, die die selbe Zahl besitzen, sobald man die Maus über einen aus der Gruppe bewegt.
Mit dem Attribut '''data-cursorgroup''' können Graphen gruppiert werden. Am Cursor werden dann die Momentanwerte aller Graphen gleichzeitig angezeigt, die die selbe Zahl besitzen, sobald man die Maus über einen aus der Gruppe bewegt.


===Legende===
===Legende===
Mit dem Attribut '''data-legendpos''' kann die Position der Legende innerhalb des Diagramms festgelegt werden. Die Position wird mit einem Array, bestehend aus zwei Werten im Format <code>'["<horizontal>","<vertikal>"]'</code> angegeben. Für die horizontale Positionierung sind <code>'left'</code> und <code>'right'</code>, die vertikale Positionierung <code>'top'</code> und <code>'bottom'</code> erlaubt. Alternativ können auch Zahlen verwendet werden, die die Position in Prozent angeben. In Desktop-Browsern kann die Legende auch an eine andere Position verschoben werden. Das funktioniert jedoch nicht unter iOS und Android.
Mit dem Attribut '''data-legendpos''' kann die Position der Legende innerhalb des Diagramms festgelegt werden. Die Position wird mit einem Array, bestehend aus zwei Werten im Format <code>'["<horizontal>","<vertikal>"]'</code> angegeben. Für die horizontale Positionierung sind <code>'left'</code>, <code>'right'</code>, <code>'before'</code>, und <code>'behind'</code>, die vertikale Positionierung <code>'top'</code>, <code>'bottom'</code>, <code>'above'</code>, <code>'below'</code> erlaubt (der Unterschied zwischen <code>'left'</code> und <code>'before'</code> liegt darin, dass im zweiten Fall die Legende nicht in den Zeichenbereich gesetzt wird sondern vor das ganze Chart (entsprechend für <code>'after'</code>, <code>'above'</code> und <code>'below'</code>). Alternativ können auch Zahlen verwendet werden, die die Position in Prozent angeben. Durch verschieben mit der Maus oder durch verschieben mit dem Finger oder Stift auf Touch Devices kann die Legende auch an eine andere Position verschoben werden.


Wenn die Legende eingeblendet ist, kann mittels Klick auf einen Legendeneintrag der zugehörige Graph ein- und ausgeblendet werden.
Wenn die Legende eingeblendet ist, kann mittels Klick auf einen Legendeneintrag der zugehörige Graph ein- und ausgeblendet werden.
Zeile 302: Zeile 451:


Beispiel: <code>data-ddd='["40","60","0"]'</code>.  
Beispiel: <code>data-ddd='["40","60","0"]'</code>.  
Wenn der 3D Modus aktiv ist ('''data-ddd''' gesetzt) sind 2 zusätzliche Parameter verfügbar um das Aussehen der Graphen zu beeinflussen. '''data-dddspace''' gibt an, wie viele pixel der Raum zwischen den einzelnen in z-Richtung hintereinander angeordneten Graphen betragen soll.
'''data-dddwidth''' legt fest, wie viele pixel die einzelnen Graphen tief (oder dick) sein sollen.


Wenn das Array angegeben wird, erscheinen zwei zusätzliche Buttons im Diagramm, mit denen die Drehung in X- und Y-Richtung verändert werden kann.
Wenn das Array angegeben wird, erscheinen zwei zusätzliche Buttons im Diagramm, mit denen die Drehung in X- und Y-Richtung verändert werden kann.
Zeile 319: Zeile 471:


Durch Einsetzen einer anderen Zahl statt '1' können auch die Werte der anderen Graphen angezeigt werden. Das Weglassen der Zahl bewirkt, dass der jeweils zutreffende Wert automatisch ermittelt wird. Bedeutet: <code>max</code> führt dazu, dass der höchste Wert aller angezeigter Graphen verwendet wird.
Durch Einsetzen einer anderen Zahl statt '1' können auch die Werte der anderen Graphen angezeigt werden. Das Weglassen der Zahl bewirkt, dass der jeweils zutreffende Wert automatisch ermittelt wird. Bedeutet: <code>max</code> führt dazu, dass der höchste Wert aller angezeigter Graphen verwendet wird.
Zusätzlich ist es möglich durch "$eval(<regexp>)" regular Expressions auszuwerten (also z.B. Berechnungen durchzuführen). In <regexp> können auch "$data()" vorkommen.


Beispiel: <code>data-title="Min: $data{mindate4}, Max: $data{maxdate4}, Last: $data{currdate4}"</code>
Beispiel: <code>data-title="Klima Wohnzimmer Average: $eval(parseInt($data{avg1}*10)/10)°C / Max: $eval(parseInt($data{max1}*10)/10)°C"</code>


===Buttons im Diagramm===
===Buttons im Diagramm===
Es gibt mehrere Buttons, mit denen sich die Anzeige des Diagramms verändern lässt. <code><-</code> und <code>-></code> bewegen die Graphen nach links und rechts. <code>+</code> und <code>-</code> zoomen die Anzeige. <code>legend</code> und <code>cursor</code> schalten die zugehörigen Anzeigen ein und aus.
Es gibt mehrere Buttons, mit denen sich die Anzeige des Diagramms verändern lässt. <code><-</code> und <code>-></code> bewegen die Graphen nach links und rechts. <code>+</code> und <code>-</code> zoomen die Anzeige. <code>legend</code> und <code>cursor</code> schalten die zugehörigen Anzeigen ein und aus. Falls der 3D Modus eingeschaltet ist, gibt es Buttons zum Drehen der Darstellung um die X- und Y-Achse. Falls <code>data-timeranges</code> gesetzt ist, wird ein Pulldown Menü dargestellt, welches die Auswahl von dort definierten Zeiträumen für die X-Achse erlaubt.


==Beispiele==
==Beispiele==
Zeile 331: Zeile 484:
[[File:Chart_tabletUI.png]]
[[File:Chart_tabletUI.png]]


<source lang="html">
<syntaxhighlight lang="html">
<div data-type="chart"
<div data-type="chart"
data-logdevice='["Log.Garden","Log.Garden","Log.Garden","Log.Predicted"]'
data-logdevice='["Log.Garden","Log.Garden","Log.Garden","Log.Predicted"]'
Zeile 356: Zeile 509:
data-xticks="auto">
data-xticks="auto">
</div>
</div>
</source>
</syntaxhighlight>


===7-Tage-Wettervorhersage mit Proplanta===
===7-Tage-Wettervorhersage mit Proplanta===
Zeile 369: Zeile 522:


'''2.''' In der Datei <code>99_myUtils.pm</code> muss folgende Routine hinzugefügt werden, die die Daten bereitstellt:
'''2.''' In der Datei <code>99_myUtils.pm</code> muss folgende Routine hinzugefügt werden, die die Daten bereitstellt:
<source lang="perl">
<syntaxhighlight lang="perl">
#---------------------------------------
#---------------------------------------
# Proplanta LogProxy-Funktion
# Proplanta LogProxy-Funktion
Zeile 436: Zeile 589:
# add first value at start of plot range
# add first value at start of plot range
if( !$ret && $prev_value ) {
if( !$ret && $prev_value ) {
$min = $prev_value if( $prev_value < $min );
  $min = $prev_value if( (looks_like_number($prev_value) && ($prev_value < $min)) || ($prev_value lt $min) );
$max = $prev_value if( $prev_value > $max );
  $max = $prev_value if( (looks_like_number($prev_value) && ($prev_value > $max)) || ($prev_value gt $max) );
$ret .= "$from $prev_value\n";
  $ret .= "$from $prev_value\n";
}
}


Zeile 444: Zeile 597:
last if($sec > $tosec);
last if($sec > $tosec);


$min = $value if( $value < $min );
$min = $value if( (looks_like_number($value) && ($value < $min )) || ($value lt $min) );
$max = $value if( $value > $max );
$max = $value if( (looks_like_number($value) && ($value > $max )) || ($value gt $max) );


# add actual controll point
# add actual controll point
Zeile 467: Zeile 620:
return ($ret,$min,$max,$prev_value);
return ($ret,$min,$max,$prev_value);
}
}
</source>
</syntaxhighlight>


Anschließend können die Daten im Chart-Widget angezeigt werden. Der Device-Name von Proplanta heißt hier im Beispiel <code>AU.xx.WE.Proplanta</code>.
Anschließend können die Daten im Chart-Widget angezeigt werden. Der Device-Name von Proplanta heißt hier im Beispiel <code>AU.xx.WE.Proplanta</code>.


<source lang="html">
<syntaxhighlight lang="html">
<div data-type="chart"
<div data-type="chart"
data-device="AU.xx.WE.Proplanta"
data-logdevice='[
data-logdevice='[
"myLogProxy",
"myLogProxy",
Zeile 520: Zeile 674:
class="nobuttons fullsize">
class="nobuttons fullsize">
</div>
</div>
</source>
</syntaxhighlight>


'''Hilfreiche Links und Quellen zu diesem Beispiel:'''
'''Hilfreiche Links und Quellen zu diesem Beispiel:'''
*[[LogProxy|LogProxy im FHEM-Wiki]]
*[[LogProxy|LogProxy im FHEM-Wiki]]
*[https://forum.fhem.de/index.php/topic,22967.msg246973.html#msg246973 Stundengenaue Wettervorhersage (#1) im FHEM-Forum]
*{{Link2Forum|Topic=22967|Message=246973|LinkText=Stundengenaue Wettervorhersage (#1) im FHEM-Forum}}
*[https://forum.fhem.de/index.php/topic,22967.msg334713.html#msg334713 Stundengenaue Wettervorhersage (#2) im FHEM-Forum]
*{{Link2Forum|Topic=22967|Message=334713|LinkText=Stundengenaue Wettervorhersage (#2) im FHEM-Forum}}
 
===Darstellung der Wetter Icons im Diagramm===
 
[[File:Wetterchart2.png]]
 
Wie oben bereits beschrieben, gibt es beim Chart grundsätzlich die Möglichkeit, Icons, welche in Form von URLs in den Logs abgelegt sind oder welche per logProxy generiert werden, darzustellen. Die Icons werden auf genau dem gleichen Weg von FHEM gelesen, wie alle anderen Datenpunkte. Im Folgenden wird ein Beispiel gezeigt, mit dem die im Proplanta Modul als Readings abgelegten Icons per logProxy Funktion gelesen und in ein Chart eingebaut werden könnnen.
Da es beim Proplanta Modul für die ersten 7 Tage nicht das Reading <code>fc#_weatherIcon</code> gibt, sondern mehrere Readings für unterschiedliche Tageszeiten wogegen für die zweiten 7 Tage ausschließlich das Reading <code>fc#_weatherIcon</code> vorhanden ist, sollte per <code>attr device userReading</code> mit folgendem Eintrag dafür gesorgt werden, dass für alle Tage ein Reading <code>fc#_weatherIcon</code> vorhanden ist (alternativ könnten auch 2 Graphen gezeichnet werden, wobei der erste dann nur die ersten 7 Tage enthält und der zweite die letzen 7 Tage, will man nur die ersten 7 Tage darstellen braucht man das userReading nicht unbedingt).
<syntaxhighlight lang="perl">
fc0_weatherIcon {ReadingsVal("AU.xx.WE.Proplanta","fc0_weatherDayIcon","");},
fc1_weatherIcon {ReadingsVal("AU.xx.WE.Proplanta","fc1_weatherDayIcon","");},
fc2_weatherIcon {ReadingsVal("AU.xx.WE.Proplanta","fc2_weatherDayIcon","");},
fc3_weatherIcon {ReadingsVal("AU.xx.WE.Proplanta","fc3_weatherDayIcon","");},
fc4_weatherIcon {ReadingsVal("AU.xx.WE.Proplanta","fc4_weatherDayIcon","");},
fc5_weatherIcon {ReadingsVal("AU.xx.WE.Proplanta","fc5_weatherDayIcon","");},
fc6_weatherIcon {ReadingsVal("AU.xx.WE.Proplanta","fc6_weatherDayIcon","");}
</syntaxhighlight>
Um die Icons darzustellen muss ein zusätzlicher Graph definiert werden. Dieser nutzt neben der Columnspec, die die URLs abruft den Parameter <code>data-ptype="icons:#"</code> (# ist eine Zahl und steht für die Nummer, beginnend bei 0 des Graphen, welcher für die y-Position der Icons verwendet werden soll) und den Stil <code>sym</code>. Der Wert für die Symbolgröße sollte z.B. durch eine zusätzliche Definition im File fhem-tablet-ui-user.css in der Form:
<syntaxhighlight lang="css">
/* icon lines */
.ftui.l99icon { stroke:#DDA400; stroke-width:48px; fill:none; }
</syntaxhighlight>
angepasst werden.
 
Im folgenden ein Beispiel, welches eine Linie für die Maximale Tagestemperatur zeichnet und auf dieser Linie die Wetter Icons darstellt.
<syntaxhighlight lang="html">
<div data-type="chart"
data-device="AU.xx.WE.Proplanta"
data-logdevice='[
"myLogProxy",
"myLogProxy"
]'
data-columnspec='[
"Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22weatherIcon\\x22,$from,$to,12,\\x22day\\x22)",
"Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22tempMax\\x22,$from,$to,12,\\x22day\\x22)"
]'
data-style='[
"ftui l99icon",
"ftui l1fill"
]'
data-ptype='[
"icons:1",
"quadraticSmooth"
]'
data-uaxis='[
"primary",
"primary"
]'
data-legend='[
"Wetterbedingung",
"Max. Temperature"
]'
data-yunit="°C"
data-ytext="Temperature (°C)"
data-timeformat="ee\LF\dd.MM"
data-minvalue="auto"
data-maxvalue="auto"
data-minvalue_sec="auto"
data-maxvalue_sec="auto"
data-daysago_start="-1w"
data-y_margin="20"
data-daysago_end="-3w"
data-xticks="1440"
data-yticks="auto"
data-title="14-Tage-Wettervorhersage"
data-showlegend="true"
class="nobuttons fullsize">
</div>
</syntaxhighlight>
 
===Kuchendiagramme===
In folgendem Beispiel wird gezeigt, wie man ein "Kuchendiagramm" darstellen kann.
 
[[File:PieChart.png]]
 
Ähnlich wie bei den Beispielen für die Wetter Darstellungen wird hierzu auch wieder logProxy benötigt. Zunächst muss die folgende zusätzliche Funktion in <code>99_myUtils.pm</code> einfügen.
<syntaxhighlight lang="perl">
#---------------------------------------
# Funktion zum Erzeugen der Inputs für Kuchendiagramme
#---------------------------------------
sub logProxy_values2PieChart($$$$;$$) {
my ($device, $reading, $angle_start, $angle_dif, $inner_rad, $show_text) = @_;
Log3 undef, 1, "$device, $reading, $angle_start, $angle_dif, $inner_rad, $show_text\n";
 
use constant PI => 4 * atan2(1,1);
my $value=ReadingsVal($device,$reading,0);
 
my $angle_delta = $value/100*360;
$angle_start = $angle_start/100*360;
my $rad=10;
my $irad=0;
if ($inner_rad) {
$irad = $rad*$inner_rad;
}
my $angle=$angle_start/360*2.0*PI;
my $x=$irad*sin($angle);
my $y=$irad*cos($angle);
my $ret .= ";p ".$x." ".$y."\n"; # add segment at angle $angle
for (my $i=$angle_start; $i<=$angle_start+$angle_delta; $i+=$angle_dif) {
$angle = $i/360*2.0*PI;
$x = $rad*sin($angle);
$y = $rad*cos($angle);
$ret .= ";p ".$x." ".$y."\n"; # add segment at angle $angle
}
$angle = ($angle_start+$angle_delta)/360*2.0*PI; # add last segment
$ret .= ";p ".$rad*sin($angle)." ".$rad*cos($angle)."\n";
 
if ($inner_rad) {
for (my $i=$angle_start; $i<$angle_start+$angle_delta; $i+=$angle_dif) {
$angle = ($angle_start+$angle_start+$angle_delta-$i)/360*2.0*PI;
$x = $irad*sin($angle);
$y = $irad*cos($angle);
$ret .= ";p ".$x." ".$y."\n"; # add segment at angle $angle
}
}
 
$angle = ($angle_start)/360*2.0*PI; # add last segment
$ret .= ";p ".$irad*sin($angle)." ".$irad*cos($angle)."\n";
 
if ($show_text) { # show text values
$x = ($rad+$irad)/2*sin((2*$angle_start+$angle_delta)/2/360*2.0*PI);
$y = ($rad+$irad)/2*cos((2*$angle_start+$angle_delta)/2/360*2.0*PI);
 
$ret .= ";t ".$x." ".$y." middle ".$show_text.":".$value."%\n";
}
 
return($ret);
}
</syntaxhighlight>
In FHEM braucht man Readings, welche eine Zahl enthalten, die als Prozentwert interpretiert wird. Für jeden Prozentwert (also für jedes Reading) generiert die o.a. Funktion nun den Chart Input für ein Kuchenstück und liefert diesen als Antwort auf das GET, welches das Chart Widget auslöst. Dazu braucht die Funktion folgende Parameter: (Name des FHEM Devices, Name des Readings, Start Winkel des Kuchenstücks (Mathematisch gegen den Uhrzeigersinn in Grad), Delta Winkel zum Zeichnen (legt fest in welchen Schritten der Teilkreis des Kuchenstücks gezeichnet wird), Skalierungsfaktor für inneren Ring wenn ein Ring gezeichtnet werden soll (0 bedeutet komplette Kuchenstücke), optionaler Text der ins Kuchenstück vor die Prozentzahl geschrieben wird).
Im Folgenden eine Beispielkonfiguration für die Darstellung als Kuchendiagramm, die Readings heißen hier dPer1 bis dPer4. Der Startwinkel wird duch Aufsummierung der jeweils vorher schon gezeichneten Kuchenstücke gebildet, dadurch entstehen aneinander hängende Stücke.
<syntaxhighlight lang="html">
[[Datei:[[Datei:Beispiel.jpg]]]]<div class="normal noaxes nobuttons"
        data-type="chart"
        data-logdevice='["lp"]'
data-logfile="CURRENT"
        data-columnspec='[
"Func:logProxy_values2PieChart(\"dPer1\",\"state\",ReadingsVal(\"dPer4\",\"state\",0)+ReadingsVal(\"dPer3\",\"state\",0),5,0,\"first\")",
"Func:logProxy_values2PieChart(\"dPer2\",\"state\",ReadingsVal(\"dPer4\",\"state\",0)+ReadingsVal(\"dPer3\",\"state\",0)+ReadingsVal(\"dPer1\",\"state\",0),5,0,\"second\")",
"Func:logProxy_values2PieChart(\"dPer3\",\"state\",ReadingsVal(\"dPer4\",\"state\",0),5,0,\"third\")",
"Func:logProxy_values2PieChart(\"dPer4\",\"state\",0,5,0,\"fourth\")"
]'
        data-style='["ftui l0fill","ftui l1fill","ftui l2fill","ftui l3fill"]'
        data-ptype='["lines"]'
        data-uaxis='["primary"]'
        data-legend='["First","Second","Third","Fourth"]'
data-legendpos='["left","top"]'
        data-yunit=""
        data-height="300"
        data-width="300"
data-ddd='["-40","0","0"]'
data-dddspace='["-10"]'
data-dddwidth='["10"]'
data-showlegend="true"
data-legend_horiz="true"
        data-xticks="auto">
</div>
</syntaxhighlight>


===Fensterstatus offen/geschlossen===
===Fensterstatus offen/geschlossen===
Dieses Beispiel zeigt, wie ein Fensterkontakt, dessen Reading die Werte <code>closed</code> und <code>open</code> einnimmt, als Graph gezeichnet werden kann. Technisch gesehen werden hier die Werte <code>0</code> und <code>1</code> gezeichnet, indem über das Attribut '''data-columnspec''' dem Zustand <code>open</code> der Wert <code>1</code> und allen anderen Zuständen der Wert <code>0</code> zugeordnet wird. Über das Attribut '''data-yticks''' wird die Beschriftung an der Y-Achse (<code>0</code> und <code>1</code>) gegen einen frei definierbaren Text ausgetauscht.
Dieses Beispiel zeigt, wie ein Fensterkontakt, dessen Reading die Werte <code>closed</code> und <code>open</code> einnimmt, als Graph gezeichnet werden kann. Technisch gesehen werden hier die Werte <code>0</code> und <code>1</code> gezeichnet, indem über das Attribut '''data-columnspec''' dem Zustand <code>open</code> der Wert <code>1</code> und allen anderen Zuständen der Wert <code>0</code> zugeordnet wird. Über das Attribut '''data-yticks''' wird die Beschriftung an der Y-Achse (<code>0</code> und <code>1</code>) gegen einen frei definierbaren Text ausgetauscht.


<source lang="html">
<syntaxhighlight lang="html">
<div data-type="chart"
<div data-type="chart"
data-device="wz_fensterstatus"
data-logdevice='["myDbLog"]'
data-logdevice='["myDbLog"]'
data-logfile='["HISTORY"]'
data-logfile='["HISTORY"]'
Zeile 547: Zeile 863:
data-scrollgroup="1">
data-scrollgroup="1">
</div>
</div>
</source>
</syntaxhighlight>
 
'''Hinweis:''' Das Beispiel funktioniert nur mit DbLog. Falls Logfiles verwendet werden muss statt '$val' '$fld[''num'']' verwendet werden. Hierbei steht ''num'' für die Spalte (beginnend bei 0) in der die Daten stehen.


==Links==
{{Link2Forum|Topic= 48450 |Message=401006|LinkText=Thread im FHEM-Forum}}


[[Kategorie:FHEM Tablet UI]]
[[Kategorie:FHEM Tablet UI V2|Chart]]

Aktuelle Version vom 2. August 2024, 15:37 Uhr

Das Chart Widget ist ein Widget für FHEM Tablet UI V2, mit dem sich verschiedenste Diagramme darstellen lassen. Die Aneinanderreihung mehrerer Werte eines Device-Readings zu einem zeitlichen Verlauf wird dabei als Graph bezeichnet.

Es können beliebige Werte dargestellt und entsprechend der Sinnhaftigkeit, oder persönlichem Geschmack, formatiert werden. Farbe und Form der Linien sind je Graph einstellbar, auch wenn mehrere gleichzeitig in einem Diagramm angezeigt werden.

Jedes Diagramm kann zwei Y-Achsen besitzen. Die primäre Y-Achse (primary) wird auf der linken Seite angezeigt, die sekundäre Y-Achse (secondary) auf der rechten Seite. Beide Achsen können unterschiedlich formatiert werden.

Attribute

Attribut Beschreibung Standard-Wert Beispiel
data-device Name des FHEM-Device, das die Aktualisierung des Charts triggert data-device="WohnzimmerHeizung"
data-get Reading, das das Update des Diagramms triggert 'STATE'
data-logdevice Name des Log-Device, das dargestellt werden soll, oder ein Array, um mehrere Werte in einem Diagramm darzustellen data-logdevice="FileLog_WohnzimmerHeizung"
data-logfile Name des Log-Files, aus dem die Daten entnommen werden sollen (oder Array) '-' = aktuelle Datei data-logfile="WohnzimmerHeizung-2015.log"
Beachte: Der Wert "CURRENT" ermöglicht die Navigation auch zu älterne Logfiles (Jahreswechsel)
data-columnspec Ermittelt den Wert aus dem Log-File, der angezeigt werden soll (oder Array) data-columnspec="4:meas.*"
data-style Stil, wie die Graph-Linien dargestellt werden sollen (z.B. 'SVGplot l0' oder 'ftui l0dash'), oder ein Array, wenn mehrere Linien unterschiedlich dargestellt werden sollen (siehe Hinweise)
data-ptype Form, wie die Graphen dargestellt werden sollen (z.B. 'lines', 'cubic' oder 'fa-cog'), oder ein Array (siehe Hinweise) 'lines'
data-uaxis Name der Achse, die verwendet werden soll ('primary' = links, oder 'secondary' = rechts), oder ein Array 'primary'
data-legend Bezeichnung des Graphen (wird in Legende und am Cursor angezeigt), oder ein Array
data-minvalue Minimaler Wert, der auf der linken Y-Achse ('primary') angezeigt werden soll. 'auto' = automatische Berechnung '10'
data-maxvalue Maximaler Wert, der auf der linken Y-Achse ('primary') angezeigt werden soll. 'auto' = automatische Berechnung '30'
data-minvalue_sec Minimaler Wert, der auf der rechten Y-Achse ('secondary') angezeigt werden soll. 'auto' = automatische Berechnung 'auto'
data-maxvalue_sec Maximaler Wert, der auf der rechten Y-Achse ('secondary') angezeigt werden soll. 'auto' = automatische Berechnung 'auto'
data-xticks Abstand zwischen den vertikalen Hilfslinien (bezogen auf die X-Achse) in Minuten. 'auto' = automatische Berechnung 'auto'
data-yticks Abstand zwischen den horizontalen Hilfslinien (bezogen auf die linke Y-Achse). Kann auch ein Array mit Werte-Paaren enthalten, um die Linien mit Text zu beschriften. 'auto' data-yticks='[[0,"open"],[1,"closed"]]'
data-yticks_format Dient zur Formatierung der Ticks der Y-Achse. Die Formatierung geschieht über Platzhalter, Trenner und einen beliebigen durch ' ' getrennten Text. Als Platzhalter dient ein oder mehrere '#', als Trenner können '.', ',' und ':' verwendet werden. Ist ein Trenner enthalten (z.B. '#.##') dann bedeutet das in dem Beispiel, dass der Ytick mit 2 Nachkommastellen versehen wird und vorne Platz für eine Stelle vor dem Komma vorgehalten wird (führende Nullen werden nicht dargestellt, aber de Platz wird reserviert so dass das ganze rechtsbündig immer passt). Ist kein Trenner vorhanden, dann wird der Ytick auf die Summe der Platzhalter mit einer festen Gesamtbreite gesetzt (#### würde also bedeuten, dass immer 4 Stellen (ohne Trenner) verwendet werden. aus 0.4 würde 0.400 aus 10.437 würde 10.44). Als Trenner kann man z.B. für Zeiten auch einen ':' verwenden und dadurch auch so etwas wie "12:00 Uhr" realisieren (in dem Beispiel wäre data-yticks_format="##:## Uhr" und kein data-yunit oder data-yticks="##:##" und data-yunit="Uhr"). data-yticks_format="#.##"
data-yticks_sec Abstand zwischen den horizontalen Hilfslinien (bezogen auf die rechte Y-Achse). Kann auch ein Array mit Werte-Paaren enthalten, um die Linien mit Text zu beschriften. 'auto' data-yticks='[[0,"open"],[1,"closed"]]'
data-yticks_format_sec Dient zur Formatierung der Ticks der Y-Achse. Die Formatierung geschieht über Platzhalter, Trenner und einen beliebigen durch ' ' getrennten Text. Als Platzhalter dient ein oder mehrere '#', als Trenner können '.', ',' und ':' verwendet werden. Ist ein Trenner enthalten (z.B. '#.##') dann bedeutet das in dem Beispiel, dass der Ytick mit 2 Nachkommastellen versehen wird und vorne Platz für eine Stelle vor dem Komma vorgehalten wird (führende Nullen werden nicht dargestellt, aber de Platz wird reserviert so dass das ganze rechtsbündig immer passt). Ist kein Trenner vorhanden, dann wird der Ytick auf die Summe der Platzhalter mit einer festen Gesamtbreite gesetzt (#### würde also bedeuten, dass immer 4 Stellen (ohne Trenner) verwendet werden. aus 0.4 würde 0.400 aus 10.437 würde 10.44). Als Trenner kann man z.B. für Zeiten auch einen ':' verwenden und dadurch auch so etwas wie "12:00 Uhr" realisieren (in dem Beispiel wäre data-yticks_format="##:## Uhr" und kein data-yunit oder data-yticks="##:##" und data-yunit="Uhr"). data-yticks_format_sec="#.##"
data-yticks_prio Legt fest, ob die horizontalen Hilfslinien der linken (primary) oder der rechten (secondary) Y-Achse zugeordnet werden sollen data-yticks_prio='secondary'
data-ytype Legt fest, ob die primäre y Achse logarithmisch sein soll (wert "log") data-ytype="log"
data-ytype_sec Legt fest, ob die sekundäre y Achse logarithmisch sein soll (wert "log") data-ytype_sec="log"
data-margin Abstand zwischen Buttons und Chart (Einheit Pixel). "0" data-margin="10"
data-y_margin Gibt die Möglichkeit, Abstände zwischen den Graphen und dem oberen Rand des Plots zu definieren (Einheit Pixel). Falls der Wert skalar ist, werden oben und unten die gleichen Abstände eingehalten. Falls ein 2D Array angegeben wird, können die Werte unten (erster Wert im Array) und oben (zweiter Wert im Array) getrennt festgelegt werden "0" data-y_margin='["10","20"]'
data-y_margin_sec Gibt die Möglichkeit, Abstände zwischen den Graphen und dem oberen Rand des Plots zu definieren (Einheit Pixel). Falls der Wert skalar ist, werden oben und unten die gleichen Abstände eingehalten. Falls ein 2D Array angegeben wird, können die Werte unten (erster Wert im Array) und oben (zweiter Wert im Array) getrennt festgelegt werden "0" data-y_margin='["10","20"]'
data-daysago_start Anzahl der vergangenen Tage, wo das Diagramm beginnen soll. '0' = Beginn heute 0:00 Uhr. (siehe Hinweise) '0'
data-daysago_end Anzahl der vergangenen Tage, wo das Diagramm enden soll. '-1' = Ende heute 24:00 Uhr. (siehe Hinweise) '-1'
data-xticks_round Wenn vorhanden und entweder 'h', 'd', 'w', wird auf Stunde, Tag oder Woche bei den xticks gerundet (also die Tickmarks und die Gridlines bei den entsprechend gerundeten Zeiten gesetzt). Es kann auch 'auto' angegeben werden, um eine autmoatische Rundung durchzuführen
data-nofulldays Aktiviert/deaktiviert die Rundung der X-Achse auf ganze Tage. Binärwert ('true' oder 'false') 'false'
data-timeformat Zeitformat für die Anzeige an der X-Achse (siehe Hinweise)
data-timeranges Hierdurch können vordefinierte Zeiträume für die X-Achse festgelegt werden, die dann durch eine pulldown menu (neuer Button oben neben dem "-" Button) direkt ausgewählt werden können. Der Parameter ist ein Array aus Array Einträgen, welche jeweils [<Name>,<daysago_start>,<daysago_end>] enthalten) data-timeranges='[

["Actual Year","0Y","-1Y"],
["Last Year","1Y","0Y"],
["Actual Month","0M","-1M"],
["Last Month","1M","0M"],
["Actual Week","0W","-1W"],
["Last Week","1W","0W"],
["Today","0D","-1D"],
["Yesterday","1D","0D"]
]'

data-ytext Text, der neben der linken Y-Achse angezeigt wird
data-ytext_sec Text, der neben der rechten Y-Achse angezeigt wird
data-yunit Einheit, die an der linken Y-Achse angezeigt wird
data-yunit_sec Einheit, die an der rechten Y-Achse angezeigt wird
data-show_both_axes Legt fest ob beide Y-Achsen Linien gezeichnet werden sollen false
data-crosshair Aktiviert/deaktiviert den Fadenkreuz-Cursor. Binärwert ('true' oder 'false') 'false'
data-cursorgroup Zahl zur Gruppierung der Werte am Fadenkreuz-Cursor (Hinweise)
data-scrollgroup Zahl zur Gruppierung der Graphen beim Bewegen und Zoomen. Alle Linien mit der selben Zahl werden miteinander gekoppelt und bewegen sich gemeinsam.
data-showlegend Aktiviert/deaktiviert die Anzeige der Legene. Binärwert ('true' oder 'false') 'false'
data-legendpos Array von zwei Werten, die die horizontale und vertikale Position der Legende festlegen (Hinweise) '["right","top"]'
data-legend_horiz legt fest, dass die Legendeneinträge horizontal angeordnet sind (anstatt vertikal wie im default Fall) false data-legend_horiz="true"
data-width Breite des Diagramms (in % oder px)
data-height Höhe des Diagramms (in % oder px)
data-graphsshown Aktiviert/deaktiviert die initiale Anzeige von Graphen. Binärwert ('true' oder 'false'). Array, wenn mehrere Linien angezeigt werden sollen. data-graphsshown='[true,false,true]'
data-ddd Einstellung für die 3D-Drehung (Hinweise) data-ddd='["40","60","0"]'
data-dddspace Abstand zwischen zwei Graphen, wenn die 3D-Anzeige aktiviert wurde (px) '15'
data-dddwidth Breite, bzw. Tiefe der Graphen, wenn diese 3-dimensional angezeigt werden (px) '10'
data-title Titel, der über dem Diagramm angezeigt werden soll. Der Inhalt kann auch dynamisch erzeugt werden (Hinweise)
data-title_class Klassenname für die Formatierung des Titels. Die Eigenschaften müssen dann entsprechend in einem CSS File angegeben werden (z.B. in fhem-tablet-ui-user.css)
data-prefetch Legt fest, ob zusätzliche Daten rechts und links des Plots im Hintergrund vom Server geholt werden sollen false data-prefetch="true"
data-xtext_offset Verschiebt den Text auf der x-Achse um die angegebene Anzahl in Minuten.

Einige Parameter (style, maxvalue, minvalue, maxvalue_sec, minvalue_sec) können auch aus Readings dynamisch gesetzt werden wenn "<device>:<reading>" als Parameter gesetzt wird. Damit kann man z.B. in FHEM über notify etc. die Linientypen dynamisch anpassen (z.B. wenn der Wert eines Devices in einem bestimmten Bereich liegt, ändert sich die Farbe des Graphen).

CSS Klassen

Klasse Beschreibung
fullsize 100% Breite und Höhe
noticks Hilfslinien und Beschriftungen an X- und Y-Achse werden ausgeblendet
nobuttons Buttons werden ausgeblendet
small Setzt die Größe des Elementes auf 80%
normal Setzt die Größe des Elementes auf 100%
big Setzt die Größe des Elementes auf 150%

Folgende Widget-spezifsche Klassen können zusätzlich in einer eigenen CSS-Datei definiert werden:

Klasse Beschreibung
chart-background Hintergrundfarbe des Diagramms
buttons Größe und Farbe der Buttons
text.axes Generelle Schriftart und Farbe der Achsen
gridlines Generelle Farbe und Größe der Gitternetzlinien
xaxis Schriftart, Größe und Farbe der X-Achse
yaxis Schriftart, Größe und Farbe der Y-Achse
xticks Schriftart, Größe und Farbe der X-Achse (Zwischenlinien)
yticks Schriftart, Größe und Farbe der Y-Achse (Zwischenlinien)
crosshair Schriftart, Größe und Vordergrund/Hintergrundfarbe der Momentanwerte am Fadenkreuzcursor
caption Schriftart, Größe und Farbe der Text-Buttons für Legende und Cursor
legend Schriftart, Größe und Farbe der Legende

Die Standardwerte sind in der Datei css/ftui_chart.css zu finden.

Datenquellen

Beim Chart-Widget können die gleichen Datenquellen genutzt werden, die auch für SVG-Plots verwendet werden können:

  1. FileLog: Verlaufsdaten einer Textdatei entnehmen
  2. DbLog: Verlaufsdaten einer Datenbank entnehmen
  3. LogProxy: Daten dynamisch berechnet

FileLog

Um FileLog zu nutzen, wird als data-logdevice das FHEM-Device für das FileLog angegeben. In der Regel entstehen hier im Laufe der Zeit mehrere Log-Dateien. Name und Anzahl sind von der Definition abhängig - meist wird jeden Monat oder jedes Jahr eine neue Datei angelegt. Die gewünschte Datei kann mit data-logfile ausgewählt werden. Möchte man stets die aktuelle Datei verwenden (macht vor allem dann Sinn, wenn man die neusten Daten anzeigen will), kann das Attribut weggelassen, oder explizit - eingetragen werden. Zuletzt wird data-columnspec benötigt, um die gewünschten Daten zu in der Logdatei zu identifizieren. Hier wird die Spalte, in der die Daten stehen, gefolgt von Doppelpunkt und Readingname angegeben.

Für ein Heizungsthermostat von Homematic mit dem Namen DG.wz.HZ.Heizungsventil ergibt sich somit beispielhaft folgende Definition, um gemessene Temperatur, Sollwert und Ventilstellung im Diagramm darzustellen:

<div data-type="chart"
	 data-device="DG.wz.HZ.Heizungsventil"
	 data-logdevice="FileLog_DG.wz.HZ.Heizungsventil"
	 data-logfile="-"
	 data-columnspec='["4:measured-temp","4:desired-temp","4:actuator"]'
	 ...>
</div>

Sollen Daten von unterschiedlichen Geräten in einem Diagramm angezeigt werden, muss data-logdevice als Array nach dem Schema data-logdevice='["<Logdatei_1>","<Logdatei_2>","<Logdatei_3>"]' definiert werden. Für jeden Eintrag in data-columnspec muss es auch den passenden Eintrag in data-logdevice geben (auch die Reihenfolge ist relevant).

DbLog

Um die Daten aus DbLog anzeigen zu können, werden die gleichen Attribute verwendet und mit für die Datenbank angepassten Werten beschrieben. Bei data-logdevice das FHEM-Device für die Datenbank angegeben. Im nachfolgenden Beispiel heißt diese logdb und besitzt wie üblich zwei Tabellen: current und history (der zeitliche Verlauf liegt in letzterer). Der Tabellenname wird bei data-logfile eingetragen. Da die Daten in der Datenbank etwas anders abgelegt werden, muss auch data-columnspec entsprechend angepasst werden. Statt der Spalte wird hier das FHEM-Device, gefolgt von Doppelpunkt und Readingname angegeben.

Für das oben beschriebene Homematic-Heizungsthermostat ergibt sich dann folgende Definition, um die gleichen Daten aus einer Datenbank, statt einem LogFile zu lesen:

<div data-type="chart"
	 data-device="DG.wz.HZ.Heizungsventil"
         data-get="measured-temp"
         data-style='["ftui l0"]'
	 data-logdevice="logdb"
	 data-logfile="HISTORY"
	 data-columnspec='["DG.wz.HZ.Heizungsventil:measured-temp","DG.wz.HZ.Heizungsventil:desired-temp","DG.wz.HZ.Heizungsventil:actuator"]'
	 ...>
</div>

Für die Anzeige von unterschiedlichen Geräten in einem Diagramm, muss nur data-columnspec entsprechend angepasst werden, solange sich alle Daten in der Datenbank befinden.

LogProxy

Um die Daten mittels LogProxy berechnen und anzeigen zu können, muss in FHEM ein LogProxy-Device definiert sein:

define myLogProxy logProxy

Weitere Einstellungen am LogProxy sind nicht nötig, die bloße Existenz reicht.

Bei data-logdevice wird das FHEM-Device für den LogProxy angegeben. Im nachfolgenden Beispiel heißt dieses myLogProxy. Das Attribut data-logfile wird für LogProxy nicht benötigt. Befinden sich nur LogProxy-Werte im Diagramm kann das Attribut komplett entfallen. Sollen weitere Werte angezeigt werden, bleibt die Definition im Array einfach leer.

Im Attribut data-columnspec wird eine Formel angegeben, wie die Werte berechnet werden sollen. Hier können die Formeln 1:1 von einem eventuell vorhandenen SVG-Plot übernommen werden. Dabei gibt es jedoch folgendes zu beachten: Befindet sich die Formel in einem Array, dürfen die Formeln keine Anführungszeichen (") beinhalten. Stattdessen müssen sie als escapter Ascii-Code (\\x22) eingefügt werden.

Das nachfolgende Beispiel zeigt, wie Vorhersagewerte aus einem FHEM-Device vom Typ Proplanta (Name hier AU.xx.WE.Proplanta) angezeigt werden können.

<div data-type="chart"
	 data-device="AU.xx.WE.Proplanta"
	 data-logdevice='[
						"myLogProxy",
						"myLogProxy",
						"myLogProxy",
						"myLogProxy"
					]'
	 data-columnspec='[
						"Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22temp_\\x22,$from,$to,12,\\x22day\\x22)",
						"Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22rain_\\x22,$from,$to,12,\\x22day\\x22)",
						"Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22chOfRain_\\x22,$from,$to,12,\\x22day\\x22)",
						"Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22cloud_\\x22,$from,$to,12,\\x22day\\x22)"
					]'
	 ...>
</div>

Auch alle anderen Funktionen, die LogProxy bietet, können hier angewendet werden.

Hinweise

Aktualisierung des Charts

Damit der Refresh des Charts funktioniert, muss auch ein Device angegeben werden, der das Refresh triggert. Das Diagramm wird immer dann aktualisiert, wenn sich der Inhalt von data-get ändert.

<div data-type="chart"
	data-device="WohnzimmerHeizung"
	data-logdevice="FileLog_WohnzimmerHeizung"
	...>
</div>

Aussehen der Linien

Mit dem Attribut data-style kann das Aussehen der Linien des jeweiligen Graphen verändert werden. Hierfür können die Standard-FHEM-Styles verwendet werden. Dazu wird das Attribut mit SVGplot, gefolgt von einem Leerzeichen und der gewünschten Farbe/Stil befüllt. Es existieren jedoch auch noch weitere, an FTUI angepasste Styles, zu finden in der CSS-Datei css/ftui_chart.css. Um diese zu verwenden, wird das Attribut mit ftui, gefolgt von einem Leerzeichen und der gewünschten Farbe/Stil befüllt. Eigene Styles können zum Beispiel in der Datei css/fhem-table-ui-user.css definiert werden.

Folgende Übersicht zeigt die im Standard verfügbaren Farben, alle Abbildungen sind mit im FTUI-Style entstanden:

  • Farbe "l0"
  • Farbe "l1"
  • Farbe "l2"
  • Farbe "l3"
  • Farbe "l4"
  • Farbe "l5"
  • Farbe "l6"

Die Angabe zur Farbe kann dann mit der Linienart kombiniert werden. Dazu stehen folgende Stile zur Verfügung:

  • Darstellung in 2D: Stil "normal"
  • Darstellung in 2D: Stil "dot"
  • Darstellung in 2D: Stil "dash"
  • Darstellung in 2D: Stil "fill"
  • Darstellung in 2D: Stil "sym"
  • Darstellung in 3D: Stil "normal"
  • Darstellung in 3D: Stil "dot"
  • Darstellung in 3D: Stil "dash"
  • Darstellung in 3D: Stil "fill"
  • Darstellung in 3D: Stil "sym"

Farbe und Stil werden kombiniert (zusammengeschrieben) beim Attribut data-style angegeben, sodass sich beispielsweise für eine graue Punktlinie folgendes ergibt: data-style="ftui l1dot". Um die Darstellung als normale Linie zu erhalten, darf im Gegensatz zu den anderen Linienformen der Stil normal nicht angegeben werden. Für eine einfache graue Linie ist also die Angabe data-style="ftui l1" korrekt, wohingegen data-style="ftui l1normal" zu einer fehlerhaften Anzeige führt.

Hinweis: Der Stil sym ist speziell dafür geeignet, Symbole statt Linien zu zeichnen. Dazu kann beim Attribut data-ptype als Linienform ein beliebiges Font-Awsome-, oder Open Automation-Icon angegeben werden. Alle in diesem Abschnitt enthaltenen Abbildungen sind mit data-ptype="lines" entstanden.

Übergänge mit datenabhängigen Grenzen: Plotstile (data-style) können auch direkt als Gradienten auf Basis von Plot-Datenwerten definiert werden. Dazu muss der Plotstil als Array angegeben werden. Der erste Wert des Arrays gibt an, ob nur die Linie gezeichnet werden soll (Zahl angeben, die die Dicke der Linie definiert) oder gefüllt ("fill" eintragen). Alle danach folgenden Array Elemente sind beliebig viele Stopp Punkte für die Farbübergänge, welche wiederum aus Arrays mit 3 Parametern bestehen. Für jeden Stopp Punkt werden der Datenwert, die Farbe und die Durchsichtigkeit gesetzt. Hierdurch lassen sich z.B. Einfärbungen setzen, die für Temperaturplots immer negative Werte blau einfärben und positive Werte rot. Zwischen den Stop Punkten wird die Farbe interpoliert, also ein weicher Übergang generiert. Will man harte Übergänge muss man Zwei Stopp Punkte mit unterschiedlichen Farbwerten aber dem gleichen Datenwert erzeugen.
Beispiel 1 für einen weichen Gradienten, der bei 0 von blau nach rot übergeht, bei diesem Übergang durchsichtig ist und von dort nach negativen bzw. positiven Werden immer deckender wird:
data-style='["fill",["-20","#0000ff","0.7"],["0","#0000ff","0"],["0","#ff0000","0"],["302","#ff0000","0.7"]]'
Beispiel 2 mit einem harten Übergang von blau nach rot bei 0:
data-style='["fill",["-20","#0000ff","0.7"],["0","#0000ff","0.7"],["0","#ff0000","0.7"],["50","#ff0000","0.7"]]' Es gibt auch die Möglichkeit den Bereich zwischen zwei Graphen einzufärben. Dazu muss ein Wert in Columnspec als Array angegeben werden. Ist dies der Fall, dann wird der zweite Graph umgekehrt an den ersten angehängt.
Beispiel:

data-columnspec='[
    "Func:logProxy_proplanta2Plot(\\x22AgroWeather\\x22,\\x22weatherIcon\\x22,$from,$to,12)",
    [
        "Func:logProxy_proplanta2Plot(\\x22AgroWeather\\x22,\\x22tempMax\\x22,$from,$to,12)",
        "Func:logProxy_proplanta2Plot(\\x22AgroWeather\\x22,\\x22tempMin\\x22,$from,$to,12)"
    ],
    "Func:logProxy_proplanta2Plot(\\x22AgroWeather\\x22,\\x22rain\\x22,$from,$to,0,\\x22day\\x22)"
]'
dynamischer Übergang

Form der Linien

Das Attribut data-ptype beeinflusst die Form der Linien. Hier sind folgende Werte möglich (in den Bildern sind zur Info zusätzlich auch immer points dargestellt):

  • Darstellung in 2D: Stil "lines"
  • Darstellung in 2D: Stil "points"
  • Darstellung in 2D: Stil "steps"
  • Darstellung in 2D: Stil "fsteps"
  • Darstellung in 2D: Stil "histeps"
  • Darstellung in 2D: Stil "bars"
  • Darstellung in 2D: Stil "ibars"
  • Darstellung in 2D: Stil "cubic"
  • Darstellung in 2D: Stil "quadratic"
  • Darstellung in 2D: Stil "quadraticSmooth"

Zusätzlich ist es möglich, Symbole anzeigen zu lassen. Unterstützt werden Font-Awesome ('fa-...'), Open Automation ('oa-...') und FHEM-Symbole ('fs-...')). Damit die Symbole korrekt angezeigt werden, muss im Attribut data-style der Stil sym gewählt werden, da sonst nur Punkte, statt der Symbole gezeichnet werden.

<div data-type="chart"
	 data-device="DG.wz.HZ.Heizungsventil"
	 data-logdevice="FileLog_DG.wz.HZ.Heizungsventil"
	 ...
	 data-style="ftui l1sym"
	 data-ptype="fa-cloud"
	 ...>
</div>
  • Darstellung in 2D: Stil "symbol fa-cloud"
  • Die Größe der Symbole ist in der Datei css/ftui_chart.css auf 12px festgelegt. Dieser Wert kann in einer eigenen CSS-Datei durch Anpassung von stroke-width überschrieben werden.

    .ftui.l0sym		{ stroke:#DDA400; stroke-width:12px; fill:none; }
    .ftui.l1sym		{ stroke:#BBBBBB; stroke-width:12px; fill:none; }
    .ftui.l2sym		{ stroke:#CC0000; stroke-width:12px; fill:none; }
    .ftui.l3sym		{ stroke:#CCCC00; stroke-width:12px; fill:none; }
    .ftui.l4sym		{ stroke:#33CC33; stroke-width:12px; fill:none; }
    .ftui.l5sym		{ stroke:#33CCCC; stroke-width:12px; fill:none; }
    .ftui.l6sym		{ stroke:#3333CC; stroke-width:12px; fill:none; }
    

    data-ptype kann auch Inhalt im Format 'icon:1' verarbeiten. Dann muss der zugehörige Wert in data-columnspec den Pfad zu einem Icon (z.B. für Wettervorhersagen) beinhalten. Der Y-Wert wird dann vom ersten Graphen übernommen. Weitere Ausführungen hierzu im Beispiel #Darstellung der Wetter Icons im Diagramm.

  • Darstellung in 2D: Stil "Beispiel mit icons aus Readings"

  • Stapeln von Linien

    Über data-ptype kann zusätzlich festgelegt werden, ob Graphen übereinander gestapelt werden sollen. data-ptype='lines:1' bedeutet, dass der zugehörige Graph auf den Graph mit der Nummer 1 gestapelt werden soll. So etwas kann z.B. Sinn machen, wenn man den Stromverbrauch einzelner Devices darstellen und zusätzlich sehen will, wie hoch die Summe ist. Beispiel siehe unten.

    FTUI Widget Chart Stacked.png

    Zeitstrahl / Start & Ende auf der X-Achse

    Die Attribute data-daysago_start und data-daysago_end dienen der Definition von Anfang und Ende der X-Achse. Im einfachsten Fall wird eine Anzahl an Tagen eingegeben, die sich auf das aktuelle Datum beziehen. Dabei gilt es zu beachten, dass es sich um vergangene Tage handelt. Das bedeutet, dass Tage in der Vergangenheit als positive Zahl angegeben werden, Tage in der Zukunft hingegen als negative Zahl. Es kann jeweils auch ein fixes Datum (z.B. '2013-10-23') angegeben werden. Uhrzeitangaben werden nur berücksichtigt, wenn data-nofulldays='true' verwendet wird.

    Relative Zeitangabe in Stunden/Tagen/Wochen/Monaten/Jahren
    Zur Ausgabe einer Anzahl an zurückliegenden Stunden bis zum aktuellen Zeitpunkt wird als Startzeitpunkt die Anzahl der Stunden/Tage/Wochen/Monate/Jahre angegeben, die angezeigt werden sollen, gefolgt vom Kleinbuchstaben h für Stunden, d für Tage, w für Wochen, m für Monate, y für Jahre, . Als Endzeitpunkt wird now gewählt.
    Das nachfolgende Beispiel zeigt die Werte der vergangenen 3 Stunden an:

    data-nofulldays="true"
    data-daysago_start="3h"
    data-daysago_end="now"
    

    Fester Zeitbereich des heutigen Tages (Stunden/Tage/Wochen/Monate/Jahre)
    Um ein festes Stunden/Tages/Wochen/Monats/Jahresfenster anzuzeigen, werden die absoluten Stunden/Tages/Wochen/Monats/Jahreszahlen mit negativem Vorzeichen, gefolgt vom Großbuchstaben H (entsprechend D/W/M/Y für Tage/Wochen/Monate/Jahre) angegeben. Wird data-daysago_start als positiver Wert angegeben, wird die Anzahl der Stunden/Tage/Wochen/Monate/Jahre von heute 0:00 Uhr subtrahiert (siehe Rechenweg weiter unten).
    Das Beispiel zeigt den Zeitbereich von heute 5:00 Uhr bis heute 22:00 Uhr:

    data-nofulldays="true"
    data-daysago_start="-5H"
    data-daysago_end="-22H"
    

    Fester Zeitbereich Tage-übergreifend
    Die Zeit in Tagen kann als Gleitkommazahl angegeben werden. Damit ist es möglich, Tage und Uhrzeiten zu kombinieren. Die Werte sind dann als Teil eines ganzen Tages, bezogen auf heute 0:00 Uhr zu errechnen und mit . als Teiler anzugeben.
    Das nachfolgende Beispiel zeigt einen Zeitbereich von gestern 15:00 Uhr bis morgen 3:00 Uhr.

    data-nofulldays="true"
    data-daysago_start="0.375"
    data-daysago_end="-1.125"
    

    Für die nachfolgenden Rechenwege sind die Einheiten nur zur Verdeutlichung angegeben. Die Einheiten werden im Attribut nicht angegeben.

    Der Wert für GESTERN wird wie folgt ermittelt:
    Ausgangspunkt ist heute 0:00 Uhr, gestern 15:00 Uhr liegt also 9 Stunden davor. Diese 9 Stunden sind ein 9/24 Tag und errechnet sich so:

    1d / 24h = 0.0416666...d/h
    0.0416d/h * 9h = 0.375d
    

    Der Wert für MORGEN wird wie folgt ermittelt:
    Ausgangspunkt ist wieder heute 0:00 Uhr, morgen 3:00 Uhr liegt dann 27 Stunden dahinter. Der Einfachheit halber werden hier nur die 3 Stunden errechnet und dann ein ganzer Tag addiert:

    1d / 24h = 0.0416666...d/h
    0.0416d/h * 3h = 0.125d
    
    0.125d + 1d = 1.125d
    

    Da das Attribut Tage in der Vergangenheit erwartet, muss für einen Wert in der Zukunft wieder eine negative Zahl angegeben werden.

    Zeitformat der X-Achse

    Die Zeitanzeige auf der X-Achse kann sehr flexibel eingestellt werden. Dafür stehen verschiedene Platzhalter zur Verfügung, die durch spezielle Zeichen (-, ., /, (Leerzeichen), :, ,, \) getrennt werden. Alle Zeichen werden trotz Escape-Zeichen (\) in der Ausgabe angezeigt.

    Folgende Platzhalter werden unterstützt:

    • 'mm': Minuten als zweistellige Zahl
    • 'hh': Stunden als zweistellige Zahl
    • 'dd': Tag als zweistellige Zahl (Kalenderdatum)
    • 'MM': Monat als zweistellige Zahl (z.B. 02 für Februar)
    • 'MMM': Monat als dreistellige Abkürzung (z.B. Dec für Dezember)
    • 'MMMM': Langname des Monats (z.B. March)
    • 'ee': Wochentag als zweistellige Zahl (z.B. 00 für Sonntag)
    • 'eee': Wochentag als dreistellige Abkürzung (z.B. Mon für Montag)
    • 'eeee': Langname des Wochentags (z.B. Tuesday)
    • 'yy': Jahr als zweistellige Zahl (z.B. 16 für 2016)
    • 'yyyy': Jahr als vierstellige Zahl (z.B. 2016)
    • 'LF': Fügt einen Zeilenumbruch hinzu

    Beispiel: Der String 'MMM\LF\yyyy' zeigt 'Jan' in der ersten, und '2016' in der zweiten Zeile. 'MM.dd 2016' wird zu '03.05 2016'.

    Fadenkreuz-Cursor

    Der Fadenkreuz-Cursor zeigt die Momentanwerte, indem man ihn über die Graphen bewegt. In Desktop-Browsern reicht einfaches Bewegen der Maus. Unter iOS und Android wird der Cursor durch einfaches Tippen auf die neue Position bewegt.

    Mit dem Attribut data-cursorgroup können Graphen gruppiert werden. Am Cursor werden dann die Momentanwerte aller Graphen gleichzeitig angezeigt, die die selbe Zahl besitzen, sobald man die Maus über einen aus der Gruppe bewegt.

    Legende

    Mit dem Attribut data-legendpos kann die Position der Legende innerhalb des Diagramms festgelegt werden. Die Position wird mit einem Array, bestehend aus zwei Werten im Format '["<horizontal>","<vertikal>"]' angegeben. Für die horizontale Positionierung sind 'left', 'right', 'before', und 'behind', die vertikale Positionierung 'top', 'bottom', 'above', 'below' erlaubt (der Unterschied zwischen 'left' und 'before' liegt darin, dass im zweiten Fall die Legende nicht in den Zeichenbereich gesetzt wird sondern vor das ganze Chart (entsprechend für 'after', 'above' und 'below'). Alternativ können auch Zahlen verwendet werden, die die Position in Prozent angeben. Durch verschieben mit der Maus oder durch verschieben mit dem Finger oder Stift auf Touch Devices kann die Legende auch an eine andere Position verschoben werden.

    Wenn die Legende eingeblendet ist, kann mittels Klick auf einen Legendeneintrag der zugehörige Graph ein- und ausgeblendet werden.

    3-dimensionale Drehung

    data-ddd ermöglicht, den Graphen 3-dimensional zu drehen. Als Wert wird ein Array mit den 3 Winkeln für x, y und z erwartet, wobei z selbst bisher nicht unterstützt wird.

    Beispiel: data-ddd='["40","60","0"]'.

    Wenn der 3D Modus aktiv ist (data-ddd gesetzt) sind 2 zusätzliche Parameter verfügbar um das Aussehen der Graphen zu beeinflussen. data-dddspace gibt an, wie viele pixel der Raum zwischen den einzelnen in z-Richtung hintereinander angeordneten Graphen betragen soll. data-dddwidth legt fest, wie viele pixel die einzelnen Graphen tief (oder dick) sein sollen.

    Wenn das Array angegeben wird, erscheinen zwei zusätzliche Buttons im Diagramm, mit denen die Drehung in X- und Y-Richtung verändert werden kann.

    Diagrammtitel

    Mit dem Attribut data-title kann dem Diagramm, ähnlich wie in FHEM-SVG-Plots, ein Titel hinzugefügt werden.

    Folgende Platzhalter werden unterstützt:

    • 'min1': Minimaler Y-Wert des ersten Graphs
    • 'max1': Maximaler Y-Wert des ersten Graphs
    • 'avg1': Mittlerer Y-Wert des ersten Graphs
    • 'cnt1': Anzahl der dargestellten Einzelwerte im ersten Graph
    • 'currval1': Letzter, bzw. aktuellster Y-Wert des ersten Graphs
    • 'mindate1': Niedrigster Wert auf der X-Achse des ersten Graphs
    • 'maxdate1': Höchster Wert auf der X-Achse vom ersten Graphs
    • 'currdate1': Letzter, bzw. aktuellster Wert auf der X-Achse des ersten Graphs

    Durch Einsetzen einer anderen Zahl statt '1' können auch die Werte der anderen Graphen angezeigt werden. Das Weglassen der Zahl bewirkt, dass der jeweils zutreffende Wert automatisch ermittelt wird. Bedeutet: max führt dazu, dass der höchste Wert aller angezeigter Graphen verwendet wird. Zusätzlich ist es möglich durch "$eval(<regexp>)" regular Expressions auszuwerten (also z.B. Berechnungen durchzuführen). In <regexp> können auch "$data()" vorkommen.

    Beispiel: data-title="Klima Wohnzimmer Average: $eval(parseInt($data{avg1}*10)/10)°C / Max: $eval(parseInt($data{max1}*10)/10)°C"

    Buttons im Diagramm

    Es gibt mehrere Buttons, mit denen sich die Anzeige des Diagramms verändern lässt. <- und -> bewegen die Graphen nach links und rechts. + und - zoomen die Anzeige. legend und cursor schalten die zugehörigen Anzeigen ein und aus. Falls der 3D Modus eingeschaltet ist, gibt es Buttons zum Drehen der Darstellung um die X- und Y-Achse. Falls data-timeranges gesetzt ist, wird ein Pulldown Menü dargestellt, welches die Auswahl von dort definierten Zeiträumen für die X-Achse erlaubt.

    Beispiele

    Einfaches Diagramm

    Das Beispiel zeigt ein einfaches Diagramm mit 4 unterschiedlich formatierten Graphen, Legende und Momentanwerten am Fadenkreuz-Cursor.

    Chart tabletUI.png

    <div data-type="chart"
    	data-logdevice='["Log.Garden","Log.Garden","Log.Garden","Log.Predicted"]'
    	data-columnspec='["4:Garden.T:15:","10:Garden.T:0:delta-h","10:Garden.T:0:delta-d","4:predicted.*:15:"]'
    	data-style='["ftui l0fill","ftui l1fill","ftui l2","ftui l3dot"]'
    	data-ptype='["lines","histeps","histeps","cubic"]'
    	data-uaxis='["primary","secondary","secondary","primary"]'
    	data-legend='["Temperature","Rain/hour","Rain/day","Predicted Temp."]'
    	data-yunit="°C"
    	data-ytext="Temperature"
    	data-minvalue="auto"
    	data-maxvalue="auto"
    	data-yunit_sec="mm"
    	data-ytext_sec="Rain (mm)"
    	data-height="250"
    	data-yticks="auto"
    	data-minvalue_sec="auto"
    	data-maxvalue_sec="auto"
    	data-nofulldays="true"
    	data-daysago_start="2013-08-13T00:00:00"
    	data-daysago_end="2013-08-14T00:00:00"
    	data-cursorgroup="1"
    	data-scrollgroup="1"
    	data-xticks="auto">
    </div>
    

    7-Tage-Wettervorhersage mit Proplanta

    In diesem Beispiel wird gezeigt, wie die Vorhersagewerte von PROPLANTA in einem Diagramm dargestellt werden können. Da die Werte nicht in einer Datenbank oder einem FileLog vorliegen, müssen sie über LogProxy verarbeitet werden. Dafür sind einige Vorbereitungen in FHEM nötig.

    FTUI Widget Chart-fc-Proplanta.png

    1. Ein LogProxy-Device muss vorhanden sein:

    define myLogProxy logProxy
    

    2. In der Datei 99_myUtils.pm muss folgende Routine hinzugefügt werden, die die Daten bereitstellt:

    #---------------------------------------
    # Proplanta LogProxy-Funktion
    #---------------------------------------
    sub logProxy_proplanta2Plot($$$$;$$) {
    	my ($device, $fcValue, $from, $to, $fcHour, $expMode) = @_;
        my $regex;
        my @rl;
        
    	return undef if(!$device);
        
        if($fcValue =~ s/_$//) {
            $regex = "^fc[\\d]+_".$fcValue."[\\d]{2}\$";
        }
        else {
            $regex = "^fc[\\d]+_".$fcValue."\$";
        }
        
        $fcHour = 12 if(!defined $fcHour);
        $expMode = "point" if(!defined $expMode);
    
    	if( defined($defs{$device}) ) {
    		if( $defs{$device}{TYPE} eq "PROPLANTA" ) {
                @rl = sort{
                    my ($an) = ($a =~ m/fc(\d+)_.*/);
                    my ($bn) = ($b =~ m/fc(\d+)_.*/);
                    $an <=> $bn or $a cmp $b;
                    }( grep /${regex}/,keys %{$defs{$device}{READINGS}} );
    			return undef if( !@rl );
    		} else {
    			Log3 undef, 2, "logProxy_proplanta2Plot: $device is not a PROPLANTA device";
    			return undef;
    		}
    	}
    
    	my $fromsec = SVG_time_to_sec($from);
    	my $tosec   = SVG_time_to_sec($to);
    	my $sec = $fromsec;
    	my ($h,$fcDay,$mday,$mon,$year);
    	my $timestamp;
        
    	my $reading;
    	my $value;
    	my $prev_value;
    	my $min = 999999;
    	my $max = -999999;
    	my $ret = "";
    
    	# while not end of plot range reached
    	while(($sec < $tosec) && @rl) {
    		#remember previous value for start of plot range
    		$prev_value = $value;
    
    		$reading = shift @rl;
            ($fcDay) = $reading =~ m/^fc(\d+).*/;
       		$h = ($reading =~ m/.*(\d\d)$/)?$1:$fcHour;
    		$value = ReadingsVal($device,$reading,undef);
            
    		($mday,$mon,$year) = split('\.',ReadingsVal($device,"fc".$fcDay."_date",undef));
    		$timestamp = sprintf("%04d-%02d-%02d_%02d:%02d:%02d", $year, $mon, $mday, $h, 0, 0);
    		$sec = SVG_time_to_sec($timestamp);
            
    		# skip all values before start of plot range
    		next if( SVG_time_to_sec($timestamp) < $fromsec );
    
    		# add first value at start of plot range
    		if( !$ret && $prev_value ) {
    		  $min = $prev_value if( (looks_like_number($prev_value) && ($prev_value < $min)) || ($prev_value lt $min) );
    		  $max = $prev_value if( (looks_like_number($prev_value) && ($prev_value > $max)) || ($prev_value gt $max) );
    		  $ret .= "$from $prev_value\n";
    		}
    
    		# done if after end of plot range
    		last if($sec > $tosec);
    
    		$min = $value if( (looks_like_number($value) && ($value < $min )) || ($value lt $min) );
    		$max = $value if( (looks_like_number($value) && ($value > $max )) || ($value gt $max) );
    
    		# add actual controll point
    		$ret .= "$timestamp $value\n";
    
    #		Log 1, "$timestamp $value -0- $reading";
    	}
        if(($sec < $tosec) && !@rl && ($expMode eq "day")) {
        	$timestamp = sprintf("%04d-%02d-%02d_%02d:%02d:%02d", $year, $mon, $mday, 23, 59, 59);
        	if(SVG_time_to_sec($timestamp) < $tosec) {
            	$ret .= "$timestamp $value\n";
            }
            else {
    			$ret .= "$to $value\n";
            }
        }
        elsif(($sec > $tosec) && ($expMode eq "day")) {
           	$value = $prev_value + ($value - $prev_value)*(86400 + ($tosec - $sec))/86400;
           	$ret .= "$to $value\n";
        }
    	return ($ret,$min,$max,$prev_value);
    }
    

    Anschließend können die Daten im Chart-Widget angezeigt werden. Der Device-Name von Proplanta heißt hier im Beispiel AU.xx.WE.Proplanta.

    <div data-type="chart"
    	 data-device="AU.xx.WE.Proplanta"
    	 data-logdevice='[
    	 					"myLogProxy",
    	 					"myLogProxy",
    	 					"myLogProxy"
    	 				]'
    	 data-columnspec='[
    	 					"Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22rain_\\x22,$from,$to,12,\\x22day\\x22)",
    	 					"Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22chOfRain_\\x22,$from,$to,12,\\x22day\\x22)",
    	 					"Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22cloud_\\x22,$from,$to,12,\\x22day\\x22)"
    	 				]'
    	 data-style='[
    	 					"ftui l6fill",
    	 					"ftui l5fill",
    	 					"ftui l1fill"
    	 			]'
    	 data-ptype='[
    	 					"steps",
    	 					"quadraticSmooth",
    	 					"quadraticSmooth"
    	 			]'
    	 data-uaxis='[
    	 					"primary",
    	 					"secondary",
    	 					"secondary"
    	 			]'
    	 data-legend='[
    	 					"Regen",
    	 					"Regenwahrscheinlichkeit",
    	 					"Wolken"
    	 			]'
    	 data-yunit="mm"
    	 data-ytext="Regen"
    	 data-yunit_sec="%"
    	 data-ytext_sec="Chance auf Regen / Wolken"
    	 data-timeformat="eeee"
    	 data-minvalue="auto"
    	 data-maxvalue="auto"
    	 data-minvalue_sec="auto"
    	 data-maxvalue_sec="auto"
    	 data-daysago_start = "0"
    	 data-daysago_end = "-7"
    	 data-xticks="1440"
    	 data-yticks="auto"
    	 data-title="7-Tage-Wettervorhersage"
    	 data-showlegend="true"
    	 class="nobuttons fullsize">
    </div>
    

    Hilfreiche Links und Quellen zu diesem Beispiel:

    Darstellung der Wetter Icons im Diagramm

    Wetterchart2.png

    Wie oben bereits beschrieben, gibt es beim Chart grundsätzlich die Möglichkeit, Icons, welche in Form von URLs in den Logs abgelegt sind oder welche per logProxy generiert werden, darzustellen. Die Icons werden auf genau dem gleichen Weg von FHEM gelesen, wie alle anderen Datenpunkte. Im Folgenden wird ein Beispiel gezeigt, mit dem die im Proplanta Modul als Readings abgelegten Icons per logProxy Funktion gelesen und in ein Chart eingebaut werden könnnen. Da es beim Proplanta Modul für die ersten 7 Tage nicht das Reading fc#_weatherIcon gibt, sondern mehrere Readings für unterschiedliche Tageszeiten wogegen für die zweiten 7 Tage ausschließlich das Reading fc#_weatherIcon vorhanden ist, sollte per attr device userReading mit folgendem Eintrag dafür gesorgt werden, dass für alle Tage ein Reading fc#_weatherIcon vorhanden ist (alternativ könnten auch 2 Graphen gezeichnet werden, wobei der erste dann nur die ersten 7 Tage enthält und der zweite die letzen 7 Tage, will man nur die ersten 7 Tage darstellen braucht man das userReading nicht unbedingt).

    fc0_weatherIcon {ReadingsVal("AU.xx.WE.Proplanta","fc0_weatherDayIcon","");},
    fc1_weatherIcon {ReadingsVal("AU.xx.WE.Proplanta","fc1_weatherDayIcon","");},
    fc2_weatherIcon {ReadingsVal("AU.xx.WE.Proplanta","fc2_weatherDayIcon","");},
    fc3_weatherIcon {ReadingsVal("AU.xx.WE.Proplanta","fc3_weatherDayIcon","");},
    fc4_weatherIcon {ReadingsVal("AU.xx.WE.Proplanta","fc4_weatherDayIcon","");},
    fc5_weatherIcon {ReadingsVal("AU.xx.WE.Proplanta","fc5_weatherDayIcon","");},
    fc6_weatherIcon {ReadingsVal("AU.xx.WE.Proplanta","fc6_weatherDayIcon","");}
    

    Um die Icons darzustellen muss ein zusätzlicher Graph definiert werden. Dieser nutzt neben der Columnspec, die die URLs abruft den Parameter data-ptype="icons:#" (# ist eine Zahl und steht für die Nummer, beginnend bei 0 des Graphen, welcher für die y-Position der Icons verwendet werden soll) und den Stil sym. Der Wert für die Symbolgröße sollte z.B. durch eine zusätzliche Definition im File fhem-tablet-ui-user.css in der Form:

    /* icon lines */
    .ftui.l99icon	{ stroke:#DDA400; stroke-width:48px; fill:none; }
    

    angepasst werden.

    Im folgenden ein Beispiel, welches eine Linie für die Maximale Tagestemperatur zeichnet und auf dieser Linie die Wetter Icons darstellt.

    <div data-type="chart"
    	 data-device="AU.xx.WE.Proplanta"
    	 data-logdevice='[
    	 					"myLogProxy",
    	 					"myLogProxy"
    	 				]'
    	 data-columnspec='[
    	 					"Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22weatherIcon\\x22,$from,$to,12,\\x22day\\x22)",
    	 					"Func:logProxy_proplanta2Plot(\\x22AU.xx.WE.Proplanta\\x22,\\x22tempMax\\x22,$from,$to,12,\\x22day\\x22)"
    	 				]'
    	 data-style='[
    	 					"ftui l99icon",
    	 					"ftui l1fill"
    	 			]'
    	 data-ptype='[
    	 					"icons:1",
    	 					"quadraticSmooth"
    	 			]'
    	 data-uaxis='[
    	 					"primary",
    	 					"primary"
    	 			]'
    	 data-legend='[
    	 					"Wetterbedingung",
    	 					"Max. Temperature"
    	 			]'
    	 data-yunit="°C"
    	 data-ytext="Temperature (°C)"
    	 data-timeformat="ee\LF\dd.MM"
    	 data-minvalue="auto"
    	 data-maxvalue="auto"
    	 data-minvalue_sec="auto"
    	 data-maxvalue_sec="auto"
    	 data-daysago_start="-1w"
    	 data-y_margin="20"
    	 data-daysago_end="-3w"
    	 data-xticks="1440"
    	 data-yticks="auto"
    	 data-title="14-Tage-Wettervorhersage"
    	 data-showlegend="true"
    	 class="nobuttons fullsize">
    </div>
    

    Kuchendiagramme

    In folgendem Beispiel wird gezeigt, wie man ein "Kuchendiagramm" darstellen kann.

    PieChart.png

    Ähnlich wie bei den Beispielen für die Wetter Darstellungen wird hierzu auch wieder logProxy benötigt. Zunächst muss die folgende zusätzliche Funktion in 99_myUtils.pm einfügen.

    #---------------------------------------
    # Funktion zum Erzeugen der Inputs für Kuchendiagramme
    #---------------------------------------
    sub logProxy_values2PieChart($$$$;$$) {
    	my ($device, $reading, $angle_start, $angle_dif, $inner_rad, $show_text) = @_;
    	Log3 undef, 1, "$device, $reading, $angle_start, $angle_dif, $inner_rad, $show_text\n";
    
    	use constant PI => 4 * atan2(1,1);
    	
    	my $value=ReadingsVal($device,$reading,0);
    
    	my $angle_delta = $value/100*360;
    	$angle_start = $angle_start/100*360;
    	
    	my $rad=10;
    	my $irad=0;
    	if ($inner_rad) {
    		$irad = $rad*$inner_rad;
    	}
    	my $angle=$angle_start/360*2.0*PI;
    	my $x=$irad*sin($angle);
    	my $y=$irad*cos($angle);
    	my $ret .= ";p ".$x." ".$y."\n"; # add segment at angle $angle
    	
    	for (my $i=$angle_start; $i<=$angle_start+$angle_delta; $i+=$angle_dif) {
    		$angle = $i/360*2.0*PI;
    		$x = $rad*sin($angle);
    		$y = $rad*cos($angle);
    		$ret .= ";p ".$x." ".$y."\n"; # add segment at angle $angle
    	}
    	
    	$angle = ($angle_start+$angle_delta)/360*2.0*PI; # add last segment 
    	$ret .= ";p ".$rad*sin($angle)." ".$rad*cos($angle)."\n";
    
    	if ($inner_rad) {
    		for (my $i=$angle_start; $i<$angle_start+$angle_delta; $i+=$angle_dif) {
    			$angle = ($angle_start+$angle_start+$angle_delta-$i)/360*2.0*PI;
    			$x = $irad*sin($angle);
    			$y = $irad*cos($angle);
    			$ret .= ";p ".$x." ".$y."\n"; # add segment at angle $angle
    		}
    	}
    
    	$angle = ($angle_start)/360*2.0*PI; # add last segment 
    	$ret .= ";p ".$irad*sin($angle)." ".$irad*cos($angle)."\n";
    
    	if ($show_text) { # show text values
    		$x = ($rad+$irad)/2*sin((2*$angle_start+$angle_delta)/2/360*2.0*PI);
    		$y = ($rad+$irad)/2*cos((2*$angle_start+$angle_delta)/2/360*2.0*PI);
    
    		$ret .= ";t ".$x." ".$y." middle ".$show_text.":".$value."%\n";
    	}
    
    	return($ret);
    }
    

    In FHEM braucht man Readings, welche eine Zahl enthalten, die als Prozentwert interpretiert wird. Für jeden Prozentwert (also für jedes Reading) generiert die o.a. Funktion nun den Chart Input für ein Kuchenstück und liefert diesen als Antwort auf das GET, welches das Chart Widget auslöst. Dazu braucht die Funktion folgende Parameter: (Name des FHEM Devices, Name des Readings, Start Winkel des Kuchenstücks (Mathematisch gegen den Uhrzeigersinn in Grad), Delta Winkel zum Zeichnen (legt fest in welchen Schritten der Teilkreis des Kuchenstücks gezeichnet wird), Skalierungsfaktor für inneren Ring wenn ein Ring gezeichtnet werden soll (0 bedeutet komplette Kuchenstücke), optionaler Text der ins Kuchenstück vor die Prozentzahl geschrieben wird). Im Folgenden eine Beispielkonfiguration für die Darstellung als Kuchendiagramm, die Readings heißen hier dPer1 bis dPer4. Der Startwinkel wird duch Aufsummierung der jeweils vorher schon gezeichneten Kuchenstücke gebildet, dadurch entstehen aneinander hängende Stücke.

    [[Datei:[[Datei:Beispiel.jpg]]]]<div class="normal noaxes nobuttons"
            data-type="chart"
            data-logdevice='["lp"]'
    		data-logfile="CURRENT"
            data-columnspec='[
    			"Func:logProxy_values2PieChart(\"dPer1\",\"state\",ReadingsVal(\"dPer4\",\"state\",0)+ReadingsVal(\"dPer3\",\"state\",0),5,0,\"first\")",
    			"Func:logProxy_values2PieChart(\"dPer2\",\"state\",ReadingsVal(\"dPer4\",\"state\",0)+ReadingsVal(\"dPer3\",\"state\",0)+ReadingsVal(\"dPer1\",\"state\",0),5,0,\"second\")",
    			"Func:logProxy_values2PieChart(\"dPer3\",\"state\",ReadingsVal(\"dPer4\",\"state\",0),5,0,\"third\")",
    			"Func:logProxy_values2PieChart(\"dPer4\",\"state\",0,5,0,\"fourth\")"
    		]'
            data-style='["ftui l0fill","ftui l1fill","ftui l2fill","ftui l3fill"]'
            data-ptype='["lines"]'
            data-uaxis='["primary"]'
            data-legend='["First","Second","Third","Fourth"]'
    		data-legendpos='["left","top"]'
            data-yunit=""
            data-height="300"
            data-width="300"
    		data-ddd='["-40","0","0"]'
    		data-dddspace='["-10"]'
    		data-dddwidth='["10"]'
    		data-showlegend="true"
    		data-legend_horiz="true"
            data-xticks="auto">
    </div>
    

    Fensterstatus offen/geschlossen

    Dieses Beispiel zeigt, wie ein Fensterkontakt, dessen Reading die Werte closed und open einnimmt, als Graph gezeichnet werden kann. Technisch gesehen werden hier die Werte 0 und 1 gezeichnet, indem über das Attribut data-columnspec dem Zustand open der Wert 1 und allen anderen Zuständen der Wert 0 zugeordnet wird. Über das Attribut data-yticks wird die Beschriftung an der Y-Achse (0 und 1) gegen einen frei definierbaren Text ausgetauscht.

    <div data-type="chart"
    	data-device="wz_fensterstatus"
    	data-logdevice='["myDbLog"]'
    	data-logfile='["HISTORY"]'
    	data-columnspec='["wz_fensterstatus:state:0::$val=($val=~\\x22open\\x22?1:0)"]'
    	data-style='["ftui l4fill"]'
    	data-ptype='["steps"]'
    	data-height="290"
    	data-yticks='[[0,"geschlossen"],[1,"offen"]]'
    	data-minvalue="0"
    	data-maxvalue="1.1"
    	data-nofulldays="true"
    	data-daysago_start="1"
    	data-daysago_end="-1"
    	data-cursorgroup="1"
    	data-scrollgroup="1">
    </div>
    

    Hinweis: Das Beispiel funktioniert nur mit DbLog. Falls Logfiles verwendet werden muss statt '$val' '$fld[num]' verwendet werden. Hierbei steht num für die Spalte (beginnend bei 0) in der die Daten stehen.

    Links

    Thread im FHEM-Forum