Regex und Zeitspanne seit letzter Reading-Änderung

Begonnen von alpha1974, 01 September 2018, 21:24:30

Vorheriges Thema - Nächstes Thema

alpha1974

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
FHEM/Z-Wave USB-Dongle + div. Devices

Damian

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.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

alpha1974

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.
FHEM/Z-Wave USB-Dongle + div. Devices

Damian

(["^Presence_SP111:presence"] or [?sonoffSP111_1:transmission-state:sec]>600 or [?sonoffSP111_2:transmission-state:sec]>600) ()
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

alpha1974

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...
FHEM/Z-Wave USB-Dongle + div. Devices

Damian

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")
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

alpha1974

#6
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.
FHEM/Z-Wave USB-Dongle + div. Devices

Damian

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.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Damian

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!"}}
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Per

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 600
und
do resetwait
Aber für jedes Reading ein DOIF, weil DOIF (ohne Perl) nur ein Timer verwalten kann.

alpha1974

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
FHEM/Z-Wave USB-Dongle + div. Devices

Damian

#11
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
  }
}
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

alpha1974

#12
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\
  }\
}
FHEM/Z-Wave USB-Dongle + div. Devices

Damian

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 ;)
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

alpha1974

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 :)
FHEM/Z-Wave USB-Dongle + div. Devices