Batterieüberwachung: Unterschied zwischen den Versionen

Aus FHEMWiki
K (Änderung der Bedingung)
(Code für pushover geändert (Leerzeichen, Log3))
 
(18 dazwischenliegende Versionen von 10 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
[[:Kategorie:FS20 Components|FS20 Sender]] und [[:Kategorie:HomeMatic Components|Homematic-Komponenten]] übermitteln unter anderem den Zustand der eingelegten Batterie. Um Ausfälle frühzeitig zu erkennen, kann man sich per E-Mail benachrichtigen lassen, sobald eine Batteriemeldung mit etwas anderem als "ok" gesendet wird (z.B. "low"). Zusätzlich erzeugt der unten stehende Code einen Eintrag im Logfile.
Verschiedene batteriebetriebene Geräte ([[:Kategorie:HomeMatic Components|Homematic]], RFXtrx, ZWave,..) übermitteln unter anderem den Zustand der eingelegten Batterie. Bei diesen kann der Batteriestatus übersichtlich dargestellt und / oder aktiv überwacht werden. Bei Geräten ohne eigenen Batteriestatus muss man diesen "nachrüsten".


  <nowiki>define n_batt_chk notify .*:[Bb]attery.* { $EVENT !~ m/ok/) { \
== Geräte mit Batteriestatus ==
=== Übersichtsdarstellung per readingsGroup ===
Mit Hilfe einer ReadingsGroup kann einfach eine Übersicht aller Geräte mit "battery"-Reading erstellt werden, s. [[ReadingsGroup#Auswahl_.C3.BCber_Reading-Namen.2C_Status_als_Symbol_dargestellt|hier]].
 
=== Benachrichtigung per notify ===
Um Ausfälle frühzeitig zu erkennen, kann man sich per E-Mail benachrichtigen lassen, sobald eine Batteriemeldung mit etwas anderem als "ok" gesendet wird (z.B. "low"). Zusätzlich erzeugt der unten stehende Code einen Eintrag im Logfile. Der Code ist für die Raw Definition und nicht für den DEF Editor!
 
  <nowiki>define n_batt_chk notify .*:[Bb]attery.* { if ($EVENT !~ m/ok/) { \
   { FB_mail('recipient@internet.de', 'FHEM Batteriewarnung', $NAME.': '.$EVENT)};; \
   { FB_mail('recipient@internet.de', 'FHEM Batteriewarnung', $NAME.': '.$EVENT)};; \
   Log 3, "$NAME : Batteriewarnung $EVENT";; \
   Log 3, "$NAME : Batteriewarnung $EVENT";; \
Zeile 13: Zeile 20:
Man würde bei der Verwendung des o.g. Codes bei jeder Batteriemeldung eines HM-CC-RT-DN eine E-Mail erhalten. Daher muss der o.g. Code wie folgt geändert werden (Doppelpunkt hinter "[Bb]attery"):
Man würde bei der Verwendung des o.g. Codes bei jeder Batteriemeldung eines HM-CC-RT-DN eine E-Mail erhalten. Daher muss der o.g. Code wie folgt geändert werden (Doppelpunkt hinter "[Bb]attery"):


  <nowiki>define n_batt_chk notify .*:[Bb]attery:.* { if("%"&#160;!~ m/ok/) { \
  <nowiki>define n_batt_chk notify .*:[Bb]attery:|.*:[Bb]atteryS { if($EVENT !~ m/ok/) { \
   { FB_mail('recipient@internet.de', 'FHEM Batteriewarnung', '@&#160;%')};; \
   { FB_mail('recipient@internet.de', 'FHEM Batteriewarnung', $NAME.': '.$EVENT)};; \
   Log 3, "$NAME: Batteriewarnung $EVENT";; \
   Log 3, "$NAME: Batteriewarnung $EVENT";; \
   } \
   } \
Zeile 20: Zeile 27:


Achtung: FB_mail setzt die Installation auf einer FritzBox voraus. Für andere Hardware-/OS-Plattformen ist die Vorgehensweise unter dem Titel [[E-Mail_senden]] beschrieben.
Achtung: FB_mail setzt die Installation auf einer FritzBox voraus. Für andere Hardware-/OS-Plattformen ist die Vorgehensweise unter dem Titel [[E-Mail_senden]] beschrieben.
Wer statt einer email lieber eine Pushover-Nachricht auf sein Smartphone bekommen möchte, kann diesen Code benutzen:
<nowiki>define n_batt_chk notify .*:[Bb]attery:|.*:[Bb]atteryS { if($EVENT !~ m/ok/) { \                                                                                                   
  fhem ("set PushoverChristoph msg FHEM Batteriewarnung, $NAME: $EVENT:\nBatterien sollten demnächst gewechselt werden!");; \
  Log3($NAME, 3, "Batteriewarnung $EVENT");; \
  } \
}</nowiki>
Natürlich muß dafür eine Pushover-Installation in fhem vorhanden sein - sonst bitte gem. [[Pushover]] nachholen.


Testen kann man dies z.B. mit <code>trigger HeizungWZ Battery:low</code>
Testen kann man dies z.B. mit <code>trigger HeizungWZ Battery:low</code>


Man sollte auch darauf achten, dass sich das Ereignis, auf das man triggert, nicht zu häufig wiederholt (z.B. durch das Attribut <code>event-on-change-reading</code>).
Man sollte auch darauf achten, dass sich das Ereignis, auf das man triggert, nicht zu häufig wiederholt (z.B. durch das Attribut <code>event-on-change-reading</code>).
== Geräte ohne Batteriestatus ==
Bei Geräten ohne Reading für den Batteriestatus kann man diesen auf verschiedene Weisen schätzen und als Reading eintragen. Dies funktioniert aber natürlich nur, wenn das Gerät sendet - bei einem rein empfangenden Aktor wie dem [[FHT 8v direkt ansprechen|FHT Stellantrieb]] klappt es also nicht...
=== Erweiterung des Geräts um battery-Reading ===
Mit Hilfe von {{Link2CmdRef|Lang=de|Anker=userReadings|Label=userReadings}} kann man recht einfach einen Batteriestatus schätzen und als Reading bereitstellen. Dann greift auch direkt die oben beschriebene Auswertung.
Die Idee ist, den zeitlichen Abstand des aktuellen Timestamps mit dem letzten geloggten Timestamp zu vergleichen und daraus auf den Batteriestatus zu schliessen - bspw. Abstand > 10min = Batterie low.
Dazu muss lediglich folgendes userReading für jedes batteriebetriebene Device (ohne Batteriestatus) angelegt werden (um bei >10min "low" zu setzen):
; Konfiguration:
Lediglich der Schwellwert (600) braucht nach Wunsch angepasst zu werden, alles andere passt automatisch (vgl. [[Notify#Hinweise]]).
; Im Webinterface:
<pre>
battery { return "ok" if ( (time_str2num(ReadingsTimestamp($NAME,"state","0")) - time_str2num(OldTimestamp($NAME))) < 600 ); return "low" }
</pre>
; Alternativ im Config-File:
<pre>
attr MeinSensor userReadings battery { return "ok" if ( (time_str2num(ReadingsTimestamp($NAME,"state","0")) - time_str2num(OldTimestamp($NAME))) < 600 ); return "low" }
</pre>
; Erläuterung:
: <code>$NAME</code> - ist die Variable für das Device (und braucht nicht angepasst zu werden)
: <code>battery {...}</code> - Name des userreadings mit Spezifikation, vgl. {{Link2CmdRef|Lang=de|Anker=userReadings}}.
: <code>return "ok" if ( ... ); return "low"</code> - Spezifikation: Reading = "ok", wenn if erfüllt, sonst "low"
: <code>time_str2num(ReadingsTimestamp($NAME,"state","0")</code> - Aktueller Timestamp in Sekunden, vgl. {{Link2CmdRef|Lang=de|Anker=perl}}, [[Notify#Hinweise]]
: <code>time_str2num(OldTimestamp($NAME))</code> - Letzter Timestamp im Log in Sekunden (egal ob FileLog oder DbLog), vgl. {{Link2CmdRef|Lang=de|Anker=perl}}, [[Notify#Hinweise]]
: <code>600</code> - Schwellwert für "low" (600 sec = 10 min), nach Bedarf anpassen
=== Alternativ per Skript ===
Andere Komponenten, wie z. B. [[:Kategorie:FS20 Components|FS20 Komponenten]], übermitteln keinen Batteriestatus.
Um dort dennoch einen Test darauf zu machen, ob die Batterie evtl. leer ist, kann man z. B. prüfen, wann der letzte Status des jeweiligen Gerätes empfangen wurde, etwa mit folgender Funktion in [[99_myUtils_anlegen|99_myUtils.pm]]:
<pre>sub check_if_alive($$) {
  # Expects:
  # 1. Devicename to be checked
  # 2. Age in hours, after the expiry of which with no new state the device will be considered as dead.
  # Returns:
  # 0 -> Device dead
  # 1 -> Device alive
  # 2 -> Error
  my ($Device,$hours_threshold) = @_;
  my ($Device) = @_;
  my $now = time;
  my $Timestamp = ReadingsTimestamp($Device,"state","0");
  if ($Timestamp eq "0") {
    return 2;
  }
  my @splitdatetime = split(/ /,$Timestamp);
  my @splitdate = split(/-/, $splitdatetime[0]);
  my @splittime = split(/:/, $splitdatetime[1]);
  my $last_state_time =  timelocal($splittime[2], $splittime[1], $splittime[0], $splitdate[2], $splitdate[1]-1, $splitdate[0]);
  my $age_in_hours = ($now - $last_state_time) / 3600;
  if ($age_in_hours > $hours_threshold) {
    Log 1, ("check_if_alive: $Device dead, last state was $age_in_hours hours ago");
    return 0;
  } else {
    return 1;
  }
 
}</pre>
Diese Funktion kann man z.B. in einem at je zu prüfendem Gerät regelmäßig (z. B. einmal am Tag um 05:55 Uhr) aufrufen, und testen, ob die letzten 12 Stunden etwas empfangen wurde:
<pre>*05:55:55 {
  check_if_alive("KS300", 12);
}</pre>
KS300 ist dabei der Name des Devices in fhem.
Wenn das Gerät nicht geantwortet hat, erzeugt die oben vorgeschlagene Funktion einen Logeintrag.
Hinweis: Dieser Batterietest schlägt natürlich auch an, wenn die FS20 Geräte noch funktionieren, aber der CUL zum Empfangen der Signale nicht mehr funktioniert. In dem Fall sind dann auf einen Schlag angeblich alle Batterien leer. Um dies zumindest teilweise abzufangen, könnte man vor dem Erzeugen des Logeintrags noch auf den state des CUL testen, dass dieser nicht "disconnected" ist.
==== Visualisierung ====
Der Abschnitt Links unten enthält einen Verweis, wie man den Batteriestatus visuell anzeigen kann. Das funktioniert mit der oben vorgeschlagenen Funktion mit einigen Ergänzungen auch, wenn das Gerät selbst keinen Batteriestatus anzeigt.
Dafür braucht man einen zusätzlichen Dummy je zu überwachendem Gerät, mit dem Namen dum_<zu_überwachendes_Gerät>_dead. Für das Gerät KS300 heißt dieser dummy also z. B. dum_KS300_dead:
<pre>Internals:
  NAME      dum_KS300_dead
  NR        795
  STATE      nein
  TYPE      dummy
  Readings:
    2015-04-28 07:47:48  state          nein
Attributes:
  devStateIcon ja:measure_battery_50@red nein:measure_battery_100@green</pre>
Dieser dummy soll hier die Zustände "ja" und "nein" annehmen können. Bei ja ist ihm über devStateIcon ein rotes Icon einer eher leeren Batterie zugewiesen, bei nein ein grünes Icon einer vollen Batterie.
Nun muss noch die oben vorgeschlagene Funktion angepasst werden, um den Zustand des dummy entsprechend dem ermittelten Batteriestatus neu zu setzen. Dafür wird die Abfrage des Alters am Ende der Funktion um eine Zeile erweitert, die den Status des dummy setzt:
<pre>  if ($age_in_hours > $hours_threshold) {
    Log 1, ("check_if_alive: $Device dead, last state was $age_in_hours hours ago");
    fhem("set dum_".$Device."_dead ja");
    return 0;
  } else {
    fhem("set dum_".$Device."_dead nein");
    return 1;
  }</pre>
   
Den Dummy mit diesem devStateIcon kann man so der unter "Links" unten vorgeschlagenen readingsGroup hinzufügen, und damit auch Geräte ohne eigenen Batteriestatus überwachen.
== Links ==
* [[ReadingsGroup#Auswahl_.C3.BCber_Reading-Namen.2C_Status_als_Symbol_dargestellt|visuelle Batterieüberwachung mit readingsGroup]]
* {{Link2CmdRef|Lang=de|Anker=userReadings}} - userReadings
* {{Link2CmdRef|Lang=de|Anker=perl}} - Perl specials
* [[Notify#Hinweise|Hinweise zu Variablen]] (ansonsten auch an div. Stellen in der {{Link2CmdRef}})


[[Kategorie:HOWTOS]]
[[Kategorie:HOWTOS]]

Aktuelle Version vom 29. Dezember 2020, 10:56 Uhr

Verschiedene batteriebetriebene Geräte (Homematic, RFXtrx, ZWave,..) übermitteln unter anderem den Zustand der eingelegten Batterie. Bei diesen kann der Batteriestatus übersichtlich dargestellt und / oder aktiv überwacht werden. Bei Geräten ohne eigenen Batteriestatus muss man diesen "nachrüsten".

Geräte mit Batteriestatus

Übersichtsdarstellung per readingsGroup

Mit Hilfe einer ReadingsGroup kann einfach eine Übersicht aller Geräte mit "battery"-Reading erstellt werden, s. hier.

Benachrichtigung per notify

Um Ausfälle frühzeitig zu erkennen, kann man sich per E-Mail benachrichtigen lassen, sobald eine Batteriemeldung mit etwas anderem als "ok" gesendet wird (z.B. "low"). Zusätzlich erzeugt der unten stehende Code einen Eintrag im Logfile. Der Code ist für die Raw Definition und nicht für den DEF Editor!

define n_batt_chk notify .*:[Bb]attery.* { if ($EVENT !~ m/ok/) { \
  { FB_mail('recipient@internet.de', 'FHEM Batteriewarnung', $NAME.': '.$EVENT)};; \
   Log 3, "$NAME : Batteriewarnung $EVENT";; \
  } \
 }

Achtung: Für Nutzer eines HM-CC-RT-DN muss der Code anders aussehen, da mit diesem Thermostat erstmalig der aktuelle Spannungswert der Batterie gesendet wird, also z.B.:

UG.Treppe.Heizung batteryLevel: 3.1 V

Man würde bei der Verwendung des o.g. Codes bei jeder Batteriemeldung eines HM-CC-RT-DN eine E-Mail erhalten. Daher muss der o.g. Code wie folgt geändert werden (Doppelpunkt hinter "[Bb]attery"):

define n_batt_chk notify .*:[Bb]attery:|.*:[Bb]atteryS { if($EVENT !~ m/ok/) { \
  { FB_mail('recipient@internet.de', 'FHEM Batteriewarnung', $NAME.': '.$EVENT)};; \
   Log 3, "$NAME: Batteriewarnung $EVENT";; \
  } \
 }

Achtung: FB_mail setzt die Installation auf einer FritzBox voraus. Für andere Hardware-/OS-Plattformen ist die Vorgehensweise unter dem Titel E-Mail_senden beschrieben.

Wer statt einer email lieber eine Pushover-Nachricht auf sein Smartphone bekommen möchte, kann diesen Code benutzen:

define n_batt_chk notify .*:[Bb]attery:|.*:[Bb]atteryS { if($EVENT !~ m/ok/) { \                                                                                                    
  fhem ("set PushoverChristoph msg FHEM Batteriewarnung, $NAME: $EVENT:\nBatterien sollten demnächst gewechselt werden!");; \
  Log3($NAME, 3, "Batteriewarnung $EVENT");; \
  } \
 }

Natürlich muß dafür eine Pushover-Installation in fhem vorhanden sein - sonst bitte gem. Pushover nachholen.


Testen kann man dies z.B. mit trigger HeizungWZ Battery:low

Man sollte auch darauf achten, dass sich das Ereignis, auf das man triggert, nicht zu häufig wiederholt (z.B. durch das Attribut event-on-change-reading).

Geräte ohne Batteriestatus

Bei Geräten ohne Reading für den Batteriestatus kann man diesen auf verschiedene Weisen schätzen und als Reading eintragen. Dies funktioniert aber natürlich nur, wenn das Gerät sendet - bei einem rein empfangenden Aktor wie dem FHT Stellantrieb klappt es also nicht...

Erweiterung des Geräts um battery-Reading

Mit Hilfe von userReadings kann man recht einfach einen Batteriestatus schätzen und als Reading bereitstellen. Dann greift auch direkt die oben beschriebene Auswertung.

Die Idee ist, den zeitlichen Abstand des aktuellen Timestamps mit dem letzten geloggten Timestamp zu vergleichen und daraus auf den Batteriestatus zu schliessen - bspw. Abstand > 10min = Batterie low.

Dazu muss lediglich folgendes userReading für jedes batteriebetriebene Device (ohne Batteriestatus) angelegt werden (um bei >10min "low" zu setzen):

Konfiguration

Lediglich der Schwellwert (600) braucht nach Wunsch angepasst zu werden, alles andere passt automatisch (vgl. Notify#Hinweise).

Im Webinterface
battery { return "ok" if ( (time_str2num(ReadingsTimestamp($NAME,"state","0")) - time_str2num(OldTimestamp($NAME))) < 600 ); return "low" }
Alternativ im Config-File
attr MeinSensor userReadings battery { return "ok" if ( (time_str2num(ReadingsTimestamp($NAME,"state","0")) - time_str2num(OldTimestamp($NAME))) < 600 ); return "low" }
Erläuterung
$NAME - ist die Variable für das Device (und braucht nicht angepasst zu werden)
battery {...} - Name des userreadings mit Spezifikation, vgl. commandref/userReadings.
return "ok" if ( ... ); return "low" - Spezifikation: Reading = "ok", wenn if erfüllt, sonst "low"
time_str2num(ReadingsTimestamp($NAME,"state","0") - Aktueller Timestamp in Sekunden, vgl. commandref/perl, Notify#Hinweise
time_str2num(OldTimestamp($NAME)) - Letzter Timestamp im Log in Sekunden (egal ob FileLog oder DbLog), vgl. commandref/perl, Notify#Hinweise
600 - Schwellwert für "low" (600 sec = 10 min), nach Bedarf anpassen

Alternativ per Skript

Andere Komponenten, wie z. B. FS20 Komponenten, übermitteln keinen Batteriestatus.

Um dort dennoch einen Test darauf zu machen, ob die Batterie evtl. leer ist, kann man z. B. prüfen, wann der letzte Status des jeweiligen Gerätes empfangen wurde, etwa mit folgender Funktion in 99_myUtils.pm:

sub check_if_alive($$) {
  # Expects:
  # 1. Devicename to be checked
  # 2. Age in hours, after the expiry of which with no new state the device will be considered as dead.
  # Returns:
  # 0 -> Device dead
  # 1 -> Device alive
  # 2 -> Error
  my ($Device,$hours_threshold) = @_;
  my ($Device) = @_;
  my $now = time;
  my $Timestamp = ReadingsTimestamp($Device,"state","0");
  if ($Timestamp eq "0") {
    return 2;
  }

  my @splitdatetime = split(/ /,$Timestamp);
  my @splitdate = split(/-/, $splitdatetime[0]);
  my @splittime = split(/:/, $splitdatetime[1]);
  my $last_state_time =  timelocal($splittime[2], $splittime[1], $splittime[0], $splitdate[2], $splitdate[1]-1, $splitdate[0]);
  my $age_in_hours = ($now - $last_state_time) / 3600;

  if ($age_in_hours > $hours_threshold) {
    Log 1, ("check_if_alive: $Device dead, last state was $age_in_hours hours ago");
    return 0;
  } else {
    return 1;
  }
   
}

Diese Funktion kann man z.B. in einem at je zu prüfendem Gerät regelmäßig (z. B. einmal am Tag um 05:55 Uhr) aufrufen, und testen, ob die letzten 12 Stunden etwas empfangen wurde:

*05:55:55 { 
  check_if_alive("KS300", 12);
}

KS300 ist dabei der Name des Devices in fhem.

Wenn das Gerät nicht geantwortet hat, erzeugt die oben vorgeschlagene Funktion einen Logeintrag.

Hinweis: Dieser Batterietest schlägt natürlich auch an, wenn die FS20 Geräte noch funktionieren, aber der CUL zum Empfangen der Signale nicht mehr funktioniert. In dem Fall sind dann auf einen Schlag angeblich alle Batterien leer. Um dies zumindest teilweise abzufangen, könnte man vor dem Erzeugen des Logeintrags noch auf den state des CUL testen, dass dieser nicht "disconnected" ist.

Visualisierung

Der Abschnitt Links unten enthält einen Verweis, wie man den Batteriestatus visuell anzeigen kann. Das funktioniert mit der oben vorgeschlagenen Funktion mit einigen Ergänzungen auch, wenn das Gerät selbst keinen Batteriestatus anzeigt.

Dafür braucht man einen zusätzlichen Dummy je zu überwachendem Gerät, mit dem Namen dum_<zu_überwachendes_Gerät>_dead. Für das Gerät KS300 heißt dieser dummy also z. B. dum_KS300_dead:

Internals: 
   NAME       dum_KS300_dead 
   NR         795 
   STATE      nein 
   TYPE       dummy 
   Readings: 
     2015-04-28 07:47:48   state           nein 
Attributes: 
   devStateIcon ja:measure_battery_50@red nein:measure_battery_100@green

Dieser dummy soll hier die Zustände "ja" und "nein" annehmen können. Bei ja ist ihm über devStateIcon ein rotes Icon einer eher leeren Batterie zugewiesen, bei nein ein grünes Icon einer vollen Batterie.

Nun muss noch die oben vorgeschlagene Funktion angepasst werden, um den Zustand des dummy entsprechend dem ermittelten Batteriestatus neu zu setzen. Dafür wird die Abfrage des Alters am Ende der Funktion um eine Zeile erweitert, die den Status des dummy setzt:

  if ($age_in_hours > $hours_threshold) {
    Log 1, ("check_if_alive: $Device dead, last state was $age_in_hours hours ago");
    fhem("set dum_".$Device."_dead ja");
    return 0;
  } else {
    fhem("set dum_".$Device."_dead nein");
    return 1;
  }

Den Dummy mit diesem devStateIcon kann man so der unter "Links" unten vorgeschlagenen readingsGroup hinzufügen, und damit auch Geräte ohne eigenen Batteriestatus überwachen.

Links