Battery-Attribute mehrere Devices zusammenführen

Begonnen von snx, 27 Dezember 2016, 19:49:57

Vorheriges Thema - Nächstes Thema

snx

Ich gestallte derzeit eine Oberfläche für PC und Smartphone zur Übersicht der wichtigsten Informationen sowie einigen simplen Ansteuerungen.
Auf der Übersichtseite habe ich eine Fläche erstellt, worin der Batteriestatus meines systems (Zusammenfassung aller batteriebetrieben Devices) dargestellt wird:
Dabei gibt es 2 Stati:
1. ok - jedes Device meldet "battery ok"
2. nok - mind. ein Device meldet "battery low" - am liebsten noch die Anzahl der Problem-Devices

Nun wollte ich "mal eben" das Pendant zur Datenlieferung in FHEM anlegen :-\

Zur Anzeige der Batteriestände alles Devices in FHEM habe ich eine ReadingsGroup auf *.[Bb]attery angelegt.
Daher habe ich aber immer keine Verdichtung auf einen Status.
Bei dem Thema mehrere "Gerätestatus zusammenführen" landet man direkt bei structure.
Es ist aber ziemlich unpraktisch alle Devices fix anzugeben. Eine generische Definition wie bei der ReadingsGroup wäre natürlich wünschenswert, da immer mal ein neues Gerät hinzukommt ;)

Für monatliche Mails aufgrund von niegrigen Batterieständen habe ich zudem einen Dummy, der via DOIF gesetzt wird, wenn ein Device "Battery low" meldet.
Aber auch hier wüsste ich nicht wie ich einfach die Problematik umgehe, dass bei einer Änderung immer alle Battery-Devices geprüft und konsolidiert werden.

Spätestens wenn ich auch noch die Anzahl der Battery-low-Devices haben möchte komme ich wahrscheinlich nicht um Zusatzcoding (einfache Funktion oder direkt nen kleines Modul) herum..

Hat jemand eine Idee?
Ich bin doch gewiss nicht der erste mit einer solchen Problematik...

KernSani

Hi,

ich stand gerade vor der selben Fragestellung und habe mir kurz eine ganz simple sub gebaut:


sub myUtils_getBatStatus() {
my @list = devspec2array("battery=^(?!\\s*\$).+");
my $state = "ok";
foreach my $dev (@list) {
  if (ReadingsVal($dev,"battery","nok") ne "ok") {return "nok";}
}
return $state;
}


Über die sub aktualisiere ich regelmäßig den Status eines Dummies.

Grüße,

Oli
RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

Otto123

Hi,

da gibt es im Wiki was dazu -> https://wiki.fhem.de/wiki/Batterie%C3%BCberwachung

Ich habe das mit dem notify gemacht. Das läuft bei mir zufriedenstellend.

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

KernSani

Hi Otto,

Ich hatte auch zuerst darüber nachgedacht, den Dummy über notify zu setzen, da ich aber perspektivisch die Routine noch ein klein wenig erweitern will (z.B. zählen von low Battery devices) habe ich es gleich per myUtils gelöst.

Grüße,

Oli
RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

Rheingold

Hi,

ich stehe vor dem gleichen Problem: ich möchte in einem Icon sehen, ob alle Batterien ok sind oder nicht.

Würdest du dein Script teilen, damit andere das gleiche Problem mit deinem Lösungsansatz angehen können? :)
Fhem auf Raspi 3; Jeelink mit 6x TX29DTH; CUL433 mit 9x RCS 1000 N und Somfy-Steuerung; CUL868; MAX-Cube + Thermostate; Philips Hue & Ikea Tradfri; Google Home Assistant; FTUI für Tablet und SmartPhone via Reverse-Proxy

KernSani

#5
oben steht das script ;-)

wobei ich es mittlerweile angepasst habe.

Hier die aktualisierte Version:


