Plot-Abriss vermeiden: Unterschied zwischen den Versionen

Aus FHEMWiki
K (Sichtung / Bearbeitung der letzten Änderung)
 
(17 dazwischenliegende Versionen von 8 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
== Motivation ==
{{Randnotiz|RNTyp=g|RNText='''HINWEIS''': Es gibt mittlerweile (12/2019) das Attribut ''addLog'' für [[FileLog]] Devices.    
Bei Nutzung des Attributs event-on-change werden Log-Einträge nur bei Werteänderung geschrieben. Dies führt
This attribute takes a comma-separated list of devspec:reading:maxInterval triples. You may use regular expressions for reading. The last value of the reading will be written to the logfile, if after maxInterval seconds no event for this device/reading has arrived.  
a) zum Abriss der Logs zum Ende des alten und zum Beginn des neuen Tages
b) zu inadäquat langen Pausen zwischen Logeinträgen, z.B. für actuator, der zB in den Wintermonaten bei Anwesenheit durchgängig 100%, bei Abwesenheit durchgängig 0% betragen kann. Der Wechsel zwischen diesen Werten wird mit langen Flanken dargestellt.


== Funktionsweise ==
Siehe auch {{Link2Forum|Topic=106489|LinkText=dieses Forenthema}}.}}
Die Routine addLog fügt zu definierten Zeitpunkten Einträge im Log hinzu. Dadurch sollen die o.g. Effekte vermieden werden. Zusätzliche Einträge sind mit dem Anhang "<< addLog" gekennzeichnet.
 
Der Aufruf erfolgt sinnvollerweise aus einem at. Üblich ist der Aufruf für alle Geräte bzw. readings, für die "event-on-change" gesetzt ist.
== Attribut addLog ==
Seit 12/2019 können mit dem Attribut ''addLog'' am [[FileLog]] Device maximale Zeitspannen vorgegeben werden, nach denen der letzte bekannte Wert des Readings erneut in das Logfile übernommen werden soll, sofern zwischenzeitlich kein neuer Wert eingetroffen ist. Im Attribut sind Triplette in der Form <code>devspec:reading:maxInterval</code> anzugeben, mehrere Einträge durch Komma getrennt. Die betreffenden Devices und Readings können über Regex bestimmt werden.
 
== Timerbasierte Zusatzeinträge ==
=== Motivation ===
Bei Nutzung des Attributs <code>event-on-change</code> werden Log-Einträge nur bei Werteänderung geschrieben. Dies führt
# zum Abriss der Logs zum Ende des alten und zum Beginn des neuen Tages
# zu inadäquat langen Pausen zwischen Logeinträgen, z.B. für <code>actuator</code>, der z.B. in den Wintermonaten bei Anwesenheit durchgängig 100%, bei Abwesenheit durchgängig 0% betragen kann. Der Wechsel zwischen diesen Werten wird mit langen Flanken dargestellt.
 
=== Funktionsweise ===
Aus diesem Grund wurde die Routine <code>addLog</code> erstellt (siehe [[#Implementierung|Implementierung]]).
Sie fügt zu definierten Zeitpunkten Einträge im Log hinzu.
Dadurch sollen die o.g. Effekte vermieden werden.
Zusätzliche Einträge sind mit dem Anhang <code><< addLog</code> gekennzeichnet.
Der Aufruf erfolgt sinnvollerweise aus einem <code>at</code> oder einem <code>DOIF</code>.
Üblich ist der Aufruf für alle Geräte bzw. readings, für die <code>event-on-change</code> gesetzt ist.


Die Routine hat zwei Aufrufparameter:
Die Routine hat zwei Aufrufparameter:
<syntaxhighlight lang=text>
addLog(<devicename>, <reading>)
</syntaxhighlight>


<nowiki>addLog(&lt;devicename&gt;, &lt;reading&gt;)</nowiki>
=== Beispiele aus fhem.cfg ===
== Beispiele aus fhem.cfg ==
<syntaxhighlight lang=text>
<nowiki>### jede Stunde einen Eintrag für FHT actuator
### jede Stunde einen Eintrag für FHT actuator
define a_actuator at +*01:00 {addLog(&quot;ez_FHT&quot;,&quot;actuator&quot;)}
define a_actuator at +*01:00 {addLog("ez_FHT","actuator")}
attr a_actuator room 99_System</nowiki>
attr a_actuator room 99_System
</syntaxhighlight>


addLog für mehrere devices in einem "Makro" zusammenfassen:
<code>addLog</code> für mehrere <code>devices</code> in einem "Makro" zusammenfassen:
<syntaxhighlight lang=text>
define addLog notify addLog {addLog("ez_Aussensensor","state");;\
    addLog("ez_FHT","actuator");;\
    addLog("ez_FHT","measured-temp");;\
    addLog("MunichWeather","humidity");;\
    addLog("MunichWeather","pressure");;\
    addLog("MunichWeather","temperature");;\
    addLog("MunichWeather","wind_chill");;}
attr addLog room 99_System
</syntaxhighlight>


<nowiki>define addLog notify addLog {addLog(&quot;ez_Aussensensor&quot;,&quot;state&quot;);;addLog(&quot;ez_FHT&quot;,&quot;actuator&quot;);;addLog(&quot;ez_FHT&quot;,&quot;measured-temp&quot;);;addLog(&quot;MunichWeather&quot;,&quot;humidity&quot;);;addLog(&quot;MunichWeather&quot;,&quot;pressure&quot;);;addLog(&quot;MunichWeather&quot;,&quot;temperature&quot;);;addLog(&quot;MunichWeather&quot;,&quot;wind_chill&quot;);;}
<syntaxhighlight lang=text>
attr addLog room 99_System</nowiki>
### Hier ist ein trigger des o.g. notify verwendet, um nicht in beiden at-defines alle Aufrufe listen zu müssen.
 
<nowiki>### Hier ist ein trigger des o.g. notify verwendet, um nicht in beiden at-defines alle Aufrufe listen zu müssen.
define a_midnight1 at *23:59 trigger addLog
define a_midnight1 at *23:59 trigger addLog
attr a_midnight1 room 99_System
attr a_midnight1 room 99_System
define a_midnight2 at *00:01 trigger addLog
define a_midnight2 at *00:01 trigger addLog
attr a_midnight2 room 99_System
attr a_midnight2 room 99_System
# Alternativ können auch die Einzelaufrufe direkt im at erfolgen, zB
# Alternativ können auch die Einzelaufrufe direkt im at erfolgen, z.B.
# define a_midnight_before at *23:59 {addLog(&quot;device&quot;,&quot;reading&quot;)}</nowiki>
define a_midnight_before at *23:59 {addLog("device","reading")}
</syntaxhighlight>
 
===Beispiele mit DOIF ===
Seitdem es [[DOIF]] gibt, lässt sich das Ganze auch etwas anders umsetzen:
 
<syntaxhighlight lang=text>
define DF_addLogDaily DOIF ([23:59] or [00:01]) ({addLog("ez_FHT", "actuator")})
attr DF_addLogDaily room 99_System
attr DF_addLogDaily do always
</syntaxhighlight>
Da mit diesem Aufruf aber die Problematik nur nach unten verschoben wird (Zoom auf Stunde oder Vierteltag),
ist folgendes möglich:
<syntaxhighlight lang=text>
define DF_addLogHourly DOIF ([:59] or [:01]) ({addLog("ez_FHT", "actuator")})
attr DF_addLogHourly room 99_System
attr DF_addLogHourly do always
</syntaxhighlight>
Das Ganze lässt sich auch noch auf minütlich runterbrechen, erzeugt dadurch ggf. eine große Menge Logeinträge. Dies sollte man stets bedenken.


== Log-Beispiele ==
=== Log-Beispiele ===
<nowiki>2012-11-04_23:46:28 ez_Aussensensor T: 9.4 H: 78.5
<syntaxhighlight lang=text>
2012-11-04_23:59:00 ez_Aussensensor T: 9.4 H: 78.5  &lt;&lt; addLog
2012-11-04_23:46:28 ez_Aussensensor T: 9.4 H: 78.5
2012-11-04_23:59:00 ez_FHT actuator: 0%  &lt;&lt; addLog
2012-11-04_23:59:00 ez_Aussensensor T: 9.4 H: 78.5  << addLog
2012-11-04_23:59:00 ez_FHT measured-temp: 17.4  &lt;&lt; addLog
2012-11-04_23:59:00 ez_FHT actuator: 0%  << addLog
2012-11-05_00:01:00 ez_Aussensensor T: 9.4 H: 78.5  &lt;&lt; addLog
2012-11-04_23:59:00 ez_FHT measured-temp: 17.4  << addLog
2012-11-05_00:01:00 ez_FHT actuator: 0%  &lt;&lt; addLog
2012-11-05_00:01:00 ez_Aussensensor T: 9.4 H: 78.5  << addLog
2012-11-05_00:01:00 ez_FHT measured-temp: 17.4  &lt;&lt; addLog
2012-11-05_00:01:00 ez_FHT actuator: 0%  << addLog
2012-11-05_00:24:31 ez_FHT actuator: 0%  &lt;&lt; addLog
2012-11-05_00:01:00 ez_FHT measured-temp: 17.4  << addLog
2012-11-05_00:24:31 ez_FHT actuator: 0%  << addLog
2012-11-05_00:42:32 ez_Aussensensor T: 9.1 H: 78.1
2012-11-05_00:42:32 ez_Aussensensor T: 9.1 H: 78.1
2012-11-05_16:02:59 ez_Aussensensor T: 10.3 H: 65.9
2012-11-05_16:02:59 ez_Aussensensor T: 10.3 H: 65.9
2012-11-05_16:05:56 ez_Aussensensor T: 10.2 H: 66.3
2012-11-05_16:05:56 ez_Aussensensor T: 10.2 H: 66.3
2012-11-05_16:21:47 ez_Aussensensor T: 10.2 H: 66.3  &lt;&lt; addLog
2012-11-05_16:21:47 ez_Aussensensor T: 10.2 H: 66.3  << addLog
2012-11-05_16:21:48 ez_FHT actuator: 100%  &lt;&lt; addLog
2012-11-05_16:21:48 ez_FHT actuator: 100%  << addLog
2012-11-05_16:21:48 ez_FHT measured-temp: 18.5  &lt;&lt; addLog
2012-11-05_16:21:48 ez_FHT measured-temp: 18.5  << addLog
2012-11-05_16:30:26 ez_FHT measured-temp: 18.7
2012-11-05_16:30:26 ez_FHT measured-temp: 18.7
2012-11-05_16:44:18 ez_Aussensensor T: 9.9 H: 65.8</nowiki>
2012-11-05_16:44:18 ez_Aussensensor T: 9.9 H: 65.8
== Nebeneffekte ==
</syntaxhighlight>
addLog verwendet die Funktion trigger. Für fhem ist das gleichwertig mit dem Eintreffen eines Funktelegramms. Es werden also ggf. alle notifies ausgeführt, die für das relevante Gerät abzuarbeiten sind.
Dies ist wohl zu bedenken, bevor man addLog verwendet.


== Bekannte Probleme ==
=== Nebeneffekte ===
Das Modul dewpoint fügt dem state eines device den zusatz "D: xx" hinzu. Timing-abhängig kann dies zu "verwurschtelten" Darstellungen führen. Die Verwendung von addLog in Verbindung mit dewpoint ist daher nicht empfohlen.
<code>addLog</code> verwendet die Funktion <code>trigger</code>.
Für fhem ist das gleichwertig mit dem Eintreffen eines Ereignisses.
Es werden also ggf. alle <code>notifies</code> ausgeführt, die für das relevante Gerät abzuarbeiten sind.
Dies ist wohl zu bedenken, bevor man <code>addLog</code> verwendet.


addLog funktioniert nicht mit HMS-Sensoren, weil im Log keine Einträge hinzugefügt werden. Den Grund weiss ich aber (noch ) nicht, sobald ich was rausfinde oder wenn jemand was weiss, ergänze ich. Diese Liste ist nicht vollständig oder ausschließlich.
=== Bekannte Probleme ===
Das Modul [[dewpoint]] fügt dem <code>state</code> eines <code>device</code> den zusatz <code>D: xx</code> hinzu.
Abhängig vom Timing kann dies zu "verwurschtelten" Darstellungen führen.
Die Verwendung von <code>addLog</code> in Verbindung mit <code>dewpoint</code> ist daher nicht empfohlen.


== Implementierung ==
=== Implementierung ===
Die Routine wird in die lokale Programmdatei integriert, z.B. 99_myUtils.pm, siehe [http://www.fhemwiki.de/wiki/99_myUtils_anlegen 99_myUtils_anlegen].
Die Routine wird in eine lokale Programmdatei integriert, z.B. <code>99_myUtils.pm</code> (siehe [[99 myUtils anlegen]]).
Nach dem hineinkopieren bitte daran denken, ein reload 99_myUtils.pm durchzuführen.
Wird die Funktion dort mit einem externen Editor eingefügt, muss anschließend <code>reload 99_myUtils.pm</code> ausgeführt werden.
Auf Fehlermeldungen im fhem.log achten.
Auf Fehlermeldungen im fhem.log achten.  
 
<syntaxhighlight lang=perl>
<nowiki>#### Log-abriss vermeiden
#### Log-abriss vermeiden
# called by
# called by
# define addLog notify addLog {addLog(&quot;ez_Aussensensor&quot;,&quot;state&quot;);addLog(&quot;ez_FHT&quot;,&quot;actuator&quot;);\
# define addLog notify addLog {addLog("ez_Aussensensor","state");;\
#               addLog(&quot;MunichWeather&quot;,&quot;humidity&quot;);addLog(&quot;MunichWeather&quot;,&quot;pressure&quot;);\
#            addLog("ez_FHT","actuator");;\
#               addLog(&quot;MunichWeather&quot;,&quot;temperature&quot;);addLog(&quot;MunichWeather&quot;,&quot;wind_chill&quot;);}
#           addLog("MunichWeather","humidity");;\
#            addLog("MunichWeather","pressure");;\
#           addLog("MunichWeather","temperature");;\
#            addLog("MunichWeather","wind_chill");;}
# define a_midnight1 at *23:59 trigger addLog
# define a_midnight1 at *23:59 trigger addLog
# define a_midnight2 at *00:01 trigger addLog
# define a_midnight2 at *00:01 trigger addLog
Zeile 70: Zeile 121:
addLog($$) {
addLog($$) {
   my ($logdevice, $reading) = @_; # device and reading to be used
   my ($logdevice, $reading) = @_; # device and reading to be used
   my $logentry = ReadingsVal($logdevice,$reading,&quot;addLog: invalid reading&quot;);
   my $logentry = ReadingsVal($logdevice,$reading,"addLog: invalid reading");
   if ($reading =~ m,state,i) {
   if ($reading =~ m,state,i) {
     fhem &quot;trigger $logdevice $logentry  &lt;&lt; addLog&quot;;
     fhem "trigger $logdevice $logentry  << addLog";
   } else {
   } else {
     fhem &quot;trigger $logdevice $reading: $logentry  &lt;&lt; addLog&quot;;
     fhem "trigger $logdevice $reading: $logentry  << addLog";
   }
   }
}</nowiki>
}
</syntaxhighlight>
 
Zu Problemen mit diesem Code, der auch die Sonderbehandlung des speziellen FHEM-Readings <code>state</code> sicherstellen soll, in Verbindung mit anderen Readingnamen, die den Bestandteil "state" in beliebiger Groß-/Kleinschreibung und an beliebiger Position beinhalten siehe {{Link2Forum|Topic=92111|LinkText=dieses Forenthema}} mit Lösungsansätzen.
 
== Alternativen ==
Um Plot-Abrisse zu vermeiden, kann man auch [[LogProxy]] verwenden (sofern erforderlich in Verbindung mit dem ''createGluedFile''-Attribut des FileLog-Devices).
 
Da das Modul LogProxy direkt auf der Ebene der Darstellung (SVG-Plot Definition) ansetzt, kann es bei der Darstellung von Daten auf andere Weise (z.B. [[Grafana]]) nicht verwendet werden.


[[Kategorie:Code Snippets]]
[[Kategorie:Code Snippets]]
[[Kategorie:Logging]]

Aktuelle Version vom 21. November 2021, 10:28 Uhr

Info green.pngHINWEIS: Es gibt mittlerweile (12/2019) das Attribut addLog für FileLog Devices.

This attribute takes a comma-separated list of devspec:reading:maxInterval triples. You may use regular expressions for reading. The last value of the reading will be written to the logfile, if after maxInterval seconds no event for this device/reading has arrived.

Siehe auch dieses Forenthema.


Attribut addLog

Seit 12/2019 können mit dem Attribut addLog am FileLog Device maximale Zeitspannen vorgegeben werden, nach denen der letzte bekannte Wert des Readings erneut in das Logfile übernommen werden soll, sofern zwischenzeitlich kein neuer Wert eingetroffen ist. Im Attribut sind Triplette in der Form devspec:reading:maxInterval anzugeben, mehrere Einträge durch Komma getrennt. Die betreffenden Devices und Readings können über Regex bestimmt werden.

Timerbasierte Zusatzeinträge

Motivation

Bei Nutzung des Attributs event-on-change werden Log-Einträge nur bei Werteänderung geschrieben. Dies führt

  1. zum Abriss der Logs zum Ende des alten und zum Beginn des neuen Tages
  2. zu inadäquat langen Pausen zwischen Logeinträgen, z.B. für actuator, der z.B. in den Wintermonaten bei Anwesenheit durchgängig 100%, bei Abwesenheit durchgängig 0% betragen kann. Der Wechsel zwischen diesen Werten wird mit langen Flanken dargestellt.

Funktionsweise

Aus diesem Grund wurde die Routine addLog erstellt (siehe Implementierung). Sie fügt zu definierten Zeitpunkten Einträge im Log hinzu. Dadurch sollen die o.g. Effekte vermieden werden. Zusätzliche Einträge sind mit dem Anhang << addLog gekennzeichnet. Der Aufruf erfolgt sinnvollerweise aus einem at oder einem DOIF. Üblich ist der Aufruf für alle Geräte bzw. readings, für die event-on-change gesetzt ist.

Die Routine hat zwei Aufrufparameter:

addLog(<devicename>, <reading>)

Beispiele aus fhem.cfg

### jede Stunde einen Eintrag für FHT actuator
define a_actuator at +*01:00 {addLog("ez_FHT","actuator")}
attr a_actuator room 99_System

addLog für mehrere devices in einem "Makro" zusammenfassen:

define addLog notify addLog {addLog("ez_Aussensensor","state");;\
    addLog("ez_FHT","actuator");;\
    addLog("ez_FHT","measured-temp");;\
    addLog("MunichWeather","humidity");;\
    addLog("MunichWeather","pressure");;\
    addLog("MunichWeather","temperature");;\
    addLog("MunichWeather","wind_chill");;}
attr addLog room 99_System
### Hier ist ein trigger des o.g. notify verwendet, um nicht in beiden at-defines alle Aufrufe listen zu müssen.
define a_midnight1 at *23:59 trigger addLog
attr a_midnight1 room 99_System
define a_midnight2 at *00:01 trigger addLog
attr a_midnight2 room 99_System
# Alternativ können auch die Einzelaufrufe direkt im at erfolgen, z.B.
define a_midnight_before at *23:59 {addLog("device","reading")}

Beispiele mit DOIF

Seitdem es DOIF gibt, lässt sich das Ganze auch etwas anders umsetzen:

define DF_addLogDaily DOIF ([23:59] or [00:01]) ({addLog("ez_FHT", "actuator")})
attr DF_addLogDaily room 99_System
attr DF_addLogDaily do always

Da mit diesem Aufruf aber die Problematik nur nach unten verschoben wird (Zoom auf Stunde oder Vierteltag), ist folgendes möglich:

define DF_addLogHourly DOIF ([:59] or [:01]) ({addLog("ez_FHT", "actuator")})
attr DF_addLogHourly room 99_System
attr DF_addLogHourly do always

Das Ganze lässt sich auch noch auf minütlich runterbrechen, erzeugt dadurch ggf. eine große Menge Logeinträge. Dies sollte man stets bedenken.

Log-Beispiele

2012-11-04_23:46:28 ez_Aussensensor T: 9.4 H: 78.5
2012-11-04_23:59:00 ez_Aussensensor T: 9.4 H: 78.5   << addLog
2012-11-04_23:59:00 ez_FHT actuator: 0%   << addLog
2012-11-04_23:59:00 ez_FHT measured-temp: 17.4   << addLog
2012-11-05_00:01:00 ez_Aussensensor T: 9.4 H: 78.5   << addLog
2012-11-05_00:01:00 ez_FHT actuator: 0%   << addLog
2012-11-05_00:01:00 ez_FHT measured-temp: 17.4   << addLog
2012-11-05_00:24:31 ez_FHT actuator: 0%   << addLog
2012-11-05_00:42:32 ez_Aussensensor T: 9.1 H: 78.1
2012-11-05_16:02:59 ez_Aussensensor T: 10.3 H: 65.9
2012-11-05_16:05:56 ez_Aussensensor T: 10.2 H: 66.3
2012-11-05_16:21:47 ez_Aussensensor T: 10.2 H: 66.3   << addLog
2012-11-05_16:21:48 ez_FHT actuator: 100%   << addLog
2012-11-05_16:21:48 ez_FHT measured-temp: 18.5   << addLog
2012-11-05_16:30:26 ez_FHT measured-temp: 18.7
2012-11-05_16:44:18 ez_Aussensensor T: 9.9 H: 65.8

Nebeneffekte

addLog verwendet die Funktion trigger. Für fhem ist das gleichwertig mit dem Eintreffen eines Ereignisses. Es werden also ggf. alle notifies ausgeführt, die für das relevante Gerät abzuarbeiten sind. Dies ist wohl zu bedenken, bevor man addLog verwendet.

Bekannte Probleme

Das Modul dewpoint fügt dem state eines device den zusatz D: xx hinzu. Abhängig vom Timing kann dies zu "verwurschtelten" Darstellungen führen. Die Verwendung von addLog in Verbindung mit dewpoint ist daher nicht empfohlen.

Implementierung

Die Routine wird in eine lokale Programmdatei integriert, z.B. 99_myUtils.pm (siehe 99 myUtils anlegen). Wird die Funktion dort mit einem externen Editor eingefügt, muss anschließend reload 99_myUtils.pm ausgeführt werden. Auf Fehlermeldungen im fhem.log achten.

#### Log-abriss vermeiden
# called by
# define addLog notify addLog {addLog("ez_Aussensensor","state");;\
#            addLog("ez_FHT","actuator");;\
#            addLog("MunichWeather","humidity");;\
#            addLog("MunichWeather","pressure");;\
#            addLog("MunichWeather","temperature");;\
#            addLog("MunichWeather","wind_chill");;}
# define a_midnight1 at *23:59 trigger addLog
# define a_midnight2 at *00:01 trigger addLog
sub
addLog($$) {
  my ($logdevice, $reading) = @_; # device and reading to be used
  my $logentry = ReadingsVal($logdevice,$reading,"addLog: invalid reading");
  if ($reading =~ m,state,i) {
    fhem "trigger $logdevice $logentry   << addLog";
  } else {
    fhem "trigger $logdevice $reading: $logentry   << addLog";
  }
}

Zu Problemen mit diesem Code, der auch die Sonderbehandlung des speziellen FHEM-Readings state sicherstellen soll, in Verbindung mit anderen Readingnamen, die den Bestandteil "state" in beliebiger Groß-/Kleinschreibung und an beliebiger Position beinhalten siehe dieses Forenthema mit Lösungsansätzen.

Alternativen

Um Plot-Abrisse zu vermeiden, kann man auch LogProxy verwenden (sofern erforderlich in Verbindung mit dem createGluedFile-Attribut des FileLog-Devices).

Da das Modul LogProxy direkt auf der Ebene der Darstellung (SVG-Plot Definition) ansetzt, kann es bei der Darstellung von Daten auf andere Weise (z.B. Grafana) nicht verwendet werden.