Hauptmenü

$EVENT vs $EVENTS?

Begonnen von vbs, 12 März 2017, 11:03:15

Vorheriges Thema - Nächstes Thema

vbs

Hi,

ich hätte mal zwei Fragen zu der Eventverarbeitung (hängen irgendwie zusammen).

1. Was ist der Unterschied zwischen $EVENT und $EVENTS?
Die commandref sagt:
$EVENT
für das zugehörige Ereignis

$EVENTS
für alle zugehörigen Ereignisse eines Triggers


Was bedeutet "für alle zugehörigen Ereignisse eines Triggers"? Es kann doch immer nur ein Event gleichzeitig passieren, oder? Wie können zu einem Trigger mehrere Events gehören?

2. Ich verstehe ein Reading meines DOIFs nicht (ähnliche Thematik):
Das ist mein Device:
Internals:
   CHANGED
   DEF        ([env_presence:"^state:"]) ({updateDevices("$DEVICE", "$EVENT")})
   NAME       sys_di_updateDevices
   NR         519
   NTFY_ORDER 50-sys_di_updateDevices
   STATE      cmd_1
   TYPE       DOIF
   Readings:
     2017-03-12 10:06:40   Device          env_presence
     2017-03-12 10:06:40   cmd             1
     2017-03-12 10:06:40   cmd_event       env_presence
     2017-03-12 10:06:40   cmd_nr          1
     2017-03-12 10:06:40   e_env_presence_events state: home,statHomeDuration: Hour: 66.705714448 Day: 660.185474630 Month: 11432.228700591 Year: 23787.504933322 (since: 2017-02-16 ),statHomeDurationDay: 660.185474630,statHomeDurationMonth: 11432.228700591,statHomeDurationYear: 23787.504933322
     2017-03-12 10:06:40   state           cmd_1
     2017-03-12 10:06:40   wait_timer      no timer


Das DOIF soll auf alle state-Events von "env_presence" reagieren. Im Reading "e_env_presence_events" stehen aber offenbar durch Komma getrennt mehrere Events drin. Nämlich "state: home" und die ganzen statistic-Events.

Was bedeutet das? Das DOIF sollte doch mit dem Statistik-Event eigentlich nichts zu tun haben?

Danke euch!

Damian

Ein Trigger ist oft mehr als eine Ereigniszeile. Das kannst du im Eventmonitor am gleichen Zeitstempel erkennen. All die zusammengehörenden Ereignisse werden an ein Modul zum Zeitpunkt des Triggers übergeben. Das sind $EVENTS. $EVENT ist dagegen nur die Zeile die genau zu einem Ereignisfilter passt. Das ist z.B. bei Angaben [device:"regex"] interessant. Bei Angaben [device:reading] nimm ich einfach die erste Ereigniszeile für $EVENT, weil hier auf alle Trigger des Devices reagiert wird, ob das Reading drin vorkommt oder nicht.

Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

vbs

Ahh ok danke. Ich vermute mal, dass passiert nur, wenn ein Modul per readingsBeginUpdate/readingsBulkUpdate/readingsEndUpdate mehrere Events auf einmal absetzt? Könnte mir zumindest sonst nicht erklären, wie das technisch funktioniert. FHEM müsste sonst ja eine Zeit lang Events sammeln und sie dann geschlossen den Modulen zustellen.

Damian

Zitat von: vbs am 12 März 2017, 12:46:38
Ahh ok danke. Ich vermute mal, dass passiert nur, wenn ein Modul per readingsBeginUpdate/readingsBulkUpdate/readingsEndUpdate mehrere Events auf einmal absetzt? Könnte mir zumindest sonst nicht erklären, wie das technisch funktioniert. FHEM müsste sonst ja eine Zeit lang Events sammeln und sie dann geschlossen den Modulen zustellen.

Genau. Das sollten alle Module tun, denn dafür sind diese Trigger-Mechanismen geschaffen worden.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

PatrickR

Mahlzeit!

Sorry, dass ich diesen Dinosaurierthread defibrilliere, aber mein aktuelles Problem knüpft hier so schön an.

