Hauptmenü

$EVENT vs $EVENTS?

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

Vorheriges Thema - Nächstes Thema

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, ...