FHEM Forum

FHEM => Automatisierung => DOIF => Thema gestartet von: Sany am 12 Juli 2022, 11:44:03

Titel: [erledigt] DOIF/Perl-Modus: wie triggere ich resourcenschonend
Beitrag von: Sany am 12 Juli 2022, 11:44:03
Hi Damian,

ich hätte da mal eine allgemeine Frage zum Perl-DOIF, genauer gehts um die Art und Weise, wie ein Perl-Block getriggert wird.
Ein Beispiel: Ein Sensor liefert die Zustände von 3 LEDs, diese können jeweils aus (0), an (1) oder blinkend (2) sein.
Verschiedene Zustände der LEDs entsprechen bestimmten Zuständen des Geräts, ähnlich einer Matrix:

Zustand LED1 LED2 LED3
--------------------------------
Normal 1 0 0
Test 1 2 0
Alarm 2 1 2


Im DOIF fallen mir nun verschiedene Wege ein, das zu schreiben:

Normal {
if ([Sensor:LED1] == 1 and [Sensor:LED2] == 0 and [Sensor:LED3] == 0){
set_State("Normal");
}
}
Test {
if ([Sensor:LED1] == 1 and [Sensor:LED2] == 2 and [Sensor:LED3] == 0){
set_State("Test");
}
}
Alarm {
if ([Sensor:LED1] == 2 and [Sensor:LED2] == 1 and [Sensor:LED3] == 2){
set_State("Normal");
}
}

   
   
oder

States {
if ([Sensor:LED1] == 1 and [Sensor:LED2] == 0 and [Sensor:LED3] == 0){
set_State("Normal");
} elsif ([Sensor:LED1] == 1 and [Sensor:LED2] == 2 and [Sensor:LED3] == 0){
set_State("Test");
} elsif ([Sensor:LED1] == 2 and [Sensor:LED2] == 1 and [Sensor:LED3] == 2){
set_State("Alarm");
}
}


oder z.B. die Bedingungen in DOIF_Readings einbauen und damit dann ein Zustandsreading setzen.


oder....??


Was wäre der beste Weg im Bezug auf wie oft wird getriggert und das DOIF angestossen. Oder wäre es sinnvoll, die LEDs teilweise nicht-triggernd einzubauen, je nach dem, welche sich ändern, je nach Wechsel des Gerätezustands? Das birgt allerdings die Gefahr, dass ein bestimmter Zustand evtl. gar nicht angezeigt wird.
Es heisst ja: ein Perlblock wird durch passende Event- oder Zeittrigger zur Ausführung gebracht. Wie verhält es sich, wenn (wie hier) ein triggerndes Event mehrfach in einem Block ist oder eben in unterschiedlichen Blöcken?

Die Zustandsänderungen passieren selten und langsam, es geht also nicht um eine Flut von Events von aussen, nur um die schonendste Abarbeitung der Events.

Ich hoffe, das ist nicht zu verwirrend. das o.g. ist ein vereinfachtes Beispiel, in meinem Fall gehts am Ende um 4 LEDs mit jeweils 4 Zuständen.


Danke schon mal



Sany
Titel: Antw:DOIF/Perl-Modus: wie triggere ich resourcenschonend
Beitrag von: Damian am 12 Juli 2022, 12:23:25
Also wenn die gleiche Triggerangabe mehrfach in einem Block vorkommen wird, so wird dennoch der Block nur einmal getrigger und ausgeführt. Und umgekehrt, wenn die gleich Triggerangabe in mehreren Blöcken vorkomment, dann wird jeder dieser Blöcke ausgeführt.

Wenn Events unabhängig voneinander sind, dann würde ich statt alles in einen block mit  elsif zu definieren, jeweils einen eigenen separaten block mit if für das jeweilige Event definieren. Man wird zwar nicht viel merken, jedoch hat der Perl-Compiler  beim Auftregen eines Events dann wenige Code zu durchforsten - man spart ein paar Millisekunden ein. Ein entscheidender Vorteil ist aber, dass man sich nicht wie im DOIF-FHEM-Modus künstlich Abhängigkeiten schafft, die man nicht bedacht hat (DOELSE bei mehreren DOELSEIF-Fällen ist immer gefährlich).
Titel: Antw:DOIF/Perl-Modus: wie triggere ich resourcenschonend
Beitrag von: Sany am 12 Juli 2022, 12:38:57
Zitatjeweils einen eigenen separaten block mit if für das jeweilige Event definieren

wenn ich Dich recht verstehe ist das dann meine erste Variante. Es werden dann, wenn sich 1 LED ändert, zwar alle 3 Blöcke durchgearbeitet, aber nur da, wo es passt, der Status neu gesetzt.
Titel: Antw:DOIF/Perl-Modus: wie triggere ich resourcenschonend
Beitrag von: Damian am 12 Juli 2022, 20:31:38
Zitat von: Sany am 12 Juli 2022, 12:38:57
wenn ich Dich recht verstehe ist das dann meine erste Variante. Es werden dann, wenn sich 1 LED ändert, zwar alle 3 Blöcke durchgearbeitet, aber nur da, wo es passt, der Status neu gesetzt.

In deinem Beispiel  kommen alle Readings in allen Blöcken triggernd vor. Daher werden jedes mal alle drei Blöcke ausgeführt. Deswege wäre es hier sinnvoll die Variante mit einem Block zu nehmen. Da ein eval-Aufruf bei der Größe schneller abgearbeitet ist als drei.
Titel: Antw:DOIF/Perl-Modus: wie triggere ich resourcenschonend
Beitrag von: Sany am 13 Juli 2022, 07:37:13
Vielen Dank, wieder was gelernt!
Titel: Antw:[erledigt] DOIF/Perl-Modus: wie triggere ich resourcenschonend
Beitrag von: Per am 14 Juli 2022, 08:41:05
Bei (hier) drei Abfragen würde ich (!) sogar auf Mustervergleich gehen. Also alle drei (einmalig triggernd) als String "addieren" und dann das Ergebnis prüfen. Sehr übersichtlich und schnell zu warten.
Vergleich = [A]++[C]
case Vergleich
"aBC":
"ABc":
...
(Jetzt mal allgemeine Syntax)
Titel: Antw:[erledigt] DOIF/Perl-Modus: wie triggere ich resourcenschonend
Beitrag von: Sany am 14 Juli 2022, 09:16:43
das wäre bestimmt eine übersichtliche Lösung, nur hat, soweit ich das beurteilen kann, Perl5 das nicht eingebaut und würde das Modul switch erfordern**. Erst ab Perl6 soll es sowas geben (given/when). Ich habe das schon öfter mal "vermisst" und deshalb nicht weiterverfolgt.
Mir ging es auch haupsächlich darum herauszufinden, wie sich die triggernden Einträge verhalten, wenn diese in einem Perl-Block mehrfach vorkommen. Das hat Damian ja ausführlich geklärt.
Und wie schon beschrieben gibt es hier eher selten events, ist also "unkritsch".

Trotzdem: guter Hinweis.

Gruß


Sany


** https://perlmaven.com/switch-case-statement-in-perl5 (https://perlmaven.com/switch-case-statement-in-perl5)
Titel: Antw:[erledigt] DOIF/Perl-Modus: wie triggere ich resourcenschonend
Beitrag von: Per am 15 Juli 2022, 15:38:57
Kannst ja auch eine if Folge machen
if (x eq "ABc"){}
if (x eq "abC"){}

Oder als if elsif...