Folgende Situation:
Ich habe ein DOIF geschrieben, was deviceunabhängig verschiedene Fehler-Events von allen Homematic-IP-Geräten sammelt. Das DOIF geht davon aus, dass $EVENT exakt ein Event enthält. Heute Morgen trat allerdings der Fall auf, dass mehrere Events kommagetrennt geliefert wurden, was zu einem kleinen Chaos geführt hat.


defmod D_S_HMIP_Problems DOIF {\
  if ([":^0\.(ERROR_CODE|ERROR_OVERHEAT|UNREACH|DUTY_CYCLE): \d+"]) {\
  my ($reading, $value) = "$EVENT" =~ m/^(.*):\s+(.*)$/g;;\
  Log(3,"$SELF: Device Event - Device: '$DEVICE', Event: '$EVENT', Reading: '$reading', Value: '$value'");;\
if ($value != 0) {\
set_Timer ("CALLBACK__$DEVICE__$reading", 60);;\
if (ReadingsVal("$SELF", "READINGS", "") !~ m/(^|;;)$reading($|;;)/g) { # DOIF doesnt tolerate square brackets\
my @readings = split(";;", ReadingsVal("$SELF", "READINGS", ""));;\
push(@readings, $reading);;\
set_Reading("READINGS", join(";;", @readings), 0);;\
}\
} else {\
del_Timer ("CALLBACK__$DEVICE__$reading");;\
my $problem_devices = ReadingsVal("$SELF", "PROBLEMS__$reading", "");;\
$problem_devices =~ s/(^|;;)$DEVICE($|;;)//g;;\
set_Reading("PROBLEMS__$reading", $problem_devices, 1);;\
}\
  }\
}\
[zweiter Fall der Timer-Bearbeitung ausgelassen.]


Im Log stand Folgendes:

2018.07.08 11:47:41.767 3: D_S_HMIP_Problems: Device Event - Device: 'UG.KE.Stromzaehler', Event: '0.STICKY_UNREACH: 1,0.UNREACH: 1,hmstate: unreachable', Reading: '0.STICKY_UNREACH: 1,0.UNREACH: 1,hmstate', Value: 'unreachable'
2018.07.08 11:47:41.768 3: eval: D_S_HMIP_Problems: warning in condition c01
2018.07.08 12:04:00.854 3: D_S_HMIP_Problems: Device Event - Device: 'UG.KE.Stromzaehler', Event: '0.UNREACH: 0,1.ENERGY_COUNTER: 729299.300000,1.POWER: 1099.000000,hmstate: Initialized,1.ENERGY_COUNTER_FHEM: 729246.101123,stat1.ENERGY_COUNTER_FHEM: Hour: 1080.100000 Day: 7040.100000 Month: 101453.500781 Year: 705733.501123 (since: 2018-05-24 ),stat1.ENERGY_COUNTER_FHEMHour: 1080.100000,stat1.ENERGY_COUNTER_FHEMDay: 7040.100000,stat1.ENERGY_COUNTER_FHEMMonth: 101453.500781,stat1.ENERGY_COUNTER_FHEMYear: 705733.501123', Reading: '0.UNREACH: 0,1.ENERGY_COUNTER: 729299.300000,1.POWER: 1099.000000,hmstate: Initialized,1.ENERGY_COUNTER_FHEM: 729246.101123,stat1.ENERGY_COUNTER_FHEM: Hour: 1080.100000 Day: 7040.100000 Month: 101453.500781 Year: 705733.501123 (since: 2018-05-24 ),stat1.ENERGY_COUNTER_FHEMHour: 1080.100000,stat1.ENERGY_COUNTER_FHEMDay: 7040.100000,stat1.ENERGY_COUNTER_FHEMMonth: 101453.500781,stat1.ENERGY_COUNTER_FHEMYear', Value: '705733.501123'


Nach der Info oben sollte $EVENT ausschließlich das matchende Event, nämlich 0.UNREACH enthalten.
Was übersehe ich?

Patrick
lepresenced - Tracking von Bluetooth-LE-Tags (Gigaset G-Tag) mittels PRESENCE

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning." - Rich Cook

