Hallo,
ich brauche (mal wieder...) einen kurzen Denkanstoß zu Doif und Regex. Ich möchte mit einem Doif mehrere PRESENCE-Devices und zusätzlich die Zeitspanne der letzten Reading-Änderung überwachen. So ist es bislang realisiert:
((["^Presence_SP111"] eq "absent") or ([sonoffSP111_1:transmission-state:sec]>600) or ([sonoffSP111_2:transmission-state:sec]>600)) ()
Ich weiß, der Ausführungsteil ist noch leer, es geht mir um die Optimierung des Bedingungsteils. Ich habe es nicht hinbekommen, die beiden letzten or-Bedingungen mit Regex zusammenzufassen.
Das klappt leider nicht:
["^sonoffSP111:transmission-state:sec"]>600
Wo liegt mein Denkfehler? Das triggern auf die beiden Presence-Devices, deren Namen mit "Presence_SP111" beginnen, klappt hingegen mit (["^Presence_SP111"] eq "absent") problemlos.
Besten Dank und Gruß
alpha1974
Zitat von: alpha1974 am 01 September 2018, 21:24:30
Hallo,
ich brauche (mal wieder...) einen kurzen Denkanstoß zu Doif und Regex. Ich möchte mit einem Doif mehrere PRESENCE-Devices und zusätzlich die Zeitspanne der letzten Reading-Änderung überwachen. So ist es bislang realisiert:
((["^Presence_SP111"] eq "absent") or ([sonoffSP111_1:transmission-state:sec]>600) or ([sonoffSP111_2:transmission-state:sec]>600)) ()
Ich weiß, der Ausführungsteil ist noch leer, es geht mir um die Optimierung des Bedingungsteils. Ich habe es nicht hinbekommen, die beiden letzten or-Bedingungen mit Regex zusammenzufassen.
Das klappt leider nicht:
["^sonoffSP111:transmission-state:sec"]>600
Wo liegt mein Denkfehler? Das triggern auf die beiden Presence-Devices, deren Namen mit "Presence_SP111" beginnen, klappt hingegen mit (["^Presence_SP111"] eq "absent") problemlos.
Besten Dank und Gruß
alpha1974
1. (["^Presence_SP111"] eq "absent") funktioniert nicht, da "^Presence_SP111" ein Ereignis darstellt, welches nur wahr oder nicht wahr ist. Es ist kein Reading, das einen Inhalt hätte.
1. ["^sonoffSP111:transmission-state:sec"] diese Syntax gibt es nicht. sec gibt er nur in Verbindung mit Readings wie bei [sonoffSP111_1:transmission-state:sec]. Abgesehen davon wäre die Angabe 0 zum Zeitpunkt des Triggers, daher macht auch nur [?sonoffSP111_1:transmission-state:sec] als Abfrage einen Sinn, weil sie nicht triggert.
Super, vielen Dank für die Denkanstöße.
Ziel soll sein, dass mir das DOIF eine Nachricht schickt (Ausführungsteil kommt noch),
Wenn
1. eines der Presence-Devices (Presence_SP111_1 oder Presence_SP111_2) mit dem Reading "presence" auf "absent" geht (dachte, es ginge auch ohne Reading, da der state des Devices dem Presence-Reading entspricht)
oder wenn
2. sich bei den Devices sonoffSP111_1 oder sonoffSP111_2 länger als 10 Minuten das Reading transmission-state nicht verändert hat.
Jetzt sieht die Syntax bei mir so aus:
((["^Presence_SP111:presence"] eq "absent") or ([?sonoffSP111_1:transmission-state:sec]>600) or ([?sonoffSP111_2:transmission-state:sec]>600)) ()
Da vermutlich noch weitere Devices mit dem Namensmuster sonoffSP111_... und Presence_SP111_... hinzukommen, hatte ich die Hoffnung, ein universelles DOIF hinzubekommen. Also auch mittels Regex auch die Zeitspanne seit der letzten Veränderung des Readings transmission-state auswerten zu können, ohne für jedes Einzeldevice eine entsprechende Bedingung einfügen zu müssen.
(["^Presence_SP111:presence"] or [?sonoffSP111_1:transmission-state:sec]>600 or [?sonoffSP111_2:transmission-state:sec]>600) ()
Den Presence-Teil habe ich noch nicht ganz verstanden. Die Presence-Devices erzeugen standardmäßig regelmäßige Events, bei denen state/STATE und das Reading "presence" auf "present" oder "absent" gesetzt werden.
Das DOIF soll aber nur anschlagen, wenn state oder das Reading "presence" auf "absent" geht. Ich habe diesen Teil jetzt mal so umgebaut:
(["^Presence_SP111:presence"] and [$DEVICE:presence] eq "absent")
Uff, ganz schon knifflig...
Zitat von: alpha1974 am 02 September 2018, 14:28:14
Den Presence-Teil habe ich noch nicht ganz verstanden. Die Presence-Devices erzeugen standardmäßig regelmäßige Events, bei denen state/STATE und das Reading "presence" auf "present" oder "absent" gesetzt werden.
Das DOIF soll aber nur anschlagen, wenn state oder das Reading "presence" auf "absent" geht. Ich habe diesen Teil jetzt mal so umgebaut:
(["^Presence_SP111:presence"] and [$DEVICE:presence] eq "absent")
Uff, ganz schon knifflig...
besser
(["^Presence_SP111:presence: absent")
Top! So läuft es (habe noch eine ] ergänzt). Ich habe die Wifi-Steckdosen-Überwachung jetzt auf zwei DOIFs aufgeteilt.
Zur Überwachung der Presence-Devices Presence_SP111_1 und Presence_SP111_2 (die die Steckdosen regelmäßig anpingen):
(["^Presence_SP111:presence: absent"]) (set jabber msg xxx@xxx.net FHEM: $DEVICE absent)
DOELSEIF (["^Presence_SP111:presence: present"]) (set jabber msg xxx@xxx.net FHEM: $DEVICE wieder present)
attr DI_Presence_SP111_absent do always
attr DI_Presence_SP111_absent repeatsame 1:1
attr DI_Presence_SP111_absent room Überwachung
Zusätzlich für das Ausbleiben von regelmäßigen MQTT-Meldungen der Steckdosen (sonoffSP111_1 und sonoffSP111_2):
(["^sonoffSP111:SENSOR"]) (defmod at_$DEVICE at +00:10 set jabber msg xxx@xxx.net FHEM: $DEVICE sendet seit 10 Minuten nicht mehr!)
Wenn ich eine weitere Steckdose einbinden will, kann ich das MQTT-Device dann sonoffSP111_3 und das Presence-Device Presence_SP111_3 nennen. Dann sollten die beiden o.g. DOIFs die neue Steckdose direkt mit überwachen.
Zitat von: alpha1974 am 02 September 2018, 15:47:09
Top! So läuft es (habe noch eine ] ergänzt). Ich habe die Wifi-Steckdosen-Überwachung jetzt auf zwei DOIFs aufgeteilt.
Zur Überwachung der Presence-Devices Presence_SP111_1 und Presence_SP111_2 (die die Steckdosen regelmäßig anpingen):
(["^Presence_SP111:presence: absent"]) (set jabber msg xxx@xxx.net FHEM: $DEVICE absent)
DOELSEIF (["^Presence_SP111:presence: present"]) (set jabber msg xxx@xxx.net FHEM: $DEVICE wieder present)
attr DI_Presence_SP111_absent do always
attr DI_Presence_SP111_absent repeatsame 1:1
attr DI_Presence_SP111_absent room Überwachung
Zusätzlich für das Ausbleiben von regelmäßigen MQTT-Meldungen der Steckdosen (sonoffSP111_1 und sonoffSP111_2):
(["^sonoffSP111:SENSOR"]) (defmod at_$DEVICE at +00:10 set jabber msg xxx@xxx.net FHEM: $DEVICE sendet seit 10 Minuten nicht mehr!)
Wenn ich eine weitere Steckdose einbinden will, kann ich das MQTT-Device dann sonoffSP111_3 und das Presence-Device Presence_SP111_3 nennen. Dann sollten die beiden o.g. DOIFs die neue Steckdose direkt mit überwachen.
attr DI_Presence_SP111_absent do always
attr DI_Presence_SP111_absent repeatsame 1:1
hebt sich gegenseitig auf. Es ist das Gleiche, als wenn du beide nicht gesetzt hättest.
DOIF (["^sonoffSP111:SENSOR"]) (defmod at_$DEVICE at +00:10 set jabber msg xxx@xxx.net FHEM: $DEVICE sendet seit 10 Minuten nicht mehr!)
lässt sich in einem Modul (ohne at) erledigen:
DOIF {if (["^sonoffSP111:SENSOR"]) {set_Timer("$DEVICE",600)}} \
{if (["$SELF:$DEVICE"]) {fhem"set jabber msg xxx@xxx.net FHEM: $DEVICE sendet seit 10 Minuten nicht mehr!"}}
Zitat von: alpha1974 am 02 September 2018, 13:28:592. sich bei den Devices sonoffSP111_1 oder sonoffSP111_2 länger als 10 Minuten das Reading transmission-state nicht verändert hat.
wait 600und
do resetwaitAber für jedes Reading ein DOIF, weil DOIF (ohne Perl) nur ein Timer verwalten kann.
Zitat von: Damian am 02 September 2018, 16:33:36
lässt sich in einem Modul (ohne at) erledigen:
DOIF {if (["^sonoffSP111:SENSOR"]) {set_Timer("$DEVICE",600)}} \
{if (["$SELF:$DEVICE"]) {fhem"set jabber msg xxx@xxx.net FHEM: $DEVICE sendet seit 10 Minuten nicht mehr!"}}
Die Lösung gefällt mir ausgesprochen gut!
Jetzt würde mich noch interessieren, wie ich es in dem o.g. Konstrukt umsetzen kann, dass mir (einmalig) eine Nachricht geschickt, wenn das Device wieder sendet. Ich habe mich bei meinen Versuchen leider hoffnungslos im Perl-else und in den Attributen do always / repeatsame verheddert :-[
Gruß
alpha1974
Zitat von: alpha1974 am 03 September 2018, 15:53:57
Die Lösung gefällt mir ausgesprochen gut!
Jetzt würde mich noch interessieren, wie ich es in dem o.g. Konstrukt umsetzen kann, dass mir (einmalig) eine Nachricht geschickt, wenn das Device wieder sendet. Ich habe mich bei meinen Versuchen leider hoffnungslos im Perl-else und in den Attributen do always / repeatsame verheddert :-[
Gruß
alpha1974
Ein Vorteil bei DOIF-Perl ist, dass du ohne Attribute auskommst, da kannst du schon mal nichts falsch machen :)
Die Perl-Syntax ist nicht wesentlich komplizierter: if (bedingung) {...} else {...}
Da du Ereignisse mit [...] wie beim DOIF FHEM-Modus verwenden kannst, ist da nicht mehr so viel, was man am Anfang noch lernen müsste.
DOIF
{
if (["^sonoffSP111:SENSOR"]) { # wenn Sensor sendet
if ($_meldung{$device}==1) { # wenn es bereits eine Meldung zum Device gab
fhem"set jabber msg xxx@xxx.net FHEM: $device sendet wieder!" # Meldung ok
$_meldung{$device}=0; # Fehlermeldung zurücksetzen
}
set_Timer("Timer_$device",600); # Timer setzen mit dem Namen des Devices im Event
}
}
{
if (["$SELF:^Time_"]) { # Wenn ein Timer abläuft
my ($time,$device)=split("_","$EVENT"); # hole das Device aus dem Event
fhem"set jabber msg xxx@xxx.net FHEM: $device sendet seit 10 Minuten nicht mehr!"} # Meldung
$_meldung{$device}=1; # Meldung für Device merken
}
}
Ich bin für perl wohl zu blöd. Mit deinem Code erhalte ich folgende Fehlermeldung:
PERL WARNING: Use of uninitialized value in numeric eq (==) at (eval 546) line 3.
EDIT: Damit läuft es jetzt ganz gut, habe ein defined in die If-Abfrage eingebaut (außerdem musste ich noch ein @-Zeichen maskieren und die Split-Funktion anpassen, weil auch im Device-Namen ein Unterstrich auftaucht):
{\
if (["^sonoffSP111:SENSOR"]) { # wenn Sensor sendet\
if (defined($_meldung{$device}) && $_meldung{$device}==1) { # wenn es bereits eine Meldung zum Device gab\
fhem"set jabber msg xxx\@xxx.net DI_sonoffSP111_silence_perl: $device sendet wieder!";; # Meldung ok\
$_meldung{$device}=0;; # Fehlermeldung zurücksetzen\
}\
set_Timer("Timer_$device",600);; # Timer setzen mit dem Namen des Devices im Event\
} \
}\
{\
if (["$SELF:^Timer_"]) { # Wenn ein Timer abläuft\
my ($time,$device)=split("Timer_","$EVENT");; # hole das Device aus dem Event\
fhem"set jabber msg xxx\@xxx.net DI_sonoffSP111_silence_perl: $device sendet seit 10 Minuten nicht mehr!";; # Meldung\
$_meldung{$device}=1;; # Meldung für Device merken\
}\
}
Zitat von: alpha1974 am 03 September 2018, 19:00:52
Ich bin für perl wohl zu blöd. Mit deinem Code erhalte ich folgende Fehlermeldung:
PERL WARNING: Use of uninitialized value in numeric eq (==) at (eval 546) line 3.
EDIT: Damit läuft es jetzt ganz gut, habe ein defined in die If-Abfrage eingebaut (außerdem musste ich noch ein @-Zeichen maskieren und die Split-Funktion anpassen, weil auch im Device-Namen ein Unterstrich auftaucht):
{\
if (["^sonoffSP111:SENSOR"]) { # wenn Sensor sendet\
if (defined($_meldung{$device}) && $_meldung{$device}==1) { # wenn es bereits eine Meldung zum Device gab\
fhem"set jabber msg xxx\@xxx.net DI_sonoffSP111_silence_perl: $device sendet wieder!";; # Meldung ok\
$_meldung{$device}=0;; # Fehlermeldung zurücksetzen\
}\
set_Timer("Timer_$device",600);; # Timer setzen mit dem Namen des Devices im Event\
} \
}\
{\
if (["$SELF:^Timer_"]) { # Wenn ein Timer abläuft\
my ($time,$device)=split("Timer_","$EVENT");; # hole das Device aus dem Event\
fhem"set jabber msg xxx\@xxx.net DI_sonoffSP111_silence_perl: $device sendet seit 10 Minuten nicht mehr!";; # Meldung\
$_meldung{$device}=1;; # Meldung für Device merken\
}\
}
Na dann, bist ja jetzt der perfekte DOIF-Perl-Anwender ;)
Zitat von: Damian am 03 September 2018, 19:50:07
Na dann, bist ja jetzt der perfekte DOIF-Perl-Anwender ;)
Zuviel der Ehre! ::) Ich habe eine gefühlte Ewigkeit gebraucht, um eine eigentlich simple Aufgabenstellung zu lösen. Aber das Ergebnis kann sich ja sehen lassen und zeigt wieder einmal, wie unglaublich flexibel DOIF ist. Allerdings befürchte ich, dass ich spätestens in vier Wochen wieder die Grundlagen vergessen habe...
Aber wer weiß... vielleicht bringt ja irgendwann ein DOIF-Update die Möglichkeit, Regexp fürs Device/Reading mit "sec" zu kombinieren nach dem Muster [?"^sonoffSP111:transmission-state":sec]>600 :)
Zitat von: alpha1974 am 04 September 2018, 07:52:09
Zuviel der Ehre! ::) Ich habe eine gefühlte Ewigkeit gebraucht, um eine eigentlich simple Aufgabenstellung zu lösen. Aber das Ergebnis kann sich ja sehen lassen und zeigt wieder einmal, wie unglaublich flexibel DOIF ist. Allerdings befürchte ich, dass ich spätestens in vier Wochen wieder die Grundlagen vergessen habe...
Aber wer weiß... vielleicht bringt ja irgendwann ein DOIF-Update die Möglichkeit, Regexp fürs Device/Reading mit "sec" zu kombinieren nach dem Muster [?"^sonoffSP111:transmission-state":sec]>600 :)
Na ja, so etwas wie [?"^sonoffSP111:transmission-state":sec] gehört schon zum Thema Aggregationsfunktionen, denn ohne Trigger weiß man nicht welches Device gemeint ist, also muss man alle im System abscannen und davon kann es mehrere geben. Mit Trigger ist es wiederum sinnfrei, weil sec logischerweise zum Triggerzeitpunkt 0 ist.