sub myUtils_getBatStatus($) {
my ($name) = @_;
my @list = devspec2array("battery=^(?!\\s*\$).+");
my $state = "ok";
my $nokCount = 0;
my $count = 0;
my $nokDevs = "";
foreach my $dev (@list) {
$count++;
if (ReadingsVal($dev,"battery","nok") ne "ok" and ReadingsVal($dev,"ignore",0) != 1) {
$nokCount++;
$state = "nok";
$nokDevs .= $dev.",";
}
}
if ($nokCount == 0) {$nokDevs = "-"};
fhem ("setreading ".$name." totalDev ".$count);
fhem ("setreading ".$name." nokDev ".$nokCount);
fhem ("setreading ".$name." nokDevs ".$nokDevs);
fhem ("set ".$name." ".$state);

}

Das Script befüllt readings eines Dummies mit der Anzahl der Devices (mit "battery" reading), der Anzahl der Devices, die nicht "ok" melden und den nicht-Ok Devicenamen. Aufgeruden wird es bei mir mittels notify:

defmod ev_batteryStatus notify .*:battery.* {myUtils_getBatStatus("batteryStatus")}

der Dummy hat ein stateFormat Attribut, das folgende Sub aufruft:

sub myUtils_batStatusIcon($) {
my ($name) = @_;
my $icon = "";
my $state = ReadingsVal($name,"state","");
if ($state eq "ok") {
$icon = "measure_battery_100\@green";
}
else {
$icon = "measure_battery_25\@red";
}
my $img = FW_makeImage( $icon, $state);
my $text = "<a href='fhem?detail=rg_battery'>".ReadingsVal($name,"nokDev",0)."/".ReadingsVal($name,"totalDev",0)."</a>";
return $img.$text;

}

Dadurch wird ein Icon und die Anzahl der nicht-ok Devices / Total Devices dargestellt. Diese Zahlen verlinken auf meine Batterie-Readingsgroup (rg_battery - hart codiert)

Grüße,

Oli

RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

Rheingold

Zitat von: KernSani am 15 Februar 2017, 22:33:33
Das Script befüllt readings eines Dummies mit der Anzahl der Devices (mit "battery" reading), der Anzahl der Devices, die nicht "ok" melden und den nicht-Ok Devicenamen. Aufgeruden wird es bei mir mittels notify...
der Dummy hat ein stateFormat Attribut, das folgende Sub aufruft:

Hi,

meinst du das so in der config?
define Temp_Batterie dummy
attr Temp_Batterie stateFormat sub myUtils_batStatusIcon($) {\
my ($name) = @_;;\
my $icon = "";;\
my $state = ReadingsVal($name,"state","");;\
if ($state eq "ok") {\
$icon = "measure_battery_100\@green";;\
}\
else {\
$icon = "measure_battery_25\@red";;\
}\
my $img = FW_makeImage( $icon, $state);;\
my $text = "<a href='fhem?detail=rg_battery'>".ReadingsVal($name,"nokDev",0)."/".ReadingsVal($name,"totalDev",0)."</a>";;\
return $img.$text;;\
\
}

define ev_batteryStatus notify .*:battery.* {myUtils_getBatStatus("batteryStatus")}
Fhem auf Raspi 3; Jeelink mit 6x TX29DTH; CUL433 mit 9x RCS 1000 N und Somfy-Steuerung; CUL868; MAX-Cube + Thermostate; Philips Hue & Ikea Tradfri; Google Home Assistant; FTUI für Tablet und SmartPhone via Reverse-Proxy

KernSani

Hi,

die beiden Subs sollten in der 99_myUtils.pm angelegt werden.

Bei mir heisst der Dummy "batteryStatus", dieser name wird auch and die sub im notify übergeben. In deinem Fall müsste es also so aussehen:
define ev_batteryStatus notify .*:battery.* {myUtils_getBatStatus("Temp_Batterie")}

Für das stateFormat:
attr Temp_Batterie stateFormat {myUtils_batStatusIcon($name)}

Grüße,

Oli
RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

Rheingold

Ah jetzt ja :D
Vielen Dank, jetzt siehts in FHEM auch richtig aus.

Hast du das zufällig auch in das Tablet UI eingebunden? ;)