Damian

#5
Ich habe gerade im Sourcecode nachgeschaut, bei EventTriggerabfragen wie in deinem Fall, wird eine kommagtrennte Liste der zusammengehörenden Events in $event abgelegt:

$hash->{helper}{event}=join(",",@{$eventa})


In den Ferien werde ich mir die Sache genauer anschauen, denn bei Eventabfragen sollte eigentlich nur das passende Event gespeichert werden.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

PatrickR

#6
Danke Dir!

Muss ich mal sehen, wie ich damit umgehe...  Hast Du zufällig ne Idee für einen temporären Workaround (ohne die Liste der interessanten Readings zu doppeln)?


Von unterwegs gesendet.
lepresenced - Tracking von Bluetooth-LE-Tags (Gigaset G-Tag) mittels PRESENCE

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning." - Rich Cook

Damian

Zitat von: PatrickR am 08 Juli 2018, 23:14:37
Danke Dir!

Muss ich mal sehen, wie ich damit umgehe...  Hast Du zufällig ne Idee für einen temporären Workaround (ohne die Liste der interessanten Readings zu doppeln)?


Von unterwegs gesendet.

Mit split könntest du die Events in einer Schleife prüfen.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

PatrickR

Zitat von: Damian am 09 Juli 2018, 08:00:19
Mit split könntest du die Events in einer Schleife prüfen.
Wie mache ich das, ohne die Liste der interessanten Readings zu doppeln?


Von unterwegs gesendet.
lepresenced - Tracking von Bluetooth-LE-Tags (Gigaset G-Tag) mittels PRESENCE

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning." - Rich Cook

Damian

Zitat von: PatrickR am 09 Juli 2018, 18:14:27
Wie mache ich das, ohne die Liste der interessanten Readings zu doppeln?


Von unterwegs gesendet.

foreach my $e (split(",",$event)) {
my ($reading, $value) = $e =~ m/^(.*):\s+(.*)$/g;
...
}


sollte funktionieren.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Damian

Ich habe das Problem gefunden.

Im FHEM-Modus ist die Bedingung und der Ausführungsteil getrennt, dort beinhaltet $EVENT tatsächlich den Match.
Im Perl-Modus entspricht der ganze Block der DOIF-Bedingung im FHEM-Modus (wird mit eval ausgewertet), DOIF kommt nicht mehr dazwischen um $EVENT vorzubelegen.

Der Match der letzten Eventabfrage ist allerdings intern unter $hash->{helper}{event} abgelegt.

Daher reicht:

my ($reading, $value) = "$EVENT" =~ m/^(.*):\s+(.*)$/g;

durch

my ($reading, $value) = $hash->{helper}{event} =~ m/^(.*):\s+(.*)$/g;

zu ersetzen.

Da wollen wir hoffen, dass der undokumentierte Hack zukünftig immer noch funktioniert. ;)
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Damian

Eine weitere Alternative ohne Hacks ist DOIF-Filter zu verwenden. Dann braucht man noch nicht mal if.

statt
Zitatif ([":^0\.(ERROR_CODE|ERROR_OVERHEAT|UNREACH|DUTY_CYCLE): \d+"]) {
     my ($reading, $value) = "$EVENT" =~ m/^(.*):\s+(.*)$/g;

definieren:

Zitatmy $event =[":^0\.(ERROR_CODE|ERROR_OVERHEAT|UNREACH|DUTY_CYCLE): \d+":"(.*)",0];
my ($reading, $value) = $event =~ m/^(.*):\s+(.*)$/g;
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

PatrickR

#12
Hallo Damian,

damit wir uns nicht missverstehen. Mir ging es nur um einen Tipp, wie ich das Doppeln der Readings verhindere, nicht um einen Grundkurs in der geheimen Kunst der Stringverarbeitung :)

Letztlich - korrigiere mich, wenn ich falsch liege - kann kann ich die Doppelung (gemeint ist die des Strings ERROR_CODE|ERROR_OVERHEAT|UNREACH|DUTY_CYCLE) nur mit der Hack-Variante mit dem helper umgehen. Die werde ich mir jetzt näher ansehen.

Interessant dürfte vor allem sein, was passiert, wenn mehrere matchende Events in einem Stapel vorbeikommen. Wie willst Du in der gefixten Version damit umgehen? Die Events vereinzeln und den Ausführungsteil mehrfach ausführen oder übergibst Du dann in $EVENT die Liste der matchenden(!) Events?

Patrick

lepresenced - Tracking von Bluetooth-LE-Tags (Gigaset G-Tag) mittels PRESENCE

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning." - Rich Cook

Damian

Zitat von: PatrickR am 09 Juli 2018, 21:10:57
Hallo Damian,

damit wir uns nicht missverstehen. Mir ging es nur um einen Tipp, wie ich das Doppeln der Readings verhindere, nicht um einen Grundkurs in der geheimen Kunst der Stringverarbeitung :)

Letztlich - korrigiere mich, wenn ich falsch liege - kann kann ich die Doppelung (gemeint ist des Strings ERROR_CODE|ERROR_OVERHEAT|UNREACH|DUTY_CYCLE) nur mit der Hack-Variante mit dem helper umgehen. Die werde ich mir jetzt näher ansehen. Interessant dürfte vor allem sein, was passiert, wenn mehrere matchende Events in einem Stapel vorbeikommen.

Patrick

Was verstehst du unter Dopplung? Wenn du alle Events eines Event-Blocks meinst, dann funktioniert das, wie beschrieben,  nicht in der Perl-Variante mit $EVENT bzw. $event als echte Perlvariable.

Unabhängig davon wird nur der erste Match eines Events-Blocks gespeichert, denn dann ist die Bedingung bereits wahr und es wird nicht weiter geprüft (dafür sind in erster Linie die Eventabfragen ["..."] programmiert worden).

Wenn du alle Events eines Event-Block (gleicher Zeipunkt) auswerten willst, dann musst über die Schleife gehen - mein Beispiel mit foreach-Schleife.


Meistens kommt aber immer nur ein Event-Typ (Reading) in einem Event-Block vor, wie eine z. B. Fehlermeldung ERROR_CODE|ERROR_OVERHEAT|UNREACH|DUTY_CYCLE

Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

PatrickR

#14
Zitat von: Damian am 09 Juli 2018, 21:29:09
Was verstehst du unter Dopplung?

Ich meine, dass ich die Liste der interessanten Readings sowohl in der DOIF-Bedingung als auch in der foreach-Zerlegung des Eventstapels benötige:

{
  if ([":^0\.(ERROR_CODE|ERROR_OVERHEAT|UNREACH|DUTY_CYCLE): \d+"]) { # <<<<<<<<<<<<<<<<< Dopplung 1
  my ($reading, $value) = "$EVENT" =~ m/^(.*):\s+(.*)$/g;
  Log(3,"$SELF: Device Event - Device: '$DEVICE', Event: '$EVENT', Reading: '$reading', Value: '$value', hash->{helper}{event}: '" . $hash->{helper}{event} . "'");
foreach my $e (split(",",$event)) {
my ($reading, $value) = $e =~ m/^(0\.ERROR_CODE|0\.ERROR_OVERHEAT|0\.UNREACH|0\.DUTY_CYCLE)):\s+(.*)$/g; # <<<<<<<<<<<<<<<<<<<<<<<<<<<< Dopplung 2
    # Dieser Teil soll nur für die relevanten Readings ausgeführt werden, nicht für den Beifang
}
}

Hast Du eine Idee, wie ich das umgehe?

Zitat von: Damian am 09 Juli 2018, 21:29:09
Meistens kommt aber immer nur ein Event-Typ (Reading) in einem Event-Block vor, wie eine z. B. Fehlermeldung ERROR_CODE|ERROR_OVERHEAT|UNREACH|DUTY_CYCLE
Ich fürchte, dass das in meinem Fall problematisch ist, weil bestimmte Fehler mehrere Readings in einem Schlag aktualisieren und die möchte ich ungern verpassen.

Zitat von: Damian am 09 Juli 2018, 21:29:09
Unabhängig davon wird nur der erste Match eines Events-Blocks gespeichert, denn dann ist die Bedingung bereits wahr und es wird nicht weiter geprüft (dafür sind in erster Linie die Eventabfragen ["..."] programmiert worden).
Ich hatte es befürchtet, und leider auch gerade verifiziert, da es programmiertechnisch Sinn ergibt.

Patrick

/Edit: Codebeispiel war falsch, bitte als Pseudocode sehen :)
lepresenced - Tracking von Bluetooth-LE-Tags (Gigaset G-Tag) mittels PRESENCE

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning." - Rich Cook

Damian

Also ich gehe davon aus, dass ERROR_CODE|ERROR_OVERHEAT|UNREACH|DUTY_CYCLE alles Fehlerwerte eines Readings sind und daher nicht gleichzeitig innerhalb eines Events-Blocks kommen werden. Das würde ich erst mal prüfen, bevor du unnötig Schleifen programmierst.

Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

PatrickR

Mahlzeit!

Zitat von: Damian am 09 Juli 2018, 21:55:26
Also ich gehe davon aus, dass ERROR_CODE|ERROR_OVERHEAT|UNREACH|DUTY_CYCLE alles Fehlerwerte eines Readings sind und daher nicht gleichzeitig innerhalb eines Events-Blocks kommen werden. Das würde ich erst mal prüfen, bevor du unnötig Schleifen programmierst.
Um ehrlich zu sein bin ich fest überzeugt davon, dass sich die Implementierung nach den Anforderungen richten sollte und nicht umgekehrt. Im Übrigen bin ich bemüht, robusten Code zu schreiben.

Aber da die Beweislast ja scheinbar bei mir liegt, bitte:

D_S_HMIP_Problems: Device Event - Device: 'UG.KE.Stromzaehler', Event: '0.STICKY_UNREACH: 1,0.UNREACH: 1,hmstate: unreachable', Reading: '0.STICKY_UNREACH: 1,0.UNREACH: 1,hmstate', Value: 'unreachable'

Aktuell matcht das DOIF sowohl auf UNREACH als auch auf STICKY_UNREACH. Bitte lass uns diesen Diskussionszweig nun abhaken und einen letzten Versuch starten, uns der Frage zu widmen, wie ich die Readingliste nur einmal im DOIF habe.

Aktueller Codeausschnitt:

{
if ([":^0\.(ERROR_CODE|ERROR_OVERHEAT|STICKY_UNREACH|UNREACH|DUTY_CYCLE): \d+"]) {
Log(3,"$SELF: Device Event - Device: '$device', Events: '$events'");

foreach my $e (split(",", $events)) {
Log(3,"$SELF:  Current event: '$e'");
if(my ($reading, undef, $value) = $e =~ m/^(0\.(ERROR_CODE|ERROR_OVERHEAT|STICKY_UNREACH|UNREACH|DUTY_CYCLE)):\s+(.*)$/g) {
Log(3,"$SELF:    Reading: '$reading', Value: '$value'");
if ($value != 0) {
set_Timer ("CALLBACK__$DEVICE__$reading", 60);
if (ReadingsVal("$SELF", "READINGS", "") !~ m/(^|;)$reading($|;)/g) { # Thou shalt not use square brackets in DOIF!
my @readings = split(";", ReadingsVal("$SELF", "READINGS", ""));
push(@readings, $reading);
set_Reading("READINGS", join(";", @readings), 0);
}
} else {
del_Timer ("CALLBACK__$DEVICE__$reading");
my $problem_devices = ReadingsVal("$SELF", "PROBLEMS__$reading", "");
$problem_devices =~ s/(^|;)$DEVICE($|;)//g;
set_Reading("PROBLEMS__$reading", $problem_devices, 1);
}

}
}
}
}


Patrick
lepresenced - Tracking von Bluetooth-LE-Tags (Gigaset G-Tag) mittels PRESENCE

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning." - Rich Cook

Damian

OK.

Du willst also die Angabe ERROR_CODE|ERROR_OVERHEAT|STICKY_UNREACH|UNREACH|DUTY_CYCLE nur einmal im Programmcode angeben, um sie nicht an zwei Stellen pflegen zu müssen? Ist das das was du meinst?

