neue Features: ereignisgesteuertes Perl - DOIF-Perl

Begonnen von Damian, 25 Februar 2018, 21:29:16

Vorheriges Thema - Nächstes Thema

cwagner

So ganz habe ich die Perl-Variante wohl noch nicht durchdrungen. Wollte dieses klassische DOIF auf Perl umsetzen, weil ich inzwischen die Reduktion der Systemlast deutlich feststelle:

([Umweltsensor:Helligkeit] < 0.3 and [?16:30-05:00]) (set ROLL_Schlafzimmer AB,set Rolllaeden on) \
DOELSEIF ([Umweltsensor:Helligkeit] > 0.1 and [05:45-08:30] or ([08:31] and [?Umweltsensor:Helligkeit] < 0.3 )) (set ROLL_Terrasse AUF,set Rolllaeden off)


Die Oder-Bedingung um 8.31 ist an einigen Tagen im Winter notwendig, damit trotz "Dunkelheit" die Rolllaeden (eine Struktur) geöffnet werden.

Das habe ich so umgestellt:
{if ([Umweltsensor:Helligkeit] < 0.3 and [?16:30-05:00]) {fhem "set ROLL_Schlafzimmer AB,set Rolllaeden on} \
elsif {[Umweltsensor:Helligkeit] > 0.1 and [05:45-08:30] or ([08:31] and ReadingsVal("Umweltsensor","Helligkeit","") < 0.3 ) {fhem "set ROLL_Terrasse AUF;set Rolllaeden off")}}}


Da auch unterhalb von 0.3 Helligkeit der Sensor wechselnde Messwerte erzeugt, triggert nun jedes mal das Modul und alle paar Minuten ziehen alle Relais der Rollläden noch einmal. Da die Entposition erreicht ist, bleibt es beim Klicken. Doch schön ist anders.

Was mache ich falsch, eigentlich verstehe ich DOIF auch im Perlmodus als Ereignismaschine, die mit einer Bedingung einrastet und dann bis zum nächsten Zustandswechsel zu verharren. Dann dürfte ein Helligkeit 0.1 z.B. den elsif-Zweig noch nicht auslösen?

Herzliche Grüße

Christian

PI 2B+/3B+ Raspbian 12, Perl 5.36.0, FHEM 6.3: 295 Module in ConfigDB: Steuerung Heizkessel, FBH, Solarthermie, kontr. Lüftung mit WRG. Smarthome u.a. HMCUL, 1-Wire (FT232RL ; DS2480B), EnOcean (TCM EPS3), MQTT2. DOIF, PID20, Threshold, OWX; Micropelt IRTV, Volkszähler, SolarForecast; MariaDB

obi

Zitat von: Damian am 04 Februar 2019, 20:56:39
Für welche Lösung hast du dich denn entschieden?
Die erste, das war dann am einfachsten anzupassen
sub $SELF_sub1 {

Per

Zitat von: cwagner am 06 Februar 2019, 14:35:29Was mache ich falsch, eigentlich verstehe ich DOIF auch im Perlmodus als Ereignismaschine, die mit einer Bedingung einrastet und dann bis zum nächsten Zustandswechsel zu verharren. Dann dürfte ein Helligkeit 0.1 z.B. den elsif-Zweig noch nicht auslösen?
Nein, genau das ist sie nicht. Das ist, neben der Syntax, einer der Unterschiede. Hauptvorteil des Perl-DOIF ist die vereinfachte Schreibweise von [Events:Readings] und der integrierten Event-Triggerung.

Damian

#153
Zitat von: cwagner am 06 Februar 2019, 14:35:29
So ganz habe ich die Perl-Variante wohl noch nicht durchdrungen. Wollte dieses klassische DOIF auf Perl umsetzen, weil ich inzwischen die Reduktion der Systemlast deutlich feststelle:

([Umweltsensor:Helligkeit] < 0.3 and [?16:30-05:00]) (set ROLL_Schlafzimmer AB,set Rolllaeden on) \
DOELSEIF ([Umweltsensor:Helligkeit] > 0.1 and [05:45-08:30] or ([08:31] and [?Umweltsensor:Helligkeit] < 0.3 )) (set ROLL_Terrasse AUF,set Rolllaeden off)


Die Oder-Bedingung um 8.31 ist an einigen Tagen im Winter notwendig, damit trotz "Dunkelheit" die Rolllaeden (eine Struktur) geöffnet werden.

Das habe ich so umgestellt:
{if ([Umweltsensor:Helligkeit] < 0.3 and [?16:30-05:00]) {fhem "set ROLL_Schlafzimmer AB,set Rolllaeden on} \
elsif {[Umweltsensor:Helligkeit] > 0.1 and [05:45-08:30] or ([08:31] and ReadingsVal("Umweltsensor","Helligkeit","") < 0.3 ) {fhem "set ROLL_Terrasse AUF;set Rolllaeden off")}}}


Da auch unterhalb von 0.3 Helligkeit der Sensor wechselnde Messwerte erzeugt, triggert nun jedes mal das Modul und alle paar Minuten ziehen alle Relais der Rollläden noch einmal. Da die Entposition erreicht ist, bleibt es beim Klicken. Doch schön ist anders.

Was mache ich falsch, eigentlich verstehe ich DOIF auch im Perlmodus als Ereignismaschine, die mit einer Bedingung einrastet und dann bis zum nächsten Zustandswechsel zu verharren. Dann dürfte ein Helligkeit 0.1 z.B. den elsif-Zweig noch nicht auslösen?

Herzliche Grüße

Christian

Im Perlmodus gibt es keine Zustände, wie du sie im FHEM-Modus kennst. Dennoch lassen sich Aufgaben aus dem FHEM-Modus in den Perl-Modus überführen.

Zunächst musst du Abfragen von zyklisch sendenden Sensoren in DOIF_Readings verbannen. Damit verhinderst du ständiges Triggern, weil DOIF_Readings nur bei Zustandsänderung intern triggern. Wenn man so will, ist in DOIF_Readings die Zustandsauswertung, wie man sie im FHEM-Modus kennt, untergebracht. In der Bedingung fragt man dann DOIF_Readings ab. Desweiteren wird der gesamte Block abgearbeitet, wenn irgendein Trigger kommt, daher besser separate Blöcke definieren als elsif-Zweige, wenn sie sich ohnehin gegenseitig ausschließen.

So könnte deine neue Definition aussehen:

{if ([$SELF:dunkel] and [?16:30-05:00]) {fhem "set ROLL_Schlafzimmer AB,set Rolllaeden on}} \
{if ([$SELF:hell] and [05:45-08:30] or [08:31] and [?$SELF:dunkel]) {fhem "set ROLL_Terrasse AUF;set Rolllaeden off")}}}


attr ... DOIF_Readings dunkel:[Umweltsensor:Helligkeit] < 0.3,\
hell: [Umweltsensor:Helligkeit] > 0.1



Allerdings kann man auch sagen, dass bei wenigen Schaltvorgängen am Tag es ziemlich egal ist, ob man paar Millisekunden im Perl-Modus einspart oder nicht.

Ob im FHEM-Modus oder im Perl-Modus, es wird bei jedem passenden Event die Bedingung ausgewertet, auch wenn es nur in DOIF_Readings stattfindet.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

cwagner

Zitat von: Damian am 06 Februar 2019, 17:04:59
Ob im FHEM-Modus oder im Perl-Modus, es wird bei jedem passenden Event die Bedingung ausgewertet, auch wenn es nur in DOIF_Readings stattfindet.

Danke für die Erklärung, mein Beispiel diente hier zur Illustration, habe aber auch Steuerungs-DOIFs die dutzende Male in der Stunde auswerten. An Rollläden lässt sich aber schön langsam üben :-)

Christian
PI 2B+/3B+ Raspbian 12, Perl 5.36.0, FHEM 6.3: 295 Module in ConfigDB: Steuerung Heizkessel, FBH, Solarthermie, kontr. Lüftung mit WRG. Smarthome u.a. HMCUL, 1-Wire (FT232RL ; DS2480B), EnOcean (TCM EPS3), MQTT2. DOIF, PID20, Threshold, OWX; Micropelt IRTV, Volkszähler, SolarForecast; MariaDB

Damian

#155
Zitat von: cwagner am 06 Februar 2019, 19:12:09
Danke für die Erklärung, mein Beispiel diente hier zur Illustration, habe aber auch Steuerungs-DOIFs die dutzende Male in der Stunde auswerten. An Rollläden lässt sich aber schön langsam üben :-)

Christian

Allgemein würde ich sagen:

Überall dort, wo man in einer DOIF-Definition do always verwendet, hebelt man die Zustand-Verwaltung des FHEM-Modus aus, dann kann man gleich zum Perl-Modus greifen und braucht noch nicht mal ein Attribut zu definieren. 

Wenn man dann die Syntax verstanden und die Möglichkeiten des Perl-Modus erkannt hat, kann man innerhalb eines Devices mit Hilfe strukturierter Programmierung komplexere Problemstellungen elegant lösen.

Dazu hat man einen eigenen Namensraum für eigene Subroutinen, eigene Instanzvariablen, die ihren Inhalt behalten, vereinfachte Perl-Funktionen (ohne $hash), die performanter sind als FHEM-Befehle sowie Perlfunktionen (ebenfalls ohne $hash) zum Handling (setzen, abfragen, löschen) beliebig vieler Wait-Timer.

Für einfache Aufgaben, wie "wenn ... Lampe an, sonst Lampe aus" würde ich dennoch den FHEM-Modus aufgrund seiner einfachen Syntax weiter empfehlen.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

travelling-man

Hallo,

Ich setze mit einem Doif mehrere Timer mittels set_Exec und einen Status aktiv.

Jetzt scheitere ich an der Abfrage ob ein bestimmter Status gesetzt ist und alle Timer abgelaufen sind, da das doif nur einmalig triggert wenn der Status gesetzt wird jedoch nicht wenn ein Timer abgelaufen ist.


if ([$SELF:aktiv, ""] eq "on" and !get_Exec("kreislauf1") and !get_Exec("kreislauf2"))
  {
    set_Reading ("aktiv","off);;
   }


Wie kann ich das doif triggern wenn ein Timer abgelaufen ist?

VG
Basti

Damian

Zitat von: travelling-man am 16 April 2019, 08:50:07
Hallo,

Ich setze mit einem Doif mehrere Timer mittels set_Exec und einen Status aktiv.

Jetzt scheitere ich an der Abfrage ob ein bestimmter Status gesetzt ist und alle Timer abgelaufen sind, da das doif nur einmalig triggert wenn der Status gesetzt wird jedoch nicht wenn ein Timer abgelaufen ist.


if ([$SELF:aktiv, ""] eq "on" and !get_Exec("kreislauf1") and !get_Exec("kreislauf2"))
  {
    set_Reading ("aktiv","off);;
   }


Wie kann ich das doif triggern wenn ein Timer abgelaufen ist?

VG
Basti

Wie hast du die Timer gesetzt?
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

travelling-man

#158
Die Timer werden über ein for gesetzt der dann eine Funktion mit Parameter aufruft.

Es gibt ein Timer zum starten und ein zum stoppen.

set_Exec("kreislauf$i-start",30,'ventil_on',"$i")

set_Exec("kreislauf$i-stop",60,'ventil_off',"$i")

Damian

Zitat von: travelling-man am 16 April 2019, 09:03:07
Die Timer werden über ein for gesetzt der dann eine Funktion mit Parameter aufruft.

Es gibt ein Timer zum starten und ein zum stoppen.

set_Exec("kreislauf$i-start",30,'ventil_on',"$i")

set_Exec("kreislauf$i-stop",60,'ventil_off',"$i")


Dann weißt du doch wann sie ablaufen, wenn deine Funktion ventil_on/ventil_off aufgerufen wird, das kannst du darin auswerten.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

travelling-man

Moin,

Warum kompliziert wenn es auch einfach geht.

Daran habe ich gar nicht gedacht. Vielen Dank.

lichtimc

Hey Damian,

ich habe ein DOIF im FHEM Modus, welches di_WC_Licht heißt und eins im Perl-Modus, das di_WC_Licht_Helper heißt.
Wenn ich set_State im di_WC_Licht_Helper benutze ändert sich der state im di_WC_Licht.

Wie kann denn das sein?

Danke, lg, lmc

Damian

Zitat von: lichtimc am 28 April 2019, 04:04:03
Hey Damian,

ich habe ein DOIF im FHEM Modus, welches di_WC_Licht heißt und eins im Perl-Modus, das di_WC_Licht_Helper heißt.
Wenn ich set_State im di_WC_Licht_Helper benutze ändert sich der state im di_WC_Licht.

Wie kann denn das sein?

Danke, lg, lmc

Poste mal ein list von di_WC_Licht_Helper, wo das set_State benutzt wird.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

lichtimc

Das ist das List:

Internals:
   DEF        subs {
sub ZoneInnenOff {
if (Value("WC_KLS_ZoneInnen") eq "off") {
fhem("setreading di_WC_Licht shutoff now");
set_State("Timer off");
}
}
}
{
if ([WC_KLS_ZoneTuer] eq "off") {
if (ReadingsVal("di_WC_Licht", "shutoff", "") eq "no") {
if (Value("WC_KLS_ZoneInnen") eq "off") {
fhem("setreading di_WC_Licht shutoff now");
set_State("Regular off");
} else {
set_Exec('wait_for_ZoneInnen_off', 1, 'ZoneInnenOff', 1);
}
}
}
}
   FUUID      5cc4f593-f33f-f183-eb27-34481c3f8aa30345
   MODEL      Perl
   NAME       di_WC_Licht_Helper
   NR         1038
   NTFY_ORDER 50-di_WC_Licht_Helper
   STATE      initialized
   TYPE       DOIF
   VERSION    18890 2019-03-13 18:56:41
   READINGS:
     2019-04-28 04:51:35   Device          WC_KLS_ZoneTuer
     2019-04-28 04:51:35   block_01        executed
     2019-04-28 04:51:35   e_WC_KLS_ZoneTuer_STATE off
     2019-04-28 04:11:18   mode            enabled
     2019-04-28 02:35:48   shutoff         now
     2019-04-28 02:37:24   state           initialized
   Regex:
     accu:
   condition:
     0         
if (::InternalDoIf($hash,'WC_KLS_ZoneTuer','STATE') eq "off") {
if (ReadingsVal("di_WC_Licht", "shutoff", "") eq "no") {
if (Value("WC_KLS_ZoneInnen") eq "off") {
fhem("setreading di_WC_Licht shutoff now");
set_State("Regular off");
} else {
set_Exec('wait_for_ZoneInnen_off', 1, 'ZoneInnenOff', 1);
}
}
}

   devices:
     0           WC_KLS_ZoneTuer
     all         WC_KLS_ZoneTuer
   helper:
     event      getG1: off,last-sender: 1/0/83,off
     globalinit 1
     last_timer 0
     sleeptimer -1
     triggerDev WC_KLS_ZoneTuer
     triggerEvents:
       getG1: off
       last-sender: 1/0/83
       off
     triggerEventsState:
       getG1: off
       last-sender: 1/0/83
       state: off
   internals:
     0           WC_KLS_ZoneTuer:STATE
     all         WC_KLS_ZoneTuer:STATE
   itimer:
   perlblock:
     0         
   ptimer:
     wait_for_ZoneInnen_off:
       name       wait_for_ZoneInnen_off
       param      1
       subname    ZoneInnenOff
       time       1556419896.99748
       hash:
   readings:
   trigger:
   uiState:
   uiTable:
Attributes:
   icon       helper_doif
   room       WC


Danke, lg

Damian

Bei mir kann ich das Problem nicht nachvollziehen.

Wie sieht das andere DOIF-Device aus? Benutzt du irgendwo anders deine Routine : ZoneInnenOff?
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF