[erledigt] DOIF/Perl-Modus: wie triggere ich resourcenschonend

Begonnen von Sany, 12 Juli 2022, 11:44:03

Vorheriges Thema - Nächstes Thema

Sany

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
fhem als LXC auf Proxmox auf einem minix Z100 , weitere LXC mit ZigBee2MQTT, MariaDB und Grafana. Homematic, FS20, mySensors, MQTT2, Tasmota, Shelly, Z-Wave  ....

Damian

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

Sany

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.
fhem als LXC auf Proxmox auf einem minix Z100 , weitere LXC mit ZigBee2MQTT, MariaDB und Grafana. Homematic, FS20, mySensors, MQTT2, Tasmota, Shelly, Z-Wave  ....

Damian

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

Sany

fhem als LXC auf Proxmox auf einem minix Z100 , weitere LXC mit ZigBee2MQTT, MariaDB und Grafana. Homematic, FS20, mySensors, MQTT2, Tasmota, Shelly, Z-Wave  ....

Per

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)

Sany

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
fhem als LXC auf Proxmox auf einem minix Z100 , weitere LXC mit ZigBee2MQTT, MariaDB und Grafana. Homematic, FS20, mySensors, MQTT2, Tasmota, Shelly, Z-Wave  ....

Per

Kannst ja auch eine if Folge machen
if (x eq "ABc"){}
if (x eq "abC"){}

Oder als if elsif...