Normalerweise würde man es in eine Variable packen, nun funktionieren aber die DOIF-Angaben [...] nicht mit Variablen, daher sehe ich da z. Zt. nur die Lösung mit der doppelten Angabe.

Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

PatrickR

Hi!

Zitat von: Damian am 08 Juli 2018, 21:16:00
In den Ferien werde ich mir die Sache genauer anschauen, denn bei Eventabfragen sollte eigentlich nur das passende Event gespeichert werden.

Das wäre gut, bin nämlich leider gerade wieder in das Problem gelaufen und bei meiner aktuellen Anwendung wäre sogar ein Verzicht auf das händische Durchiterieren der Liste ohne Nebenwirkungen möglich.

Patrick
lepresenced - Tracking von Bluetooth-LE-Tags (Gigaset G-Tag) mittels PRESENCE

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning." - Rich Cook

Damian

Zitat von: PatrickR am 24 Juli 2018, 22:05:33
Hi!

Das wäre gut, bin nämlich leider gerade wieder in das Problem gelaufen und bei meiner aktuellen Anwendung wäre sogar ein Verzicht auf das händische Durchiterieren der Liste ohne Nebenwirkungen möglich.

Patrick

Wie ich bereits danach feststellen musste, geht es nicht ohne Weiteres:

ZitatIch habe das Problem gefunden.

Im FHEM-Modus ist die Bedingung und der Ausführungsteil getrennt, dort beinhaltet $EVENT tatsächlich den Match.
Im Perl-Modus entspricht der ganze Block der DOIF-Bedingung im FHEM-Modus (wird mit eval ausgewertet), DOIF kommt nicht mehr dazwischen um $EVENT vorzubelegen.

Immerhin habe ich heute die Erkennung von Timerangaben eingebaut, die Version ist aber noch nicht veröffentlicht.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Damian

#20
Ich habe mal etwas im Sourcecode geschaut.

Den entsprechenden Match sollte man mit Hilfe von Filtern bekommen können siehe:

https://fhem.de/commandref_DE.html#DOIF_Ereignissteuerung_ueber_Auswertung_von_Events

ZitatAllgemeine Ereignistrigger können ebenfalls so definiert werden, dass sie nicht nur wahr zum Triggerzeitpunkt und sonst nicht wahr sind, sondern Inhalte des Ereignisses zurückliefern. Initiiert wird dieses Verhalten durch die Angabe eines Default-Wertes.

Syntax:

["regex for trigger",<default value>]

Anwendungsbeispiel:

define di_warning DOIF ([":^temperature",0]< 0 and [06:00-09:00] ) (set pushmsg danger of frost)

Damit wird auf alle Devices getriggert, die mit "temperature" im Event beginnen. Zurückgeliefert wird der Wert, der im Event hinter "temperature: " steht. Wenn kein Event stattfindet, wird der Defaultwert, hier 0, zurückgeliefert.
Ebenfalls kann ein Ereignisfilter mit Ausgabeformatierung angegeben werden.

Syntax:

["regex for trigger":"<regex filter>":<output>,<default value>]

Regex-Filter- und Output-Parameter sind optional. Der Default-Wert ist verpflichtend.

my($reading, $event)=split (",",[":^0\.(ERROR_CODE|ERROR_OVERHEAT|STICKY_UNREACH|UNREACH|DUTY_CYCLE): \d+":"^0\.(.*): (\d+)":"$1,$2",""])

Ein if und eine doppelte regex-Angabe wäre damit überflüssig ;)
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

PatrickR

Hi!

Zitat von: Damian am 24 Juli 2018, 22:20:37
Wie ich bereits danach feststellen musste, geht es nicht ohne Weiteres:
Sorry, das hatte ich übersehen.

Zitat von: Damian am 24 Juli 2018, 22:47:49
Den entsprechenden Match sollte man mit Hilfe von Filtern bekommen können siehe:
[...]
Ein if und eine doppelte regex-Angabe wäre damit überflüssig ;)

