Zyklische Überprüfung von Readings

Begonnen von Klinki, 22 Oktober 2015, 11:43:11

Vorheriges Thema - Nächstes Thema

Klinki

Moin,

Aufgabenstellung:
- Ich wollte, dass zu einer bestimmten Zeit geprüft wird ob alle Fenster im Haus zu sind. Wenn nicht, soll eine Nachricht auf dem Handy erscheinen
- Meine Tür/Fenster-Kontakte sind unterschiedlichen Typs (Homematic, FS20...)

Bei meiner Suche bin ich auf den Code aus dem Wiki gestoßen: http://www.fhemwiki.de/wiki/Zyklische_%C3%9Cberpr%C3%BCfung_von_Ger%C3%A4ten_mit_Benachrichtigung_per_Email
Schon mal eine sehr feine Idee!!
Leider konnte ich das so nicht übernehmen, da der Status von Geräten per get abgefragt wird und FS20-Geräte nicht auf get antworten.
Also habe ich den Code modifiziert, so dass das Reading betrachtet wird. Man möge mir den schlechten Code verzeihen. Perl ist einfach nicht meine Welt...

Da ich mein FHEM auf einem Raspberry Pi 2 betreibe, habe ich auf eine ältere Funktion "DebianMail" zurückgegriffen. Diese verwendet das Tool sendEMail. Muss ggf. noch installiert werden.

Aufruf
1. Parameter
Es wird ein Suchmuster erstellt (wie bei list). Intern wird eine Liste mit passenden Geräten generiert und für jedes Gerät das hinterlegte Reading abgefragt. Als Drittes wird der erwartete Wert für "AllesInOrdnung" hinterlegt. Gitb das Readding einen anderen Wert zurück, wird das als Fehler gewertet.

Diese 3 Werte für das Such- und FindMuster können als komma-separierte Liste eingegeben werden
Beispiel: TYPE=CUL_FHTTK,Battery,ok,.*_TFK.*:FILTER=TYPE=CUL_HM,battery,ok,TYPE=FHT,battery,ok,TYPE=HMS,battery,ok,TYPE=LaCrosse,battery,ok


2. Parameter
Die E-Mail-Adressen der Empfänger. Ebenfalls als Komma-separierte Liste. Das @ muss mit einem Backslash entwertet werden

3. Parameter (Info/Error)
Soll die Mail immer alle Werte (also auch wenn alles OK ist) enthalten, oder nur wenn ein Problem auftritt

Hier der Aufruf in der fhem.cfg: "Überprüfe, ob Batterien OK sind - außer am Wochenende ::)"
Das Suchmuster ist leider so aufwändig, da manche Geräte das Reading "Battery" haben und nicht "battery".
Außerdem will man auch nicht alle Gerät drin haben, wie z.B. den VCCU bei Homematic oder generell Geräte, die gar keine Batterie intus haben

define checkDevice_Batterie at *12:00:00 {\
if ( !$we ) {\
  checkDevice("TYPE=CUL_FHTTK,Battery,ok,.*_TFK.*:FILTER=TYPE=CUL_HM,battery,ok,TYPE=FHT,battery,ok,TYPE=HMS,battery,ok,TYPE=LaCrosse,battery,ok","XXX\@api.pushover.net","Info");;\
}\
}
attr checkDevice_Batterie room Hilfsmodule


Hier der Aufruf in der fhem.cfg: "Überprüfe, ob alle Fenster zu sind - außer am Wochenende"
## Das @ der E-Mail Adresse muss entwertet werden
define checkDevice_FensterOffen at *06:00:00 {\
if ( !$we ) {\
  checkDevice(".*_TFK.*,state,closed","XXX\@api.pushover.net","Error");;\
}\
}
attr checkDevice_FensterOffen room Hilfsmodule




Hier die relevanten Zeilen aus meiner 99_MyUtils.pm
 
package main;

use strict;
use warnings;
use POSIX;
use Net::SMTP;

######## DebianMail  Mail auf dem RPi versenden ############
sub
DebianMail
{
my $rcpt = shift;
my $subject = shift;
my $text = shift;
my $ret = "FHEM Raspi";
my $sender = "ABSENDER\@MEINEDOMAIN.ORG";
my $konto = "KONTOBEIPROVIDER";
my $passwrd = "FUCKINGPASSWORD";
my $provider = "smtp.1und1.de:25";
Log 1, "sendEmail RCP: $rcpt";
Log 1, "sendEmail Subject: $subject";
Log 1, "sendEmail Text: $text";

$ret .= qx(sendEmail -f '$sender' -t '$rcpt' -u '$subject' -m '$text' -s '$provider' -xu '$konto' -xp '$passwrd' -o tls=no -o message-charset=utf-8);
$ret =~ s,[\r\n]*,,g;    # remove CR from return-string
Log 1, "sendEmail returned: $ret";
}




##############################################
# Prozedur zur Überprüfung der Geräte
# Parameter:
#   1. Suchstring für die Geräte und der Parameter (z.B. TYPE=CUL_FHTTK,Battery,ok)
#     Es werden 3 Parameter erwartet:
# 1. Suchstring (.*_TFK.*:FILTER=TYPE=CUL_HM  > alle Geräte mit _TFK im Namen vom Typ Homematic)
# 2. Reading, case-sensitiv
# 3. iO Wert. Ergebnis des Readings muss dem iO-Wert entsprechen. Sonst wird Error ausgegeben. nicht case-sensitiv
#   4. Empfänger Emailadressen (z.B. recipient@fhem.de,recipient1@fhem.de)
#   5. Mailbenachrichtigung bei (Info,Error)
#
##############################################


