neue Features: ereignisgesteuertes Perl - DOIF-Perl

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

Vorheriges Thema - Nächstes Thema

dusti64

Hallo und Guten Abend :)

ich bin dabei, zwei DOIFs von morgens und abends auf eins in Perl zu ändern, allerdings spielt morgens Twilight (zyklisch) mit rein:
## WE=ja,Abwesend, Zeit=08:00 ==> Rollladen auf
{ if ([08:00|7] && [Abwesend] eq "ja")
{
fhem_set("sz_Rollladen on");
set_Reading("Rollladen", "auf");
set_State("WE - Abwesend - Rollladen auf")
}
}
## WE=nein,Zeit=05:20-08:00 ==> Rollladen auf
{ if ([05:20-08:00|8] && [myTwilight:twilight] > 42)
{
fhem_set("sz_Rollladen on");
set_Reading("Rollladen", "auf");
set_State("kein WE - Rollladen auf")
}
}
## Abwesend ja ===> Rollladen zu
{if ([Abwesend] eq "ja" && [{sunset(-2000,"16:00","22:30")}])
{
fhem_set ("sz_Rollladen off");
set_Reading ("Rollladen", "zu");
set_State ("Rollladen zu")
}
}
## Anwesend nein ===> Rollladen zu
{if ([Status_Fenster_SZ] eq "ZU" && [Abwesend] eq "nein" && [{sunset(-1500,"16:00","22:30")}])
{
fhem_set ("sz_Rollladen off");
set_Reading ("Rollladen", "zu");
set_State ("Rollladen zu")
}
}

Wenn der RL morgens aufgefahren ist und man ihn in der angegebenen Zeit von Hand schließt, fährt er wieder hoch, wenn das Twilight sich ändert (Problem ist bekannt)...
Jetzt wollte ich mit einem DOIF_Readings arbeiten, weiß aber nicht richtig wie...:
Frage ich den RL auf "eq off" ab, wird das Reading ja wieder 1, wenn er von Hand zu gefahren wurde. Frage ich auf "eq on" ab, erfasse ich eventuelle Zwischenstände nicht.

Gefunden habe ich auch noch dies hier von Damian:
DOIF { #Diese set-Anweisung wird nicht ausgeführt, wenn ereignis2 in der letzten Sekunde stattgefunden hat
  if ([ereignis1] and get_Timer("ereignis2")==0) {fhem"set ...";set_Timer("ereignis1",1)}
}
{ #Diese set-Anweisung wird nicht ausgeführt, wenn ereignis1 in der letzten Sekunde stattgefunden hat
  if ([ereignis2] and get_Timer("ereignis1")==0) {fhem"set ...";set_Timer("ereignis2",1)}
}

aber dabei benötige ich mal Unterstützung bei der Umsetzung oder gibt es noch eine andere/bessere Möglichkeit?

Gruß Dusti
2x Debian virtualisiert auf QNAP mit FHEM, 2x HMLAN, VCCU, Homatic Heizung+Licht-Rollläden, Alexa mit 2 Echos, Homebridge, Hue, Instar

Damian

Mit DOIF_Readings:

attr DOIF_Readings hell:[myTwilight:twilight] > 42

und

if ([05:20-08:00|8] and hell)...
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

dusti64

#167
...hab herzlichen Dank dafür Damian...ich werde es probieren.

Das bedeutet, dass Hell = 1 ist, wenn die Helligkeit erreicht ist, doch dann wäre es ja genauso wie die Abfrage nach Twilight direkt und wenn die Frau innerhalb der vorgegeben Zeit von Hand runterfährt, geht er doch auch wieder hoch, oder sehe ich das falsch? Eigentlich möchte ich erreichen, dass er nur einmal morgens in Automatik hoch fährt

Gruß Dusti o/

Edit: Ok ich denke ich habs, der Zustand von "Hell" ändert sich nur einmal morgens und damit wird auch der Befehl nur einmal abgesetzt, sehe ich das richtig?

Nochmal Danke :)
2x Debian virtualisiert auf QNAP mit FHEM, 2x HMLAN, VCCU, Homatic Heizung+Licht-Rollläden, Alexa mit 2 Echos, Homebridge, Hue, Instar

Gisbert

Hallo,

kann solch eine Defintion Erfolg haben?
...
DOELSEIF (... or  sunset_abs(-3420) le $hms))
(set Treppenhaus.Markise on)
({if sunset_abs(-7020) le $hms {fhem_set"RollladenWZWest DriveUp"}})


Ich möchte im Ausführungsteil einen Zweig davon abhängig machen, dass er nur dann ausgeführt wird, wenn der Sonnenuntergang ("sunset_abs(-7020)") kleiner als die aktuelle Zeit ("$hms") ist.
Die Änderung in der Definition ging ohne Gemecker ab, aber das will ja nicht viel heißen.

Viele Grüße Gisbert
Aktuelles FHEM | PROXMOX | Fujitsu Futro S740 | Debian 12 | UniFi | Homematic, VCCU, HMUART | ESP8266 | ATtiny85 | Wasser-, Stromzähler | Wlan-Kamera | SIGNALduino, Flamingo Rauchmelder FA21/22RF | RHASSPY

Damian

#169
Zitat von: Gisbert am 27 August 2019, 20:54:16
Hallo,

kann solch eine Defintion Erfolg haben?
...
DOELSEIF (... or  sunset_abs(-3420) le $hms))
(set Treppenhaus.Markise on)
({if sunset_abs(-7020) le $hms {fhem_set"RollladenWZWest DriveUp"}})


Ich möchte im Ausführungsteil einen Zweig davon abhängig machen, dass er nur dann ausgeführt wird, wenn der Sonnenuntergang ("sunset_abs(-7020)") kleiner als die aktuelle Zeit ("$hms") ist.
Die Änderung in der Definition ging ohne Gemecker ab, aber das will ja nicht viel heißen.

Viele Grüße Gisbert

Naja, du bist hier in der "Perl-Abteilung" da gibt es schon mal kein DOELSEIF. ;) Wenn eine Funktion insb. HH:MM:SS als Rückgabe liefert dann kann man sie mit $hms  tatsächlich vergleichen und das gilt auch für den FHEM-Modus.

EDIT: fhem_set gibt es nur im DOIF-Perlmodus
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

cwagner