Klasse, das funktioniert gut und hilft mir zumindest in Fällen, in denen ich sicher bin, dass maximal ein Event eines Bulks matcht und erlaubt sogar noch eleganteren Code, da ich gleich das Splitten miterledigen kann.

Im Fall meines D_S_HM_HMIP_Problems muss ich leider weiterhin mit dem Codemonster überleben.

Patrick
lepresenced - Tracking von Bluetooth-LE-Tags (Gigaset G-Tag) mittels PRESENCE

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning." - Rich Cook

Damian

Zitat von: PatrickR am 26 Juli 2018, 21:27:34
Hi!
Sorry, das hatte ich übersehen.

Klasse, das funktioniert gut und hilft mir zumindest in Fällen, in denen ich sicher bin, dass maximal ein Event eines Bulks matcht und erlaubt sogar noch eleganteren Code, da ich gleich das Splitten miterledigen kann.

Im Fall meines D_S_HM_HMIP_Problems muss ich leider weiterhin mit dem Codemonster überleben.

Patrick

Ich habe eine neue Version erstellt, siehe hier: https://forum.fhem.de/index.php/topic,84969.msg821563.html#msg821563

Damit sollten falsch erkannte Angaben [...] vom Tisch sein. Vorallem lassen sich jetzt unmittelbar Perlfunktionen definieren und timergesteuert aufrufen.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Thyraz

Bei der Fehlersuche zu einem DOIF bin ich über die ersten Posts aus diesem Thread gestolpert.

Dass heißt im FHEM Modus, wenn ein Modul mit Begin... End... mehrere Readings auf einmal updated, dann wird das betreffende DOIF nur einmal aufgerufen?

Ich hatte nämlich ein DOIF erstellt, welches mehrere Dinge per DOELSEIF anstößt die durch das gleiche Device ausgelöst werden.
Einfach weil sie für mich thematisch zusammen gehörten und ich die Masse an DOIFs im Zaum halten wollte.

Nun reagiert ein Strang des DOIFs aber öfter mal nicht und ich glaube mir wird klar warum:
Da das Device zyklisch polled, werden hier zufällig mal ein oder mal mehrere Readings in einem Rutsch übertragen.

Mir war nicht klar, dass dies bedeuted, dass manche Trigger dann nicht ausgeführt werden weil das DOIF das nur einmal prüft und dann eben den ersten Treffer nimmt (sind alles Event-basierte Trigger).

An sich logisch, aber doch eine fiese Sache zum finden...
Ich schätze ich muss so maches Monster-DOIF mit zahlreichen Zweigen in unzählige Einzel-DOIFs splitten.
Fhem und MariaDB auf NUC6i5SYH in Proxmox Container (Ubuntu)
Zwave, Conbee II, Hue, Harmony, Solo4k, LaMetric, Echo, Sonos, Roborock S5, Nuki, Prusa Mini, Doorbird, ...

Damian

Das ist richtig. DOIF triggert nur auf ein Event eines Event-Blocks. Dh. wenn mehrere Events in einem Block zusammengefasst sind (das kann man an den Tausenderstellen der Uhrzeit erkennen) dann wird dieser nur einmal ausgewertet.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Damian

Zitat von: Damian am 03 Januar 2022, 17:45:06
Das ist richtig. DOIF triggert nur auf ein Event eines Event-Blocks. Dh. wenn mehrere Events in einem Block zusammengefasst sind (das kann man an den Tausenderstellen der Uhrzeit erkennen) dann wird dieser nur einmal ausgewertet.

Daher besser solche unabhängigen Zweige im DOIF-Perl-Modus zusammenfassen:

DOIF
{if ([bla:test1]) {....}}
{if ([bla:test2]) {....}}



Hier sollte jeder Block unabhängig voneinander ausgeführt werden, auch wenn test1 und test2 in einem Event-Block kommen.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Thyraz

DOIF-Perl hab ich bisher noch gemieden, da ich der Meinung war Perl kann ich auch so programmieren und das über ein entsprechendes Notify triggern. :P

Aber wenn ich nun eh Einiges umprogrammieren werde, ist es evtl. auch mal an der Zeit nach Vorteilen / Unterschieden von DOIF-Perl vs. Notify+komplexem Perl Code zu suchen.  ;)
Fhem und MariaDB auf NUC6i5SYH in Proxmox Container (Ubuntu)
Zwave, Conbee II, Hue, Harmony, Solo4k, LaMetric, Echo, Sonos, Roborock S5, Nuki, Prusa Mini, Doorbird, ...

Damian

Zitat von: Thyraz am 03 Januar 2022, 22:38:48
DOIF-Perl hab ich bisher noch gemieden, da ich der Meinung war Perl kann ich auch so programmieren und das über ein entsprechendes Notify triggern. :P

Aber wenn ich nun eh Einiges umprogrammieren werde, ist es evtl. auch mal an der Zeit nach Vorteilen / Unterschieden von DOIF-Perl vs. Notify+komplexem Perl Code zu suchen.  ;)

Dann kann ich dir die neue Dokumentation zum DOIF-Perl ans Herz legen, die ich gerade erstelle: https://wiki.fhem.de/wiki/DOIF/Perl-Modus
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Damian

Ich habe noch mal den DOIF-FHEM-Modus getestet.

Im Device bla wurde in einem Eventblock temperature und humidity gesetzt.

Das getestete Device sah so aus:

([bla:temperature] == 2) ()
DOELSEIF([bla:humidity]) ()

wurde temperature z. B. auf 21 gesetzt wurde der Zweig cmd_2 ausgeführt

bei temperature 2 wurde cmd_1 ausgeführt.

Es werden also schon alle Events eines Event-Blocks bei jedem Zweig geprüft - es geht also kein Event verloren.

Es liegt natürlich in der Natur der Sache, dass im DOIF-FHEM-Modus ja nur ein Zweig pro Eventblock ausgeführt wird. Daher kann nicht temperature und humidity gleichzeitig eine Aktion auslösen.

Es ist klar, wenn der Benutzer keine Kenntnis von einem Eventblock hat, dass er zwei Trigger von außen erwartet, obwohl es nur einen gibt.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Thyraz

#29
Zitat von: Damian am 04 Januar 2022, 16:47:20
Es ist klar, wenn der Benutzer keine Kenntnis von einem Eventblock hat, dass er zwei Trigger von außen erwartet, obwohl es nur einen gibt.

Ja, das ist das einzig Fiese an der Sache. ;)

Mir sind die internen Funktionen zum Updaten von Readings ja sogar geläufig, dennoch habe ich beim Erstellen der DOIFs nicht an diese Auswirkungen gedacht.
Immerhin hat's dann bei der Fehlersuche geholfen zu erkennen woran es liegen könnte.

Um das zu Umgehen müsste man ja die Events erst splitten und dann das DOIF für jedes dieser Events nacheinander abarbeiten, so dass mehr als ein Zweig ausgeführt wird.

Das mag dann im Fall meines DOIFs das gewünschte Verhalten sein,
aber ich kann mir vorstellen, dass das in anderen Situationen evtl. zu unerwünschtem Verhalten führt.
Es ist dann eben nicht mehr so, dass der oberste Zweig gewinnt bei mehreren simultanen Events.

Edit: Wäre evtl. ein Featurewunsch, dieses Verhalten über ein Attribut zu steuern?  ;)
Fhem und MariaDB auf NUC6i5SYH in Proxmox Container (Ubuntu)
Zwave, Conbee II, Hue, Harmony, Solo4k, LaMetric, Echo, Sonos, Roborock S5, Nuki, Prusa Mini, Doorbird, ...

Damian

Zitat von: Thyraz am 04 Januar 2022, 21:23:27
Edit: Wäre evtl. ein Featurewunsch, dieses Verhalten über ein Attribut zu steuern?  ;)

Das dürfte das DOIF-Modul intern auf den Kopf stellen und mehrere Zweige in einem Durchlauf ausführen zu lassen - dem widerspricht das Wort ELSE, dann lieber auf DOIF-Perl umsteigen.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Per

Oder mit IF (und bei Bedarf mit $EVENTS) arbeiten.