sub
checkDevice($$$)
{

my($deviceParameter,$mailrecipient,$checkDevice_mailsend) = @_;



        if ( $deviceParameter eq "???" ) {
                Log 3, "Abbruch: checkDevice_device_parameter ist nicht initialisiert";
                return;
        }
        if ( $mailrecipient eq "???" ) {
                Log 3, "Abbruch: checkDevice_recipient ist nicht initialisiert";
                return;
        }
        if ( $checkDevice_mailsend eq "???" ) {
                Log 3, "Abbruch: checkDevice_mailsend ist nicht initialisiert";
                return;
        }

my @deviceParameterArray = split(/,/,$deviceParameter);

        if ( (scalar(@deviceParameterArray) % 3) ) {
                Log 3, "Abbruch: checkDevice_device_parameter enthält eine unglültige Anzahl von Parametern";
                return;
        }

my ($Sekunden, $Minuten, $Stunden, $Monatstag, $Monat, $Jahr, $Wochentag, $Jahrestag, $Sommerzeit) = localtime(time);

$Monat += 1;
$Jahr += 1900;

$Sekunden = sprintf("%02d", $Sekunden);
$Minuten = sprintf("%02d", $Minuten);
$Stunden = sprintf("%02d", $Stunden);
$Monatstag = sprintf("%02d", $Monatstag);
$Monat = sprintf("%02d", $Monat);


$mailrecipient =~ tr/;/,/;

my @mailrecipientArray = split(/,/,$mailrecipient);
my $recipient;
my $device;
my $deviceCounter;
my $deviceValue;
my $error=0;
my $deviceString;
my $deviceListe;
my @deviceArray;

my $deviceOKParameter;

my $mailsubject_info = "Info zum StasiHaus am $Monatstag\.$Monat\.$Jahr um $Stunden:$Minuten:$Sekunden";
my $mailsubject_error = "FehlerMeldung von StasiHaus am $Monatstag\.$Monat\.$Jahr um $Stunden:$Minuten:$Sekunden";

#my $mailHeader ="Start der Prüfung: $Stunden:$Minuten:$Sekunden $Monatstag\.$Monat\.$Jahr\n";
my $mailHeader ="";
my $mailData;
my $mailDataError;
my $devicename;
my $str_reading;
my $str_alias;

for ($deviceCounter=0;$deviceCounter<=$#deviceParameterArray;$deviceCounter+=3) {

$deviceString = $deviceParameterArray[$deviceCounter];
$deviceParameter = $deviceParameterArray[($deviceCounter)+1];
$deviceOKParameter = $deviceParameterArray[($deviceCounter)+2];

# tmi
#$mailData = $mailData."\n\nSuchstring fuer die Geräte: ".$deviceString."\n";
#$mailData = $mailData."Parameter der Geräte: ".$deviceParameter."\n\n";

$deviceListe = fhem("list $deviceString");

$deviceListe =~ tr/\n/,/;

@deviceArray = split(/,/,$deviceListe);

foreach $device (@deviceArray) {

$device =~ s/^(.*) (.*)$/$1/;

#$deviceValue = fhem("get $device $deviceParameter");
# Trim
$device =~ s/^\s+|\s+$//g;+
#$device = lc($device);

# Name des Reading. Ist CS
#$deviceParameter = lc($deviceParameter);
$deviceOKParameter = lc($deviceOKParameter);

$str_reading = "{ReadingsVal('" . $device . "' ,'" . $deviceParameter . "','') }";
$str_alias = "{AttrVal('" . $device . "' ,'alias','NAMENLOS') }";

$deviceValue = fhem(" $str_reading ");
$devicename = fhem(" $str_alias ");
       
$deviceValue = lc($deviceValue);

if ( $deviceValue eq "???" ) {
$error++;
$deviceValue = "Error";
$mailDataError = "$mailDataError $deviceValue \n";
}
if ( $deviceValue eq "" ) {
$error++;
$deviceValue = "Error";
$mailDataError = "$mailDataError $deviceValue \n";
}

if ( $deviceValue !~ m/$deviceOKParameter/ ) {
$error++;
$deviceValue = "Achtung! " . $devicename. " (". $device . ") -> " . $deviceValue ;
$mailDataError = "$mailDataError $deviceValue \n";
}

$mailData = "$mailData$devicename ($device)\t$deviceValue\n";
}
}


if ($checkDevice_mailsend eq "Info")
{
$mailData ="$mailHeader\n$mailData\n";
if ( $error > 0 )
{
foreach $recipient (@mailrecipientArray)
{
DebianMail($recipient,$mailsubject_error,$mailData);
}
}
else
{
foreach $recipient (@mailrecipientArray)
{
DebianMail($recipient,$mailsubject_info,$mailData);
}
}
}

if ($checkDevice_mailsend eq "Error")
{
$mailData ="$mailHeader\n$mailDataError\n";
if ( $error > 0 )
{
foreach $recipient (@mailrecipientArray)
{
DebianMail($recipient,$mailsubject_error,$mailData);
}
}
}

}




Vielleicht nutzt es euch ja. Viel Spaß!