DOIF erzeugt ja inzwischen eine bemerkenswerte geringere Systemlast. Und der Perlmodus gefällt mir auch wegen der Lastthematik immer mehr. Etliche meiner klassischen DOIFs haben pro Stunde einige Hundert Ausführungen. Die würde ich gerne umstellen, aber mir fehlt (mal wieder  :'( ) die zündende Idee.

Aufgabe: Meine Denkovi 8-Fach-Switche mögen es nicht, wenn sie innerhalb von Sekunden zwei Schaltbefehle (set ... on|off) bekommen. Deshalb verzögere ich aktuell die einzelnen Befehle über das wait-Kommando im klassischen Modus attr DI_Solarthermie wait 120,25:120,25:180

Beispiel für eine Definition:
{
([T_Kollektor:temperature:d]>([?T_Solarspeicher_1:temperature:d]+15) and [?T_Warmwasser:temperature:d]<60)
(set Switch_Heizkeller output Kollektor_Pumpe ON) (set Switch_Heizkeller output 3Wege-Ventil OFF)   ## Vorrang Warmwasser aufheizen
DOELSEIF ([T_Kollektor:temperature:d]>([?T_Solarspeicher_2:temperature:d]+15) and [?T_Solarspeicher_2:temperature:d]<101)
(set Switch_Heizkeller output Kollektor_Pumpe ON) (set Switch_Heizkeller output 3Wege-Ventil ON)     ## Rücklaufanhebung aufheizen
DOELSE (set Switch_Heizkeller output Kollektor_Pumpe OFF) (set Switch_Heizkeller output 3Wege-Ventil OFF)     ##wir warten auf mehr Sonne


Im Perlmodus von DOIF habe ich kein wait, aber ich hätte die Möglichkeit, durch das Senden eines veränderten GPIOs mehrere Relais gleichzeitig zu schalten, das funktioniert sogar höchst zu verlässig sogar im Sekundentakt.

Also: hole mir den aktuellen Zustand, z.B. dec. 133, binär 10000101. Ich will Bit 6 auf 0 und Bit 7 auf 1 setzen, das eräbe also 10000011 (Dec. 131). Jo, ganz einfach, doch ich kriege die Umrechnung von Dezimal auf Binär  und umgekehrt nicht hin, über Split- und String-Operationen habe ich tatsächlich den Change von 10000101 nach 10000011 (nur ein Beispiel) schon hinbekommen.

Da ich insgesamt drei 8fach- und ein 4fach-Relais verbaut habe, ist das für mich ein extrem häufig anzutreffender Fall, für das mir schlicht und ergreifend das Handwerkzeug fehlt, es elegant zu lösen.

Hat jemand so ein Thema schon gelöst und spendiert eine Idee(nskizze)?

Liebe Grüße

Christian

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

Damian

schau mal: https://asciich.ch/wordpress/binare-operationen-in-perl-durchfuhren/

Setzen von Bits sollte gehen mit |:

my $data=0b1000;

my $dataneu=$data | 0b101

Löschen geht mit &


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

cwagner

#172
Super Anstoß, Damian - und mit einem kleinen Übungsaspekt: In diesem Fall führt OR nämlich nur dann zu einem nützlichen Ergebnis, wenn die zu verändernden Bits 0 (Relais aus) ist. Eine 1 wird durch eine 0 nicht genullt.

Einige Stunden war ich dann am Ziel und zwar mit XOR
my $data=0b1001;                  # ist 9
my $dataneu=$data ^ 0b01;   # ergibt 8
my $dataneu=$data ^ 0b00;   # ergibt 9
my $dataneu=$data ^ 0b11;   # ergibt 10
my $dataneu=$data ^ 0b10;   # ergibt 11

Zum Vergleich or
my $data=0b1001;                  # ist 9
my $dataneu=$data | 0b01;   # ergibt 9
my $dataneu=$data | 0b00;   # ergibt 9
my $dataneu=$data | 0b11;   # ergibt 11
my $dataneu=$data | 0b10;   # ergibt 11

Vielen Dank erneut für Deine Arbeit am DOIF und vor allem für Deine immer kompetente, unendliche Hilfsbereitschaft.



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

#173
Vielleicht zum Verständnis für andere.

XOR negiert ein Bit bei Angabe von 1 und lässt es unverändert bei Angabe 0

Beispiel: Die ersten beiden Bits (von links) sollen negiert werden (aus 1 wird 0 und aus 0 wird 1), die letzten beiden sollen unverändert bleiben

$data =0b1010

$data ^ 0b1100 -> 0b0110



OR setzt ein Bit bei Angabe 1 und lässt es unverändert bei Angabe 0

Beispiel: Das zweite und dritte Bit soll gesetzt werden (Angabe 1), die anderen sollen unverändert bleiben

$data | 0b0110 -> 0b1110

AND löscht ein Bit bei Angabe von 0 und lässt es unverändert bei Angabe 1

Beispiel: Das zweite und dritte Bit soll gelöscht werden (Angabe 0), die anderen sollen unverändert bleiben

$data & 0b1001 -> 0b1000
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

cwagner

Zitat von: Damian am 01 August 2019, 23:30:07
Mit DOIF_Readings:

attr DOIF_Readings hell:[myTwilight:twilight] > 42

und

if ([05:20-08:00|8] and hell)...

Ich habe dieses Beispiel nachgebaut, und beobachte nun, dass ich grundsätzlich $SELF benutzen muss, um wirklich einen Trigger auszulösen. Dabei hat mich verwirrt, dass in der Liste der Events "hell" bei wahrer Bedingung eine "1" zeigt, bei unwahrer Bedingung aber leer ist. Durch Probieren habe versuche ich es  != 1 ist.

{if ([05:20-08:00|8] and [$SELF:hell] ==1 ) {...}}
elsif ([$SELF:hell] !=1) {...}}

[/quote]

Ist das richtig so oder übersehe ich etwas?
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

#175
Zitat von: cwagner am 28 September 2019, 23:16:18
Ich habe dieses Beispiel nachgebaut, und beobachte nun, dass ich grundsätzlich $SELF benutzen muss, um wirklich einen Trigger auszulösen. Dabei hat mich verwirrt, dass in der Liste der Events "hell" bei wahrer Bedingung eine "1" zeigt, bei unwahrer Bedingung aber leer ist. Durch Probieren habe versuche ich es  != 1 ist.

{if ([05:20-08:00|8] and [$SELF:hell] ==1 ) {...}}
elsif ([$SELF:hell] !=1) {...}}



Ist das richtig so oder übersehe ich etwas?

Es muss natürlich [$SELF:hell] bei der Abfrage heißen, hell allein ist falsch.

Dass bei unwahr nichts steht ist normal, das ist Perl, wenn du bei unwahr 0 haben willst, dann kannst du es z. B. so definieren:

attr DOIF_Readings hell:([myTwilight:twilight] > 42 ? 1:0)

Unwahr kann man auch so abfragen: ![$SELF:hell]  (unabhängig davon, ob da nichts drin steht oder 0)
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

kumue

Ich freunde mich gerade mit dem DOIF-Perl Modus an und mache meine ersten Versuche..

Aus einem Kalender wird ein Wert ausgelesen und dieser soll in einen Dummy geschrieben werden..
Klappt auch, solange ein Wert vohanden ist, falls kein Eintrag vorhanden ist, dann bekomme ich diese Warning...

2019.11.24 16:14:00 3: eval: DO_CA_KU: warning in condition c02
2019.11.24 16:14:00 1: PERL WARNING: Use of uninitialized value in concatenation (.) or string at (eval 3379664) line 1.


Wie kann ich das noch abfangen, wenn im Kalender nichts steht ?
Das DOIF sieht so aus:


init {$_evt=fhem('get CA_KU events format:custom="$S" limit:from=0d,to=0d')}
{[16:14];fhem ("set DU_Kalender Schicht $_evt")}


Damian

Zitat von: kumue am 24 November 2019, 16:31:33
Ich freunde mich gerade mit dem DOIF-Perl Modus an und mache meine ersten Versuche..

Aus einem Kalender wird ein Wert ausgelesen und dieser soll in einen Dummy geschrieben werden..
Klappt auch, solange ein Wert vohanden ist, falls kein Eintrag vorhanden ist, dann bekomme ich diese Warning...

2019.11.24 16:14:00 3: eval: DO_CA_KU: warning in condition c02
2019.11.24 16:14:00 1: PERL WARNING: Use of uninitialized value in concatenation (.) or string at (eval 3379664) line 1.


Wie kann ich das noch abfangen, wenn im Kalender nichts steht ?
Das DOIF sieht so aus:


init {$_evt=fhem('get CA_KU events format:custom="$S" limit:from=0d,to=0d')}
{[16:14];fhem ("set DU_Kalender Schicht $_evt")}

Du kannst abfragen, ob in $_evt überhaupt etwas drin steht.

{[16:14];if (defined $_evt) {fhem ("set DU_Kalender Schicht $_evt")}}
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

kumue


lichtimc

#179
Hallo Damian,


hast du eine Ahnung, warum nicht alle Befehle vor und nach einem
fhem("setreading xxx yyy zzz");
ausgeführt werden?


Ich habe beispielsweise folgenden Code in einem DOIF:

   sub stopCounter {
      del_Exec("exec_stopCounter");

      set_Reading_Begin;
      if (not $_aWc == 0) {
         set_Reading_Update("Letzte_Messung", $_aWc);
         $_aWc = 0;
      }
      set_Reading_Update("state", "stopped");
      if (get_Reading("Anzeige") eq "on") {
         set_Reading_Update("Anzeige", "off");
         fhem("setreading di_Taster_Meldung_WaterCounter Meldung off");
      }
      set_Reading_End(1);
     
      Log 1, "WaterCounter beendet!";
   }


Leider wird durch die Zeile fhem("..."); das set_Reading_Update("state", "stopped"); gar nicht ausgeführt und beim set_Reading_End(1); wird kein Event erzeugt und somit auch nicht das Fhemweb aktualisiert. Lasse ich die Zeile fhem("..."); weg funktionieren alle Befehle und das Event wird generiert.

EDIT: OK, das set_Reading_Update("state", "stopped"); wird doch ausgeführt, nur das set_Reading_End(1); anscheinend nicht.
Jetzt hab ich es so, das funktioniert erstmal, aber sobald ich das fhem("..."); vor das set_Reading("Anzeige", "off", 1); wird letzteres nicht ausgeführt:

   sub stopCounter {
      del_Exec("exec_stopCounter");
     
      if (not $_aWc == 0) {
         set_Reading("Letzte_Messung", $_aWc);
         $_aWc = 0;
      }
      set_State("stopped");
      if (get_Reading("Anzeige") eq "on") {
         set_Reading("Anzeige", "off", 1);
         fhem("setreading di_Taster_Meldung_WaterCounter Meldung off");
      }
     
      Log 1, "WaterCounter beendet!";
   }

Vielleicht fällt dir dazu was ein...


Vielen Dank und lg,
LichtiMC