Fhem auf Raspi 3; Jeelink mit 6x TX29DTH; CUL433 mit 9x RCS 1000 N und Somfy-Steuerung; CUL868; MAX-Cube + Thermostate; Philips Hue & Ikea Tradfri; Google Home Assistant; FTUI für Tablet und SmartPhone via Reverse-Proxy

Rheingold

#9
Kleiner Nachtrag noch: Ich sehe zufällig gerade im Log, dass die Aktion Temp_Batterie seeeeehr viele Einträge produziert. Alle haben den gleichen Inhalt:

2017.02.19 10:13:36 3: setreading Temp_Batterie nokDevs  : Usage: setreading <name> <reading> <value>
where <name> is a single device name, a list separated by komma (,) or a regexp. See the devspec section in the commandref.html for details


Ist dir das bekannt?

Ich habe die Definitionen in FHEM mal vorübergehend auskommentiert und nun läuft es schneller/stabiler. Als der Code noch lief, hat mein Tablet UI immer wieder gemeckert, dass die Verbindung verloren gegangen sei. Es scheint wohl oder übel hieran gelegen zu haben :-/

# - Batteriestatus-Abfrage
# define ev_batteryStatus notify .*:battery.* {myUtils_getBatStatus("Temp_Batterie")}
# attr ev_batteryStatus room Temperatur
# define Temp_Batterie dummy
# attr Temp_Batterie room Temperatur
# attr Temp_Batterie stateFormat {myUtils_batStatusIcon($name)}
# define BatterieCheck at *11:59 IF () (set Temp_Batterie:empty)
# attr BatterieCheck room Temperatur

Fhem auf Raspi 3; Jeelink mit 6x TX29DTH; CUL433 mit 9x RCS 1000 N und Somfy-Steuerung; CUL868; MAX-Cube + Thermostate; Philips Hue & Ikea Tradfri; Google Home Assistant; FTUI für Tablet und SmartPhone via Reverse-Proxy

KernSani

Hmmm, die Fehlermeldung ist komisch... kann ich mir aktuell nicht erklären. Unabhängig davon: Hast du bei deinen Sonsoren event-on-change-reading gesetzt?

Edit: Kannst du mal deine myUtils Routine posten?
RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

Rheingold

Ein Event-On-Change habe ich nicht definiert. Macht es Sinn? Ich habe die Temperatur-Sensoren nach dieser Anleitung eingerichtet: http://blog.gestreift.net/2015/04/fhem-temperatur-fuehlen-mit-jeelink/

Hier meine komplette myUtils:
##############################################
# $Id: myUtilsTemplate.pm 7570 2015-01-14 18:31:44Z rudolfkoenig $
#
# Save this file as 99_myUtils.pm, and create your own functions in the new
# file. They are then available in every Perl expression.

package main;

use strict;
use warnings;
use POSIX;

sub
myUtils_Initialize($$)
{
  my ($hash) = @_;
}

# Enter you functions below _this_ line.

#####################################################
#
# Hilfsfunktion für Kalenderauswertungen
#

sub
KalenderDatum($$)
{
   my ($KalenderName, $KalenderUid) = @_;
   my $dt = fhem("get $KalenderName start uid=$KalenderUid 1");
   my $ret = time - (2*86400);  #falls kein Datum ermittelt wird Rückgabewert auf "vorgestern" -> also vergangener Termin;

   if ($dt and $dt ne "")
   {
      my @SplitDt = split(/ /,$dt);
      my @SplitDate = split(/\./,$SplitDt[0]);
      $ret = timelocal(0,0,0,$SplitDate[0],$SplitDate[1]-1,$SplitDate[2]);
   }

   return $ret;
}


#
# Abfall Kalender auswerten / Google Kalender: "Abfall"
#

sub
Abfalltermine()
{
   my $t  = time;
   my @Tonnen = ("Papier", "GelberSack", "Restmuell", "BioTonne");
   my @SuchTexte = (".*Papier.*", ".*GelberSack.*", ".*Restmuell.*", ".*Biotonne.*");
   my $uid;
   my $dayDiff;
 
   for(my $i=0; $i<4; $i++)
   {
      $dayDiff = -1; #BUG behoben
      my @uids = split(/;/,fhem("get Abfall find $SuchTexte[$i]"));
       
      # den nächsten Termine finden
      foreach $uid (@uids)
      {
         my $eventDate = KalenderDatum('Abfall', $uid);
         my $dayDiffNeu = floor(($eventDate - $t) / 60 / 60 / 24 + 1);
         if ($dayDiffNeu >= 0 && ($dayDiffNeu < $dayDiff || $dayDiff == -1)) #BUG behoben
         {
            $dayDiff = $dayDiffNeu;
         }
      }
       
      fhem("setreading MuellterminDummy $Tonnen[$i] $dayDiff");
   }
}
# Ende Abfallkalender
#####################################################

#####################################################
# Anruf Funktionen
#
sub CheckAnrufe($)
{
   my ($aktion) = @_;

   #bei ausgehenden Anrufen wird der Dummy hochgezählt
   if (ReadingsVal("fbCallMonitor", "direction", "outgoing") eq "incoming")
   {
      fhem("set duVerpassteAnrufe ".(Value("duVerpassteAnrufe")+1));
   }
}
# Ende Anruf Funktion
#####################################################

#####################################################
# Batterie-Statusabfrage
sub myUtils_getBatStatus($) {
my ($name) = @_;
my @list = devspec2array("battery=^(?!\\s*\$).+");
my $state = "ok";
my $nokCount = 0;
my $count = 0;
my $nokDevs = "";
foreach my $dev (@list) {
$count++;
if (ReadingsVal($dev,"battery","nok") ne "ok" and ReadingsVal($dev,"ignore",0) != 1) {
$nokCount++;
$state = "nok";
$nokDevs .= $dev.",";
}
}
fhem ("setreading ".$name." totalDev ".$count);
fhem ("setreading ".$name." nokDev ".$nokCount);
fhem ("setreading ".$name." nokDevs ".$nokDevs);
fhem ("set ".$name." ".$state);

}

sub myUtils_batStatusIcon($) {
my ($name) = @_;
my $icon = "";
my $state = ReadingsVal($name,"state","");
if ($state eq "ok") {
$icon = "measure_battery_100\@green";
}
else {
$icon = "measure_battery_25\@red";
}
my $img = FW_makeImage( $icon, $state);
my $text = "<a href='fhem?detail=rg_battery'>".ReadingsVal($name,"nokDev",0)."/".ReadingsVal($name,"totalDev",0)."</a>";
return $img.$text;

}
# Ende Batterie-Statusabfrage
#####################################################



1;
Fhem auf Raspi 3; Jeelink mit 6x TX29DTH; CUL433 mit 9x RCS 1000 N und Somfy-Steuerung; CUL868; MAX-Cube + Thermostate; Philips Hue & Ikea Tradfri; Google Home Assistant; FTUI für Tablet und SmartPhone via Reverse-Proxy

KernSani

Hab's... der Fehler kommt, weil nokDevs leer ist... muss ich heute abend mal ran...
RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

KernSani

Event-on-change-reading macht m.E. Sinn, um die Anzahl der events (und log-Einträge) zu reduzieren. Bei temperature und humidity habe ich auch noch thresholds, da mich nicht jede 0.1 Grad Änderung interessiert...
RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

Rheingold

Es freut mich, wenn ich mit meiner Meldung dazu beitragen kann, dass dein Script/Modul stabiler wird :)

Danke für den Tipp mit dem Event-On-Change. Habe es mal angepasst auf:
attr Temp_Draussen event-on-change-reading temperature:0,1,humidity:1
usw.
Fhem auf Raspi 3; Jeelink mit 6x TX29DTH; CUL433 mit 9x RCS 1000 N und Somfy-Steuerung; CUL868; MAX-Cube + Thermostate; Philips Hue & Ikea Tradfri; Google Home Assistant; FTUI für Tablet und SmartPhone via Reverse-Proxy