FHEM Forum

FHEM => Automatisierung => DOIF => Thema gestartet von: Damian am 25 Februar 2018, 21:29:16

Titel: neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 25 Februar 2018, 21:29:16
Wie bereits hier diskutiert https://forum.fhem.de/index.php/topic,84692.0.html habe ich eine neue DOIF-Version erstellt, die neue Syntax (Perlmodus) unterstützt. Sie ist im Anhang hinterlegt.

Der neue Perlmodus im DOIF kommt ohne Attribute aus. Er ist nicht mit dem bisherigen Modus (MODE: FHEM) kombinierbar. Der aktuelle Device-Modus wird automatisch aufgrund der Syntax vom Modul erkannt und im Internal MODE: Perl/FHEM abgelegt.

Im Perlmodus lassen sich insb. komplexere Abläufe innerhalb eines DOIF-Devices programmieren. Der Anwender hat mehr Einfluss auf den Ablauf, er muss sich dafür selbst um die möglichen Zustände kümmern, dafür gibt es keine vorgegebenen Abhängigkeiten im Modul, die man beachten müsste.

Maximale Performance: Zum Zeitpunkt der Definition, werden alle DOIF-spezifischen Angaben in Perl übersetzt, zum Zeitpunkt der Ausführung wird nur noch Perl ausgeführt.

Die Doku zum Perl-Modus lässt sich in wenigen Zeilen aufschreiben:

Edit: siehe Commandref
Titel: Antw:neue Features: ereignisgesteuertes Perl
Beitrag von: Damian am 03 März 2018, 16:53:51
Was kann man nun mit einem DOIF-Perl machen, was man mit einem DOIF nicht kann?

z. B. Einknopffernbedienung:

defmod di_shutter DOIF init {$hash->{var}{Timer}=0}\
{if ([FS:"on"] and $hash->{var}{Timer}==0){\
   set_Timer("Timer shutter",2);;$hash->{var}{Timer}=1\
} else {\
   fhem"set shutter up";;$hash->{var}{Timer}=0;;del_Timer("Timer shutter")\
}\
}\
{if ([$SELF:"Timer shutter"]){$hash->{var}{Timer}=0;;fhem"set shutter down"}}


Wenn FS innerhalb von zwei Sekunden zwei mal betätigt wird, wird "set shutter up" ausgeführt, bei einmaligem Tastendruck "set shutter down".
Titel: Antw:neue Features: ereignisgesteuertes Perl
Beitrag von: Ellert am 03 März 2018, 20:38:18
Zitat von: Damian am 03 März 2018, 16:53:51
Was kann man nun mit einem DOIF-Perl machen, was man mit einem DOIF nicht kann?

z. B. Einknopffernbedienung:

defmod di_shutter DOIF init {$hash->{var}{Timer}=0}\
{if ([FS:"on"] and $hash->{var}{Timer}==0){\
   set_Timer("Timer shutter",2);;$hash->{var}{Timer}=1\
} else {\
   fhem"set shutter up";;$hash->{var}{Timer}=0;;del_Timer("Timer shutter")\
}\
}\
{if ([$SELF:"Timer shutter"]){$hash->{var}{Timer}=0;;fhem"set shutter down"}}


Wenn FS innerhalb von zwei Sekunden zwei mal betätigt wird, wird "set shutter up" ausgeführt, bei einmaligem Tastendruck "set shutter down".
Es geht auch mit einem DOIF ;)
defmod updown DOIF ([FS:"on"])\
  (setreading $SELF counter {([$SELF:counter,"0"] + 1)})\
DOELSEIF ([$SELF:state] eq "cmd_1")\
  (\
  IF ([$SELF:counter] == 1)\
    (set shutter up, setreading $SELF counter 0) \
  ELSE \
    (set shutter down, setreading $SELF counter 0)\
  )
attr updown checkReadingEvent 1
attr updown do resetwait
attr updown room 0_Test
attr updown selftrigger wait
attr updown wait 0.1:2

setstate updown initialized
setstate updown 2018-03-03 20:35:37 cmd 0
setstate updown 2018-03-03 20:34:43 counter 0
setstate updown 2018-03-03 20:35:37 mode enabled
setstate updown 2018-03-03 20:35:37 state initialized
Titel: Antw:neue Features: ereignisgesteuertes Perl
Beitrag von: Damian am 03 März 2018, 21:27:22
Zitat von: Ellert am 03 März 2018, 20:38:18
Es geht auch mit einem DOIF ;)
defmod updown DOIF ([FS:"on"])\
  (setreading $SELF counter {([$SELF:counter,"0"] + 1)})\
DOELSEIF ([$SELF:state] eq "cmd_1")\
  (\
  IF ([$SELF:counter] == 1)\
    (set shutter up, setreading $SELF counter 0) \
  ELSE \
    (set shutter down, setreading $SELF counter 0)\
  )
attr updown checkReadingEvent 1
attr updown do resetwait
attr updown room 0_Test
attr updown selftrigger wait
attr updown wait 0.1:2

setstate updown initialized
setstate updown 2018-03-03 20:35:37 cmd 0
setstate updown 2018-03-03 20:34:43 counter 0
setstate updown 2018-03-03 20:35:37 mode enabled
setstate updown 2018-03-03 20:35:37 state initialized


Es ging mir in erster Linie um die Attribute waitsame und waitdel, die sich in diesem Fall nicht kombinieren lassen (siehe Commandref-Beispiele: https://fhem.de/commandref_DE.html#DOIF_waitsame)

Deine Lösung ist, wie meine auch, weitgehend "programmiert". Für deine muss man DOIF-Experte sein. Im DOIF-Perl-Modus muss man dagegen etwas Perl und die beiden DOIF-spezifischen Aufrufe kennen (hier: set_Time, del_Timer), dafür muss man keine Kenntnis über DOIF-spezifische Attribute haben. DOIF-Perl ist natürlich um einiges performanter. Da muss jeder für sich entscheiden, was ihm besser liegt. Beides ist möglich. Ich denke der Programmierer wird zu der Perl-Variante greifen.

Titel: Antw:neue Features: ereignisgesteuertes Perl
Beitrag von: Damian am 04 März 2018, 13:52:21
Ich habe noch eine Funktion get_Timer spendiert (v0.5 im ersten Post). Damit kann man erkennen, ob ein Timer noch läuft, bzw. in wie viel Sekunden er abläuft. Damit lässt sich die Einknopffernbedienung noch einfacher gestalten:

defmod di_shutter DOIF {if ([FS:"on"] and get_Timer("Timer shutter")==0){\
  set_Timer("Timer shutter",2)} else {fhem"set shutter up";;del_Timer("Timer shutter")}\
}\
{if ([$SELF:"Timer shutter"]){fhem"set shutter down"}}
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 04 März 2018, 21:08:15
Hier ein Beispiel mit mehreren wait-Timern in einem DOIF: verzögerte Fenster-offen-Meldung mit Wiederholung, für alle Fenster, die mit "Fenster" enden.

defmod di_window DOIF { if (["Fenster$:open"]) {set_Timer ("WINDOW $DEVICE",600)}}\
{ if (["Fenster$:closed"]) {del_Timer ("WINDOW $DEVICE")}}\
{ if (["^$SELF:^WINDOW"]) {my ($window,$device)=split(" ","$EVENT");;Log 3,"Fenster offen, bitte schließen: $device";;set_Timer ("WINDOW $device",1800)}}

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 07 März 2018, 18:54:25
Ich habe die Nutzung von Instanzvariablen $hash->{var}{<varname>} etwas vereinfacht. Variablen, die mit $_ beginnen können als Instanzvariablen genutzt werden. Die Perl-Sondervariable $_ kann wie üblich im Perlcode trotzdem benutzt werden.

Was macht wohl dieses kleine Programmchen?

defmod di_var DOIF init {$_i=0}\
{if ([FS]) {set_Reading ("state",$_i++,1)}}


Im konventionellen DOIF nur umständlich über Readings mit setreading umsetzbar.

Edit:

Ebenso funktionieren hash-Variablen z.B.

$_betrag{heute}=100;

Die Instanzvariablen müssen nicht deklariert werden, sie sind am Anfang nicht definiert, wenn man sie nicht vorbelegt. Man kann sie abfragen, ob sie definiert sind  z. B. mit if (defined $_...) ...

Ebenso lassen sich Instanzvariablen indizieren, z. B.:

my $i=0;
$_betrag{$i}=100;


Instanzvariablen überleben nicht den Neustart, sie können aber z.B. im init-Block aus Readings vorbelegt werden:

init {$_status=[?$SELF:state]}

oder einfach

init {$_status=ReadingsVal("$SELF","state",0)}
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 10 März 2018, 11:55:58
Zum Thema Selbsttriggerung:

Im bisherigen DOIF-FHEM-Modus ist Selbsttriggerung, zum Schutz des Users, unterbunden und muss über das Attribut selftrigger erlaubt werden.

Im DOIF-Perl-Modus wird eine andere Strategie verfolgt: Die Selbsttriggerung ist grundsätzlich erlaubt, sie wird vom Modul nicht unterbunden.  Hinter set_Event(<Event>) verbirgt sich set_Timer(<Event>, 0). Damit wird sogar die Unterbindung von Loops seitens FHEM umgangen und es entstehen keine rekursiven Aufrufe im Modul selbst, D.h. hier können mehr als 2 Loops programmiert werden, was durchaus sinnvoll sein kann. Der User hat hier volle Kontrolle über das Geschehen, muss sich aber dessen bewusst sein, was er "programmiert" hat, um Endlos-Loops nicht zu erzeugen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: choenig am 10 März 2018, 18:46:43
Hi,

ich habe gerade bemerkt, dass auf einmal diverse "normale" DOIFs als Perl-Mode erkannt werden. Betroffen scheinen solche mit Kommentaren am Anfang zu sein:


##
## Updated die sysTime auf allen Wandthermostaten und Heizungsthermostaten
##

([05:05])
(set model=(HM-TC-IT-WM-W-EU|HM-CC-RT-DN):FILTER=chanNo= sysTime)


Ich glaube, ich setze noch die Version 0.4 ein. Kann grad nicht besser nachsehen.

LG
Christian
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 10 März 2018, 19:03:19
Zitat von: choenig am 10 März 2018, 18:46:43
Hi,

ich habe gerade bemerkt, dass auf einmal diverse "normale" DOIFs als Perl-Mode erkannt werden. Betroffen scheinen solche mit Kommentaren am Anfang zu sein:


##
## Updated die sysTime auf allen Wandthermostaten und Heizungsthermostaten
##

([05:05])
(set model=(HM-TC-IT-WM-W-EU|HM-CC-RT-DN):FILTER=chanNo= sysTime)


Ich glaube, ich setze noch die Version 0.4 ein. Kann grad nicht besser nachsehen.

LG
Christian

Du musst die aktuelle Version (v0.6) aus dem ersten Post nehmen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 10 März 2018, 22:30:30
Bei folgendem Problem, welches in der Automatisation durchaus häufig auftritt, müsste man beim konventionellen DOIF schon etwas nachdenken.

Anforderung: Wenn innerhalb einer Zeitspanne (hier eine Stunde) ein bestimmtes Ereignis mehr als x mal eintritt (hier 10 mal), dann führe eine Aktion aus (hier ein Log-Eintrag).

So sieht es mit DOIF-Perl aus (performant, da ohne FHEM-Befehle, in einer Definition gekapselt und ohne Attribute):

defmod di_count DOIF {if (["FS:on"] and get_Timer("Timer counter")==0){$_count=1;;set_Timer("Timer counter",3600)} else {$_count++}}\
{if ([$SELF:"Timer counter"]) {if ($_count > 10) {Log 3,"count: $_count action"}}}
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 18 März 2018, 11:49:47
Aktuelle Version v0.10 im ersten Post. Laufende Timer werden jetzt in Readings festgehalten. Ich habe angefangen die Doku im Modul zu aktualisieren. Der Countdown zum Einchecken läuft.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 19 März 2018, 23:16:01
Version v.12 im Anhang. Neues FHEM-Feature implementiert: https://forum.fhem.de/index.php/topic,85868.0.html . Abhängig vom Modus, wird aufgrund der Definition die Attributliste automatisch angepasst, dh. im Perl-Modus lassen sich nur noch sinnvolle Attribute für diesen Modus auswählen.

Doku ist weitgehend fertig. Es kommen nur noch ein paar weitere Anwendungsbeispiele hinzu.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 21 März 2018, 21:26:17
DOIF-Perl eingecheckt. Bitte beachten, dass diese Version nur mit der aktuellen fhem.pl Version funktioniert.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 23 März 2018, 18:12:03
commandref_join liefert für # $Id: 98_DOIF.pm 16471 2018-03-23 11:42:27Z Damian $
Zitat98_DOIF.pm: negative tagcount for code, line 3830

In Zeile 3827 wird der code-tag zu früh geschlossen er müsste gelöscht werden.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 23 März 2018, 19:09:18
Zitat von: Ellert am 23 März 2018, 18:12:03
commandref_join liefert für # $Id: 98_DOIF.pm 16471 2018-03-23 11:42:27Z Damian $
In Zeile 3827 wird der code-tag zu früh geschlossen er müsste gelöscht werden.

Danke für den Hinweis. Der code-tag war da immer schon falsch drin. Warum liefert commandref_join bei mir keine Fehlermeldung?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 23 März 2018, 22:53:49
Ich vermute Du hast eine ältere commandref_join. Seit 26.2.18 werden negative code-tags gezählt, s. https://forum.fhem.de/index.php/topic,84953.0.html
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 24 März 2018, 11:25:51
Zitat von: Ellert am 23 März 2018, 22:53:49
Ich vermute Du hast eine ältere commandref_join. Seit 26.2.18 werden negative code-tags gezählt, s. https://forum.fhem.de/index.php/topic,84953.0.html
ok, muss ich dann bei mir aktualisieren.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 26 März 2018, 10:36:30
Einen init-Block gibt es ja schon, wäre auch ein beforeShutdown-Block denkbar?

Ein Vorteil wäre, dass init-Variablen bei häufigen Aktualisierungen im Betrieb nicht in Readings oder als KeyValues gespeichert werden müssten, sondern nur vor einem Shutdown.

Als nächsten Schritt könnte das Lesen und Schreiben von Variablen, die einen Neustart überleben sollen automatisiert werden.

Es könnten alle Variablennamen, die in einem Array @_INIT stehen, automatisch geladen und gespeichert werden.

Siehe auch setKeyValue/getKeyValue https://wiki.fhem.de/wiki/DevelopmentModuleAPI#setKeyValue
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 26 März 2018, 11:37:34
Zitat von: Ellert am 26 März 2018, 10:36:30
Einen init-Block gibt es ja schon, wäre auch ein beforeShutdown-Block denkbar?

Ein Vorteil wäre, dass init-Variablen bei häufigen Aktualisierungen im Betrieb nicht in Readings oder als KeyValues gespeichert werden müssten, sondern nur vor einem Shutdown.

Als nächsten Schritt könnte das Lesen und Schreiben von Variablen, die einen Neustart überleben sollen automatisiert werden.

Es könnten alle Variablennamen, die in einem Array @_INIT stehen, automatisch geladen und gespeichert werden.

Siehe auch setKeyValue/getKeyValue https://wiki.fhem.de/wiki/DevelopmentModuleAPI#setKeyValue

ja, das wäre eine Möglichkeit, aber man kann jetzt schon Variablen sichern, z. B.:

{ if (["^global$:^SHUTDOWN$"]) {setKeyValue("$SELF_$_myvariable", $_myvariable)}}
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 26 März 2018, 12:05:44
Alle Variablen sichern könnte so aussehen:

{ if (["^global$:^SHUTDOWN$"]) {
    foreach my $key (keys %{$hash->{var}}) {
        setKeyValue("$SELF_$hash->{var}{$key}", $hash->{var}{$key});
    }
  }
}


Man könnte Funktionen zur Verfügung stellen: saveVar() und getVar().

Automatisches Speichern würde ich eher vermeiden. Es soll möglichst wenig interne Abhängigkeiten geben. Der Programmierer will auch schon mal sauber initialisierte Variablen haben, zumal es sich hier um hash-Variablen handelt, die man nicht deklarieren muss.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 26 März 2018, 13:09:33
saveVar() und getVar() sollten mit Parameter funktionieren, damit nur die benötigten Keys gespeichert werden

saveVar(<Regex für Keys>) und keine Angabe (oder .*) für Alles.

Bei einem getKeyValue muss Key bekannt sein.
Ich denke der Geräte-Hash ändert sich beim Neustart.
Daher dürfte $SELF_$hash nicht funktionieren, sondern $SELF_$key, also
setKeyValue("$SELF_$hash->{var}{$key}", $hash->{var}{$key})

($error, $hash->{var}{$key}) = getKeyValue("$SELF_$hash->{var}{$key}", $hash->{var}{$key})


Edit:
Ich bin nicht sicher ob es reicht das globale Event SHUTDOWN auszuwerten.
Ich denke ein beforeShutdown Block müsste in der Modul-Funktion X_Shutdown untergebracht werden.
https://wiki.fhem.de/wiki/DevelopmentModuleIntro#X_Shutdown
und $key muss aus einer, nach dem Neustart bekannten, Liste kommen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 26 März 2018, 13:23:27
Zitat von: Ellert am 26 März 2018, 13:09:33
saveVar() und getVar() sollten mit Parameter funktionieren, damit nur die benötigten Keys gespeichert werden

saveVar(<Regex für Keys>) und keine Angabe (oder .*) für Alles.

Bei einem getKeyValue muss Key bekannt sein.
Ich denke der Geräte-Hash ändert sich beim Neustart.
Daher dürfte $SELF_$hash nicht funktionieren, sondern $SELF_$key, also
setKeyValue("$SELF_$hash->{var}{$key}", $hash->{var}{$key})

($error, $hash->{var}{$key}) = getKeyValue("$SELF_$hash->{var}{$key}", $hash->{var}{$key})


und $key muss aus einer, nach dem Neustart bekannten, Liste kommen.

Die key-Liste müsste mitgespeichert werden.

Was mir noch grundsätzlich im Perl-Modus nicht gefällt, ist das ständige Patchen des Codes vor der Ausführung, mit $DEVICE, $EVENTS .... Das kostet unnötig Performance.

Man kann jetzt schon Variablen $device, $events usw. verwenden. Allerdings müsste ich dann die Erkennung in der DOIF-Syntax einbauen, z. B.

[$device] soll [$DEVICE] entsprechen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 26 März 2018, 13:32:35
Zitat von: Damian am 26 März 2018, 13:23:27
Die key-Liste müsste mitgespeichert werden.

Was mir noch grundsätzlich im Perl-Modus nicht gefällt, ist das ständige Patchen des Codes vor der Ausführung, mit $DEVICE, $EVENTS .... Das kostet unnötig Performance.

Man kann jetzt schon Variablen $device, $events usw. verwenden. Allerdings müsste ich dann die Erkennung in der DOIF-Syntax einbauen, z. B.

[$device] soll [$DEVICE] entsprechen.

Ja, wenn es performanter ist.

Bevor es in der vorhergehenden Antwort untergeht:

Ich bin nicht sicher ob es reicht das globale Event SHUTDOWN auszuwerten.
Ich denke ein beforeShutdown Block müsste in der Modul-Funktion X_Shutdown untergebracht werden.
https://wiki.fhem.de/wiki/DevelopmentModuleIntro#X_Shutdown
und $key muss aus einer, nach dem Neustart bekannten, Liste kommen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 26 März 2018, 13:53:22
Zitat von: Ellert am 26 März 2018, 13:32:35
Ja, wenn es performanter ist.

Bevor es in der vorhergehenden Antwort untergeht:

Ich bin nicht sicher ob es reicht das globale Event SHUTDOWN auszuwerten.
Ich denke ein beforeShutdown Block müsste in der Modul-Funktion X_Shutdown untergebracht werden.
https://wiki.fhem.de/wiki/DevelopmentModuleIntro#X_Shutdown
und $key muss aus einer, nach dem Neustart bekannten, Liste kommen.

ja, müsste ich mal umsetzen und testen, der Aufwand ist überschaubar.

Ich denke das Patchen werde ich wohl drin lassen müssen, allein wegen der Kompatibilität, der Performance-Verlust dürfte nicht messbar sein. Bei mir 0,0003 mSek für ca. 80 Zeichen-Code. Raspi ist vermutlich 10 mal langsamer - immer noch nicht "messbar".
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 02 April 2018, 14:28:27
Zitat von: Damian am 26 März 2018, 13:53:22
ja, müsste ich mal umsetzen und testen, der Aufwand ist überschaubar.

Ich habe mir die Sache mit dem Speichern von Instanzvariablen genauer angeschaut und bin zu der Erkenntnis gekommen, da nichts zu unternehmen, denn

-es wird keine Eindeutigkeit der Schlüssel gewährleistet, der gleiche Schlüssel wird mehrfach mit verschieden Inhalten gespeichert.
-erforderliche Verwaltung der Schlüssel, wenn z. B. ein DOIF-Modul gelöscht wird, müssten die Einträge ebenfalls gelöscht werden.
-wenn ein User etwas bewusst sichern will, dann kann er das in Readings des Moduls tun, diese sind eindeutig und verschwinden mit dem Löschen des Devices



Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 26 Juli 2018, 16:03:43
Neue Features.

1. Man kann jetzt ohne Umwege über myutils Perlfunktionen im Block subs im DOIF definieren
2. Timer können jetzt nicht nur Events auslösen, sondern auch Perlfunktionen aufrufen (neue Funtionen set_Exec, get_Exec, del_Exec)
3. Angaben in eckigen Klammern können jetzt im Perl-Modus verwendet werden, wenn sie mit DOIF-Syntax nicht kollidieren, insb. Arrays z. B. a[1] oder regex /^[\d].*/

Das Beispiel aus der Commandref

Treppenhauslicht mit Bewegungsmelder

define di_light DOIF bewegung {   #Perlblock namens "bewegung" reagiert auf Bewegung von FS
  if (["FS:motion"]) {
    if ([?lamp:state] ne "on") {   #wenn Lampe aus ist
      fhem"set lamp on";   #Lampe einschalten
      set_Reading ("state","on",1);   #setze Status des DOIF-Moduls auf "on"
    }
    set_Timer("lamp_off",30);   #Timer wird gesetzt bzw. verlängert
  }
}
ausschalten {   #Perlblock namens "ausschalten" reagiert auf Trigger vom des Timers "lamp_off"
  if ([$SELF:"lamp_off"]) {   #Wenn Timer lamp_off abläuft
    fhem"set lamp off";   #schalte Lampe aus
    set_Reading ("state","off",1);   #setze Status des DOIF-Modus auf "off"
  }
}


lässt sich zukünftig auch wie folgt definieren:

define di_light DOIF
##block subs für Definition eigener Perl-Funktionen, hier ist nur Perl erlaubt ohne DOIF-Syntax
subs {
   sub ein {if (ReadingsVal ("lamp","state","") ne "on") { fhem"set lamp on"; set_Reading ("state","on",1)}} # Perlfunktion ein zum Einschalten wird definiert
   sub aus {fhem"set lamp off";set_Reading ("state","off",1)}                                                # Perlfunkton aus zum Ausschalten wird definiert
}
bewegung {                          #Perlblock namens "bewegung" reagiert auf Bewegung von FS
  if (["FS:motion"]) {
    ein();                          #Perlfunktion "ein" wird ausgeführt
    set_Exec("Timer_aus",30,"aus");             #Timer für das Ausschalten über Perlfunktion "aus" wird gesetzt bzw. verlängert
  }
}


Doku wird noch erstellt.

Edit: Syntax angepasst
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 29 Juli 2018, 19:33:41
Ich habe nun die Version v0.3 mit Doku fertiggestellt.

Auszüge aus der Doku:

ZitatEin besonderer Perlblock ist der Block namens "subs". Dieser Block wird nur zum Definitionszeitpunkt ausgeführt. In diesem Block sollten vornehmlich Perlfunktionen definiert werden, die innerhalb des DOIFs genutzt werden. Um eine möglichst hohe Kompatibilität zu Perl sicherzustellen, wird keine DOIF-Syntax in eckigen Klammern unterstützt, insb. gibt es keine Trigger, die den Block ausführen können.

und

Zitat
Funktionstimer

Timer setzen: set_Exec(<timerName>, <seconds>, <function>, <parameter>), mit <timerName>: beliebige Angabe, sie spezifiziert eindeutig einen Timer, welcher nach Ablauf die angegebene Perl-Funktion <function> mit optionalen Parameter <parameter> aufruft. Die Perlfunkion muss eindeutig sein und in FHEM zuvor deklariert worden sein. Wird set_Exec mit dem gleichen <timerName> vor seinem Ablauf erneut aufgerufen, so wird der laufender Timer gelöscht und neugesetzt.

Timer holen: get_Exec(<timerName>), Returnwert: 0, wenn Timer abgelaufen oder nicht gesetzt ist, sonst Anzahl der Sekunden bis zum Ablauf des Timers

Laufenden Timer löschen: del_Exec(<timerName>)


Zur Demonstration der neuen Funktionalität wird hier ein größeres Projekt (ähnlich diesem https://forum.fhem.de/index.php/topic,48847.0.html) vorgestellt, welches eine Einknopf Garagentor-/Rollladen-Steuerung realisiert. Dabei werden zwei Relais (rauf/runter), die sich gegenseitig sperren und automatische Endabschaltung des Tores/Rollos vorausgesetzt.

Zur Funktionsweise: Ein geschlossenes Tor wird beim Tastendruck geöffnet, ein geöffnetes wird geschlossen, wenn während der Laufzeit Taste gedrückt wird, bleibt das Tor stehen, ein erneuter Tastendruck bewegt das Tor in umgekehrte Richtung. Dabei werden unterschiedliche Laufzeiten des Tores (rauf/runter) berücksichtigt, ebenso wird die aktuelle Position des Tores aufgrund der Laufzeit berechnet und im Reading abgelegt.

Der Sourcecode ist weitgehend dokumentiert und kann mit Dummys (switch_up, switch_down) ausprobiert werden.


DOIF subs {                                       # im Block subs werden Perlfunktionen definiert, die innerhalb des DOIFs benutzt werden
sub drive { my ($downup)=@_;                      # Funktion zum Herunterfahren oder Hochfahren des Garagentors
  my $seconds; 
  if ($downup eq "up") {
    fhem"set $_up on";                            # Schalter zum Hochfahren einschalten
    $seconds=$_drive_up_time*(1-$_pos/100);       # Laufzeit in Sekunden berechnen
    $_pos=100;                                    # Endposition vorbelegen
  } else {
    fhem"set $_up on";                            # Schalter zum Herunterfahren einschalten
    $seconds=$_drive_down_time*($_pos/100);       # Laufzeit in Sekunden berechnen
    $_pos=0;                                      # Endposition vorbelegen
  }
  set_Reading("state","drive_$downup",1);         # Status des Modus auf drive_down oder drive_up setzen
  set_Exec("Timer_off",$seconds,"off",$downup);   # Setze Timer zum Abschalten des Switches switch_down oder switch_up
}                                             
 
sub off {                                         # Funktion zum Abschalten des hoch-/runter-Schalters
  my ($downup)=@_;
  if ($downup eq "up") {
    fhem"set $_up off";                           # Schalter zum Hochfahren abschalten
  } else {
    fhem"set $_down off";                         # Schalter zum Herunterfahren  abschalten
  }
  set_Reading("state",$downup,1);                 # setze Status des Moduls auf up oder down
  set_Reading("position",int($_pos),1);           # aktuelle Position im Reading festhalten
}

}

init {                                      # Vorbelegung von Instanzvariablen
   $_up="switch_up";                        # Name des Schalters zum Hochfahren
   $_down="switch_down";                    # Name des Schalters zum Herunterfahren
   $_drive_up_time=15;                      # Fahrzeit des Garagentors nach oben
   $_drive_down_time=10;                    # Fahrzeit des Garagentors nach unten
   $_pos=0;                                 # aktuelle Position des Garagentors (0-down, 100-up)
   set_Reading("position",0,0);             # Reading mit der Position auf 0 setzen
}

main {                                                         # Hauptblock reagiert auf Fernbedienung FS und steuert switch up/down abhängig vom Zustand
if ([FS]) {
  if ([?$SELF] eq "up") {                                      # wenn Garagentor oben dann herunterfahren
    drive ("down");                                            # Garagentor herunterfahren
  } elsif ([?$SELF] eq "drive_up") {                           # Garagentor fährt nach oben
    $_pos = (1 - get_Exec("Timer_off")/$_drive_up_time)*100;   # Position bestimmen
    off ("up");                                                # Garagentor stoppen
    del_Exec("Timer_off");                                     # Timer löschen
    set_Reading("state","stop_drive_up",1);                    # Zustand des Moduls setzen
  } elsif ([?$SELF] eq "drive_down") {                         # Garagentor fährt nach unten
    $_pos = (get_Exec("Timer_off")/$_drive_down_time)*100;     # Position bestimmen
    off ("down");                                              # Garagentor stoppen
    del_Exec("Timer_off");                                     # Timer löschen
    set_Reading("state","stop_drive_down",1);                  # Zustand des Moduls setzen
  } elsif ([?$SELF] eq "stop_drive_up") {                      # Garagentor wurde beim Hochfahren gestoppt
    drive ("down");                                            # Herunterfahren
  } elsif ([?$SELF] eq "stop_drive_down") {                    # Garagentor wurde beim Herunterfahren gestoppt
    drive ("up");                                              # Garagentor Hochfahren
  } else {                                                     # "down-Zustand oder ein sonstiger Anfangszustand
    drive ("up");                                              # Garagentor hochfahren
  }
}
}


Edit: aktuelle Version eingecheckt
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 17 August 2018, 13:50:35
neue Version eingecheckt
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 26 August 2018, 19:10:06
Ich habe die Commandref angepasst, in der Version # $Id: 98_DOIF.pm 17155 2018-08-17 11:45:19Z Damian $, commandref_join.pl zeigt keine Fehler.

- Label eingefügt, damit werden bei Auswahl von Attribut, Set oder Get auch für DOIF die Hilfetexte angezeigt, wenn das globale Attribut language auf DE gestellt ist, s. Bild.

- Kurzreferenz aktualisiert.

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 26 August 2018, 23:10:42
Zitat von: Ellert am 26 August 2018, 19:10:06
Ich habe die Commandref angepasst, in der Version # $Id: 98_DOIF.pm 17155 2018-08-17 11:45:19Z Damian $, commandref_join.pl zeigt keine Fehler.

- Label eingefügt, damit werden bei Auswahl von Attribut, Set oder Get auch für DOIF die Hilfetexte angezeigt, wenn das globale Attribut language auf DE gestellt ist, s. Bild.

- Kurzreferenz aktualisiert.

Ich werde noch ein paar Rechtschreibfehler in meinem Teil korrigieren und dann einchecken.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 27 August 2018, 08:57:56
Ich habe den neuen DOIF-Sourcecode mit commandref_join bei mir eingebunden, kann aber keine Hilfe zum Attribut sehen. language ist auf DE gesetzt. Ich benutze den f18-Style, muss man noch etwas beachten? "Device specific help"-Knopf funktioniert dagegen für die gesamte Doku wie gewohnt.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 27 August 2018, 09:41:06
Du benötigst wenigstens diese Revision von fhemweb.js https://forum.fhem.de/index.php/topic,89778.0.html

Und nicht vergessen den Browsercache zu löschen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 27 August 2018, 10:13:16
Zitat von: Ellert am 27 August 2018, 09:41:06
Du benötigst wenigstens diese Revision von fhemweb.js https://forum.fhem.de/index.php/topic,89778.0.html

Und nicht vergessen den Browsercache zu löschen.

fhemweb.js hatte ich schon aktualisiert, aber es war wohl noch der alte Stand im Cache. Nach dem Löschen des Caches klappt es nun.

Die Direkthilfe war mir neu. Wurde das irgendwo hier im Forum thematisiert? Es ist sicherlich eine gute Hilfe für DOIF-Nutzer bei der Vielzahl der Attribute selektiert die passenden Infos zu bekommen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 27 August 2018, 11:49:26
Eine vorherige Diskussion ist mir nicht bekannt, ich habe es in den FHEM Code changes gesehen, habe mich aber jetzt erst damit befasst.

Eine Diskussion über die Positionierung des Textes gibt es hier: https://forum.fhem.de/index.php/topic,90592.msg830618.html#msg830618

Es werden noch Befürworter gesucht.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 27 August 2018, 12:59:26
Zitat von: Ellert am 27 August 2018, 11:49:26
Eine vorherige Diskussion ist mir nicht bekannt, ich habe es in den FHEM Code changes gesehen, habe mich aber jetzt erst damit befasst.

Eine Diskussion über die Positionierung des Textes gibt es hier: https://forum.fhem.de/index.php/topic,90592.msg830618.html#msg830618

Es werden noch Befürworter gesucht.

Ja, ich habe es vorhin gelesen. Wäre nicht ggf. ein eigenes Fenster besser? Das Umsortieren der Reihenfolge könnte durchaus für Verwirrung sorgen. Vermutlich muss man für die Entscheidungsfindung selbst eine oder mehrere intuitive Lösungen realisieren, um die Handhabbarkeit ausprobieren zu können.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 30 August 2018, 20:17:17
Eine typische Anwendung für Aquaristen: Man möchte über einen längeren Zeitraum einen bestimmten Lichtverlauf mit LEDs simulieren. Das kann sowohl die Lichthelligkeit als auch den Farbton betreffen, hier als Beispiel ein Zweizeiler für bestimmte RGB-Werte.

defmod LED_Simulation DOIF init {@{$_a}=qw/121212 242424 363636 474747 595959 6B6B6B 7D7D7D 8F8F8F A1A1A1 B3B3B3 C4C4C4 D6D6D6 E8E8E8 FAFAFA FFFFFF/;;$_counter=0}\
main {if ([11:10-12:21,+00:04]) {fhem"set Aquarium RGB $_a[$_counter++]";; $_counter=($_counter==@{$_a} ? 0:$_counter)}}


Lässt sich natürlich auch für gemütliche Stunden im Schlafzimmer einsetzen - bitte Uhrzeit und Farbe anpassen :)
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 02 September 2018, 11:42:31
@Damian

Ich würde gern unterschiedliche Blockingcalls über Perl-DOIF starten und die Ergebnisse in Readings des DOIF darstellen, s. https://wiki.fhem.de/wiki/Blocking_Call

Ich denke die Subs blockingFn,finishFn und abortFn müssen weiterhin in der 99_myUtils.pm definiert sein und nicht im subs-Block.
Sehe ich das richtig?

Für jeden unterschiedlichen Blockingcall müsste im Gerätehash ein Datendsatz abgelegt werden, z.B.
$hash->{helper}{BLOCKING}{0}
$hash->{helper}{BLOCKING}{1}
...
$hash->{helper}{BLOCKING}{n}

Damit bei "shutdown" und "rereadcfg" alle laufendes Blockingcalls beendet werden, müssten sie in der undefFn von DOIF über BlockingKill beendet werden.

Würdest Du sowas einbauen wollen?
Siehst Du eine andere Möglichkeit?

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 02 September 2018, 11:57:32
Im subs-Block definierte Funktionen sind Systemweit verfügbar. Eine echte Kapselung gibt es hier nicht, bestehende Funktionen werden mit dem gleichen Namen überschrieben. Daher sollte es mit  blockingFn,finishFn und abortFn im subs-Block funktionieren, wenn sie eindeutig sind.

Du kannst einen Codevorschlag für undefFn machen, ich kann es bei mir unter Window eh nicht testen.

Andererseits könnte man einen Block mit Trigger auf shutdown und rereadcfg selbst definieren und  BlockingKill  aufrufen. Der Zugriff auf $hash->{helper}{BLOCKING} ist ja gegeben.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: travelling-man am 02 September 2018, 23:30:36
Zitat von: Damian am 29 Juli 2018, 19:33:41
Ich habe nun die Version v0.3 mit Doku fertiggestellt.

Auszüge aus der Doku:

und

Zur Demonstration der neuen Funktionalität wird hier ein größeres Projekt (ähnlich diesem https://forum.fhem.de/index.php/topic,48847.0.html) vorgestellt, welches eine Einknopf Garagentor-/Rollladen-Steuerung realisiert. Dabei werden zwei Relais (rauf/runter), die sich gegenseitig sperren und automatische Endabschaltung des Tores/Rollos vorausgesetzt.

Zur Funktionsweise: Ein geschlossenes Tor wird beim Tastendruck geöffnet, ein geöffnetes wird geschlossen, wenn während der Laufzeit Taste gedrückt wird, bleibt das Tor stehen, ein erneuter Tastendruck bewegt das Tor in umgekehrte Richtung. Dabei werden unterschiedliche Laufzeiten des Tores (rauf/runter) berücksichtigt, ebenso wird die aktuelle Position des Tores aufgrund der Laufzeit berechnet und im Reading abgelegt.

Der Sourcecode ist weitgehend dokumentiert und kann mit Dummys (switch_up, switch_down) ausprobiert werden.


DOIF subs {                                       # im Block subs werden Perlfunktionen definiert, die innerhalb des DOIFs benutzt werden
sub drive { my ($downup)=@_;                      # Funktion zum Herunterfahren oder Hochfahren des Garagentors
  my $seconds; 
  if ($downup eq "up") {
    fhem"set $_up on";                            # Schalter zum Hochfahren einschalten
    $seconds=$_drive_up_time*(1-$_pos/100);       # Laufzeit in Sekunden berechnen
    $_pos=100;                                    # Endposition vorbelegen
  } else {
    fhem"set $_up on";                            # Schalter zum Herunterfahren einschalten
    $seconds=$_drive_down_time*($_pos/100);       # Laufzeit in Sekunden berechnen
    $_pos=0;                                      # Endposition vorbelegen
  }
  set_Reading("state","drive_$downup",1);         # Status des Modus auf drive_down oder drive_up setzen
  set_Exec("Timer_off",$seconds,"off",$downup);   # Setze Timer zum Abschalten des Switches switch_down oder switch_up
}                                             
 
sub off {                                         # Funktion zum Abschalten des hoch-/runter-Schalters
  my ($downup)=@_;
  if ($downup eq "up") {
    fhem"set $_up off";                           # Schalter zum Hochfahren abschalten
  } else {
    fhem"set $_down off";                         # Schalter zum Herunterfahren  abschalten
  }
  set_Reading("state",$downup,1);                 # setze Status des Moduls auf up oder down
  set_Reading("position",int($_pos),1);           # aktuelle Position im Reading festhalten
}

}

init {                                      # Vorbelegung von Instanzvariablen
   $_up="switch_up";                        # Name des Schalters zum Hochfahren
   $_down="switch_down";                    # Name des Schalters zum Herunterfahren
   $_drive_up_time=15;                      # Fahrzeit des Garagentors nach oben
   $_drive_down_time=10;                    # Fahrzeit des Garagentors nach unten
   $_pos=0;                                 # aktuelle Position des Garagentors (0-down, 100-up)
   set_Reading("position",0,0);             # Reading mit der Position auf 0 setzen
}

main {                                                         # Hauptblock reagiert auf Fernbedienung FS und steuert switch up/down abhängig vom Zustand
if ([FS]) {
  if ([?$SELF] eq "up") {                                      # wenn Garagentor oben dann herunterfahren
    drive ("down");                                            # Garagentor herunterfahren
  } elsif ([?$SELF] eq "drive_up") {                           # Garagentor fährt nach oben
    $_pos = (1 - get_Exec("Timer_off")/$_drive_up_time)*100;   # Position bestimmen
    off ("up");                                                # Garagentor stoppen
    del_Exec("Timer_off");                                     # Timer löschen
    set_Reading("state","stop_drive_up",1);                    # Zustand des Moduls setzen
  } elsif ([?$SELF] eq "drive_down") {                         # Garagentor fährt nach unten
    $_pos = (get_Exec("Timer_off")/$_drive_down_time)*100;     # Position bestimmen
    off ("down");                                              # Garagentor stoppen
    del_Exec("Timer_off");                                     # Timer löschen
    set_Reading("state","stop_drive_down",1);                  # Zustand des Moduls setzen
  } elsif ([?$SELF] eq "stop_drive_up") {                      # Garagentor wurde beim Hochfahren gestoppt
    drive ("down");                                            # Herunterfahren
  } elsif ([?$SELF] eq "stop_drive_down") {                    # Garagentor wurde beim Herunterfahren gestoppt
    drive ("up");                                              # Garagentor Hochfahren
  } else {                                                     # "down-Zustand oder ein sonstiger Anfangszustand
    drive ("up");                                              # Garagentor hochfahren
  }
}
}


Edit: aktuelle Version eingecheckt

Hallo Damian,

wäre es möglich das du den Code um 3 Positionsschalter erweitern könntest?
1. Positionsschalter --> Tor zu
2. Positionsschalter --> Tor auf
3. Positionsschalter --> Tor darf sich nicht öffnen da eine Tür im Tor ist nicht geschlossen

Viele Grüße
T-M
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 03 September 2018, 05:15:11
Zitat von: Damian am 02 September 2018, 11:57:32
Du kannst einen Codevorschlag für undefFn machen, ich kann es bei mir unter Window eh nicht testen.
Blokierende Funktionsaufrufe (blocking calls)

DOIF verwaltet blockierende Funktionsaufrufe, d.h. die in diesem Zusammenhang gestarteten FHEM-Instanzen werden gelöscht,

  beim Herunterfahren (shutdown),
  Wiedereinlesen der Konfiguration (rereadcfg),
  Änderung der Konfiguration (modify) und
  Deaktivieren des Gerätes (disabled).

Die Handhabung von blockierenden Funktionsaufrufen ist im FHEMwiki erklärt, s. Blocking Call (https://wiki.fhem.de/wiki/Blocking_Call).

Der von der Funktion BlockingCall zurückgegebene Datensatz ist unterhalb von $_blockingcalls abzulegen, z.B.

$_blockingcalls{<blocking call name>} = BlockingCall(<blocking function>, <argument>, <finish function>, <timeout>, <abort function>, <abort argument>) unless(defined($_blockingcalls{<blocking call name>}));

Für unterschiedliche blockierende Funktionen ist jeweil ein eigener Name (<blocking call name>) unterhalb von $_blockingcalls anzulegen.

$_blockingcalls ist eine für DOIF reservierte Variable und darf nur in der beschriebenen Weise verwendet werden.

Beispieldefinition zum Testen (für Raw definition)

defmod blockingDOIF DOIF subs {\
  # blocking function\
  sub testBlocking($) {\
    my ($pn) = @_;;\
    for (my $i=0;;$i<20;;$i++) { # ist running 20 s\
      sleep 1;; # sleep is blocking\
    }\
    return "$pn|finished";;\
  }\
  # finish function\
  sub testDone($) {\
    my ($string) = @_;;\
    return unless(defined($string));;\
    my ($pn,$ret) = split("\\|", $string);;\
    my $hash = $defs{$pn};;\
    delete($_blockingcalls{test}) if (defined($_blockingcalls{test}));;\
    set_Reading("test_return", $ret, 1);;\
  }\
  # abort function\
  sub testAbort($){\
    my ($pn) = @_;;\
    my $hash = $defs{$pn};;\
    delete($_blockingcalls{test}) if (defined($_blockingcalls{test}));;\
    set_Reading("test_return", "aborted", 1);;\
  }\
}\
\
blockingcall {\
  #BlockingCall($blockingFn, $arg, $finishFn, $timeout, $abortFn, $abortArg);;\
  my $hash = $defs{$SELF};;\
  my $pn = "$SELF";;\
  if ([+60]) { # calls the blocking function every 60 s with timeout of 30 s\
    if (!defined($_blockingcalls{test})) {\
      $_blockingcalls{test} = BlockingCall("testBlocking", $pn, "testDone", 30, "testAbort", $pn);;\
      set_Reading("test_return", "called, pid:$_blockingcalls{test}{pid}", 1);;\
    } \
  }\
}\
init { # calls the blocking function initially with timeout of 15 s. The blocking call will be aborted before finishing \
  my $hash = $defs{$SELF};;\
  my $pn = "$SELF";;\
    if (!defined($_blockingcalls{test})) {\
      $_blockingcalls{test} = BlockingCall("testBlocking", $pn, "testDone", 15, "testAbort", $pn);;\
      set_Reading("test_return", "called first, pid:$_blockingcalls{test}{pid}", 1);;\
    }\
}


Der Patch basiert auf # $Id: 98_DOIF.pm 17155 2018-08-17 11:45:19Z Damian $

Edit: Anlagen entfernt
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 03 September 2018, 09:46:44
OK.

Gibt es eigentlich eine Killer-Anwendung für blocking calls?

Die Definition:

my $hash = $defs{$pn};

sollte in den Blöcken wie auch den Funktionen überflüssig sein, da $hash global definiert ist.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 03 September 2018, 09:59:22
Zitat von: travelling-man am 02 September 2018, 23:30:36
Hallo Damian,

wäre es möglich das du den Code um 3 Positionsschalter erweitern könntest?
1. Positionsschalter --> Tor zu
2. Positionsschalter --> Tor auf
3. Positionsschalter --> Tor darf sich nicht öffnen da eine Tür im Tor ist nicht geschlossen

Viele Grüße
T-M

Das etwas umfangreichere Beispiel war als Anregung zum Weitermachen gedacht. Die Abfrage eines Sensors über den Zustand des Tores/Rollos, wäre tatsächlich die nächste Aufgabe zum Ausbau der Definition. Es würde mich freuen, wenn jemand den Anfang machen würde, denn nur so lernt man am besten die Funktionsweise eines Moduls kennen. Ich stehe natürlich bereit, Lösungsvorschläge zu korrigieren bzw. zu verbessern.

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 03 September 2018, 10:38:01
Zitat von: Damian am 03 September 2018, 09:46:44
Gibt es eigentlich eine Killer-Anwendung für blocking calls?
Ich verwende BlockingCall für meine Benzinpreisabfrage (Dauer 4s) und eine Wetterdatenabfrage (Dauer 10s).
Ich verwende nicht HTTPMOD oder HTTPUtils, weil ich Mechanize verwende.
Die Daten schreibe ich bisher in einen Dummy und das Löschen der laufenden FHEM-Instanzen beim Neustart und Neueinlesen der Konfiguration hatte ich bisher nicht realisiert.
Diese Geschichten wollte ich in ein DOIF packen, das war der Anlass DOIF im Zusammenhang mit Blockingcall zu betrachten.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 03 September 2018, 11:20:22
Zitat von: Ellert am 03 September 2018, 10:38:01
Ich verwende BlockingCall für meine Benzinpreisabfrage (Dauer 4s) und eine Wetterdatenabfrage (Dauer 10s).
Ich verwende nicht HTTPMOD oder HTTPUtils, weil ich Mechanize verwende.
Die Daten schreibe ich bisher in einen Dummy und das Löschen der laufenden FHEM-Instanzen beim Neustart und Neueinlesen der Konfiguration hatte ich bisher nicht realisiert.
Diese Geschichten wollte ich in ein DOIF packen, das war der Anlass DOIF im Zusammenhang mit Blockingcall zu betrachten.

Dann wäre das ein guter Aufhänger für ein passendes DOIF-Beispiel vermutlich im Wiki, weil für Commandref zu umfangreich. Wahrscheinlich brauchen wir eine eigene Wiki-Unterseite für DOIF-Perl mit entsprechenden Beispielen. Ich bin noch am sammeln, finde aber jeden Tag neue Anwendungsfälle für sinnvolle Nutzung des Perl-Modus.

Wie gesagt, testen kann ich bei mir schlecht (ein fork funktioniert nicht gut unter Windows ;) ), das müsstest du dann machen. Die Änderungen im Sourcecode halten sich in Grenzen.


Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 03 September 2018, 16:21:56
Getestet habe ich, alles funktioniert wie es soll. Aus meiner Sicht kann es eingecheckt werden. Ein Beispiel werde ich noch basteln.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 03 September 2018, 16:42:56
Zitat von: Ellert am 03 September 2018, 16:21:56
Getestet habe ich, alles funktioniert wie es soll. Aus meiner Sicht kann es eingecheckt werden. Ein Beispiel werde ich noch basteln.

Hast du auch ohne $hash getestet?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 03 September 2018, 18:01:50
Zitat von: Damian am 03 September 2018, 16:42:56
Hast du auch ohne $hash getestet?
Ja, das funktioniert, erzeugt aber ein ungutes Gefühl.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 03 September 2018, 18:40:47
Anliegend ein Beispiel mit BlockingCall im DOIF zur Abfrage von Kraftstoffpreisen.

Als Voraussetzung müssen folgende Pakete installiert werden
  libwww-mechanize-perl
  libwww-mechanize-treebuilder-perl
bzw. über CPAN
  WWW::Mechanize
  WWW::Mechanize::TreeBuilder

Die URL für die Tankstellenliste und die Tankstellennummern können per Attribut angegeben werden.

defmod Kraftstoffpreise DOIF subs {\
  use WWW::Mechanize;;\
  use WWW::Mechanize::TreeBuilder;;\
  \
  sub KraftstoffPreise_Do {\
    my ($pn) = @_;;\
    my $tstart = gettimeofday();;\
    my ($url) = AttrVal($pn,"URL","https://www.clever-tanken.de/tankstelle_liste?spritsorte=5&r=2&lat=&lon=&ort=22049");;\
    my @tali = split(/ /,AttrVal($pn,"Tankstellen","50686"));;\
    my $mech = WWW::Mechanize->new(autocheck => 1, onerror => undef);;\
    WWW::Mechanize::TreeBuilder->meta->apply($mech);;\
    my @price;;\
    my @preis;;\
    my @station;;\
    my @name;;\
    my @street;;\
    my @strasse;;\
    my @city;;\
    my @stadt;;\
    my @erg;;\
    my $ret = $pn;;\
    $mech->get($url);;\
    if ($mech->success()) {\
      for (my $i=0;;$i<@tali;;$i++){\
        @erg = $mech->look_down("id","tankstelle-".$tali[$i]);;\
        return undef unless ($erg[0]);;\
        @price = $erg[0]->look_down("class","price");;\
        if ($price[0]) {\
          $preis[$i] = $price[0]->as_text();;\
        } else {\
          $preis[$i] = ReadingsNum($pn,"price_".$i,"2.00");;\
        }\
        @station = $erg[0]->look_down("class","row fuel-station-location-name");;\
        $name[$i] = $station[0]->as_text();;\
        @street = $erg[0]->look_down("id","fuel-station-location-street");;\
        $strasse[$i] = $street[0]->as_text();;\
        @city = $erg[0]->look_down("id","fuel-station-location-city");;\
        $stadt[$i] = $city[0]->as_text();;\
        $ret .= "|".$preis[$i]."|".$name[$i]."|".$strasse[$i]."|".$stadt[$i];;\
      }\
    }\
    my $ret_dur = gettimeofday() - $tstart;;\
    $ret .= "|$ret_dur";;\
    return $ret;; \
  }\
\
  sub KraftstoffPreise_Done {\
    my ($string) = @_;;\
    return unless(defined($string));;\
    my @ret = split("\\|", $string);;\
    my $pn = $ret[0];;\
    my $dur = int($ret[@ret-1] * 100) / 100;;\
    delete($_blockingcalls{Kraftstoff});;\
    my $cnt = 0;;\
    set_Reading_Begin();;\
    for (my $i = 1;; $i < @ret-1;; $i += 4) {\
      $ret[$i] = $ret[$i] + 0.001;;\
      if ($i == 1) {\
        set_Reading_Update("state",sprintf("%.2f",$ret[$i])." $ret[$i+1]");;\
      } else {\
         set_Reading_Update("state", sprintf("%.2f",$ret[$i])." $ret[$i+1]") if (ReadingsNum($pn,"state","99") > $ret[$i]);;\
        set_Reading_Update("state",sprintf("%.2f",$ret[$i])." $ret[$i+1]") if (ReadingsNum($pn,"state","99") > $ret[$i]);;\
      }\
      set_Reading_Update("price_$cnt", sprintf("%.2f",$ret[$i])." $ret[$i+1]");;\
      set_Reading_Update("station_$cnt", "$ret[$i+1] $ret[$i+2]  $ret[$i+3]") if ("$ret[$i+1] $ret[$i+2] $ret[$i+3]" ne ReadingsVal($pn,"station_$cnt","none"));;\
      $cnt++;;\
    }\
    set_Reading_Update("dauer", $dur);;\
    set_Reading_End(1);;\
  }\
\
  sub KraftstoffPreise_Abort {\
    delete($_blockingcalls{Kraftstoff}) if(defined($_blockingcalls{Kraftstoff}));;\
    return undef;;\
  }\
}\
\
blockingcall {\
  ##BlockingCall($blockingFn, $arg, $finishFn, $timeout, $abortFn, $abortArg);;\
  my $pn = "$SELF";;\
  if ([+3600] or ["^$SELF$:^exec$"]) { ## calls the blocking function every hour with timeout of 30 s\
    $_blockingcalls{Kraftstoff} = ::BlockingCall("DOIF::KraftstoffPreise_Do", $pn, "DOIF::KraftstoffPreise_Done", 30, "DOIF::KraftstoffPreise_Abort", $pn) if (!defined($_blockingcalls{Kraftstoff}));;\
  }\
}\

attr Kraftstoffpreise userattr Tankstellen URL
attr Kraftstoffpreise Tankstellen 50686 20385 11706
attr Kraftstoffpreise URL https://www.clever-tanken.de/tankstelle_liste?spritsorte=5&r=2&lat=&lon=&ort=22049
attr Kraftstoffpreise room DOIF_Labor
attr Kraftstoffpreise setList exec
attr Kraftstoffpreise webCmd exec


Edit: Update wg. Package DOIF
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 03 September 2018, 19:30:14
Zitat von: Ellert am 03 September 2018, 18:01:50
Ja, das funktioniert, erzeugt aber ein ungutes Gefühl.

Warum? Besser so als mit $defs{$pn} zu hantieren.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 03 September 2018, 19:36:35
Zitat von: Damian am 03 September 2018, 19:30:14
Warum? Besser so als mit $defs{$pn} zu hantieren.
Ja, besser ist es und in der geforkten FHEM-Instanz gibt es den Hash auch.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 03 September 2018, 19:38:59
Zitat von: Ellert am 03 September 2018, 18:40:47
Anliegend ein Beispiel mit BlockingCall im DOIF zur Abfrage von Kraftstoffpreisen.

Als Voraussetzung müssen folgende Pakete installiert werden
  libwww-mechanize-perl
  libwww-mechanize-treebuilder-perl
bzw. über CPAN
  WWW::Mechanize
  WWW::Mechanize::TreeBuilder
...

Wird wahrscheinlich die meisten überfordern. :)

Ich denke man könnte als Vorteil dieser Lösung folgende Punkte nennen:

-alles in einem Device gekapselt
-keine ausgelagerten Perlfunktionen in myUtils
-keine weiteren FHEM-Module erforderlich
-schneller programmiert als ein eigenständiges FHEM-Modul zu programmieren
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 03 September 2018, 19:59:26
Und in diesem Fall übernimmt DOIF das Beenden der Blocking-Instanzen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 03 September 2018, 20:10:07
Zitat von: Ellert am 03 September 2018, 19:59:26
Und in diesem Fall übernimmt DOIF das Beenden der Blocking-Instanzen.

ja, der Anfang für etwas Neues ist immer etwas zäh.

Allerdings so wie ich vor über  4 Jahren https://forum.fhem.de/index.php/topic,23833.msg170608.html#msg170608 an die Zukunft von DOIF glaubte, glaube jetzt an die Zukunft des Perl-Modus, weil man intuitiver und flexibler Ereignissteuerung programmieren kann, als im FHEM-Modus.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 03 September 2018, 21:14:03
Zitat von: Ellert am 03 September 2018, 05:15:11
Blokierende Funktionsaufrufe (blocking calls)

DOIF verwaltet blockierende Funktionsaufrufe, d.h. die in diesem Zusammenhang gestarteten FHEM-Instanzen werden gelöscht,

  beim Herunterfahren (shutdown),
  Wiedereinlesen der Konfiguration (rereadcfg),
  Änderung der Konfiguration (modify) und
  Deaktivieren des Gerätes (disabled).
...

Wo hast du im Code shutdown abgedeckt?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 03 September 2018, 23:20:44
Ich habe mich auf die Info im Wiki verlassen, dass UndefFn reicht, um beim Herunterfahren die blockierende Instanz zu beenden.

Ich habe jetzt die ShutdownFn ergänzt und getestet.

Edit: Anhänge entfernt
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 04 September 2018, 08:16:29
Zitat von: Ellert am 03 September 2018, 23:20:44
Ich habe mich auf die Info im Wiki verlassen, dass UndefFn reicht, um beim Herunterfahren die blockierende Instanz zu beenden.

Ich habe jetzt die ShutdownFn ergänzt und getestet.

OK. Ich lasse es bei mir noch etwas laufen und dann werde ich die Version einchecken.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 05 September 2018, 19:42:26
Zitat von: Damian am 04 September 2018, 08:16:29
OK. Ich lasse es bei mir noch etwas laufen und dann werde ich die Version einchecken.

Version mit blocking calls eingecheckt.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 09 September 2018, 20:23:47
Wem das holiday-Modul nicht ausrecht: https://forum.fhem.de/index.php/topic,43685.msg834725.html#msg834725
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 14 September 2018, 16:54:59
In der kommenden DOIF-Version wird man mit set_Exec unmittelbar Perl/FHEM-Code verzögert ausführen können

z. B. Lampe nach 10 Sekunden ausschalten:

set_Exec("lampe_aus",10,'fhem"set lamp off"')


Das Beispiel Treppenhauslicht mit Bewegungsmelder aus der Commandref könnte dann so aussehen:

define di_light DOIF {
  if (["FS:motion"]) {                        # bei Bewegung
    fhem"set lamp on" if ([?lamp] ne "on");   # Lampe einschalten, wenn sie nicht an ist
    set_Exec("off",30,'fhem"set lamp off"');  # Timer namens "off" für das Ausschalten der Lampe auf 30 Sekunden setzen bzw. verlängern
  }
}


Edit: auch das Beispiel für Einknopf-Rollladensteuerung lässt sich in einem Block definieren

define di_shutter DOIF {
  if (["FS:^on$"] and !get_Exec("shutter")){          # wenn Taste betätigt wird und kein Timer läuft
    set_Exec("shutter",2,'fhem"set shutter down"');   # Timer zum shutter down auf zwei Sekunden setzen
  } else {                                            # wenn Timer läuft, d.h. ein weitere Tastendruck innerhalb von zwei Sekunden
    del_Timer("shutter");                             # Timer löschen
    fhem"set shutter up";                             # Rollladen hoch
  }
}


oder das Beispiel zum Zählen von Ereignissen innerhalb einer Zeitspanne:

define di_count DOIF {                         
  if (["FS:on"] and !get_Exec("counter")) {                                        # wenn Ereignis (hier "FS:on") eintritt und kein Timer läuft
    $_count=1;                                                                     # setze count-Variable auf 1
    set_Exec("counter",3600,'Log (3,"count: $_count action") if ($_count > 10)');  # setze Timer auf eine Stunde zum Protokollieren der Anzahl der Ereignisse, wenn sie über 10 ist
  } else {
    $_count++;                                                                     # wenn Timer bereits läuft zähle Ereignis
  }
}
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 16 September 2018, 12:50:19
Neue Version eingecheck. set_Exec kann jetzt direkt Perlcode ausführen. Doku zum Perl-Modus wurde überarbeitet:

Auszug:

ZitatPerl Modus

Der Perl-Modus ist sowohl für einfache, als auch für komplexere Automatisierungsabläufe geeignet. Der Anwender hat mehr Einfluss auf den Ablauf der Steuerung als im FHEM-Modus. Die Abläufe lassen sich, wie in höheren Programmiersprachen üblich, strukturiert programmieren. Zum Zeitpunkt der Definition werden alle DOIF-spezifischen Angaben in Perl übersetzt, zum Zeitpunkt der Ausführung wird nur noch Perl ausgeführt, damit wird maximale Performance gewährleistet.

Syntax Perl-Modus:

define <name> DOIF <Blockname> {<Perlcode mit Ereignis-/Zeittriggern in eckigen Klammern>}


Ein Perlblock wird ausgeführt, wenn dieser bedingt durch Ereignis- und Zeittrigger in eckigen Klammern innerhalb des Blocks, getriggert wird. Es wird die vollständige Perl-Syntax unterstützt. Es können beliebig viele Perlblöcke innerhalb eines DOIF-Devices definiert werden. Sie werden unabhängig voneinander durch passende Trigger ausgeführt. Der Name eines Blocks ist optional.

Der Status des Moduls wird nicht vom Modul gesetzt, er kann vom Anwender mit Hilfe der Funktion set_Reading verändert werden, siehe spezifische Perl-Funktionen im Perl-Modus. FHEM-Befehle werden durch den Aufruf der Perlfunktion fhem"..." ausgeführt.

Der Benutzer kann mit der Funktion set_Timer/set_Exec beliebig viele eigene Timer definieren, die unabhängig voneinander gesetzt und ausgewertet werden können, siehe Spezifische Perl-Funktionen im Perl-Modus.

Definitionen im FHEM-Modus der Form:

DOIF (<Bedingung mit Trigger>) (<FHEM-Befehle>) DOELSE (<FHEM-Befehle>)

lassen sich wie folgt in Perl-Modus übertragen:

DOIF {if (<Bedingung mit Trigger>) {fhem"<FHEM-Befehle>"} else {fhem"<FHEM-Befehle>"}}

Die Bedingungen des FHEM-Modus können ohne Änderungen in Perl-Modus übernommen werden können.

Im Perl-Modus können beliebig viele Blöcke definiert werden, die unabhängig von einander durch einen Trigger ausgewertet und zur Ausführung führen können:

DOIF
{ if (<Bedingung mit Trigger>) ... }
{ if (<Bedingung mit Trigger>) ... }
...


Im Perlmodus sind beliebige Hierarchietiefen möglich:

DOIF
{ if (<Bedingung>) {
    if (<Bedingung>) {
      if (...
        ...
      }
    }
  }
}


Bemerkung: Innerhalb eines DOIF-Blocks muss mindestens ein Trigger in irgendeiner Bedingung definiert werden, damit der gesamte Block beim passenden Trigger ausgewertet wird.

Eigene Funktionen

Ein besonderer Perlblock ist der Block namens "subs". In diesem Block werden Perlfunktionen definiert werden, die innerhalb des DOIFs genutzt werden. Um eine möglichst hohe Kompatibilität zu Perl sicherzustellen, wird keine DOIF-Syntax in eckigen Klammern unterstützt, insb. gibt es keine Trigger, die den Block ausführen können.

Beispiel:

DOIF subs { ## Definition von Perlfunktionen lamp_on und lamp_off
  sub lamp_on {
     fhem"set lamp on";
     set_Reading("state","on",1);
  }
  sub lamp_off {
     fhem"set lamp off";
     set_Reading("state","off",1);
  }
}
{if ([06:00]) {lamp_on()  # Um 06:00 Uhr wird die Funktion lamp_on aufgerufen }
{if ([08:00]) {lamp_off() # Um 08:00 Uhr wird die Funktion lamp_off aufgerufen }

...
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 16 September 2018, 17:39:38
Welche Schreibweise ist für den nicht triggernden Zugriff auf Readings vorzuziehen? Gibt es nennenswerte Performanceunterschiede?

a) [?<name>:<Reading>,<Default>] oder
b) ReadingsVal(<name>, <Reading>,<Default>)
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 16 September 2018, 19:02:38
In set_Exec gibt es noch eine Stolperfalle, die Definition
defmod di2400 DOIF test {\
  if (["^global$:^MODIFIED $SELF$"]){\
    set_Exec("test",10,'Log 1,"[?$SELF:state]"');;\
  }\
}

erzeugt eine Fehlermeldung, wegen der Hochkommata in ReadingValDoIf
Internals:
   DEF        test {
  if (["^global$:^MODIFIED $SELF$"]){
    set_Exec("test",10,'Log 1,"[?$SELF:state]"');
  }
}
   MODEL      Perl
   NAME       di2400
   NR         172
   NTFY_ORDER 50-di2400
   STATE      initialized
   TYPE       DOIF
   READINGS:
     2018-09-16 18:50:54   Device          global
     2018-09-16 18:50:54   block_test      condition c01: Bad name after di2400', line 3.

     2018-09-16 18:50:53   mode            enabled
     2018-09-16 18:50:53   state           initialized
   Regex:
     cond:
       :
         0:
           "^global$:^MODIFIED di2400$" ^global$:^MODIFIED di2400$
   condition:
     0         
  if (EventDoIf('^global$',$hash,'^MODIFIED di2400$',0)){
    DOIF_set_Exec($hash,"test",10,'Log 1,"ReadingValDoIf($hash,'di2400','state')"');
  }

   devices:
   helper:
     event      MODIFIED di2400
     globalinit 1
     last_timer 0
     sleeptimer -1
     triggerDev global
     triggerEvents:
       MODIFIED di2400
     triggerEventsState:
       MODIFIED di2400
   internals:
   itimer:
   perlblock:
     0          test
   readings:
   trigger:
   uiState:
   uiTable:
Attributes:
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 16 September 2018, 21:08:46
Wenn es sich um keine Trigger handelt, würde ich ReadingsVal nehmen. Dann weiß auch der Perl-Programmierer, was dahinter steckt, ansonsten wird es immer Probleme mit den Anführungszeichen geben, da man nie weiß, was genau dahinter steckt.

hier also:

set_Exec("test",10,'Log 1,ReadingsVal("$SELF","state","")')

Vielleicht definiere ich noch für Readings des Device das Gegenstück zu der Funktion set_Reading:

Reading (<Reading>,<default>);

Dann könnte man angeben:

set_Exec("test",10,'Log 1,Reading("state","")')


Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 17 September 2018, 19:58:46
Ich habe vor do always Beispiele in der Doku in Perl-Modus zu überführen, weil sie meiner Meinung nach einfacher zu definieren sind, z. B.

aus
define di_rand_sunset DOIF ([{sunset()}])(set lamp on)
attr di_rand_sunset wait rand(1200)
attr di_rand_sunset timerWithWait 1
attr di_rand_sunset do always


wird
define di_rand_sunset DOIF {if ([{sunset()}]) {set_Exec("on",rand(1200),'fhem"set lamp on"')}}
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 18 September 2018, 20:27:53
Mit dem Attribut setList  kann man die Auswahlliste des Set-Befehls erweitern.
Durch die Erweiterung des Set-Befehls lassen sich bestimmte  Funktionen des DOIF im Perl-Modus direkt ausführen, z.B. um etwas zu Testen.

defmod directCommand DOIF {\
  if (["^$SELF$:^debug_1$"]){\
    Log 1,"$SELF: if-Block 1 getestet!";;\
  } elsif (["^$SELF$:^debug_2$"]) {\
    Log 1,"$SELF: if-Block 2 getestet!";;\
  } elsif (["^$SELF$:^debug_3$"]) {\
    Log 1,"$SELF: if-Block 3 getestet!";;\
  }\
}
attr directCommand setList debug_1 debug_2 debug_3
attr directCommand webCmd debug_1:debug_2:debug_3
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 18 September 2018, 20:39:20
Zitat von: Ellert am 18 September 2018, 20:27:53
Mit dem Attribut setList  kann man die Auswahlliste des Set-Befehls erweitern.
Durch die Erweiterung des Set-Befehls lassen sich bestimmte  Funktionen des DOIF im Perl-Modus direkt ausführen, z.B. um etwas zu Testen.

defmod directCommand DOIF {\
  if (["^$SELF$:^debug_1$"]){\
    Log 1,"$SELF: if-Block 1 getestet!";;\
  } elsif (["^$SELF$:^debug_2$"]) {\
    Log 1,"$SELF: if-Block 2 getestet!";;\
  } elsif (["^$SELF$:^debug_3$"]) {\
    Log 1,"$SELF: if-Block 3 getestet!";;\
  }\
}
attr directCommand setList debug_1 debug_2 debug_3
attr directCommand webCmd debug_1:debug_2:debug_3


Im Perl-Modus ist es sinnvoller Zweige, die sich gegenseitig ausschließen in eigene Blöcke zu trennen, denn dann wird bei einem passenden Trigger jeweils nur der "eigene" Block ausgeführt und nicht immer der gesamte, hier also:

defmod directCommand DOIF \
  {if (["^$SELF$:^debug_1$"]){Log 1,"$SELF: if-Block 1 getestet!"}}\
  {if (["^$SELF$:^debug_2$"]){Log 1,"$SELF: if-Block 2 getestet!"}}\
  {if (["^$SELF$:^debug_3$"]){Log 1,"$SELF: if-Block 3 getestet!"}}

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 18 September 2018, 20:57:47
Eine weitere Eigenschaft des Perl-Modus ist die Tatsache, dass bei einfachen Bedingung sogar die if-Abfrage weggelassen werden kann, hier z. b.

defmod directCommand DOIF \
  {["^$SELF$:^debug_1$"];Log 1,"$SELF: if-Block 1 getestet!"}\
  {["^$SELF$:^debug_2$"];Log 1,"$SELF: if-Block 2 getestet!"}\
  {["^$SELF$:^debug_3$"];Log 1,"$SELF: if-Block 3 getestet!"}


Es liegt am Perl, da die Angabe [...] eine Perl-Funktion darstellt, die wahr oder nicht wahr ist. Die braucht man eigentlich gar nicht auswerten, da das DOIF-Modul das bereits macht, um den passenden Block auszuführen.
if wird spätestens dann benötigt, wenn logische Abfragen erfolgen sollen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 18 September 2018, 21:20:21
Wenn man if weglassen kann, dann kann man z. B. Folgendes definieren

defmod directCommand DOIF {Log 1,"$SELF: ".["^$SELF$:^debug_":"(.*)",""]}

Hier führt die Triggerangabe [...] nicht nur dazu, dass der Block ausgeführt wird, sondern liefert gleichzeitig durch den angegebenen Regex-Filter das entsprechende Event.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 18 September 2018, 23:31:08
Interessanterweise triggert sogar der Kommentar.

defmod directCommand DOIF { # ["^$SELF$:^debug_1$"]\
  Log 1,"$SELF: Block 01 getestet!";;\
}
attr directCommand setList debug_1
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 18 September 2018, 23:36:30
Zitat von: Ellert am 18 September 2018, 23:31:08
Interessanterweise triggert sogar der Kommentar.

defmod directCommand DOIF { # ["^$SELF$:^debug_1$"]\
  Log 1,"$SELF: Block 01 getestet!";;\
}
attr directCommand setList debug_1


Ja, nur Kommentare mit ## werden vom DOIF-Modul ignoriert.

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 19 September 2018, 00:05:02
Die Verwendung von einer Raute zur Kommentierung in den Beispielen der Commandref zum Perl-Modus hat mich verführt einen Trigger mit einer einfachen Raute auszukommentieren. Es hat ein bisschen gedauert bis ich gemerkt habe, dass es nicht funktioniert.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 19 September 2018, 09:12:57
Zitat von: Ellert am 19 September 2018, 00:05:02
Die Verwendung von einer Raute zur Kommentierung in den Beispielen der Commandref zum Perl-Modus hat mich verführt einen Trigger mit einer einfachen Raute auszukommentieren. Es hat ein bisschen gedauert bis ich gemerkt habe, dass es nicht funktioniert.

Zuerst werden Kommentare mit doppelter Raute von DOIF gefiltert, der Rest wird nach Triggern durchsucht und geht anschließend an Perl. Dort gelten die Perl-Regeln mit Kommentaren mit einfacher Raute.

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 19 September 2018, 11:04:11
Mit der Version 98_DOIF.pm 17358 2018-09-16 19:54:57Z Damian führt die alte Syntax von set_Exec zu einer Fehlermeldung.
Das Ausführen von Block 0 und 1 erzeugt den Fehler.

defmod directCommand DOIF {["^$SELF$:^debug_1$"];;set_Exec("debug_1",5, "fhem", "setreading $SELF test1 Block 1 getestet!");;}\
{["^$SELF$:^debug_2$"];;set_Exec("debug_2",5, "fhem", "setreading directCommand test2 Block 2 getestet!");;}\
{["^$SELF$:^debug_3$"];;set_Exec("debug_3",5, 'fhem "setreading $SELF test3 Block 3 getestet!"');;}\
{["^$SELF$:^debug_4$"];;set_Exec("debug_4",5, 'set_Reading("test4", "Block 4 getestet!",1)');;}
attr directCommand room 0_Test
attr directCommand setList debug_1 debug_2 debug_3 debug_4
attr directCommand webCmd debug_1:debug_2:debug_3:debug_4
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 19 September 2018, 11:28:19
Zitat von: Ellert am 19 September 2018, 11:04:11
Mit der Version 98_DOIF.pm 17358 2018-09-16 19:54:57Z Damian führt die alte Syntax von set_Exec zu einer Fehlermeldung.
Das Ausführen von Block 0 und 1 erzeugt den Fehler.

defmod directCommand DOIF {["^$SELF$:^debug_1$"];;set_Exec("debug_1",5, "fhem", "setreading $SELF test1 Block 1 getestet!");;}\
{["^$SELF$:^debug_2$"];;set_Exec("debug_2",5, "fhem", "setreading directCommand test2 Block 2 getestet!");;}\
{["^$SELF$:^debug_3$"];;set_Exec("debug_3",5, 'fhem "setreading $SELF test3 Block 3 getestet!"');;}\
{["^$SELF$:^debug_4$"];;set_Exec("debug_4",5, 'set_Reading("test4", "Block 4 getestet!",1)');;}
attr directCommand room 0_Test
attr directCommand setList debug_1 debug_2 debug_3 debug_4
attr directCommand webCmd debug_1:debug_2:debug_3:debug_4


Er hat es doch bemerkt :)

Den Fehler habe ich bereits gestern korrigiert, aber noch nicht hochgeladen, dachte - benutzt noch keiner. :)

Ich werde es heute noch einchecken.

Alternative Syntax:

["^$SELF$:^debug_1$"];;set_Exec("debug_1",5, "fhem\"setreading $SELF test1 Block 1 getestet!\"")

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 19 September 2018, 21:16:54
Korrigierte Version eingecheckt.

Doku angepasst: Ich spreche jetzt nicht von Perlblöcken, sondern von Ereignisblöcken, weil es der Funktion des Blocks näher kommt.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 21 September 2018, 20:17:30
Da im Perl-Modus der Status vom User gesetzt werden muss, habe ich eine vereinfachte Funktion definiert, die das erledigt:

set_State(<content>);

entspricht:

set_Reading("state",<content>,1);

bzw.

readingsSingleUpdate($hash,"state",<content>,1);
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 21 September 2018, 22:56:08
Falls Einer in die Tiefen von Perl einsteigen möchte, hier ein Beispiel wie man Pointer vom Array an verzögerte Funktionen übergeben kann.

defmod di_test2 DOIF subs {\
sub test {\
  my @b = @{$_[0]};;\
  set_Reading("state","$b[0] $b[1] $b[2]",1)\
}\
}\
{\
  if ([FS:"on"]) {\
    my  @a=("1","2","3");;\
    #test(\@a);;\
    set_Exec("timer",1,'test',\@a);;\
  }\
}
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 21 September 2018, 23:18:53
Wer es auf die Spitze treiben will und das Parsen von fhem-Befehlen umgehen möchte:

fhem"setreading... lässt sich durch Perlfunktionen: set_Reading(... oder old school readingsSingleUpdate(... ersetzen.

auch fhem"set ..." muss nicht sein, stattdessen kann man die Perlfunktion  CommandSet(undef,"...") nutzen.

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 24 September 2018, 18:29:27
Ankündigung

Es wird bald ein größeres Update für den Perl-Modus geben.

Der Adressraum im Perl-Modus wird gekapselt. Das bedeutet, dass selbst definierte Funktionen im subs-Block bereits irgendwo anders (außerhalb von DOIF) definierte Funktionen nicht überschreiben können.

Das hat allerdings eine Inkompatibilität zur Folge. Funktionen aus dem main-Adressraum (FHEM) müssen besonders gekennzeichnet werden.

Funktionen aus main sind über ::<function> erreichbar. Z. B ::ReadingsVal(....)

Ich werde, die üblichen Funktionen wie fhem, Log, ReadingsVal usw. im DOIF-Adressraum neu definieren, so dass man da nicht umdenken muss.

Allerdings wird es neue Perlfunktionen im DOIF-Adressraum geben, die einfacher zu handhaben sind:

set_State(<content>)
get_State()
set_Reading(<reading>,<content>,<trigger>)   trigger ist optional
get_Reading(<reading>)
set_Reading_Begin()
set_Reading_Update(<reading>,<content>)
set_Reading_End(<trigger>)
fhem_set(<content>)


Funktionen aus myutil müssen dann logischerweise auch entsprechend angegeben werden ::<function> oder auch im package DOIF definiert werden.


Beispiel mit neuen Funktionen ohne FHEM-Befehle:

DOIF subs {
  sub lamp {
     my ($state)=@_;
     fhem_set("lamp $state");
     set_State($state);
  }
}
{if ([06:00]) {lamp("on")}} 
{if ([08:00]) {lamp("off")}}
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 25 September 2018, 23:52:38
Neue Version mit neuen Funktionen wurde eingecheckt.

Doku wurde überarbeitet: Anfängerfreundliche Einführung mit Beispielen:

https://fhem.de/commandref_DE.html#DOIF_Perl_Modus
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: PatrickR am 26 September 2018, 10:32:00
Ist die Änderung mit dem Package-/Namespace noch aktuell? Frage, weil das zugehörige Posting editiert wurde.

Patrick


Von unterwegs gesendet.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 26 September 2018, 10:33:16
Zitat von: PatrickR am 26 September 2018, 10:32:00
Ist die Änderung mit dem Package-/Namespace noch aktuell? Frage, weil das zugehörige Posting editiert wurde.

Patrick


Von unterwegs gesendet.

ja, bitte bei externen Perlfunktionen :: voranstellen, wenn sie angemeckert werden.
Titel: neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: PatrickR am 26 September 2018, 10:35:04
Uff, das gibt Scherben wenn man es im Changelog übersieht.

Danke für die Klarstellung.

Patrick


Von unterwegs gesendet.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 26 September 2018, 10:38:48
Zitat von: PatrickR am 26 September 2018, 10:35:04
Uff, das gibt Scherben wenn man es im Changelog übersieht.

Danke für die Klarstellung.

Patrick


Von unterwegs gesendet.

Bei ausgelagerten im DOIF-Perlmodus genutzten Funktionen z. B. in myutils kann man package DOIF; voranstellen

Folgende FHEM-Funktionen wurden im DOIF-Namensraum nachgebildet, hier muss man nichts machen:

fhem, Log, Log3, InternVal, InternalNum, OldReadingsVal, OldReadingsNum, OldReadingsTimestamp, ReadingsVal, ReadingsNum, ReadingsTeimestamp, ReadingsAge, Value, OldValue, OldTimestamp, AttrVal, AttrNum

Das steht aber alles in der aktuellen Commandref: https://fhem.de/commandref_DE.html#DOIF_Perl_Modus

Es sind z. Zt. ca. 50 User die den neuen Modus nutzen - das kriegen wir hin.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: PatrickR am 26 September 2018, 17:03:23
Damit kein falscher Eindruck entsteht. Ich finde den Patch explizit gut. Nur der Migrationspfad macht mir für den Fall Sorgen, dass jemand davon überrascht wird.

Bei neuen DOIFs sollte der Codecheck sofort greifen aber - korrigiere mich wenn ich falsch liege - bei bestehenden DOIFs würde die Ausführung einfach abbrechen und sich ggf. in den Error-Readings bzw. dem Log verewigen.

Ich selbst hätte die Änderung verpasst wenn ich nich Dein Posting gelesen hätte, bevor es editiert wurde und hätte dann ein defektes Alerting bei Wasser bzw. Feuer gehabt.

Patrick


Von unterwegs gesendet.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 26 September 2018, 17:32:33
Zitat von: PatrickR am 26 September 2018, 17:03:23
Damit kein falscher Eindruck entsteht. Ich finde den Patch explizit gut. Nur der Migrationspfad macht mir für den Fall Sorgen, dass jemand davon überrascht wird.

Bei neuen DOIFs sollte der Codecheck sofort greifen aber - korrigiere mich wenn ich falsch liege - bei bestehenden DOIFs würde die Ausführung einfach abbrechen und sich ggf. in den Error-Readings bzw. dem Log verewigen.

Ich selbst hätte die Änderung verpasst wenn ich nich Dein Posting gelesen hätte, bevor es editiert wurde und hätte dann ein defektes Alerting bei Wasser bzw. Feuer gehabt.

Patrick


Von unterwegs gesendet.

Wenn du nach dem Hochfahren kein config save machst, passiert nichts schlimmes, außer dass dein DOIF nicht funktioniert, ggf. dein DOIF-Device nicht definiert werden kann.

Nach einem save, brauchst du aus deiner letzten Sicherung der config die Definition deines nicht mehr funktionierenden DOIFs, die du anpassen und dein DOIF-Device neu definieren musst.

Edit: Bei einem Update wird die config im restoreDir-Verzeichnis gesichert
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 26 September 2018, 18:25:16
DOIF:fhem beachtet den 2.Parameter zum Stummschalten nicht.

fhem ("get ...",1) die 1 verhindert, dass der Rückgabewert von get geloggt wird.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 26 September 2018, 18:37:05
Zitat von: Ellert am 26 September 2018, 18:25:16
DOIF:fhem beachtet den 2.Parameter zum Stummschalten nicht.

fhem ("get ...",1) die 1 verhindert, dass der Rückgabewert von get geloggt wird.

Danke für die Info.

Kannst du bitte, die im Anhang bei dir schon mal antesten?


Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 26 September 2018, 18:48:25
Benutzt jemand schon die Funktion set_Time?

Ich wollte die Namensgebung vereinheitlichen.

Es gibt set_Exec zum verzögerten Ausführen von Perlcode.

Ich wollte set_Event wie folgt erweitern

set_Event (<Event>) wie bisher Event sofort absetzen

set_Event(<NameEvent>,<Sekunden>) Event verzögert absetzen, entspricht dem jetzigen set_Time (<NameEvent> ist gleichzeitig der Name des Timers)

set_Event(<Name>,<Sekunden>,<Event>) entspreche set_Exec von den Parametern her

set_Time könnte entfallen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 27 September 2018, 08:37:49
Ich habe mir gestern die Sache mit den Timern noch mal genau angeschaut. Es ist eigentlich überflüssig zwei verschieden Timerarten zu definieren. Mit set_Exec hat man alles, was man braucht. Will man ein verzögertes Event absetzen, dann reicht die Angabe mit set_Exec.

Beispiel: "blabla"-Event nach 30 Sekunden:

set_Exec("myevent",30,'set_Event("blabla")');

Damit entfallen die Funktionen: set_Timer, get_Timer, del_Timer

und der Anwender muss nur noch die Timerfunktionen: set_Exec, get_Exec, del_Exec kennen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 27 September 2018, 18:50:50
Neue Version eingecheckt: Funktionen: set_Timer, get_Timer, del_Timer sind rausgeflogen, Commandref zum Perl-Modus wurde überarbeitet

Edit: Beispiel zum Melden geöffneter Fenster wurde in der Commandref von set_Timer auf set_Exec umgestellt (ist sogar kürzer geworden :) )

Verzögerte Fenster-offen-Meldung mit Wiederholung für mehrere Fenster:

define di_window DOIF
subs {
  sub logwin {                                       # Definition der Funkton namens "logwin"
    my ($window)=@_;                                 # übernehme Parameter in die Variable $window
    Log 3,"Fenster offen, bitte schließen: $window"; # protokolliere Fenster-Offen-Meldung
    set_Exec ("$window",1800,"logwin",$window);      # setze Timer auf 30 Minuten für eine wiederholte Meldung
  }
}
{ if (["_window$:open"]) {set_Exec ("$DEVICE",600,'logwin("$DEVICE")')}} # wenn, Fenster geöffnet wird, dann setze Timer auf Funktion zum Loggen namens "logwin"
{ if (["_window$:closed"]) {del_Exec ("$DEVICE")}}                       # wenn, Fenster geschlossen wird, dann lösche Timer
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 29 September 2018, 18:11:31
Wo gibt man use-Aweisungen für das Package DOIF am sinnvollsten an?

Wenn man die use-Anweisungen in der Definition angibt, kann es unübersichtlich werden und sie könnten mehrfach in verschiedenen Definitionen stehen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 29 September 2018, 18:24:58
Zitat von: Ellert am 29 September 2018, 18:11:31
Wo gibt man use-Aweisungen für das Package DOIF am sinnvollsten an?

Wenn man die use-Anweisungen in der Definition angibt, kann es unübersichtlich werden und sie könnten mehrfach in verschiedenen Definitionen stehen.

Kommt drauf an, was du konkret mit use bekannt geben willst?

Z. Zt. in jedem Block, wo man sie benötigt.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 29 September 2018, 19:22:43
Wenn ich

define test
  subs {
    use WWW::Mechanize;
    sub1 () { ... }
  }


dann steht WWW::Mechanize im Package DOIF zur Verfügung, soweit ich es beobachtet habe, also auch in einer anderen DOIF-Perl Definition, die WWW::Mechanize benötigt. Das weiss man später vielleicht nicht mehr und gibt unnötig in einer weiteren Gerätedefinition an.

Ist es dann nicht sinvoller das in eine Datei 99_myDOIFUtils.pm auszulagern und hier die benutzten Perl-Module zu sammeln?

package DOIF;
use WWW::Mechanize;
use ...
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 29 September 2018, 19:31:19
Zitat von: Ellert am 29 September 2018, 19:22:43
Wenn ich

define test
  subs {
    use WWW::Mechanize;
    sub1 () { ... }
  }


dann steht WWW::Mechanize im Package DOIF zur Verfügung, soweit ich es beobachtet habe, also auch in einer anderen DOIF-Perl Definition, die WWW::Mechanize benötigt. Das weiss man später vielleicht nicht mehr und gibt unnötig in einer weiteren Gerätedefinition an.

Ist es dann nicht sinvoller das in eine Datei 99_myDOIFUtils.pm auszulagern und hier die benutzten Perl-Module zu sammeln?

package DOIF;
use WWW::Mechanize;
use ...


ja, warum nicht, das Gleiche gilt für Funktionen, die man in verschiedenen DOIF-Devices nutzen will.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Newbie am 05 Oktober 2018, 15:02:04
Hallo Damian und die anderen Perl-Experten,

ich lese hier immer fleisig mit und habe auch schon diverse DOIF`s auf den Perl-Modus umgestellt.

Aber bei diesem bin ich bisher am Timer gescheitert, irgendein Device triggert immer innerhalb der 15min und der Timer wird neu gesetzt, so das die Rollos nie schließen.

defmod WZ_Sonnenrollo DOIF ([myTwilight:azimuth] >135 and [myTwilight:azimuth] <278 and ($month >= 4 and $month <= 9)\
and [Vito333:Temp-Aussen] > 16 and [WZ_Weather:measured-temp] >= 21 and [Bewegungsmelder:brightness] >216\
and [Wetter:condition] =~ /teilweise wolkig|überwiegend wolkig|wolkig|teilweise sonnig|überwiegend sonnig|sonnig|heiter/)\
(set WZ1_Rollo:FILTER=STATE!=Zu off;; set WZ2_Rollo:FILTER=STATE!=25 25) DOELSE (set WZ1_Rollo:FILTER=STATE!=Auf on;; set WZ2_Rollo:FILTER=STATE!=Auf on)
attr WZ_Sonnenrollo alias Wohnzimmer-Süd
attr WZ_Sonnenrollo cmdIcon An:FS20.on Aus:FS20.off
attr WZ_Sonnenrollo cmdState An|Aus|Fehler
attr WZ_Sonnenrollo disable 0
attr WZ_Sonnenrollo group Sonnenschutz
attr WZ_Sonnenrollo room Erdgeschoss->Wohnzimmer
attr WZ_Sonnenrollo timerWithWait 1
attr WZ_Sonnenrollo wait 0:750

setstate WZ_Sonnenrollo Aus
setstate WZ_Sonnenrollo 2018-10-05 14:48:12 Device Vito333
setstate WZ_Sonnenrollo 2018-10-03 10:13:47 cmd 2
setstate WZ_Sonnenrollo 2018-10-03 10:13:47 cmd_event Vito333
setstate WZ_Sonnenrollo 2018-10-03 10:13:47 cmd_nr 2
setstate WZ_Sonnenrollo 2018-10-05 14:45:07 e_Bewegungsmelder_brightness 234
setstate WZ_Sonnenrollo 2018-10-05 14:48:11 e_Vito333_Temp-Aussen 19.5
setstate WZ_Sonnenrollo 2018-10-05 14:48:00 e_WZ_Weather_measured-temp 23.3
setstate WZ_Sonnenrollo 2018-10-05 14:30:33 e_Wetter_condition heiter
setstate WZ_Sonnenrollo 2018-10-05 14:44:47 e_myTwilight_azimuth 211.06
setstate WZ_Sonnenrollo 2018-10-03 10:00:10 mode enabled
setstate WZ_Sonnenrollo 2018-10-03 10:13:47 state Aus
setstate WZ_Sonnenrollo 2018-10-03 10:13:47 wait_timer no timer



Wie muss ich das im Perl-Modus umsetzen, damit der doelse-Zweig-Timer innerhalb der max. 15min nicht immer wieder neu gestartet wird?

vg Jens

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 05 Oktober 2018, 17:41:22
Du musst erst herausfinden, welches Device deine Bedingung (wahr/falsch) innerhalb kurzer Zeit verändert. So solange das nicht klar ist, wird auch der Perl-Modus nicht helfen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Newbie am 05 Oktober 2018, 21:31:18
Ich glaub ich hab gefunden was ich die ganze Zeit überlesen habe.

!get_Exec("Timer")

Werde mal testen.

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Newbie am 06 Oktober 2018, 13:33:24
Hallo,

kurze Rückmeldung. Ich habe aus dem hier

defmod AZ_Sonnenrollo DOIF (([myTwilight:azimuth] >94 and [myTwilight:azimuth] <182)\
and ($month >= 4 and $month <= 9)\
and ([Vito333:Temp-Aussen] > 16 and [Bad_WThermostat_Climate:measured-temp] >= 20 and [Bewegungsmelder:brightness] >216\
and [Wetter:condition] =~ /teilweise wolkig|überwiegend wolkig|wolkig|teilweise sonnig|überwiegend sonnig|sonnig|heiter/))\
(set AZ_Rollo:FILTER=level>10 10)\
DOELSE (set AZ_Rollo:FILTER=STATE!=Auf on)
attr AZ_Sonnenrollo alias Ankeide
attr AZ_Sonnenrollo cmdIcon An:FS20.on Aus:FS20.off
attr AZ_Sonnenrollo cmdState An|Aus|Fehler
attr AZ_Sonnenrollo group Sonnenschutz
attr AZ_Sonnenrollo room Erdgeschoss->Ankleidezimmer
attr AZ_Sonnenrollo timerWithWait 1
attr AZ_Sonnenrollo wait 0:750

setstate AZ_Sonnenrollo Aus
setstate AZ_Sonnenrollo 2018-10-06 13:27:28 Device Vito333
setstate AZ_Sonnenrollo 2018-09-30 13:37:24 cmd 2
setstate AZ_Sonnenrollo 2018-09-30 13:37:24 cmd_event Vito333
setstate AZ_Sonnenrollo 2018-09-30 13:37:24 cmd_nr 2
setstate AZ_Sonnenrollo 2018-10-06 13:25:51 e_Bad_WThermostat_Climate_measured-temp 21.8
setstate AZ_Sonnenrollo 2018-10-06 13:23:42 e_Bewegungsmelder_brightness 235
setstate AZ_Sonnenrollo 2018-10-06 13:27:26 e_Vito333_Temp-Aussen 19.7
setstate AZ_Sonnenrollo 2018-10-06 13:01:03 e_Wetter_condition überwiegend wolkig
setstate AZ_Sonnenrollo 2018-10-06 13:24:47 e_myTwilight_azimuth 188.8
setstate AZ_Sonnenrollo 2018-09-30 13:11:54 mode enabled
setstate AZ_Sonnenrollo 2018-09-30 13:37:24 state Aus
setstate AZ_Sonnenrollo 2018-09-30 13:37:24 wait_timer no timer



das gemacht

defmod testkleide DOIF {if (([myTwilight:azimuth] >94 and [myTwilight:azimuth] <182)\
and ($month >= 4 and $month <= 10)\
and ([Vito333:Temp-Aussen] > 14 \
and [Bad_WThermostat_Climate:measured-temp] >= 18 and [Bewegungsmelder:brightness] >216\
and [Wetter:condition] =~ /teilweise wolkig|überwiegend wolkig|wolkig|teilweise sonnig|überwiegend sonnig|sonnig|heiter/))\
{set_State("on");; fhem_set("AZ_Rollo:FILTER=level>10 10")}\
else {if ([?$SELF:state] eq "on" and !get_Exec("Timer")) {set_State ("off");; set_Exec("Timer",rand(750),'fhem_set("AZ_Rollo:FILTER=STATE!=Auf on")')}}}

setstate testkleide off
setstate testkleide 2018-10-06 13:27:54 Device Bad_WThermostat_Climate
setstate testkleide 2018-10-06 13:27:54 block_01 executed
setstate testkleide 2018-10-06 13:27:54 e_Bad_WThermostat_Climate_measured-temp 21.8
setstate testkleide 2018-10-06 13:23:42 e_Bewegungsmelder_brightness 235
setstate testkleide 2018-10-06 13:27:26 e_Vito333_Temp-Aussen 19.7
setstate testkleide 2018-10-06 13:01:03 e_Wetter_condition überwiegend wolkig
setstate testkleide 2018-10-06 13:24:47 e_myTwilight_azimuth 188.8
setstate testkleide 2018-10-05 21:10:08 mode enabled
setstate testkleide 2018-10-06 13:04:47 state off



Rollo ist heute runter und auch wieder hoch gefahren.  :)

vg Jens
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 06 Oktober 2018, 14:08:45
Zitat von: Newbie am 06 Oktober 2018, 13:33:24

Rollo ist heute runter und auch wieder hoch gefahren.  :)

vg Jens

Dann hat sich ja der Umstieg bezahlt gemacht. :)

Edit: Allerdings wird ggf. alle paar Minuten der Status auf on gesetzt.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Newbie am 06 Oktober 2018, 14:35:08
Hallo Damian

ZitatAllerdings wird ggf. alle paar Minuten der Status auf on gesetzt.

gut aufgepaßt, 1 setzen. :)

Hab ich aber zwischenzeitlich schon angepaßt.
defmod testkleide DOIF {if ([?$SELF:state] ne "on" and([myTwilight:azimuth] >94...

Richtig?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 06 Oktober 2018, 16:23:40
Zitat von: Newbie am 06 Oktober 2018, 14:35:08
Hallo Damian

gut aufgepaßt, 1 setzen. :)

Hab ich aber zwischenzeitlich schon angepaßt.
defmod testkleide DOIF {if ([?$SELF:state] ne "on" and([myTwilight:azimuth] >94...

Richtig?

Das ist eine von vielen Möglichkeiten.

Besonderes elegant finde ich die Nutzung von DOIF_Readings bei zyklisch sendenden Sensoren:


attr testkleide DOIF_Readings condition:([myTwilight:azimuth] >94 and [myTwilight:azimuth] <182) and ($month >= 4 and $month <= 9) and ([Vito333:Temp-Aussen] > 16 and [Bad_WThermostat_Climate:measured-temp] >= 20 and [Bewegungsmelder:brightness] >216 and [Wetter:condition] =~ /teilweise wolkig|überwiegend wolkig|wolkig|teilweise sonnig|überwiegend sonnig|sonnig|heiter/))

und dann nur noch

defmod testkleide DOIF {if ([$SELF:condition]) {...


DOIF_Readings ist genau für diesen Fall konzipiert, denn es gibt nur einen internen Trigger, wenn sich der Zustand des Readings (hier: condition) ändert. Damit kann man schön auch die Fälle im Perl-Modus abdecken, für die der FHEM-Modus ohne always konzipiert wurde. Damit erübrigen sich die if-Abfragen des eigenen Zustands.





Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Newbie am 06 Oktober 2018, 17:08:04
... und wieder was gelernt.

Danke für dein tolles Modul und deine Geduld beim Support.


vg Jens
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 06 Oktober 2018, 18:01:58
Zitat von: Newbie am 06 Oktober 2018, 17:08:04
... und wieder was gelernt.

Danke für dein tolles Modul und deine Geduld beim Support.


vg Jens

Es wird langsam an der Zeit ein Umsteiger-Handbuch zu verfassen. :)

Ich fange hier mal mit einem simplen Beispiel für eine Radio-Fernbedienung an:

FHEM-Mode:
DOIF ([FB] eq "on") (set radio on) DOELSEIF ([FB] eq "off") (set radio off)
attr do always


Perl-Mode
DOIF {fhem_set"radio ".[FB]}
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 06 Oktober 2018, 18:54:14
In FHEM-Mode sollte es auch recht knapp zu formulieren sein:
([FB]) (set radio [FB])
attr do always
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 06 Oktober 2018, 19:29:13
Zitat von: Ellert am 06 Oktober 2018, 18:54:14
In FHEM-Mode sollte es auch recht knapp zu formulieren sein:
([FB]) (set radio [FB])
attr do always


ja, natürlich :)

Ich wollte an dem Beispiel insb. aufzeigen, dass man aus der if-then-else Denkweise ausbrechen kann. Und immer dann, wenn do always benutzt wird, rückt die besondere Eigenschaft des FHEM-Modus, mit Zuständen zu arbeiten, in den Hintergrund. 
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Newbie am 06 Oktober 2018, 23:57:53
Hallo Damian,

Zitatattr testkleide DOIF_Readings condition:([myTwilight:azimuth] >94 and [myTwilight:azimuth] <182) and ($month >= 4 and $month <= 9) and ([Vito333:Temp-Aussen] > 16 and [Bad_WThermostat_Climate:measured-temp] >= 20 and [Bewegungsmelder:brightness] >216 and [Wetter:condition] =~ /teilweise wolkig|überwiegend wolkig|wolkig|teilweise sonnig|überwiegend sonnig|sonnig|heiter/))

funktioniert so aber nicht, liegt hier dran
Zitat... and ($month >= 4 and $month <= 9) ...

vg
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 07 Oktober 2018, 08:58:15
Zitat von: Newbie am 06 Oktober 2018, 23:57:53
Hallo Damian,

funktioniert so aber nicht, liegt hier dran
vg

ja, $month wird offenbar nicht in DOIF_Readings vorbelegt.

Es geht ja in erster Linie um die zyklischen Trigger, die man aus der Abfrage herausnimmt, daher kann man auch definieren:

attr testkleide DOIF_Readings condition:([myTwilight:azimuth] >94 and [myTwilight:azimuth] <182) and ([Vito333:Temp-Aussen] > 16 and [Bad_WThermostat_Climate:measured-temp] >= 20 and [Bewegungsmelder:brightness] >216 and [Wetter:condition] =~ /teilweise wolkig|überwiegend wolkig|wolkig|teilweise sonnig|überwiegend sonnig|sonnig|heiter/))

defmod testkleide DOIF {if ([$SELF:condition] and $month >= 4 and $month <= 9) {...
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 08 Oktober 2018, 19:01:36
Bei einem Modify, bevor der init-Block ausgeführt wird, wird state auf initialized gesetzt. Das wirkt störend, wenn es in einem anderen DOIF eine Abfrage auf state gibt und kann zur Fehlschaltung führen.

Beispiel
defmod initBlock DOIF init {\
  Log 1, "1 $SELF:".get_State;;\
  set_Reading_Begin;;\
  ::readingsBulkUpdateIfChanged($hash,"state",0);;\
  set_Reading_End(1);;\
  Log 1, "2 $SELF:".get_State;;\
}

Folgedoif
([initBlock:state]) (set lamp on)
DOELSEIF (![initBlock:state]) (set lamp off)

hier wird erst die Lampe kurz eingeschaltet und nach dem Ausführen des init-Blocks wird die Lampe ausgeschaltet.

Wäre es nicht sinnvol beim Perl-Modus auf das setzen von state zu verzichten?
Oder state nur auf initialized zu setzen, wenn state im init-Block nicht gesetzt wird, also length(get_State) gleich 0 ist?

Edit: Oder bei der Initialisierung state ohne Event setzen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 08 Oktober 2018, 19:18:20
Muss ich mir mal anschauen.

Wenn man gar nichts macht, steht dann im Status ? ? ?.

Das würde dem minimalistischen Ansatz des Perl-Modus durchaus entsprechen - für den Status ist der Anwender zuständig. Man kann den Status im init-Block selbst setzen und es gibt ja noch das Attribut initialize.

Auf der anderen Seite ist initialized ein definierter Zustand und kommt nur bei der Definition (ggf mit defmod) vor. Beim Hochfahren bleibt ja der alte Zustand bestehen.

Da muss man die Prioritäten abwägen.

Ich tendiere zu der ersten Variante, den Status gar nicht mehr vom Modul zu setzen - also auch nicht auf initialized.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 08 Oktober 2018, 19:26:24
Ja, beim Hochfahren ist es kein Problem.

Wann erscheinen die drei Fragezeichen? Vor dem Ausführen des init-Blocks oder danach, falls state undefined ist.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 08 Oktober 2018, 19:28:57
Zitat von: Ellert am 08 Oktober 2018, 19:26:24
Ja, beim Hochfahren ist es kein Problem.

Wann erscheinen die drei Fragezeichen? Vor dem Ausführen des init-Blocks oder danach, falls state undefined ist.

Die drei Fragezeichen kommen nicht von DOIF, ich meine, die sind dann zu sehen, wenn gar kein Status gesetzt wird.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 08 Oktober 2018, 19:39:40
Es reicht in Zeile 2847

readingsEndUpdate($hash, 0);

das Event rauszunehmen.

Edit: dann hat man einen definierten Zustand ohne Events zu produzieren - das dürfte die beste Lösung sein.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 09 Oktober 2018, 09:18:03
Ich denke es ist am saubersten, wenn man state nicht als Auslöser verwendet, sondern ein Benutzerreading, das behält bei Modify und Neustart den Wert bei.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 09 Oktober 2018, 18:47:22
Neue Version eingecheckt.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 10 Oktober 2018, 17:16:52
Zitat von: Damian am 08 Oktober 2018, 19:39:40
Es reicht in Zeile 2847

readingsEndUpdate($hash, 0);

das Event rauszunehmen.

Edit: dann hat man einen definierten Zustand ohne Events zu produzieren - das dürfte die beste Lösung sein.

Das kommt mir halbherzig vor.

Mit initialized im state bei modify, gibt es nach der Modifikation, Deaktivierung und Aktivierung immer kurz einen ungewollten Zustand.

Meine These dazu lautet:
Mit den Funktionen set_State und get_State wird die Hoheit über state dem Benutzer übertragen. Das Reading sollte daher vom DOIF nicht mehr benutzt werden.
Also sollte state nicht gelöscht werden, und auch nicht mit disabled, deaktivated oder initialized belegt werden. Das wird im Reading mode dargestellt.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 10 Oktober 2018, 17:35:45
Zitat von: Ellert am 10 Oktober 2018, 17:16:52
Das kommt mir halbherzig vor.

Mit initialized im state bei modify, gibt es nach der Modifikation, Deaktivierung und Aktivierung immer kurz einen ungewollten Zustand.

Meine These dazu lautet:
Mit den Funktionen set_State und get_State wird die Hoheit über state dem Benutzer übertragen. Das Reading sollte daher vom DOIF nicht mehr benutzt werden.
Also sollte state nicht gelöscht werden, und auch nicht mit disabled, deaktivated oder initialized belegt werden. Das wird im Reading mode dargestellt.

ja, an set ... habe ich nicht gedacht.

Dennoch ist defmod eine Neudefinition, die im laufenden Betrieb nicht stattfinden sollte. Es ist eine Änderung der Konfiguration, die ein internes Löschen diverse Dinge bedeutet - also ein Zurücksetzen des Devices. Diese Information ist für die Nachvollziehbarkeit bei Problemen wichtig.

Mit dem Reading mode kann man die "Initialisierung" leider nicht erkennen, dort steht nur enabled oder disabled aber nicht initialized.

Da müssen wir uns noch eine saubere Lösung für den Perl-Mode überlegen.

Man könnte sich ein neues Reading überlegen, welches diese Informationen des Status übernimmt.

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 10 Oktober 2018, 18:11:26
Wenn man im init-Block state setzt, bekommt man initialized nie zu sehen, insofern wäre ein extra Reading sinnvoll oder mode wird auf "enabled initialized" gesetzt, im initialized Fall (attr disabled 0 und modify) und auf "enabled" nach set enable.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 10 Oktober 2018, 18:34:04
Ich habe mal folgende Version gebaut:

State wird gar nicht mehr vom Modul gesetzt. Es gibt nur noch das Reading mode (enabled, disabled). Z. Zt. ohne weitere Readings nach der Neudefinition.

gerade noch getestet:

[$SELF:state] liefert leeren String

[$SELF] liefert drei Fragezeichen.

Alternativ könnte man state bei defmod ohne Trigger auf initialize setzen.

Des Weiteren habe ich in der Konsequenz die Attribute state, initialized, startup im Perl-Modus entfernt. Es gibt ja jetzt den init-Block. Ich hoffe diese Attribute benutzt noch keiner im Perl-Modus.

Neue Version 0.3 im Anhang zum Antesten.

Edit: Das disable-Attribut wird jetzt auch berücksichtigt -> mode deactivated wie bisher aber ohne Statusänderung
Edit: Jetzt werden Readings sofort angelegt, wenn man das Attribut DOIF_Readings definiert
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 11 Oktober 2018, 16:55:26
Zitat von: Damian am 10 Oktober 2018, 18:34:04
Ich habe mal folgende Version gebaut:

State wird gar nicht mehr vom Modul gesetzt. Es gibt nur noch das Reading mode (enabled, disabled). Z. Zt. ohne weitere Readings nach der Neudefinition.

gerade noch getestet:

[$SELF:state] liefert leeren String

[$SELF] liefert drei Fragezeichen.

Alternativ könnte man state bei defmod ohne Trigger auf initialize setzen.

Des Weiteren habe ich in der Konsequenz die Attribute state, initialized, startup im Perl-Modus entfernt. Es gibt ja jetzt den init-Block. Ich hoffe diese Attribute benutzt noch keiner im Perl-Modus.

Neue Version 0.3 im Anhang zum Antesten.

Edit: Das disable-Attribut wird jetzt auch berücksichtigt -> mode deactivated wie bisher aber ohne Statusänderung
Edit: Jetzt werden Readings sofort angelegt, wenn man das Attribut DOIF_Readings definiert

Ich denke immer noch das Reading state sollte nicht gelöscht werden, dann haben Veränderungen der Definition keinen ungewollten Einfluss auf state.
Wenn der Benutzer es möchte, könnte er das Reading state im init Block löschen, mit https://wiki.fhem.de/wiki/DevelopmentModuleAPI#readingsDelete

Mir ist noch aufgefallen, dass die Funktion Log und Log3, die im Package DOIF definiert wird, beim Laden der 99_myUtils während des Hochfahrens noch nicht zur Verfügung steht und vorab deklariert werden muss. Aber z.B. get_State und InternalVal funktioniert ohne Vorabdeklaration.

99_myUtils
package DOIF;
sub Log;

# Enter you functions below _this_ line.
sub testFn {
  my $s = get_State();
  my $i = InternalVal("initBlock","MODEL","---");
  Log 1, "initBlock testFN $s Mode $i";
  Log3 "initBlock",2, "initBlock testFN $s Mode $i";
}

Testdefinition
defmod initBlock DOIF init {\
  Log 1, "$SELF:".ReadingsVal("$SELF","state","none");;\
  testFn();;\
}


Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 11 Oktober 2018, 22:19:30
ja,  Readings, die das Modul nicht setzt, werden ja vom Modul nicht gelöscht - das würde dann tatsächlich auch für state zutreffen.  Das kann ich noch ausbauen.

Keine Ahnung warum man Log vordeklarieren muss und get_State nicht. Das Problem könnte man vermutlich mit der Angabe ::Log aus dem main-Bereich umgehen. Das muss ich mir noch genauer anschauen.

Edit: Es liegt wohl daran, dass Log bzw. Log3 ohne Klammern angegeben wurden. Ich weiß nicht warum sich das eingebürgert hat, Funktionen insb. mit mehreren Parametern ohne Klammern anzugeben. Also immer mit Klammern angeben:

package DOIF;

# Enter you functions below _this_ line.
sub testFn {
  my $s = get_State();
  my $i = InternalVal("initBlock","MODEL","---");
  Log (1, "initBlock testFN $s Mode $i");
  Log3 ("initBlock",2, "initBlock testFN $s Mode $i");
}
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 13 Oktober 2018, 23:41:35
neue Version eingecheckt: Perl-Modus: state wird vom Modul nicht angepackt (auch nicht gelöscht), Attribute state, initialize, startup wurden entfernt, set initialize wurde ebenfalls entfernt
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 14 Oktober 2018, 17:58:04
set_State("abc",0) erzeugt ein Event und ignoriert die Triggerangabe. Die Commandref ist dem Programmcode voraus ;)
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 14 Oktober 2018, 18:11:48
Zitat von: Ellert am 14 Oktober 2018, 17:58:04
set_State("abc",0) erzeugt ein Event und ignoriert die Triggerangabe. Die Commandref ist dem Programmcode voraus ;)

Jetzt nicht mehr, korrigiert und eingescheckt ;)
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 15 Oktober 2018, 23:11:46
Hier mal Beispiele wie man wait mit do always bzw. mit do resetwait im Perlmodus realisieren kann:

resetwait

DOIF (["EVENT"]) (set ....)
attr do resetwait
attr wait 60


entspricht im Perl-Modus:

DOIF {if (["EVENT"]) {set_Exec("Timer",60,'fhem_set("...")')}}

alternativ:

DOIF {["EVENT"];set_Exec("Timer",60,'fhem_set("...")')}

always

DOIF (["EVENT"]) (set ....)
attr do always
attr wait 60


entspricht im Perl-Modus:

DOIF {if (["EVENT"]) {if (!get_Exec("Timer")) {set_Exec("Timer",60,'fhem_set("...")')}}}

alternativ:

DOIF {["EVENT"]; set_Exec("Timer",60,'fhem_set("...")') if (!get_Exec("Timer"))}

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: kalleknx am 16 Oktober 2018, 20:19:10
Hi Damian,

ich habe eben von set_Timer/del_Timer auf set_Exec bzw. del_Exec gewechselt.

Frage: wie kann ich subroutinen aus der 99_myUtils.pm innerhalb der Subs {} des DOIFs aufrufen?
Bekomme momentan folgenden Fehler:

error - in MowerHome("Mower"): Undefined subroutine &DOIF::pushMsgDebug called at (eval 6789) line 5.


THX
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 16 Oktober 2018, 21:02:18
Zitat von: kalleknx am 16 Oktober 2018, 20:19:10
Hi Damian,

ich habe eben von set_Timer/del_Timer auf set_Exec bzw. del_Exec gewechselt.

Frage: wie kann ich subroutinen aus der 99_myUtils.pm innerhalb der Subs {} des DOIFs aufrufen?
Bekomme momentan folgenden Fehler:

error - in MowerHome("Mower"): Undefined subroutine &DOIF::pushMsgDebug called at (eval 6789) line 5.


THX

so, wie es in der Commandref beschrieben ist, indem man beim Aufruf :: vor die Routine angibt, hier also ::pushMsgDebug(...
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 17 Oktober 2018, 23:10:25
Da im Perl-Modus im Gegensatz zum FHEM-Modus bewusst keine automatische Statusabfrage (Zustandsauswertung) erfolgt , muss der Anwender selbst darauf achten insb. bei zyklisch sendenden Sensoren, das Wiederholen einer Anweisung zu unterdrücken. In diesem Zusammenhang ist die Verwendung des Attributes DOIF_Readings, welches insb. für diesen Zweck konzipiert wurde, besonders interessant. Deswegen habe ich die Commandref zu DOIF-Readings angepasst:

ZitatErzeugen berechneter Readings

Mit Hilfe des Attributes DOIF_Readings können eigene Readings innerhalb des DOIF definiert werden, auf die man im selben DOIF-Moduls zugreifen kann. Die Nutzung ist insbesondere dann sinnvoll, wenn zyklisch sendende Sensoren, im Perl-Modus oder mit dem Attribut do always, abgefragt werden. DOIF_Readings-Berechnungen funktionieren ressourcenschonend ohne Erzeugung FHEM-Events nach außen. Änderungen dieser Readings triggern allerdings das eigene DOIF-Modul, allerdings nur, wenn sich deren Inhalt ändert.

Syntax

attr <DOIF-Modul> DOIF_Readings <readingname1>:<definiton>, <readingname2>:<definition>,...

<definition>: Beliebiger Perlausdruck ergänzt um DOIF-Syntax in eckigen Klammern. Angaben in eckigen Klammern wirken triggernd und aktualisieren das definierte Reading.

Beispiel

Perl-Modus:
define heating DOIF {if ([switch] eq "on" and [$SELF:frost]) {fhem_set"heating on"} else {fhem_set"heating off"}}
attr heating DOIF_Readings frost:([outdoor:temperature] < 0)


Das Reading frost triggert nur dann die definierte Abfrage, wenn sich sein Zustand ändert. Dadurch wird sichergestellt, dass ein wiederholtes Schalten der Heizung vermieden wird, obwohl der Sensor outdoor zyklisch sendet.

Beispiel: Push-Mitteilung über die durchschnittliche Temperatur aller Zimmer

define di_temp DOIF ([$SELF:temperature]>20) (push "Die Durchschnittstemperatur ist höher als 20 Grad, sie beträgt [$SELF:temperature]")

attr di_temp DOIF_Readings temperature:[#average:d2:":temperature":temperature]


Hierbei wird der aufwändig berechnete Durchschnittswert nur einmal berechnet, statt zwei mal, wenn man die Aggregationsfunktion direkt in der Bedingung und im Ausführungsteil angeben würde.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 21 Oktober 2018, 22:16:51
Hier mal ein Beispiel wie man etwas übersichtlicher Temperaturvorgaben definieren kann:

Bisher im FHEM-Modus:

DOIF ([05:00|8] or [05:30|7])
  (set TH_Keller_HM desired-temp 20,
   set TH_Kueche desired 21,
   set TH_Bad_HM desired-temp 21,
   set TH_DG_HM desired-temp 21,
   set TH_WZ_HM desired-temp 21,
   ##set TH_Kz_o_HM desired-temp 21.5,
   set TH_Kz_w_HM desired-temp 20)
DOELSEIF ([08:00|8] or [09:00|7])
  (set TH_Keller_HM desired-temp 19.5,
   set TH_Kueche desired 17,
   set TH_Kz_w_HM desired-temp 17,
   set TH_Bad_HM desired-temp 17,
   set TH_DG_HM desired-temp 20)
DOELSEIF ([12:00])
  (set TH_Kueche desired 19.5,
   set TH_WZ_HM desired-temp 21,
   set TH_Kz_w_HM desired-temp 21,
   set TH_DG_HM desired 21)
DOELSEIF ([17:00])
  (set TH_Bad_HM desired-temp 17)
DOELSEIF ([20:00])
  (set TH_Kueche desired 17,
   set TH_WZ_HM desired-temp 20,
   set TH_Kz_w_HM desired-temp 20,
   set TH_Bad_HM desired-temp 17,
   set TH_DG_HM desired-temp 20)
DOELSEIF ([23:00])
   (set TH_Keller_HM desired-temp 19.5)


Tabellarisch im Perl-Modus:

DOIF
## Raum       Befehl          05:00 08:00 12:00 17:00 20:00 23:00
init {$_temps="
TH_Keller_HM, desired-temp,   20,   19.5, ,     ,     ,     19.5
TH_Kueche,    desired,        21,   17,   19.5, ,     17,
TH_Bad_HM,    desired-temp,   21,   17,   ,     17,   17,
TH_DG_HM,     desired-temp,   21,   20,   21,   ,     20,
TH_WZ_HM,     desired-temp,   21,   17,   21,   ,     20,
TH_Kz_w_HM,   desired-temp,   20,   17,   21,   ,     20,";
   @{$_line}=split ('\n',$_temps);
}

{temp_set(0) if ([05:00|8] or [05:30|7])}
{temp_set(1) if ([08:00|8] or [09:00|7])}
{temp_set(2) if ([12:00])}
{temp_set(3) if ([17:00])}
{temp_set(4) if ([20:00])}
{temp_set(5) if ([23:00])}

subs  {
  sub temp_set {
    my ($l)=@_;
    foreach (@{$_line}) {
      my ($raum,$Befehl,@Phase)=split (', *',$_);
      fhem_set("$raum $Befehl $Phase[$l]") if ($Phase[$l]);
    }
  } 
}


Edit: Code angepasst
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 29 Oktober 2018, 23:33:34
Ich hatte mal ein DOIF definiert, welches für jedes Device, welches eine Batteriemeldung liefert, ein Reading erstellt mit dem Status ok oder low.

Wenn man einen häufigen Statuswechsel zwischen ok/low vermeiden wollte, hätte man bei einem Device mit einem wait-Timer arbeiten können, da dieses DOIF aber viele Devices beobachtete, wäre pro Device ein eigener wait-Timer nötig.

So etwas geht nun im Perl-Modus, da hier beliebig viele wait-Timer (pro Device eins) gleichzeitig laufen können:

Beispiel:

defmod di_bat DOIF {if ([":battery: low"]) {\
  if (get_Reading ('B_$DEVICE') ne "low") {\
    if (get_Exec("Timer_$DEVICE_low")==0) {\
     set_Exec("Timer_$DEVICE_low",28800,"set_Reading ('B_$DEVICE','low')");;\
    }\
  } elsif (get_Exec("Timer_$DEVICE_ok")) {\
    del_Exec("Timer_$DEVICE_ok")\
  }\
}\
}\
{if ([":battery: ok"]) {\
  if (get_Reading ('B_$DEVICE') ne "ok") {\
    if (get_Exec("Timer_$DEVICE_ok")==0) {\
     set_Exec("Timer_$DEVICE_ok",28800,"set_Reading ('B_$DEVICE','ok')");;\
    }\
  } elsif (get_Exec("Timer_$DEVICE_low")) {\
    del_Exec("Timer_$DEVICE_low")\
  }\
}\
}\


Es entsteht mit dem obigen Code im DOIF-Device ebenfalls pro Device ein Reading namens B_<Device-Name>, allerdings erst dann, wenn jeweils 8 Stunden lang der jeweilige Batterie-Status (low/ok) stabil bleibt.

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 01 November 2018, 21:07:35
Advent, Advent, damit bald die erste Kerze brennt ;) https://forum.fhem.de/index.php/topic,42209.msg852782.html#msg852782
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 03 November 2018, 12:12:31
Neue DOIF-Version eingecheckt.

Wollte man im init-Block eine Funktion aus dem subs-block aufrufen, so musste bisher der subs-Block zuerst definiert werden. Nun ist die Reihenfolge egal (der init-Block wird jetzt als letzter ausgewertet), es funktioniert dann auch so etwas:

DOIF
init {test()}
subs {sub test {set_State("blabla")}}



Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: PatrickR am 04 November 2018, 00:02:03
Mahlzeit!

Habe nun gezwungenermaßen etwas mit set_Exec experimentiert und es gefällt mir deutlich besser als die set_timer-Veriante.

Nun eine Frage: Wie kann ich der aufgerufenen Sub denn mehr als einen Parameter übergeben? (ohne Tricks wie split() etc.)

Patrick
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 04 November 2018, 09:09:13
Zitat von: PatrickR am 04 November 2018, 00:02:03
Mahlzeit!

Habe nun gezwungenermaßen etwas mit set_Exec experimentiert und es gefällt mir deutlich besser als die set_timer-Veriante.

Nun eine Frage: Wie kann ich der aufgerufenen Sub denn mehr als einen Parameter übergeben? (ohne Tricks wie split() etc.)

Patrick

https://forum.fhem.de/index.php/topic,84969.msg838506.html#msg838506
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: PatrickR am 04 November 2018, 12:52:58
Hi!

Zitat von: Damian am 04 November 2018, 09:09:13
https://forum.fhem.de/index.php/topic,84969.msg838506.html#msg838506
Wie gesagt, um Tricks ging es mir nicht. Habe das gerade mal zum Anlass genommen, zu schauen, ob man es mit anonymen arrayrefs schöner hinbekommt, was leider scheinbar an der Ausführung mit eval gescheitert ist. Besteht die Möglichkeit, eine variable Anzahl an Parametern in set_Exec() zuzulassen?

Patrick
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 04 November 2018, 13:22:31
Zitat von: PatrickR am 04 November 2018, 12:52:58
Hi!
Wie gesagt, um Tricks ging es mir nicht. Habe das gerade mal zum Anlass genommen, zu schauen, ob man es mit anonymen arrayrefs schöner hinbekommt, was leider scheinbar an der Ausführung mit eval gescheitert ist. Besteht die Möglichkeit, eine variable Anzahl an Parametern in set_Exec() zuzulassen?

Patrick

Das sind keine Tricks, sondern das, was man in jeder Programmiersprache machen würde: ein Pointer auf eine Struktur, hier also ein Array. Eine variable Anzahl ist natürlich in Perl genauso möglich, es zählen die, die du übergibst:

set_Exec("Timer",60,'test(1,2,3,...)')

aber das willst du wahrscheinlich nicht.

Weniger elegant, aber genauso machbar, sind Arrays von Instanzvariablen, die braucht man nicht zu übergeben, da sie global pro DOIF-Device definiert sind.

Beispiel:

defmod di_test4 DOIF init{ @{$_myarray}=("a","b","c")}\
subs{\
sub test {\
set_Reading("erster",@{$_myarray}[0]);;\
set_Reading("zweiter",@{$_myarray}[1]);;\
set_Reading("dritter",@{$_myarray}[2]);;\
}\
}\
{[FS];;set_Exec("Timer",1,'test')}\




Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: PatrickR am 04 November 2018, 17:34:49
Hi!

Ich fürchte, wir haben zu einigen Punkten grundsätzlich verschiedene Ansichten :/

Zitat von: Damian am 04 November 2018, 13:22:31
Das sind keine Tricks, sondern das, was man in jeder Programmiersprache machen würde: ein Pointer auf eine Struktur, hier also ein Array.
Trick ist vielleicht nicht das richtige Wort, eher Workaround. Das würde man - exotische Fälle ausgenommen - exakt dann tun, wenn man um künstliche Beschränkungen herumarbeiten muss, die man nicht beeinflussen kann. Ansonsten würde man eher eine Sub mit exakt den gewünschten Argumenten aufrufen, ohne vorher ein Päckchen zu schnüren, das es im nächsten Schritt zu verschicken gilt.

Zitat von: Damian am 04 November 2018, 13:22:31
Eine variable Anzahl ist natürlich in Perl genauso möglich, es zählen die, die du übergibst:
set_Exec("Timer",60,'test(1,2,3,...)')

aber das willst du wahrscheinlich nicht.

Das Problem bei diesem Ansatz ist, dass er nicht nur unschön sondern auch fehlerträchtig ist, insbesondere wenn man keine Literale sondern Variablen übergeben möchte. Dann muss man etwas mehr Aufwand treiben, um den Callback EVAL-tauglich zu machen:

set_Exec("CALLBACK__$DEVICE__$reading", 6, "hmip_callback('$DEVICE', '$reading')");

Ich bin mir natürlich bewusst, dass man dies auf unzählige andere Implementierungsdetails in- und teilweise auch außerhalb von DOIF zutrifft.

Vielleicht denkst Du nochmal über die dynamische Anzahl von Argumenten in set_Exec() nach.

Patrick
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 04 November 2018, 22:30:23
Zitat von: PatrickR am 04 November 2018, 17:34:49

Vielleicht denkst Du nochmal über die dynamische Anzahl von Argumenten in set_Exec() nach.

Patrick

Mal schauen, ob es sich elegant lösen lässt - übrigens InternalTimer kann es auch nicht.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 11 November 2018, 21:39:38
Hier mal ein Beispiel für Fenster-Öffnen-Meldung beim hohen Feuchtigkeitsanstieg (über 10%) nach dem Duschen.

defmod di_fenster_bad DOIF {if ([$SELF:increase] > 10) {fhem_set("Echo_Bad speak Bitte Fenster öffnen")}}
attr di_fenster_bad DOIF_Readings increase:([TH_Bad_HM:humidity]-OldReadingsVal("TH_Bad_HM","humidity",0))/[TH_Bad_HM:humidity]*100


Echo_Bad ich ein Echo-Device im Bad.

Beim HM-Wandthermostat muss das Attribut oldreadings humidity gesetzt werden, damit OldReadingsVal einen Wert liefert.

Jetzt muss sich noch die Definition in der Praxis bewähren :)

Edit: Bewährt! Ansage kommt rechtzeitig kurz nach dem Duschen. Hier noch eine alternative Version:

defmod di_fenster_bad DOIF {if ([$SELF:increase] > 10) {fhem_set("Echo_Bad speak Bitte Fenster öffnen");;set_State("Ansage")}}
attr di_fenster_bad DOIF_Readings increase:([TH_Bad_HM:humidity]/OldReadingsVal("TH_Bad_HM","humidity",50)-1)*100



Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 19 November 2018, 19:36:46
Zitat von: Damian am 11 November 2018, 21:39:38
defmod di_fenster_bad DOIF {if ([$SELF:increase] > 10) {fhem_set("Echo_Bad speak Bitte Fenster öffnen");;set_State("Ansage")}}
attr di_fenster_bad DOIF_Readings increase:([TH_Bad_HM:humidity]/OldReadingsVal("TH_Bad_HM","humidity",50)-1)*100


Nach dem Öffnen des Fenster kann die Bude im Winter ganz schön auskühlen, wenn man vergisst das Fenster zu schließen.

Mit Fenster-Schließen-Meldung:

defmod di_fenster_bad DOIF {if ([$SELF:increase] and [?BadFenster] eq "closed") {fhem_set("Echo_Bad speak Bitte Fenster öffnen");;set_State("Ansage Öffnen")}}\
{if ([BadFenster:state] eq "open"){set_Reading ("temp",ReadingsVal("TH_Bad_HM","measured-temp",0));;set_State("Fenster geöffnet")}}\
{if ([$SELF:cold] and [?BadFenster] eq "open"){fhem_set("Echo_Bad speak Bitte Fenster schließen");;set_State("Ansage Schließen")}}

attr di_fenster_bad DOIF_Readings increase:([TH_Bad_HM:humidity]/OldReadingsVal("TH_Bad_HM","humidity",50)-1)*100 > 10, cold:([$SELF:temp]-[TH_Bad_HM:measured-temp])>0.5


Das bedeutet, wenn nach dem Öffnen des Fensters die Temperatur um 0,5 Grad fällt, dann Ansage.

Edit: Definition angepasst
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 19 November 2018, 22:30:15
Neue Version eingecheckt. Man kann jetzt zwecks Übersichtlichkeit DOIF_Readings mit Zeilenumbrüchen an beliebiger Stelle definieren, z. B. pro Reading eine Zeile:

attr di_fenster_bad DOIF_Readings
increase: [?BadFenster] eq "closed" and ([TH_Bad_HM:humidity]/OldReadingsVal("TH_Bad_HM","humidity",50)-1)*100 > 10,
cold:[?BadFenster] eq "open" and ([$SELF:temp]-[TH_Bad_HM:measured-temp])>0.5


Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 21 November 2018, 22:48:05
Wenn jemand nicht weiß wohin mit der Rechenpower.

Feuerfackeln im Garten

defmod di_garten DOIF {[+(rand(10)/10)];;fhem_set"Garten pct ".(10+rand(90))}

Funktioniert ganz gut mit Osram Smart+ LED ZigBee Außen-/Gartenleuchte über HUE-Bridge. Mit anderen Devices z. B. HM wegen credits nicht zu empfehlen. Die Farbe muss man sich selbst voreinstellen. Orange ist ganz nett für Feuer.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: sk001 am 30 November 2018, 20:26:42
Hallo!
Ich versuche mit den Perl-Funktionen im DOIF einen Lichtwecker zu realisieren. Hierzu soll ein dummy (du_Weckzeit) verwendet werden, über das eine Weckzeit in der Benutzeroberfläche festgelegt wird. Das DOIF ist wie folgt formuliert:

init {$_value=0;
     fhem"set deConz_HUEDevice1 pct 0";} main {
if ( [[du_Weckzeit]-{weckerZeitbereich(du_Weckzeit,600)},+00:01 ] and [?du_Wecker_aktiv] eq "an" ) {
   fhem"set deConz_HUEDevice1 pct $_value";
   $_value+=5;
}
else {
  $_value=0;
}
}


Die Funktion "weckerZeitbereich" ist in der 99_myUtils.pm definiert. Ihr werden als Parameter die Startzeit aus dem du_Weckzeit und die Sekunden für die Berechnung des Zeitintervalls übergeben:

sub weckerZeitbereich($$) {
  my ($beginn,$intervall)= @_;
  my $ende = ( str2time(localtime($beginn)+$intervall));

  return (strftime ("%H:%M", localtime ($ende) ) );
}


Das DOIF gibt mir leider in allen bisher probierten Konstellationen einen Fehler für den timer_02_c02 wie folgt aus: error: the function "weckerZeitbereich(du_Weckzeit,600)" must return a timespec and not Bareword "du_Weckzeit" not allowed while "strict subs" in use at (eval 61697) line 1.

Trotz aller Versuche kann ich das Problem leider nicht lösen. Was ist bei der Definition eines Zeitintervalls, wie in der Referenz beschrieben, zu beachten? Mein Ziel ist also so etwas unter Verwendung des Dummys zu erzeugen:

define di_rand_lamp DOIF ([{sunset()}-[end:state],+(rand(600)+900)|Sa So])(set lamp on-for-timer 300)

Danke für die Hilfe!
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 30 November 2018, 21:03:14
Du brauchst die Funktion nicht. Du kannst direkt angeben:

if ( [[du_Weckzeit]-([du_Weckzeit]+600),+00:01 ] and [?du_Wecker_aktiv] eq "an" ) {
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: sk001 am 30 November 2018, 21:17:25
Hallo Damian!
Dann lag es wohl an der Klammersetzung... ::). Es funktioniert jetzt!
Danke für Deine Hilfe! Klasse, was Dein Modul alles kann...!
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: obi am 03 Februar 2019, 11:21:18
Hallo,

ich habe in mehreren DOIFs Subroutinen definiert welche den gleichen Namen haben. Dies führt zu Problemen, da diese global in allen DOIF zur Verfügung stehen. Gibt es eine Möglichkeit Subs zu definieren nur für das eigene DOIF?
Ich konnte hierzu nichts in der Commandref/Wiki finden.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 03 Februar 2019, 11:43:40
Zitat von: obi am 03 Februar 2019, 11:21:18
Hallo,

ich habe in mehreren DOIFs Subroutinen definiert welche den gleichen Namen haben. Dies führt zu Problemen, da diese global in allen DOIF zur Verfügung stehen. Gibt es eine Möglichkeit Subs zu definieren nur für das eigene DOIF?
Ich konnte hierzu nichts in der Commandref/Wiki finden.

Die Subroutinen sind nur gegenüber dem Rest von FHEM (alles außerhalb von DOIFs) gekapselt. Alle DOIF-sub-Definitionen befinden sich im gleichen Namensraum DOIF.

Gleiche Subroutinen innerhalb der DOIF-Definitionen lassen sich durch Angabe von $SELF einfach eindeutig machen.

Bsp.:

define test1 DOIF
subs { sub $SELF_sub1 {...}} ## Definition von sub1
{if ([mytrigger]) { $SELF_sub1()}} ## Aufruf von sub1


Edit:

alternativ kann man ein eigenes Package definieren:

define test1 DOIF
subs {package $SELF; sub sub1 {DOIF::fhem_set"bla on"}} ## Definition von sub1
{if ([mytrigger]) { $SELF::sub1()}} ## Aufruf von sub1


oder

define test1 DOIF
subs {package $SELF; sub sub1 {DOIF::fhem_set"bla on"}} ## Definition von sub1
{package $SELF; if ([mytrigger]) {sub1()}} ## Aufruf von sub1



dabei ist zu beachten, dass DOIF-Perl spezifische Funktionen des Namensraums DOIF  im eigenen Package mit vorangestelltem DOIF:: angegeben werden müssen, FHEM-subs müssen ja ohnehin mit vorangestelltem :: angegeben werden.

Statt $SELF kann man natürlich einen beliebigen eigenen Namen angeben, dann muss man darauf achten, dass man in jedem DOIF einen anderen package-Namen angibt. Bei $SELF ist der Name bereits eindeutig, weil es der DOIF-Device-Name ist.

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: obi am 04 Februar 2019, 20:19:11
Danke Damian für die schnelle Antwort, funktioniert so super :)
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 04 Februar 2019, 20:56:39
Zitat von: obi am 04 Februar 2019, 20:19:11
Danke Damian für die schnelle Antwort, funktioniert so super :)

Für welche Lösung hast du dich denn entschieden?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag 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

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: obi am 06 Februar 2019, 14:38:23
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 {
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Per am 06 Februar 2019, 15:30:37
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.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 06 Februar 2019, 17:04:59
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.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: cwagner am 06 Februar 2019, 19:12:09
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
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 06 Februar 2019, 20:25:48
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.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag 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
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 16 April 2019, 08:53:47
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?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag 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")
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 16 April 2019, 09:45:55
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.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: travelling-man am 16 April 2019, 21:04:50
Moin,

Warum kompliziert wenn es auch einfach geht.

Daran habe ich gar nicht gedacht. Vielen Dank.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag 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
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 28 April 2019, 08:13:27
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.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: lichtimc am 28 April 2019, 11:58:00
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
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 28 April 2019, 12:58:36
Bei mir kann ich das Problem nicht nachvollziehen.

Wie sieht das andere DOIF-Device aus? Benutzt du irgendwo anders deine Routine : ZoneInnenOff?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: dusti64 am 01 August 2019, 19:44:24
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
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag 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)...
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: dusti64 am 05 August 2019, 18:56:50
...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 :)
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag 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
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 27 August 2019, 22:25:11
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
Titel: Perl-Modus: Verzögerungen im Ausführungszweig
Beitrag von: cwagner am 14 September 2019, 16:53:39
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
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 14 September 2019, 17:04:32
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 &


Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: cwagner am 15 September 2019, 00:25:04
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

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 15 September 2019, 11:19:30
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
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: cwagner am 28 September 2019, 23:16:18
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?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 28 September 2019, 23:28:18
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)
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag 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")}

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 24 November 2019, 17:02:08
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")}}
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: kumue am 24 November 2019, 17:07:59
Danke Damian, so fkt, es.  :)
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: lichtimc am 20 Februar 2020, 12:36:53
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
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 20 Februar 2020, 16:01:36
Das dürfte mit den allgemeinen FHEM-Mechanismen zu tun haben.

Dein Eventblock wird durch ein externes Event, ausgelöst durch setreading ...., beendet.

Innerhalb eines Eventblocks darf es wohl keine fremden Events geben.

Du wirst in diesem Falle auf Einzelereignisse ausweichen müssen, z. B. set_Reading ("Anzeige", "off",1);
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: lichtimc am 20 Februar 2020, 16:37:02
Danke Damian für deine Antwort.

Das hab ich inzwischen schon rausgefunden und entsprechend angepasst... (siehe EDIT: im vorigen Post.)

Dennoch bleibt das Problem, dass, wenn ein fhem("...") vor einem set_Reading kommt, das set_Reading nicht ausgeführt wird.


Gibt es noch einen anderen Weg ein Reading eines anderen DEVICE zu setzen?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 20 Februar 2020, 18:59:36
Zitat von: lichtimc am 20 Februar 2020, 16:37:02
Dennoch bleibt das Problem, dass, wenn ein fhem("...") vor einem set_Reading kommt, das set_Reading nicht ausgeführt wird.

Das kann ich nicht nachvollziehen:

ZitatInternals:
   CFGFN     
   DEF        { [FS];
  fhem"setreading bla test 20";
  set_Reading ("test",10,1);
}
   DOIFDEV    ^global$|^FS$
   FUUID      5e4ec793-f33f-c0d4-e280-b5f5748457aec9b4
   MODEL      Perl
   NAME       di_setreading
   NR         642
   NTFY_ORDER 50-di_setreading
   STATE      initialized
   TYPE       DOIF
   VERSION    20929 2020-01-10 09:44:35
   READINGS:
     2020-02-20 18:55:38   Device          FS
     2020-02-20 18:55:38   block_01        executed
     2020-02-20 18:55:38   e_FS_STATE      ???
     2020-02-20 18:55:13   mode            enabled
     2020-02-20 18:53:23   state           initialized
     2020-02-20 18:55:38   test            10

Internals:
   FUUID      5d63fc90-f33f-c0d4-a3fd-a78da754aa533c52
   NAME       bla
   NR         16
   STATE      on
   TYPE       dummy
   READINGS:
     2019-11-09 19:03:09   state           on
     2020-02-20 18:55:38   test            20
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: der-Lolo am 19 April 2020, 09:59:28
Guten Morgen Damian,
ich knobbel gerade an meinem Rasensprenger - mir fehlt aber der Ansatz...
Ziel ist es drei Buttons zu haben 5, 10 und 15 die jeweils 5, 10 oder 15 minuten on-for-timer wiederspiegeln.
Das schaltende Device ist ein ModbusCoil und versteht on-for-timer
set Rasensprenger on-for-timer 300 wären also 5 minuten.

Kannst Du mir hier eine kurze hilfe geben - im Doku wirwar blicke ich nicht durch..

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: moskito am 19 April 2020, 10:22:50
Hi der-Lolo,
schau doch mal, ob das in die Richtung geht was du suchst:

defmod dfp.rasensprenger DOIF init {set_State("off")}{["$SELF:bla"];;set_State("on");;fhem_set"Rasensprenger on-for-timer 300";;set_Exec("",300,'set_State("off")')}
attr dfp.rasensprenger devStateIcon on:radio_checked@red off:radio_checked@green:bla


Ist ein Codefragment von Damian, das ich mal irgendwo aufgeschnappt hatte.
Evtl. ein Nachteil: Es wird nicht der wirkliche Schaltzustand des Rasensprengers wiedergegeben.

Gruß
Danny
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: der-Lolo am 19 April 2020, 10:41:09
Naja - noch nicht ganz, wenn ich alles richtig verstehe starte ich so ja auch zwei Timer...
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 19 April 2020, 22:56:51
Hier mal ganz primitiv über webCmd:

defmod di_butten DOIF {["$SELF:Timer1"];;fhem_set("Rasensprenger on-for-timer 300")}\
{["$SELF:Timer2"];;fhem_set("Rasensprenger on-for-timer 600")}\
{["$SELF:Timer3"];;fhem_set("Rasensprenger on-for-timer 900")}\

attr di_butten webCmd Timer1:Timer2:Timer3
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: mumpitzstuff am 10 Juni 2020, 01:17:43
Ich habe mal versucht ein sehr komplexes DOIF aufzusetzen und dabei den Perl Modus zu verwenden. Das hat am Anfang auch ganz gut funktioniert, aber irgendwann bin ich an den Punkt gekommen, an dem ich [] innerhalb eines Regex oder für den Zugriff auf ein Array verwenden musste. Dann habe ich die Möglichkeit gefunden subs {} zu verwenden und auch getan. Leider bekommen aber die hier definierten subs keinen Zugriff auf die globalen Variablen mehr. Gibt es dafür einen Ausweg?

Beispiel:

subs {
  sub test() {
    $test = 'mist';
  }
}
{
  my $test;

}


Ich erhalte dann solche Fehler:

Global symbol "$test" requires explicit package name (did you forget to declare "my $test"?) at (eval 7924) line 16.

PS: Mit $DOIF::<variable> scheint es irgendwie weiter zu gehen oder alternativ mit package DOIF. Ich muss noch prüfen ob nur keine Fehler mehr kommen oder es jetzt wirklich geht...

Warum wird subs { } nicht standardmäßig in den DOIF Namensraum gelegt?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 10 Juni 2020, 09:07:31
Zitat von: mumpitzstuff am 10 Juni 2020, 01:17:43
Ich habe mal versucht ein sehr komplexes DOIF aufzusetzen und dabei den Perl Modus zu verwenden. Das hat am Anfang auch ganz gut funktioniert, aber irgendwann bin ich an den Punkt gekommen, an dem ich [] innerhalb eines Regex oder für den Zugriff auf ein Array verwenden musste. Dann habe ich die Möglichkeit gefunden subs {} zu verwenden und auch getan. Leider bekommen aber die hier definierten subs keinen Zugriff auf die globalen Variablen mehr. Gibt es dafür einen Ausweg?

Beispiel:

subs {
  sub test() {
    $test = 'mist';
  }
}
{
  my $test;

}


Ich erhalte dann solche Fehler:

Global symbol "$test" requires explicit package name (did you forget to declare "my $test"?) at (eval 7924) line 16.

PS: Mit $DOIF::<variable> scheint es irgendwie weiter zu gehen oder alternativ mit package DOIF. Ich muss noch prüfen ob nur keine Fehler mehr kommen oder es jetzt wirklich geht...

Warum wird subs { } nicht standardmäßig in den DOIF Namensraum gelegt?
subs werden im Namensraum DOIF gelegt. Du hast aber eine lokale Variable deklarieret, die ist außerhalb der Methode nicht bekannt. Das ist so ziemlich in allen Sprachen so.

Was du brauchst sind Instanzvariablen (hier Device-Variablen genannt). Auch dafür habe ich vorgesorgt, siehe https://fhem.de/commandref_DE.html#DOIF_Device-Variablen
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: mumpitzstuff am 10 Juni 2020, 10:33:01
Verstehe ich nicht. Ein Script in dieser Form macht keine Probleme:


my $mist;

sub test()
{
  $mist = '';
}


Was genau DOIF mit den zwei Blöcken da macht ist mir ja nicht bekannt. Ich war davon ausgegangen, das die beiden Dinge intern irgendwie als Einheit betrachtet werden. Vielleicht ist es auch nur das Problem, das ich den subs Block zuerst definiert habe? War gestern schon spät, ich spiele heute mal noch ein wenig rum.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 10 Juni 2020, 10:55:10
Außerhalb der Perl-Blöcke gibt es kein Perl (neuerdings gibt es dort Template-Definitionen), da kann man auch keine Perlvariablen nutzen.

Jeder Block wird per eval ausgeführt. mit $_<Variablenname> oder $VAR{<Variablenname>} kann man innerhalb der Perl-Blöcke blockübergreifend mit sog. Device-Variablen hantieren.

subs {

$_bla=1;

}


block {

print ($_bla);

}



 
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: mumpitzstuff am 11 Juni 2020, 01:48:14
Lustig. Ein bischen geht schon mal (das wahrscheinlich fetteste DOIF aller Zeiten). Muss ich aber noch etwas verfeinern...

PS: Port 7072 muss ohne Passwort per telnet erreichbar sein, damit es funktioniert. Außerdem muss man für den initialen Download die Bedingung temporär anpassen, bis diese einmalig ausgeführt wurde.

[00:05|Mo Do]


defmod doif_TEST DOIF subs\
{\
  use utf8;;\
  use Date::Parse;;\
  # sudo apt-get install libxml-bare-perl\
  use XML::Bare 0.53 qw(forcearray);;\
  use Blocking;;\
  \
  ### CONFIG AREA ###\
  $_channelFilter = qr/^(?:ARD\.|ZDF\.|Sat1\.|RTL2?\.|Pro(?:7|SiebenMaxx)\.|DMax\.|Vox\.|Kabel(?:EinsClassic|EinsDoku)?\.|ntv\.|Sixx\.|TLC\.|N24Doku\.|SonyEntertainmentTV\.|AandE\.|TNT(?:Serie|Film)\.|AnimalPlanet\.|History\.|Kinowelt\.|NatGeoHD\.|PLANET\.|Silverline\.|13thStreet\.|AXN\.|SciFi\.)/;;\
  $_timeAdjust = 0;;\
  $_path = '/opt/fhem/';;\
  $_dataFile = $_path.'rytecDE_Basic';;\
  # enable/disable unused channel filtering on filemerge (enabled = small file = faster)\
  $_filterChannels = 1;;\
  \
\
  sub filterText($)\
  {\
    my $text = shift;;\
\
    $text =~ s/["`;;'\r]//g;;\
    $text =~ s/[\n]/<br>/g;;\
\
    return $text;;\
  }\
  \
  sub xmltv2epoch($)\
  {\
    my $t = shift;;\
\
    return Time::Piece->strptime($t, '%Y%m%d%H%M%S %z')->epoch;;\
  }\
\
  sub FmtDateTime($)\
  {\
    my @t = localtime(shift);;\
    return sprintf("%04d-%02d-%02d %02d:%02d:%02d", $t[5]+1900, $t[4]+1, $t[3], $t[2], $t[1], $t[0]);;\
  }\
\
  sub tvParse($;;$)\
  {\
    my ($device, $mode) = @_;;\
    my $obj;;\
    my $xml;;\
    my $lastChannel = '';;\
    my $reading = '';;\
    my $i = 999;;\
    my $n = 999;;\
    my $k = 0;;\
    my $primeTime = substr(FmtDateTime(time() + $_timeAdjust), 0, 11).'20:14:00';;\
    my $sendTelnet = '';;\
\
    $obj = XML::Bare->new(file => $_dataFile);;\
    $xml = $obj->parse();;\
\
    if (!$@)\
    {\
      my $old = time() + $_timeAdjust;;\
\
      foreach (@{forcearray($xml->{'tv'}{'programme'})})\
      {\
        if ((0 != $_filterChannels) ||\
            ($_->{'channel'}{'value'} =~ $_channelFilter))\
        {\
          my $stop = xmltv2epoch($_->{'stop'}{'value'});;\
\
          # filter old stuff\
          if ($stop > $old)\
          {\
            if ($lastChannel ne $_->{'channel'}{'value'})\
            {\
              $lastChannel = $_->{'channel'}{'value'};;\
              $reading = $_->{'channel'}{'value'};;\
              $reading =~ s/[\.\s]//g;;\
              $reading =~ s/de$//;;\
              $n = 0;;\
              $i = 0;;\
            }\
\
            if ($i < 3 && 'next' eq $mode)\
            {\
              my $fi = sprintf("%03d", $i);;\
              my $start = xmltv2epoch($_->{'start'}{'value'});;\
              my $readingName;;\
              my $readingValue;;\
\
              $readingName = 'next_'.$reading.'_'.$fi.'_bdate';;\
              $readingValue = substr(FmtDateTime($start), 0, 10);;\
              $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
              $readingName = 'next_'.$reading.'_'.$fi.'_btime';;\
              $readingValue = substr(FmtDateTime($start), 11, 8);;\
              $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
              $readingName = 'next_'.$reading.'_'.$fi.'_title';;\
              $readingValue = filterText(@{forcearray($_->{'title'})}[0]->{'value'});;\
              $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
              $readingName = 'next_'.$reading.'_'.$fi.'_stitle';;\
              if (exists($_->{'sub-title'}{'value'}))\
              {\
                $readingValue = filterText($_->{'sub-title'}{'value'});;\
              }\
              else\
              {\
                $readingValue = 'na';;\
              }\
              $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
              $readingName = 'next_'.$reading.'_'.$fi.'_desc';;\
              if (exists($_->{'desc'}{'value'}))\
              {\
                $readingValue = filterText($_->{'desc'}{'value'});;\
              }\
              else\
              {\
                $readingValue = 'na';;\
              }\
              $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
              $k++;;\
              $i++;;\
            }\
\
            if ($n < 3 && 'prime' eq $mode)\
            {\
              my $start = xmltv2epoch($_->{'start'}{'value'});;\
              my $fmtStart = FmtDateTime($start);;\
              my $bdate = substr($fmtStart, 0, 10);;\
              my $btime = substr($fmtStart, 11, 8);;\
\
              if ($bdate.' '.$btime gt $primeTime)\
              {\
                my $fn = sprintf("%03d", $n);;\
                my $readingName;;\
                my $readingValue;;\
\
                $readingName = 'prime_'.$reading.'_'.$fn.'_bdate';;\
                $readingValue = substr(FmtDateTime($start), 0, 10);;\
                $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
                $readingName = 'prime_'.$reading.'_'.$fn.'_btime';;\
                $readingValue = substr(FmtDateTime($start), 11, 8);;\
                $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
                $readingName = 'prime_'.$reading.'_'.$fn.'_title';;\
                $readingValue = filterText(@{forcearray($_->{'title'})}[0]->{'value'});;\
                $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
                $readingName = 'prime_'.$reading.'_'.$fn.'_stitle';;\
                if (exists($_->{'sub-title'}{'value'}))\
                {\
                  $readingValue = filterText($_->{'sub-title'}{'value'});;\
                }\
                else\
                {\
                  $readingValue = 'na';;\
                }\
                $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
                $readingName = 'prime_'.$reading.'_'.$fn.'_desc';;\
                if (exists($_->{'desc'}{'value'}))\
                {\
                  $readingValue = filterText($_->{'desc'}{'value'});;\
                }\
                else\
                {\
                  $readingValue = 'na';;\
                }\
                $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
                $k++;;\
                $n++;;\
              }\
            }\
\
            if ($k >= 10)\
            {\
              `perl /opt/fhem/fhem.pl 7072 "$sendTelnet"`;;\
\
              $k = 0;;\
              $sendTelnet = '';;\
            }\
          }\
        }\
      }\
\
      if ('' ne $sendTelnet)\
      {\
        `perl /opt/fhem/fhem.pl 7072 "$sendTelnet"`;;\
      }\
    }\
  }\
  \
  sub tvMerge($;;$)\
  {\
    my ($dstName, $srcName) = @_;;\
    my $fh;;\
    my $dst;;\
    my $src;;\
    my $start = '';;\
    my $channels1 = '';;\
    my $channels1_flt = '';;\
    my $channels2 = '';;\
    my $channels2_flt = '';;\
    my $programms1 = '';;\
    my $programms1_flt = '';;\
    my $programms2 = '';;\
    my $programms2_flt = '';;\
    my $end = '';;\
    my $pos;;\
\
    open($fh, '<', $dstName) or die "Can't open file $!";;\
    read($fh, $dst, -s $fh);;\
    close($fh);;\
\
    if (defined($srcName))\
    {\
      open($fh, '<', $srcName) or die "Can't open file $!";;\
      read($fh, $src, -s $fh);;\
      close($fh);;\
    }\
\
    if (-1 != ($pos = index($dst, '<channel ')))\
    {\
      $start = substr($dst, 0, $pos);;\
    }\
\
    if (-1 != ($pos = rindex($dst, '</programme>')))\
    {\
      $end = substr($dst, $pos + 12);;\
    }\
\
    while ($dst =~ /(\s*<channel\s.*?id="(.*?)".*?<\/channel>)/sg)\
    {\
      if (0 != $_filterChannels)\
      {\
        $_ = $1;;\
\
        if ($2 =~ $_channelFilter)\
        {\
          $channels1_flt .= $_;;\
        }\
      }\
      else\
      {\
        $channels1 .= $1;;\
      }\
    }\
\
    while ($dst =~ /(\s*<programme\s.*?channel="(.*?)".*?<\/programme>)/sg)\
    {\
      if (0 != $_filterChannels)\
      {\
        $_ = $1;;\
\
        if ($2 =~ $_channelFilter)\
        {\
          $programms1_flt .= $_;;\
        }\
      }\
      else\
      {\
        $programms1 .= $1;;\
      }\
    }\
\
    if (defined($srcName))\
    {\
      while ($src =~ /(\s*<channel\s.*?id="(.*?)".*?<\/channel>)/sg)\
      {\
        if (0 != $_filterChannels)\
        {\
          $_ = $1;;\
\
          if ($2 =~ $_channelFilter)\
          {\
            $channels2_flt .= $_;;\
          }\
        }\
        else\
        {\
          $channels2 .= $1;;\
        }\
      }\
\
      while ($src =~ /(\s*<programme\s.*?channel="(.*?)".*?<\/programme>)/sg)\
      {\
        if (0 != $_filterChannels)\
        {\
          $_ = $1;;\
\
          if ($2 =~ $_channelFilter)\
          {\
            $programms2_flt .= $_;;\
          }\
        }\
        else\
        {\
          $programms2 .= $1;;\
        }\
      }\
    }\
\
    if (0 != $_filterChannels)\
    {\
      open($fh, '>', $dstName) or die "Can't open file $!";;\
\
      if (defined($srcName))\
      {\
        print $fh $start.$channels1_flt.$channels2_flt.$programms1_flt.$programms2_flt.$end;;\
      }\
      else\
      {\
        print $fh $start.$channels1_flt.$programms1_flt.$end;;\
      }\
\
      close($fh);;\
    }\
    else\
    {\
      open($fh, '>', $dstName) or die "Can't open file $!";;\
\
      if (defined($srcName))\
      {\
        print $fh $start.$channels1.$channels2.$programms1.$programms2.$end;;\
      }\
      else\
      {\
        print $fh $start.$channels1.$programms1.$end;;\
      }\
\
      close($fh);;\
    }\
  }\
\
  sub tvDownload()\
  {\
    my $output = '';; \
    \
    # other server\
    # http://www.xmltvepg.nl/rytecDE_Basic.xz\
    # http://91.121.106.172/~rytecepg/epg_data/rytecDE_Basic.xz\
    # http://www.vuplus-community.net/rytec/rytecDE_Common.xz\
    # http://www.xmltvepg.nl/rytecDE_Common.xz\
    # http://91.121.106.172/~rytecepg/epg_data/rytecDE_Common.xz\
    # http://www.vuplus-community.net/rytec/rytecDE_SportMovies.xz\
    # http://www.xmltvepg.nl/rytecDE_SportMovies.xz\
    # http://91.121.106.172/~rytecepg/epg_data/rytecDE_SportMovies.xz\
    $output .= qx(wget http://www.vuplus-community.net/rytec/rytecDE_Basic.xz -O /opt/fhem/rytecDE_Basic.xz 2>&1);;\
    $output .= qx(xz -df /opt/fhem/rytecDE_Basic.xz 2>&1);;\
\
    if (0 != $_filterChannels)\
    {\
      tvMerge($_dataFile);;\
    }\
    \
    return $output;;\
  }\
\
  sub tvDownloadMerge()\
  {\
    my $output = '';; \
    \
    # other server\
    # http://www.xmltvepg.nl/rytecDE_Basic.xz\
    # http://91.121.106.172/~rytecepg/epg_data/rytecDE_Basic.xz\
    # http://www.vuplus-community.net/rytec/rytecDE_Common.xz\
    # http://www.xmltvepg.nl/rytecDE_Common.xz\
    # http://91.121.106.172/~rytecepg/epg_data/rytecDE_Common.xz\
    # http://www.vuplus-community.net/rytec/rytecDE_SportMovies.xz\
    # http://www.xmltvepg.nl/rytecDE_SportMovies.xz\
    # http://91.121.106.172/~rytecepg/epg_data/rytecDE_SportMovies.xz\
    $output .= qx(wget http://www.vuplus-community.net/rytec/rytecDE_Basic.xz -O /opt/fhem/rytecDE_Basic.xz 2>&1);;\
    $output .= qx(xz -df /opt/fhem/rytecDE_Basic.xz 2>&1);;\
    $output .= qx(wget http://www.vuplus-community.net/rytec/rytecDE_Common.xz -O /opt/fhem/rytecDE_Common.xz 2>&1);;\
    $output .= qx(xz -df /opt/fhem/rytecDE_Common.xz 2>&1);;\
    \
    tvMerge($_dataFile, $_path.'rytecDE_Common');;\
\
    # download and merge other files here if needed\
    \
    return $output;;\
  }\
  \
  \
  sub startDownload($)\
  {\
    my $name = shift;;\
    \
    if (defined($_blockingcalls{PID_DOWNLOAD}))\
    {\
      ::Log3 $name, 3, $name.': Blocking call already running (download).';;\
\
      ::BlockingKill($_blockingcalls{PID_DOWNLOAD});;\
    }\
\
    $_blockingcalls{PID_DOWNLOAD} = ::BlockingCall('DOIF::doDownload', $name, 'DOIF::endDownload', 300, 'DOIF::abortDownload', $name);;\
  }\
  \
  sub DOIF::doDownload($)\
  {\
    my $name = shift;;\
    my $output = '';;\
    \
    $output = tvDownloadMerge();;\
    \
    return $name.'|'.$output;;\
  }\
  \
  sub DOIF::endDownload($)\
  {\
    my ($name, $output) = split("\\|", shift);;\
    \
    ::Log3 $name, 5, $name.': Blocking call finished to download tv data.';;\
    \
    delete($_blockingcalls{PID_DOWNLOAD});;\
  }\
  \
  sub DOIF::abortDownload($)\
  {\
    my $name = shift;;\
    \
    delete($_blockingcalls{PID_DOWNLOAD});;\
    \
    ::Log3 $name, 1, $name.': Blocking call aborted (download).';;\
  }\
  \
  sub startParse($$)\
  {\
    my ($name, $mode) = @_;;\
    \
    if (defined($_blockingcalls{PID_PARSE}))\
    {\
      ::Log3 $name, 3, $name.': Blocking call already running (parse).';;\
\
      ::BlockingKill($_blockingcalls{PID_PARSE});;\
    }\
\
    $_blockingcalls{PID_PARSE} = ::BlockingCall('DOIF::doParse', $name.'|'.$mode, 'DOIF::endParse', 300, 'DOIF::abortParse', $name);;\
  }\
  \
  sub DOIF::doParse($)\
  {\
    my ($name, $mode) = split("\\|", shift);;\
        \
    tvParse($name, $mode);;\
    \
    return $name;;\
  }\
  \
  sub DOIF::endParse($)\
  {\
    my $name = shift;;\
    \
    ::Log3 $name, 5, $name.': Blocking call finished to parse tv data.';;\
    \
    delete($_blockingcalls{PID_PARSE});;\
  }\
  \
  sub DOIF::abortParse($)\
  {\
    my $name = shift;;\
    \
    delete($_blockingcalls{PID_PARSE});;\
    \
    ::Log3 $name, 1, $name.': Blocking call aborted (parse).';;\
  }\
}\
{\
  if ([00:05|Mo Do])\
  {\
    startDownload("$SELF");;\
  }\
  \
  if ([+00:15]) \
  {\
    startParse("$SELF", 'next');;\
  }\
  \
  if ([00:30])\
  {\
    startParse("$SELF", 'prime');;\
  }\
}
attr doif_TEST alias Aktuelles TV-Programm
attr doif_TEST room TEST
attr doif_TEST uiTable {\
  package ui_Table;;\
\
  $SHOWNOSTATE=1;;\
\
  $TR{0,31} = "style='color:yellow;;text-align:center;;font-weight:bold;;font-size:18px'";;\
  $TD{0..29,31..60}{2,4} = "style='font-size:16px;;border-right-style:solid;;border-color:#CCCCCC;;border-right-width:1px;;'";;\
  $TD{0..29,31..60}{0} = "align='center' style='border-right-style:solid;;border-color:#CCCCCC;;border-right-width:1px;;'";;\
  $TD{0..60}{1,3,5,6} = "style='font-size:16px;;'";;\
  $TD{30}{1..6} = "border-top-style:solid;;border-bottom-style:solid;;border-color:#CCCCCC;;border-top-width:1px;;border-bottom-width:1px;;'";;\
\
  sub rgUnfold\
  {\
    my ($title, $desc) = @_;;\
    $title = 'na' if (!defined($title));;\
    $desc = 'na'."\n\n".'na' if (!defined($desc));;\
\
    $title =~ s/(.{1,45}|\S{46,})(?:\s[^\S\r\n]*|\Z)/$1<br>/g;;\
    $desc =~ s/<br>/\n/g;;\
    $desc =~ s/(.{1,65}|\S{66,})(?:\s[^\S\r\n]*|\Z)/$1<br>/g;; \
    $desc =~ s/[\r\'\"]/ /g;;\
    $desc =~ s/[\n]|\\n/<br>/g;;\
    return "<a href=\"#!\" onclick=\"FW_okDialog('".$desc."')\">".$title."</a>";;\
  }\
}\
\
DEF TPL_TV(ICON("tv/$4")|substr([$1:$2_$3_000_btime],0,5)|rgUnfold([$1:$2_$3_000_title],[$1:$2_$3_000_stitle]."\n\n".[$1:$2_$3_000_desc])|substr([$1:$2_$3_001_btime],0,5)|rgUnfold([$1:$2_$3_001_title],[$1:$2_$3_001_stitle]."\n\n".[$1:$2_$3_001_desc])|substr([$1:$2_$3_002_btime],0,5)|rgUnfold([$1:$2_$3_002_title],[$1:$2_$3_002_stitle]."\n\n".[$1:$2_$3_002_desc]))\
\
"Sender"|"ab"|"Aktuelle Sendung"|"ab"|"Nächste Sendung"|"ab"|"Sendung"\
TPL_TV($SELF,next,ARD,ard)\
TPL_TV($SELF,next,ZDF,zdf)\
TPL_TV($SELF,next,Sat1,sat1)\
TPL_TV($SELF,next,RTL,rtl)\
TPL_TV($SELF,next,RTL2,rtl2)\
TPL_TV($SELF,next,Pro7,pro7)\
TPL_TV($SELF,next,DMax,dmax)\
TPL_TV($SELF,next,Vox,vox)\
TPL_TV($SELF,next,Kabel,kabel1)\
TPL_TV($SELF,next,KabelEinsClassic,kabel1classic)\
TPL_TV($SELF,next,13thStreet,13thstreet)\
TPL_TV($SELF,next,Silverline,silverline)\
TPL_TV($SELF,next,TNTFilm,tntfilm)\
TPL_TV($SELF,next,AXN,axn)\
TPL_TV($SELF,next,SonyEntertainmentTV,sonytv)\
TPL_TV($SELF,next,Kinowelt,kinowelt)\
TPL_TV($SELF,next,ProSiebenMaxx,pro7maxx)\
TPL_TV($SELF,next,Sixx,sixx)\
TPL_TV($SELF,next,TNTSerie,tntserie)\
TPL_TV($SELF,next,SciFi,syfy)\
TPL_TV($SELF,next,ntv,ntv)\
TPL_TV($SELF,next,N24Doku,n24)\
TPL_TV($SELF,next,History,history)\
TPL_TV($SELF,next,PLANET,planet)\
TPL_TV($SELF,next,KabelEinsDoku,kabel1doku)\
TPL_TV($SELF,next,AnimalPlanet,animalplanet)\
TPL_TV($SELF,next,NatGeoHD,natgeo)\
TPL_TV($SELF,next,TLC,tlc)\
TPL_TV($SELF,next,AandE,ae)\
"&nbsp;;"|"&nbsp;;"|"&nbsp;;"|"&nbsp;;"|"&nbsp;;"|"&nbsp;;"|"&nbsp;;"\
"Sender"|"ab"|"Sendung"|"ab"|"Sendung"|"ab"|"Sendung"\
TPL_TV($SELF,prime,ARD,ard)\
TPL_TV($SELF,prime,ZDF,zdf)\
TPL_TV($SELF,prime,Sat1,sat1)\
TPL_TV($SELF,prime,RTL,rtl)\
TPL_TV($SELF,prime,RTL2,rtl2)\
TPL_TV($SELF,prime,Pro7,pro7)\
TPL_TV($SELF,prime,DMax,dmax)\
TPL_TV($SELF,prime,Vox,vox)\
TPL_TV($SELF,prime,Kabel,kabel1)\
TPL_TV($SELF,prime,KabelEinsClassic,kabel1classic)\
TPL_TV($SELF,prime,13thStreet,13thstreet)\
TPL_TV($SELF,prime,Silverline,silverline)\
TPL_TV($SELF,prime,TNTFilm,tntfilm)\
TPL_TV($SELF,prime,AXN,axn)\
TPL_TV($SELF,prime,SonyEntertainmentTV,sonytv)\
TPL_TV($SELF,prime,Kinowelt,kinowelt)\
TPL_TV($SELF,prime,ProSiebenMaxx,pro7maxx)\
TPL_TV($SELF,prime,Sixx,sixx)\
TPL_TV($SELF,prime,TNTSerie,tntserie)\
TPL_TV($SELF,prime,SciFi,syfy)\
TPL_TV($SELF,prime,ntv,ntv)\
TPL_TV($SELF,prime,N24Doku,n24)\
TPL_TV($SELF,prime,History,history)\
TPL_TV($SELF,prime,PLANET,planet)\
TPL_TV($SELF,prime,KabelEinsDoku,kabel1doku)\
TPL_TV($SELF,prime,AnimalPlanet,animalplanet)\
TPL_TV($SELF,prime,NatGeoHD,natgeo)\
TPL_TV($SELF,prime,TLC,tlc)\
TPL_TV($SELF,prime,AandE,ae)
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 11 Juni 2020, 09:50:48
Was mir dazu einfällt:

Ich hoffe, du benutzt Codemirror oder einen externen Editor.

Längere Definitionen würde ich in eine externe Datei auslagern (myutils-sonstwas, mit package DOIF), die man mit einem vernünftigen Programm-Editor bearbeiten kann. Ich weiß nicht, wann sich der im DEF-Editor verabschiedet.

Im subs-Block ist man im DOIF-Package, da braucht man kein "DOIF::" davorzustellen.

Wenn du "init" als Blocknamen wählst, wird dieser nach seiner Definition bzw. nach dem Hochfahren sofort ausgeführt.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: mumpitzstuff am 12 Juni 2020, 00:41:53
externe Datei = halb so viel Spass :)

Das DOIF:: habe ich nur bei BlockingCall Funktionen verwendet. Das hatte so in der Hilfe gestanden, deshalb habe ich mich daran gehalten.

Das mit dem init Block habe ich übernommen. Danke.

PS: Das DOIF ist heute denke ich fertig geworden (selektives update habe ich noch erweitert). Ich stelle es dann die nächsten Tage noch mal separat zur Verfügung, nachdem ich es noch 1-2 Tage habe laufen lassen. Ist aber wirklich super was alles in so einem DOIF geht. Vielen Dank für das tolle Modul.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: weini am 21 Juli 2020, 17:21:14
Gibt es eine Möglichkeit, im Perl-Modus auf den Status zu triggern?
Ich möchte mir ein "Überwachtungs-DOIF" für meinen ganzen CUL/LaCrosse/sDuino etc. Zoo definieren. Die einzelnen Module haben schlauerweise unterschiedliche Stati für "alles ok". Mal ist das "Initialized", mal "Connected" usw. Das lässt sich mit dem Template-Ansatz von DOIF im Prinzip sehr schön erschlagen.

Mein Problem ist nur, dass bei einem Disconnect eines Devices kein Event erzeugt wird, sondern das verantwortliche Modul nur einfach den state entsprechen setzt.
Ist der Perl-Modus damit ausgehebelt?

VG, weini
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 21 Juli 2020, 17:54:30
Zitat von: weini am 21 Juli 2020, 17:21:14
Gibt es eine Möglichkeit, im Perl-Modus auf den Status zu triggern?
Ich möchte mir ein "Überwachtungs-DOIF" für meinen ganzen CUL/LaCrosse/sDuino etc. Zoo definieren. Die einzelnen Module haben schlauerweise unterschiedliche Stati für "alles ok". Mal ist das "Initialized", mal "Connected" usw. Das lässt sich mit dem Template-Ansatz von DOIF im Prinzip sehr schön erschlagen.

Mein Problem ist nur, dass bei einem Disconnect eines Devices kein Event erzeugt wird, sondern das verantwortliche Modul nur einfach den state entsprechen setzt.
Ist der Perl-Modus damit ausgehebelt?

VG, weini

ohne irgendein Event vom Device (muss nicht state sein) kann das DOIF-Modul nicht wissen, ob etwas zu tun ist, da kannst du nur in regelmäßigen Abständen per Timer vom DOIF-Modul nachschauen lassen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: weini am 21 Juli 2020, 18:02:21
Das gilt aber nur für den Perl-Modus, richtig?

Im normalen Modus bekommt mein DOIF den Ausfalls eines CUL wunderbar mit. Nur braucht ich da halt dann auch ein DOIF je Device.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 21 Juli 2020, 18:04:58
Zitat von: weini am 21 Juli 2020, 18:02:21
Das gilt aber nur für den Perl-Modus, richtig?

Im normalen Modus bekommt mein DOIF den Ausfalls eines CUL wunderbar mit. Nur braucht ich da halt dann auch ein DOIF je Device.

Es gibt diesbezüglich keinen Unterschied zwischen Perl-Modus und FHEM-Modus, wenn es im FHEM-Modus funktioniert, dann funktioniert es auch im Perl-Modus. Dann stimmt deine Aussage nicht, das es keine Events gäbe.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: weini am 21 Juli 2020, 18:28:27
Klar, du hast völlig recht!
Ich dachte, dass ich das anders beobachtete hatte. Habe es aber gerade nochmal nachvollzogen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: weini am 22 Juli 2020, 07:35:52
Ich habe jetzt festgestellt, dass das Problem mit dem nicht gesendeten Event beim Disconnect spezifisch für das LaCrosse Modul zu sein scheint. Bei allen anderen Devices kommen entsprechende Events und die Logik funktioniert.

Hier das DOIF Template, mit dem ich die Überwachung mache:

defmod dif_CUL_monitoring DOIF subs {\
   sub raiseAlert($)  # Alarmmeldung per Email & ins Log\
   {\
     my ($dev_name)=@_;;\
::SendEMail('postmaster@domain.de', "$dev_name", "$dev_name  hat Verbindung verloren");;\
Log 3,"$dev_name hat Verbindung verloren";;\
return 0;;\
   }\
}\
DEF TPL_cul ( ## Definition des Templates namens TPL_cul zum Monitoring der CUL Devices\
cul_$1 {                                 ## DOIF Block\
                                         ## Parameter: CUL_Name Status\
                                         ## Nr.:       $1       $2\
  if ([$1] ne "$2") {                    ## wenn Status nicht dem normalen Betriebsstatus entspricht\
    set_Exec("timer_$1", 600, 'raiseAlert', "$1");;\
  } elsif ([$1] eq "$2") {              ## Status ist wieder ok\
    del_Exec("timer_$1");;\
  }\
} ## Ende des CUL-Blocks\
) ## Ende der Templatedefinition\
\
## Generierung der Steuerung pro Beschattungsszene mit Hilfe des obigen Templates\
TPL_cul (lcg_LaCrosse,initialized)\
TPL_cul (nanoCUL433,Initialized)\
TPL_cul (nanoCUL868,Initialized)\
TPL_cul (sduinoCC1101,opened)\
TPL_cul (hmUART,opened)\
TPL_cul (fhemMQTT,Initialized)\
TPL_cul (snipsMQTT,opened)\
TPL_cul (hcconn,Connected)\
## ... hier können weitere Szenarien durch hinzufügen weiterer Zeilen generiert werden


Für den LaCrosse setze ich jetzt zusätzlich ein Watchdog Device auf, damit sollte der dann auch unter Kontrolle sein.

Danke wieder mal an Damian für die neue Template Logik. Für mich bringt sie in einigen Fällen nochmal genau die Features, um Dinge noch besser zusammenzufassen und doch flexibel zu bleiben.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 12 September 2020, 10:29:34
Zitat von: Damian am 13 Oktober 2018, 23:41:35
neue Version eingecheckt: Perl-Modus: state wird vom Modul nicht angepackt (auch nicht gelöscht), Attribute state, initialize, startup wurden entfernt, set initialize wurde ebenfalls entfernt

Ich würde gerne deaktivierte DOIFs (attr disable 1) im Perl-Modus, wie auch schon im FHEM-Modus, im Status mit "deactivated" kennzeichnen wollen und nach dem dem Löschen des disable-Attributes dann logischerweise wieder auf "initialized" setzen.

Hintergrund:

Z. Zt. muss man in Details-Anzeige eines Moduls hineingehen, um zu sehen, ob ein Modul überhaupt aktiv ist oder nicht - das finde ich verwirrend, weil man auf den ersten Blick nicht erkennen kann, ob ein Modul überhaupt arbeitet oder nicht. So habe ich mich schon öfters gewundert, warum ein DOIF nicht funktionierte.  Ein deaktiviertes Modul kann ohnehin keine aktuellen und damit sinnvollen Informationen im Status haben.

Gibt es konkrete Gründe, die dagegen sprechen ein deaktiviertes Modul im Perl-Modus mit "deactivated" im Status zu kennzeichnen?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: cwagner am 12 September 2020, 10:55:14
Aus meiner Praxis heraus würde ich diese Änderung sehr begrüßen.

Christian
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 12 September 2020, 11:07:07
Zitat von: cwagner am 12 September 2020, 10:55:14
Aus meiner Praxis heraus würde ich diese Änderung sehr begrüßen.

Christian

ja, das sind auch meine Erfahrungen.

Ursprünglich war die Überlegung dem User maximale Freiheit beim Setzen des Status über set_State zu überlassen, daher hatte ich das Verändern des Status im Perl-Modus durch das Modul weitgehend ausgebaut.

Im deaktivierten Zustand ist das Beibehalten eines alten Zustands im Status allerdings eher verwirrend als nützlich.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: KyleK am 12 September 2020, 16:01:34
Ich bin ebenfalls für diese Änderung, macht die Sache viel übersichtlicher.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 12 September 2020, 18:45:36
Zitat von: Damian am 12 September 2020, 10:29:34
Ich würde gerne deaktivierte DOIFs (attr disable 1) im Perl-Modus, wie auch schon im FHEM-Modus, im Status mit "deactivated" kennzeichnen wollen und nach dem dem Löschen des disable-Attributes dann logischerweise wieder auf "initialized" setzen.

Hintergrund:

Z. Zt. muss man in Details-Anzeige eines Moduls hineingehen, um zu sehen, ob ein Modul überhaupt aktiv ist oder nicht - das finde ich verwirrend, weil man auf den ersten Blick nicht erkennen kann, ob ein Modul überhaupt arbeitet oder nicht. So habe ich mich schon öfters gewundert, warum ein DOIF nicht funktionierte.  Ein deaktiviertes Modul kann ohnehin keine aktuellen und damit sinnvollen Informationen im Status haben.

Gibt es konkrete Gründe, die dagegen sprechen ein deaktiviertes Modul im Perl-Modus mit "deactivated" im Status zu kennzeichnen?




Das Reading state auf dectivated zu setzen wäre mir egal.

Wenn das Attribut disabled gelöscht wird, dann sollte state nur dann auf initialized gesetzt werden, wenn im init Block state nicht initialisiert wird.

Es könne sonst zu unerwünschten Effekten kommen, wenn abhängige DOIF auf logisch falsch im state vertrauen.

Konsequenter wäre es einen end-Block zu schaffen der dem Benutzer die Möglichkeit bietet state vor disabled, shutdown usw. zu setzen.

ZitatZ. Zt. muss man in Details-Anzeige eines Moduls hineingehen ...

Mit dem Attribut stateFormat mode hat man die Möglichkeit deactivated anzeigen zu lassen ohne das jetzige Verhalten zu ändern
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 12 September 2020, 19:13:06
Zitat von: Ellert am 12 September 2020, 18:45:36
Das Reading state auf dectivated zu setzen wäre mir egal.

Wenn das Attribut disabled gelöscht wird, dann sollte state nur dann auf initialized gesetzt werden, wenn im init Block state nicht initialisiert wird.

Es könne sonst zu unerwünschten Effekten kommen, wenn abhängige DOIF auf logisch falsch im state vertrauen.

Konsequenter wäre es einen end-Block zu schaffen der dem Benutzer die Möglichkeit bietet state vor disabled, shutdown usw. zu setzen.

Mit dem Attribut stateFormat mode hat man die Möglichkeit deactivated anzeigen zu lassen ohne das jetzige Verhalten zu ändern

Was ich machen kann ist, den aktuellen Status z. B. im Reading last_state beim Deaktivieren zu sichern und beim Aktivieren wieder in Status zurück zu kopieren.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Ellert am 12 September 2020, 19:30:51
Ja, das wäre erstmal eine Lösung, vielleicht in einem 2. Schritt, falls meine Bedenken sich bestätigen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 12 September 2020, 19:49:05
Hier mal eine Version zum Testen.

Der init-Block wurde beim Aktivieren immer schon ausgeführt, damit wird ggf. mein kurz zuvor auf "initialized" ohne Event gesetzter Status überschrieben.

Gestestet mit:

defmod di_disable DOIF init {set_State"ok"}\
{[10:00];; fhem_set "bla on"}


Das Sichern des Status habe ich nicht eingebaut.

Das Reading mode wird wie bisher weiterhin mit Event auf "enabled" bzw. "deactivated" gesetzt, darauf kann man immer triggern.

Edit: Version eingecheckt
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 14 September 2020, 15:06:29
Noch mal zur Information:

Die neue DOIF-Version ist bereits produktiv. Zu beachten ist, dass der Status nur dann auf "deactivated" gesetzt wird, wenn man im aktiven System das Attribut disable für ein DOIF-Device auf 1 setzt. Bei DOIF-Modulen, die zuvor schon deaktiviert waren, ändert sich der Status nicht. Möchte man auch diese Module mit "deactivated" im Status haben, so muss man das Attribut disable löschen und wieder auf  1 setzen. All das gilt nur für den Perl-Modus, im FHEM-Modus wurden deaktivierte DOIF-Module immer schon auf "deactivated" im Status gesetzt.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 16 September 2020, 13:33:12
Bitte beachten: https://forum.fhem.de/index.php/topic,114263.0.html

Wenn keiner schreit, dann werde ich es wie vorgeschlagen umsetzen.

Es würde nur jemanden betreffen, wenn er bisher set_Exec mit vier Parametern benutzt hätte.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: eisenhauer1987 am 21 September 2020, 15:31:04
Hi,

set_Exec ("timer",10, 'myfunction', 'bla')

wird vermutlich immer die Funktion mit dem Parameter übergeben:

set_Exec ("timer",10, 'myfunction("bla")')


Ist das schon aktiv? Ich nutze DOIF Perl so z.b

set_Exec("Rollo_OPEN_timer",0,'Rollo_OPEN',\@Rollos);

Das würde nicht mehr gehen?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 21 September 2020, 15:50:50
Zitat von: eisenhauer1987 am 21 September 2020, 15:31:04
Hi,

set_Exec ("timer",10, 'myfunction', 'bla')

wird vermutlich immer die Funktion mit dem Parameter übergeben:

set_Exec ("timer",10, 'myfunction("bla")')


Ist das schon aktiv? Ich nutze DOIF Perl so z.b

set_Exec("Rollo_OPEN_timer",0,'Rollo_OPEN',\@Rollos);

Das würde nicht mehr gehen?
ja, die neue Version ist aktiv, die alte Syntax funktioniert nicht mehr.

so müsste es eigentlich funktionieren:

set_Exec("Rollo_OPEN_timer",0,"Rollo_OPEN(\@Rollos)");

, weil der Zeiger beim Aufruf ausgewertet und übergeben wird.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: eisenhauer1987 am 21 September 2020, 16:07:12
Ok Danke,

Probier ich nachher aus, das bedeutet nicht ganz wenig arbeit für mich  ::)

Grüße
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: eisenhauer1987 am 22 September 2020, 10:25:24
Hi,

der Aufruf:
set_Exec("Rollo_OPEN_timer",0,'Rollo_OPEN',\@Rollos);

funktioniert weiterhin.

hingegen:
set_Exec("Rollo_OPEN_timer",0,'Rollo_OPEN','100');
muss jetzt:
set_Exec("Rollo_OPEN_timer",0,'Rollo_OPEN("100")';
heißen.

Auch dies funktioniert nicht mehr:
[code]set_Exec("Rollo_OPEN_timer",0,'Rollo_OPEN','';[/code]
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 22 September 2020, 10:52:08
Zitat von: eisenhauer1987 am 22 September 2020, 10:25:24
Hi,

der Aufruf:
set_Exec("Rollo_OPEN_timer",0,'Rollo_OPEN',\@Rollos);

funktioniert weiterhin.


Dann mehr oder weniger zufällig.

Mit der aktuellen DOIF-Version ist der letzte Parameter eine Bedingung. Jetzt steht dort ein Zeiger, dieser wird vermutlich >0, damit wird der Befehl solange wiederholt, bis man ihn per del_Exec abbricht. Die Übergabe des Parameters findet nicht statt.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: eisenhauer1987 am 22 September 2020, 11:15:17
Das ist seltsam, hier mal ein größerer Auszug aus meinen code:
my @Rollos = ("EZ.Rollo", "WZ.Rollo", "HWR.Rollo", "GWC.Rollo", "KUE.Rollo.Links", "KUE.Rollo.Rechts", "SZ.Rollo.Links", "SZ.Rollo.Rechts");
set_Exec("Rollo_OPEN_timer",0,'Rollo_OPEN',\@Rollos);


Und das sub:

sub Rollo_OPEN
  {
  my @names = @{$_[0]};
my $Wind = ReadingsVal("Haus.Wind","state","0");
my $allunlock = " ";
if ($Wind eq "on")
{
fhem("setreading $SELF Shading Wind;");
}
if ($Wind eq "off")
{
fhem("setreading $SELF Shading Normal;");
foreach my $n (@names)
{
my $Sperre = ReadingsVal("$n","sperre","0");
my $Shadeposition = ReadingsVal("$n","shadeposition","0");
my $State = ReadingsVal("$n","state","0");
if ($State eq "closed" and $Sperre eq "unlock" and $Shadeposition eq "0")
{
$allunlock=$allunlock."set ".$n." opens; ";
}
if ($State eq "closed" and $Sperre eq "unlock" and $Shadeposition ne "85" and $Shadeposition ne "0")
{
fhem("setreading $SELF Shading On;");
$allunlock=$allunlock."set ".$n." position ".$Shadeposition."; ";
}
if ($State eq "closed" and $Sperre eq "unlock" and $Shadeposition eq "85")
{
fhem("setreading $SELF Shading Heiß;");
$allunlock=$allunlock."set ".$n." position ".$Shadeposition."; ";
}
}
}
if ( $allunlock ne " ")
{
fhem($allunlock)
}
}


Das macht genau das was es soll. Array wird übergeben und ausgewertet.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 22 September 2020, 13:14:51
Das ist für mich nur erklärbar, wenn bei dir nicht die aktuelle DOIF-Version  aktiv wäre, denn es wird jetzt nur das aufgerufen, was als dritter Parameter übergeben wird, hier also

eval("Rollo_OPEN")

Der vierte Parameter ist jetzt Condition, die per eval auf wahr geprüft wird, also sinngemäß:

if (eval(\@Rollos)) ...

Das kann nicht richtig funktionieren.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: eisenhauer1987 am 22 September 2020, 14:00:54
head 98_DOIF.pm sagt:

22781 2020-09-17

ab welchen release gab es den wechsel?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 22 September 2020, 14:21:32
Zitat von: eisenhauer1987 am 22 September 2020, 14:00:54
head 98_DOIF.pm sagt:

22781 2020-09-17

ab welchen release gab es den wechsel?

Das sollte die neuste sein. Wenn es aus deiner Sicht funktioniert, dann ist alles gut. Verstehen tue ich das nicht.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: eisenhauer1987 am 23 September 2020, 09:52:21
Hi ich wollte das ganze jetzt trotzdem glatziehen, aber weder:



set_Exec("Rollo_OPEN_timer",0,'Rollo_OPEN(\@Rollos)');
noch
set_Exec("Rollo_OPEN_timer",0,"Rollo_OPEN(\@Rollos)");



funktioniert.

Nur die alte Variante verhält sich wie vorher:

set_Exec("Rollo_OPEN_timer",0,'Rollo_OPEN',\@Rollos);

Das ist sehr verwirrend und inkosistent.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 23 September 2020, 10:18:04
Zitat von: eisenhauer1987 am 23 September 2020, 09:52:21
Hi ich wollte das ganze jetzt trotzdem glatziehen, aber weder:



set_Exec("Rollo_OPEN_timer",0,'Rollo_OPEN(\@Rollos)');
noch
set_Exec("Rollo_OPEN_timer",0,"Rollo_OPEN(\@Rollos)");



funktioniert.

Nur die alte Variante verhält sich wie vorher:

set_Exec("Rollo_OPEN_timer",0,'Rollo_OPEN',\@Rollos);

Das ist sehr verwirrend und inkosistent.

ja, ich werde es bei mir nachstellen
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 23 September 2020, 19:29:56
Ich habe deinen Fall nachgestellt.

Ich weiß nicht, wie du es bei dir getestet hast, aber bei mir funktioniert es, wie von mir bereits vermutet, nicht, siehe Fehlermeldung.

ZitatInternals:
   CFGFN     
   DEF        subs {
sub Rollo_OPEN
{
  my @names = @{$_[0]};;
  print("namen: $names[0] $names[2]\n")
}
}

{
my @Rollos = ("EZ.Rollo", "WZ.Rollo", "HWR.Rollo", "GWC.Rollo", "KUE.Rollo.Links", "KUE.Rollo.Rechts", "SZ.Rollo.Links", "SZ.Rollo.Rechts");
set_Exec("timer",0,'Rollo_OPEN',\@Rollos);
}

   FUUID      5f6b80dd-f33f-30f6-ae3d-6674a851dda2fe2a
   MODEL      Perl
   NAME       di_array
   NOTIFYDEV  global
   NR         190463
   NTFY_ORDER 50-di_array
   STATE      initialized
   TYPE       DOIF
   VERSION    22764 2020-09-12 20:06:36
   READINGS:
     2020-09-23 19:09:35   block_01        executed
     2020-09-23 19:09:35   error           eval condition: Undefined subroutine &DOIF::ARRAY called at (eval 891801) line 1.

     2020-09-23 19:09:34   mode            enabled
     2020-09-23 19:09:34   state           initialized
   Regex:
     accu:
   condition:
     0         
my @Rollos = ("EZ.Rollo", "WZ.Rollo", "HWR.Rollo", "GWC.Rollo", "KUE.Rollo.Links", "KUE.Rollo.Rechts", "SZ.Rollo.Links", "SZ.Rollo.Rechts");
set_Exec("timer",0,'Rollo_OPEN',\@Rollos);

Dagegen funktioniert die Syntax "Rollo_OPEN(\@Rollos)" in Perl nicht so, wie ich es mir erhofft hatte.

Ich habe dennoch eine Lösung zu mehr Kompatibilität zur ursprünglichen Version gefunden.

Ich überprüfe jetzt, ob der vierte Parameter eine Referenz darstellt, in diesem Falle wird er als Übergabeparameter der Funktion gewertet und nicht als "condition". "condition" kann man dann als fünften Parameter angeben. So sollten alle wichtigen Fälle abgedeckt sein.

Neue DOIF-Version ist ab morgen per Update verfügbar, dann brauchst du an deinen Definitionen, sofern sie eine Referenz als Übergabeparameter beinhalten nichts zu ändern.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: eisenhauer1987 am 24 September 2020, 07:34:36
Morgen!

danke für das nachstellen. Ich sehe einen winzigen unterschied von deiner Probe zu meinen Reallife Szenario.

dein Code um das Array in der Subroutine zu lesen:

my @names = @{$_[0]};;

und mein Code:

my @names = @{$_[0]};

Du hast einmal ";" mehr als ich. Ob das der Grund ist warum das bei dir auf einen Fehler läuft, bei mir aber funktioniert kann ich aber nicht sagen.

Ich übergebe das Array genauso wie du und frage es dann wieder in der Subroutine ab. Daraus bastel ich mir dann in der for schleife (siehe code oben) einen "fhem set" Command der alle Rollos öffnet, welche bestimmte Bedingungen erfüllen.  Das, dass funktioniert sehe ich jeden morgen und Abend, die Rollos öffnen und schließen wie gewünscht, es wird kein Fehler erstellt.

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 24 September 2020, 07:51:00
Zitat von: eisenhauer1987 am 24 September 2020, 07:34:36
Morgen!

danke für das nachstellen. Ich sehe einen winzigen unterschied von deiner Probe zu meinen Reallife Szenario.

dein Code um das Array in der Subroutine zu lesen:

my @names = @{$_[0]};;

und mein Code:

my @names = @{$_[0]};

Du hast einmal ";" mehr als ich. Ob das der Grund ist warum das bei dir auf einen Fehler läuft, bei mir aber funktioniert kann ich aber nicht sagen.

Ich übergebe das Array genauso wie du und frage es dann wieder in der Subroutine ab. Daraus bastel ich mir dann in der for schleife (siehe code oben) einen "fhem set" Command der alle Rollos öffnet, welche bestimmte Bedingungen erfüllen.  Das, dass funktioniert sehe ich jeden morgen und Abend, die Rollos öffnen und schließen wie gewünscht, es wird kein Fehler erstellt.

Dort steht bei mir auch nur ein Semikolon, das Doppeln wird wegen Rawdefintion angezeigt.

Ich kann nur sagen, lt. Programmcode kann es nicht funktionieren, ab heute dann wieder ;)
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Reinschki am 04 Oktober 2020, 12:50:06
Hallo,

das hat vorher funktioniert:
  sub SatDown {     
    my ($delta)=@_;
my $Val = get_Reading("sat") - $delta;
    fhem_set("deCONZ_HUEDevice13 sat $Val");
    if (get_Reading("sat") - $delta > 0) {
set_Exec("worktimer",1,"SatDown",$delta);
set_State("satDown $delta");
} else {
IdleState();
}


nach der Umstellung auf die neue Parameterübergabe von set_Exec funktioniert es nicht mehr:
  sub SatDown {     
    my ($delta)=@_;
my $Val = get_Reading("sat") - $delta;
    fhem_set("HUEGroup1 sat $Val");
    if (get_Reading("sat") - $delta > 0) {
set_Exec("worktimer",1,'SatDown($delta)');
set_Reading("command", $delta);
} else {
IdleState();
}


error
in SatDown($delta): Global symbol "$delta" requires explicit package name (did you forget to declare "my $delta"?) at (eval 19231178) line 1.

Wie kann ich die Parameterübergabe beim rekursiven Aufruf der doif-sub lösen?

Viele Grüße
Reiner
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 04 Oktober 2020, 13:04:25
so wird der Aufruf funktionieren:

set_Exec("worktimer",1,"SatDown($delta)")

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: obi am 08 Oktober 2020, 15:47:39
Hallo,

ich habe das gleiche Problem, dass seit der Änderung der Parameterübergabe der rekursive Aufruf nicht funktioniert.
Habe alle erdenklichen variationen mal durchprobiert.

set_Exec("worktimer",1,"volume($type)"); -> Bareword "Down" not allowed while "strict subs" in use
set_Exec("worktimer",1,'volume("$type")'); -> Global symbol "$type" requires explicit package name (did you forget to declare "my $type"?)
set_Exec("worktimer",1,'volume($type)'); -> Global symbol "$type" requires explicit package name (did you forget to declare "my $type"?)


Wie bekomme ich das Problem gelöst?

VG Sebastian
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 08 Oktober 2020, 16:00:22
Zitat von: obi am 08 Oktober 2020, 15:47:39
Hallo,

ich habe das gleiche Problem, dass seit der Änderung der Parameterübergabe der rekursive Aufruf nicht funktioniert.
Habe alle erdenklichen variationen mal durchprobiert.

set_Exec("worktimer",1,"volume($type)"); -> Bareword "Down" not allowed while "strict subs" in use
set_Exec("worktimer",1,'volume("$type")'); -> Global symbol "$type" requires explicit package name (did you forget to declare "my $type"?)
set_Exec("worktimer",1,'volume($type)'); -> Global symbol "$type" requires explicit package name (did you forget to declare "my $type"?)


Wie bekomme ich das Problem gelöst?

VG Sebastian

Es kommt darauf auf, wie der Aufruf vorher aussah. Wo wird $type definiert?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: obi am 08 Oktober 2020, 16:10:57
Hi Damian,

danke für die schnelle Antwort.

$type wird innerhalb der Sub als Übergabaparameter definiert, eventuell mache ich ja hier schon einen Fehler.

Hier mal mein kompletten Code der Sub:
sub $SELF_volume
{
my ($type)=@_;
...
set_Exec('$SELF_volume', 1, '$SELF_volume($type)');
  }


Der 1. Aufruf sieht so aus in einem anderen teil des DOIF (Über einen externen Trigger mit IF)
set_Exec('$SELF_volume', 0, '$SELF_volume("Up")');
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 08 Oktober 2020, 16:37:28
Dann frage ich mich, wie du es vor der Umstellung aufgerufen hast.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: obi am 08 Oktober 2020, 18:03:06
So hatte es vor der Umstellung fehlerfrei funktioniert:

sub $SELF_volume
{
my ($type)=@_;
...
set_Exec('$SELF_volume', 1, '$SELF_volume', $type);
  }


set_Exec('$SELF_volume', 0, '$SELF_volume', 'Up');
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 08 Oktober 2020, 18:06:26
Zitat von: obi am 08 Oktober 2020, 18:03:06
So hatte es vor der Umstellung fehlerfrei funktioniert:

sub $SELF_volume
{
my ($type)=@_;
...
set_Exec('$SELF_volume', 1, '$SELF_volume', $type);
  }


set_Exec('$SELF_volume', 0, '$SELF_volume', 'Up');

dann:

sub $SELF_volume
{
my ($type)=@_;
...
set_Exec('$SELF_volume', 1, "$SELF_volume('$type')");
  }


set_Exec('$SELF_volume', 0, "$SELF_volume('Up')";
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Per am 14 Januar 2021, 16:24:57
Um Lang- und Doppelclick bei meinen EnOcean-Tastern abzufragen, nutzte ich wegen der Timer jeweils ein klassisches DOIF. Ich wollte auf Templates umstellen, hat aber nicht funktioniert. Es gab keine Fehlermeldung, aber auch keine Aktion. Aber egal.
Dann habe ich mal bei Null angefangen und herausgekommen ist ein kleiner Mehrzeiler in Perl-DOIF (mein erster eigener), wahrscheinlich sogar, inkl. Attr., mit weniger Code pro DOIF als vorher. Und natürlich nur eine DOIF statt dutzender.
define EnO_T_DOIF DOIF {\
if (["EnO_T_.*:buttons: released"]) {del_Exec('$DEVICE');;fhem('setreading $DEVICE pressed off');;} ##off\
if (["EnO_T_.*:buttons: pressed"]){\
if ([?$DEVICE:pressed:sec] < 2) {fhem('setreading $DEVICE pressed double');;} ## Double\
else {fhem('setreading $DEVICE pressed on');;set_Exec('$DEVICE',1,'fhem("setreading $DEVICE pressed long")')} ## short,long\
}\
}


Das einzige verbleibende Attribut bei mir ist der Raum.
Timer werden automatisch gesetzt/gelöscht, Events werden nicht erstellt (außer bei dem jeweiligen Tastern. Das benötigte Reading wird automatisch erzeugt. Neue Taster müssen nicht eingepflegt werden, was bei Templates notwendig wäre.

Einzige Voraussetzung ist der passende Namensraum (EnOcean-Taster -> EnO_T_xxx). Könnte man über eine Typ-Anfrage noch absichern, ist bei mir aber nicht notwendig.

PS: trotzdem werde ich nicht pauschal auf Perl-DOIF umsteigen ;)
PPS: wäre es sinnvoll, neben fhem_set auch ein fhem_setreading bereitzustellen?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: hackepeter am 14 April 2021, 16:51:12
Hallo Damin :)

kurze Frage: ich habe ein Doif im PerlModus, welches auf viele Devices reagiert...
Gibt es eine elegante Möglichkeit, mehrfachtriggern zu verhindern, wenn die entsprechenden devices das reading neu setzen, sich dieses aber nicht verändert?

{if (["Event:on"]){
  my $TriggerdeviceNr = substr($device, -4);;
  my $AckType;;
  my $ReceiverNr;;
........


Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 14 April 2021, 17:04:38
Zitat von: hackepeter am 14 April 2021, 16:51:12
Hallo Damin :)

kurze Frage: ich habe ein Doif im PerlModus, welches auf viele Devices reagiert...
Gibt es eine elegante Möglichkeit, mehrfachtriggern zu verhindern, wenn die entsprechenden devices das reading neu setzen, sich dieses aber nicht verändert?
    U     "DB_Supplement_SEQ001".SupDB.Message[3]
      U     "DB_Meldungen".HM_FP[3]."1"
      =     "DB_Meldungen".Speicher_Meldungen_SEQ[1]."3"
........


Was ist das für eine Syntax? Das sagt mir nichts.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: hackepeter am 15 April 2021, 07:04:25
Moin Moin,

sorry, da hatte ich das falsche im Clipboard. Habe es geändert.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 15 April 2021, 10:23:53
Also, Events eines Devices, die innerhalb eines EventBlocks kommen, triggern ohnehin nur einmal.

Man kann in DOIF-Perl mit Instanzvariablen arbeiten, man kann dort Sachen ablegen, die man beim nächsten Mal abfragen kann, z. B.

if ($_device ne $device) {
  $_device=$device;
  mein Code ...
}


Beim sendenden Device kann man event_on_change_reading-Attribut setzen, damit bleiben Events mit gleichem Inhalt schon mal aus.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: PSI69 am 27 April 2021, 14:48:51
Mahlzeit!

Ich bin mir bewußt - das folgende ist kein DOIF Problem, sondern Perl generell und meinem Unverständnis geschuldet...

Ich habe in einem DOIF im Perl Mode folgende Funktion:

  sub $SELF_KalenderEvents {
    my $iCalEvents = "";

    ## Events für Heute besorgen
    $iCalEvents = fhem("get Kalender.iCloud events limit:when=today");

    if(length($iCalEvents) != 0){
      ## Auf *ferien oder Feiertag prüfen
      if(($iCalEvents =~ ".*ferien.*") || ($iCalEvents =~ ".*Feiertag.*") || ($iCalEvents =~ ".*Urlaub.*")){
        $SELF_DebugMessage("setze Dummy 'Jalousien.Ferien' auf 'on'");
        fhem_set"Jalousien.Ferien on";
      }
      else{
        $SELF_DebugMessage("Termine '$iCalEvents' enthalten kein Schlüsselwort");
      }
    }
  }


So lange der 'fhem("get...' - Aufruf Daten zurück liefert, klappt alles super. Werden allerdings keine Kalendereinträge gefunden, erfolgt folgende Fehlermeldung (Warnung):
2021.04.27 09:28:24 1: PERL WARNING: Use of uninitialized value $iCalEvents in numeric ne (!=) at (eval 2599711) line 18.
2021.04.27 09:28:24 3: eval: di_p_Jalousien_Ferien: warning in condition c03


Also, die Prüfung der Variable auf Inhalt mittels 'if(length($iCalEvents) != 0)' bringt mir die Warnung; hm.

Kommentiere ich '$iCalEvents = fhem("get Kalender.iCloud events limit:when=today");' komplett aus, entfällt die Warnung, denn die Variable ist ja mit 'my $iCalEvents = "";' initialisiert. Irgend etwas 'macht' also der 'fhem("get...' - Aufruf bei leeren Daten damit.

Nun zur Frage des Tages: Wie fange ich das 'nicht Zurückgeben' von Kalenderdaten sauber (ohne Warnung im Logfile) ab?
Bin dankbar für jeden Hinweis...

Peter
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 27 April 2021, 16:21:17
ganz einfach:

if (defined $iCalEvents and length($iCalEvents) != 0){
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: PSI69 am 28 April 2021, 08:08:04
Zitat von: Damian am 27 April 2021, 16:21:17
ganz einfach:
... wenn man es weiß :) - ich ja jetzt auch :D.
Danke Peter
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 09 Februar 2022, 18:09:27
Neue Version wurde eingecheckt.

Ich habe im Perlmodus die Option eingebaut, dass man mehrere init-Blöcke definieren kann. Ein init-Block wird automatisch beim Hochfahren des Systems ausgeführt oder unmittelbar nach der Definition eines DOIF-Devices. Damit lassen sich Templates erstellen, die alle einen eigenen init-Block brauchen.

D.h. wenn ein Block init heißt oder neuerdings mit init_ beginnt, so wird er wie ober beschrieben zusätzlich ausgeführt.

Hier ein Beispiel mit dem neuen Feature, wie man bei einem fortlaufenden Zähler, wie bei Strom, Wasser, Gas eine Tages-, Monats- und Jahresstatistik erstellen kann (die vorhanden Module zu dem Thema haben mir nicht zugesagt).


defmod di_counter DOIF DEF TPL_stat (midnight_$1_$2 { [00:01];;\
  set_Reading("$1_$2_counter",[?$1:$2]);;\
  set_Reading("$1_$2_last_day",get_Reading("$1_$2_day",0),1);;\
  set_Reading("$1_$2_day",0,1);;\
  set_Reading("$1_$2_month",get_Reading("$1_$2_month",0)+get_Reading("$1_$2_last_day",0),1);;\
  if ($mday == 1) {\
    set_Reading("$1_$2_last_month",get_Reading("$1_$2_month",0),1);;\
    set_Reading("$1_$2_month",0,1);;\
    set_Reading("$1_$2_year",get_Reading("$1_$2_year",0)+get_Reading("$1_$2_last_month",0),1);;\
  }\
  if ($yday == 1) {\
    set_Reading("$1_$2_last_year",get_Reading("$1_$2_year",0),1);;\
    set_Reading("$1_$2_year",0,1);;\
  }\
}\
\
day_count_$1_$2 {set_Reading ("$1_$2_day",int(([$1:$2,0]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;}\
\
init_$1_$2 {\
  set_Reading("$1_$2_counter",[?$1:$2]) if (!get_Reading("$1_$2_counter",""));;\
}\
\
)\
TPL_stat (Stromzaehler,total_c)\
TPL_stat (Stromzaehler,total_f)\
TPL_stat (CUL_WZ,total)



Ein Zähler wird einfach mit TPL_stat (<device>,<reading>) angegeben. Im obigen Beispiel wurden drei Zähler definiert.

Damit kann man Tages-, Monats- oder Jahres-Verbräuche loggen oder in card darstellen, siehe Anhang:

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: gestein am 16 Februar 2022, 00:31:29
Hallo Damian,

Danke für Dein Template für den Stromzähler.
Schön langsam verstehe ich wie das funktioniert.

Wann wird allerdings das Reading "$1_$2_day" gesetzt?
Ich weiß schon, in der Funktion ,,day_count_$1_$2".
Aber wer ruft die wann auf?

Danke, Lg, Gerhard
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 16 Februar 2022, 07:39:26
Zitat von: gestein am 16 Februar 2022, 00:31:29
Hallo Damian,

Danke für Dein Template für den Stromzähler.
Schön langsam verstehe ich wie das funktioniert.

Wann wird allerdings das Reading "$1_$2_day" gesetzt?
Ich weiß schon, in der Funktion ,,day_count_$1_$2".
Aber wer ruft die wann auf?

Danke, Lg, Gerhard

Zitatday_count_$1_$2 {set_Reading ("$1_$2_day",int(([$1:$2,0]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;}

Der Trigger ist also ein Event von $1=Device $2=Reading
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: gestein am 16 Februar 2022, 09:35:50
Verstehe. Danke. Ganz schön komplex ...

Diese Schreibweise wäre also die kürzere Version von:
day_count_$1_$2 { [$1:$2]
   set_Reading ("$1_$2_day",int(([?$1:$2]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;
}

Richtig?

Und wenn ich den Wert von "[?$1:$2]" in dieser Funktion mehrmals benötige, wie soll man dann am besten die Funktion schreiben?
z.B.:
day_count_$1_$2 { [$1:$2]
   set_Reading ("$1_$2_day",int(([?$1:$2]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;
   set_Reading ("was anderes mit [?$1:$2]");
}

oder besser so:
day_count_$1_$2 {
   set_Reading ("$1_$2_day",int(([$1:$2,0]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;
   set_Reading ("was anderes mit [?$1:$2]");
}


Danke für Deine Geduld.
lg, Gerhard
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 16 Februar 2022, 09:43:34
Zitat von: gestein am 16 Februar 2022, 09:35:50
Verstehe. Danke. Ganz schön komplex ...

Diese Schreibweise wäre also die kürzere Version von:
day_count_$1_$2 { [$1:$2]
   set_Reading ("$1_$2_day",int(([?$1:$2]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;
}

Richtig?
im Prinzip ja, da fehlt noch ein Semikolon hinter [$1:$2]. Da der Trigger überall im Block stehen kann, muss man den nicht gesondert angeben.
Zitat
Und wenn ich den Wert von "[?$1:$2]" in dieser Funktion mehrmals benötige, wie soll man dann am besten die Funktion schreiben?
z.B.:
day_count_$1_$2 { [$1:$2]
   set_Reading ("$1_$2_day",int(([?$1:$2]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;
   set_Reading ("was anderes mit [?$1:$2]");
}

oder besser so:
day_count_$1_$2 {
   set_Reading ("$1_$2_day",int(([$1:$2,0]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;
   set_Reading ("was anderes mit [?$1:$2]");
}

Das ist egal, DOIF erkennt, dass es sich um den gleichen Trigger handelt, deswegen wird der Block nur einmal getriggert, egal wie oft du [$1:$2] innerhalb eines Blocks angibst.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: gestein am 16 Februar 2022, 20:28:43
Danke, Damian.
So weit funktioniert das schon mal.
Ich hatte lange den Fehler gesucht, warum auf die Readings "energy" in den Shellys nicht im DOIF getriggert wird.
Ein "event-on-change" an der richtigen Stelle mit dem richtigen Wert hilft da ungemein ;)

Nun muss ich die Summen über Räume, Gruppen etc. machen.

Ist es eigentlich möglich eine Perl-Funktion ausserhalb des Templates zu definieren, die dann aus den Instanzen aufgerufen wird?
Diese Summen-Funktion soll ja nicht in jeder Instanz des Templates definiert sein.

Kann man eigentlich auf die Änderung eines Attributes des DOIF mit einem Funktionsaufruf reagieren?
Oder muss die Liste der zu bildenden Gruppen in einem Reading stehen?

Danke im Voraus
lg, Gerhard
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 16 Februar 2022, 20:49:33
Natürlich kannst du eine Perlfunktion in myUtils ablegen und diese aufrufen. Am besten davor noch package DOIF; angeben, damit sie direkt angegeben werden kann, sonst musst du :: vor die Funktion setzen, da sie sich sonst im package main befindet.

Du könntest für jede Gruppe ein DOIF erstellen und das gleiche Template per IMPORT-Befehl importieren.

Dann könntest du im Template die gleiche Aggregationsfunktion nutzen, die alle Readings des gleichen Typs wie last_day oder last_month addiert.

Das Reagieren auf Attributänderungen sollte über ein global-Event funktionieren. Musst du im Eventmonitor nachschauen, wenn sich ein Attribut ändert.

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: gestein am 16 Februar 2022, 21:40:44
Verstehe. Das sollte so klappen. Danke.

Prinzipiell wäre es aber auch möglich die Funktion im DOIF zu behalten und nicht ins 99_myUtils auszulagern.
Dann müsste ich sie in den uiTable-Teil geben. Oder?
Irgendwie habe ich gerne alles beisammen.

Kann man die Funktion dann aus den Instanzen der Templates heraus aufrufen?

Lg, Gerhard
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 16 Februar 2022, 21:55:59
Zitat von: gestein am 16 Februar 2022, 21:40:44
Verstehe. Das sollte so klappen. Danke.

Prinzipiell wäre es aber auch möglich die Funktion im DOIF zu behalten und nicht ins 99_myUtils auszulagern.
Dann müsste ich sie in den uiTable-Teil geben. Oder?
Irgendwie habe ich gerne alles beisammen.

Kann man die Funktion dann aus den Instanzen der Templates heraus aufrufen?

Lg, Gerhard

Eigene Funktionen im Block subs befinden sich im package DOIF und müssten in uiTable mit DOIF:: beginnen. Allerdings nutzen alle DOIF-Devices das gleiche package DOIF.

Wenn es um die Summation geht. Dafür reicht ja eine Zeile, wie ich sie dir bereits über die Aggregation aufgezeigt habe, dafür braucht man keine Funktion zu definieren.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 16 Februar 2022, 22:14:09
So könnte das Codeschnipsel um einen sum-Block erweitert werden, der nach Mitternacht entsprechende Readings des DOIF-Devices zusammenaddiert.

defmod di_zaehler DOIF DEF TPL_stat (midnight_$1_$2 { [00:01];;\
  set_Reading("$1_$2_counter",[?$1:$2]);;\
  set_Reading("$1_$2_last_day",get_Reading("$1_$2_day",0),1);;\
  set_Reading("$1_$2_day",0,1);;\
  set_Reading("$1_$2_month",get_Reading("$1_$2_month",0)+get_Reading("$1_$2_last_day",0),1);;\
  \
  if ($mday == 1) {\
    set_Reading("$1_$2_last_month",get_Reading("$1_$2_month",0),1);;\
    set_Reading("$1_$2_month",0,1);;\
    set_Reading("$1_$2_year",get_Reading("$1_$2_year",0)+get_Reading("$1_$2_last_month",0),1);;\
  }\
  if ($yday == 1) {\
    set_Reading("$1_$2_last_year",get_Reading("$1_$2_year",0),1);;\
    set_Reading("$1_$2_year",0,1);;\
  }\
}\
\
day_count_$1_$2 {set_Reading ("$1_$2_day",int(([$1:$2,0]-get_Reading("$1_$2_counter",0))*1000)/1000,1);;}\
\
init_$1_$2 {\
  set_Reading("$1_$2_counter",[?$1:$2]) if (!get_Reading("$1_$2_counter",""));;\
  #set_Reading ("$1_$2_day",0);;\
  #set_Reading ("$1_$2_last_day",0);;\
  #set_Reading ("$1_$2_last_month",0);;\
  #set_Reading ("$1_$2_last_year",0);;\
}\
)\
\
sum {[00:02];;set_Reading("last_day_sum",[?#sum:"^$SELF$":"last_day$"],1);;\
  if ($mday == 1) {\
    set_Reading("last_month_sum",[?#sum:"^$SELF$":"last_month$"],1);;\
  }\
  if ($yday == 1) {\
    set_Reading("last_year_sum",[?#sum:"^$SELF$":"last_year$"],1);;\
  }\
}\
TPL_stat (test,state)\
TPL_stat (test,r1)\
TPL_stat (test,r2)
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: gestein am 16 Februar 2022, 22:17:44
Das wollte ich gerade fragen.
Wie immer bist Du schnell, diesmal sogar die Antwort bevor ich die Frage stellen konnte  ;)

Lg, Gerhard
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 18 Februar 2022, 18:28:47
neuer Eintrag im Wiki zur Statistik: https://wiki.fhem.de/wiki/DOIF/Automatisierung#Tages-.2C_Monats-_und_Jahresstatistik_f.C3.BCr_Strom-.2C_Gas-.2C_Wasserz.C3.A4hler_und_andere_Z.C3.A4hler
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 20 Februar 2022, 10:25:20
Neue Version wurde eingecheckt: Nun werden die gesammelten Daten für card nicht gelöscht, wenn man die Definition per defmod ändert. So kann die Definition erweitert werden, ohne dass Datenverläufe in bestehenden cards verloren gehen.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 01 März 2022, 13:19:26
Energie wird nun teuer, da lohnt sich eine Analyse des eigenen Verbrauchs.

Der Wikieintrag zu dem Thema wurde aktualisiert:

https://wiki.fhem.de/wiki/DOIF/Automatisierung#Tages-.2C_Monats-_und_Jahresstatistik_f.C3.BCr_Strom-.2C_Gas-.2C_Wasserz.C3.A4hler_und_andere_Z.C3.A4hler
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 07 März 2022, 16:29:03
Zitat von: Damian am 01 März 2022, 13:19:26
Energie wird nun teuer, da lohnt sich eine Analyse des eigenen Verbrauchs.

Der Wikieintrag zu dem Thema wurde aktualisiert:

https://wiki.fhem.de/wiki/DOIF/Automatisierung#Tages-.2C_Monats-_und_Jahresstatistik_f.C3.BCr_Strom-.2C_Gas-.2C_Wasserz.C3.A4hler_und_andere_Z.C3.A4hler

Ich habe den Code weiter verfeinert.
Dieser funktioniert nun auch, wenn der Zähler seinen aktuellen Zählerstand verliert, wie z. B. beim ESP8266.
Es werden jetzt zusätzlich automatisch Logs für Tages-, Monats- und Jahresverbräuche erzeugt.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: spi3845 am 10 März 2022, 11:50:48
Hallo,

kann man inzwischen eine Perl-Variable innerhalb von [] verwenden?

Also etwas der Art:
defmod di_text DOIF {
my $geraet="sensor123";;

if ([$geraet:gesperrt,1] eq 0) {
Log 1, "es geht";;
}

}


Danke schon mal!

Noch ein Nachtrag:

wie halte ich es dann mit z. B.
set_Exec("timer", 30, 'fhem("setreading $geraet gesperrt 0")');;

Muss ich hier dann $_geraet statt $geraet deklarieren und nutzen?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 10 März 2022, 14:27:51
Zitat von: spi3845 am 10 März 2022, 11:50:48
Hallo,

kann man inzwischen eine Perl-Variable innerhalb von [] verwenden?

Also etwas der Art:
defmod di_text DOIF {
my $geraet="sensor123";;

if ([$geraet:gesperrt,1] eq 0) {
Log 1, "es geht";;
}

}


Danke schon mal!

Noch ein Nachtrag:

wie halte ich es dann mit z. B.
set_Exec("timer", 30, 'fhem("setreading $geraet gesperrt 0")');;

Muss ich hier dann $_geraet statt $geraet deklarieren und nutzen?

Man kann keine Variablen als Triggerinformation nutzen.

statt

'fhem("setreading $geraet gesperrt 0")'

definierten:

"fhem('setreading $geraet gesperrt 0')"

damit $geraet vor der Ausführung ausgewertet wird und nicht erst danach - das ist eine Perleigenschaft.

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: spi3845 am 10 März 2022, 15:24:27
Zitat von: Damian am 10 März 2022, 14:27:51
Man kann keine Variablen als Triggerinformation nutzen.
Ja, das hatte ich irgendwo schon gesehen und es hat auch nicht geklappt. Hatte gehofft, es gibt inzwischen einen Workaround. Danke aber für die Info!

Zitat von: Damian am 10 März 2022, 14:27:51
statt

'fhem("setreading $geraet gesperrt 0")'

definierten:

"fhem('setreading $geraet gesperrt 0')"

damit $geraet vor der Ausführung ausgewertet wird und nicht erst danach - das ist eine Perleigenschaft.

Danke! Der Teufel steckt im Detail. Es könnte so einfach sein, wenn es nur eine Art von Klammern und Anführunsgzeichen gäbe  8)

Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: jkriegl am 01 Februar 2023, 21:02:24
Nutze den di_counter, möchte aber gerne den Timer auf vor Mitternacht ändern.
Dazu muss in midnight_.* if ($mday==1) geändert werden.
Den Ultimo+1, also ist der nächste Tag der erste?, bekomme ich mit
defmod next_day DOIF ([20:10:30] ) (setReading test_ultimo day {(strftime('%e', localtime+86400))})
Mir gelingt es nicht die obige if-Abfrage durch das Ermitteln des ultimo+1 ($mday) im TPL zu ersetzen.
   if ((strftime("%e", localtime+86400)==1)) {
     set_Reading ("$3_last_month", get_Reading("$3_month",0),1);
     set_Reading ("$3_month",0,1);
   }
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 02 Februar 2023, 15:23:05
Du könntest den Aufruf so anpassen:

Zitatmid {[23:59];;                          ## Sicherung der Daten um Mitternacht\
  for (my $i=0;;$i<@{$_counter};;$i++) { ## Für jeden Zähler wird die Funktion midnight aufgerufen\
    midnight($_counter[$i][0],$_counter[$i][1],strftime("%e", localtime+120,strftime("%Y", localtime+120);;\
  }\
}\
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: jkriegl am 02 Februar 2023, 17:30:03
Vielen Dank.
Das obige next_day DOIF funktioniert sowieso nicht.
Ermittle über ein at, ob es sich um den Ultimo handelt und schreibe das Ergebnis in ein Reading, das ich im TPL_counter abfrage.
Übrigens gibt es ein at_ultimo at.
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: twinFHEM am 10 März 2023, 10:41:32
Hallo zusammen,

ich habe folgenden Perl-Code in einem DOIF:

defmod DI_countdowndVerbrauchTempGes DOIF {if (([savergy_actions:timerdVerbrauchTempGes] > 0) and ([+00:00:05] and [?savergy_actions:timerdVerbrauchTempGes:sec] < 5)) {\
my $c=ReadingsVal("savergy_actions","counterMeldungen",0) + 1;fhem("setreading savergy_actions counterMeldungen $c");\
my $min=ReadingsVal("savergy_actions","timerdVerbrauchTempGes",0) * 60;\
my $diffNow=ReadingsVal("savergy_actions","dVerbrauchTempDiff",0);\
\
set_Exec("TimerLog".$c,$min,'fhem{Log 1, "Timer".$c." zuende!"}');\
set_Exec("Timer".$c,$min,'fhem("setreading savergy_actions dVerbrauchTempDiff ".ReadingsVal("savergy_actions","dVerbrauchTempGes",0) - $diffNow."")');\
}}\


Mit my werden 3 lokale Variablen deklariert. Nach Ablauf des internen Timer, gestartet mit set_Exec, bekomme ich folgende Fehlermeldungen:

1:DI_countdowndVerbrauchTempGes error in fhem{Log 1, "Timer".$c." zuende!"}: Global symbol "$c" requires explicit package name (did you forget to declare "my $c"?) at (eval 18257) line 1.

1:DI_countdowndVerbrauchTempGes error in fhem("setreading savergy_actions dVerbrauchTempDiff ".ReadingsVal("savergy_actions","dVerbrauchTempGes",0) - $diffNow.""): Global symbol "$diffNow" requires explicit package name (did you forget to declare "my $diffNow"?) at (eval 18258) line 1.


Allerdings habe ich sie doch deklariert!? Und für $min taucht keine Fehlermeldung auf.
Kann mir das einer erklären?

Ich hatte noch die Vermutung, dass es an den Anführungszeichen liegt und habe es probiert mit

set_Exec("TimerLog".$c,$min,"fhem{Log 1, 'Timer'.$c.' zuende!'}");


Hier bekomme ich dann folgende Meldung:

1:PERL WARNING: String found where operator expected at (eval 19115) line 1, near "27.' zuende!'"
1:PERL WARNING: (Missing operator before ' zuende!'?)
1:DI_countdowndVerbrauchTempGes error in fhem{Log 1, 'Timer'.27.' zuende!'}: syntax error at (eval 19115) line 1, near "27.' zuende!'"


Ich taste mich gerade an den Umgang mit Perl-Code in FHEM heran.
Ab wann macht es eurer Meinung nach Sinn, den Code in eine bzw. die 99_myUtils auszulagern?
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 10 März 2023, 11:30:38
Das ist ganz einfach, wenn man die Eigenschaften und Tücken von Perl kennt.

Mit

'fhem{Log 1, "Timer".$c." zuende!"}'

übergibst du den Code mit $c an set_Exec. In set_Exec ist aber $c nicht bekannt.

mit

"fhem{Log 1, 'Timer $c zuende!'}"

wird dagegen $c aufgelöst bevor es an set_Exec übergeben wird, daher wird das funktionieren :)
Titel: Antw:neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: twinFHEM am 13 März 2023, 11:48:01
Danke Damian, passt natürlich! :)

Eigenwilliges Feature von PERL...
Aber ich glaube, wir werden Freunde... :D

Übrigens; ein sehr geiles Modul!!!
Titel: Aw: neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: tobelix am 29 Juni 2023, 17:10:11
Zitat von: Damian am 11 Juni 2020, 09:50:48Längere Definitionen würde ich in eine externe Datei auslagern (myutils-sonstwas, mit package DOIF), die man mit einem vernünftigen Programm-Editor bearbeiten kann.


Hi Damian, hättest du hierzu vielleicht zwei Code Snippets was im DOIF angegeben werden muss und wie es in der myutils Datei stehen muss damit der Codeblock entsprechend aufgerufen wird?
Titel: Aw: neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 30 Juni 2023, 14:41:55
in myUtils:

package DOIF;

sub bla {
...
}

in DOIF z. B. um 8:00 Uhr bla-Routine aus myUtils aufrufen

DOIF {[08:00];bla (...)}


Titel: Aw: neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: tobelix am 30 Juni 2023, 16:06:34
Danke. Wie kann ich das Debuggen?

Im DOIF wird zwar angezeigt "block_01 excecuted". Aber es passiert nichts.
verbose auf 5 setzen im DOIF führt auch nicht dazu, dass im Log eine Fehlermeldung eingetragen wird.
Titel: Aw: neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 30 Juni 2023, 19:55:18
Debuggen in FHEM ist schwierig.

Wenn die Routine nicht gefunden wird, dann gibt es eine Fehlermeldung im Reading  block_01

Ich habe es ohne Probleme bei mir getestet:

In 99_myUtils.pm über Edit-Files eingegeben:

###############################################################################
  #
  #  Consume a string with lines like: Timestamp: value
  #  return HTML to show the history visually
  #
  ###############################################################################
package DOIF;

sub doif_test {

set_State("30");

}

package main; 

...

und in DOIF

defmod doif_extern DOIF {doif_test()}
Der Status wird durch Ausführen von block_01 auf 30 gesetzt.
Titel: Aw: neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: RalfRog am 09 Juli 2023, 15:59:44
Hallo
Ich habe mal "aus dem Kopf" ein OldReadingsAge im DOIF eingebaut. Das läuft natürlich auf Fehler - kein Wunder, ist ja in der Doku zu finden:
Folgende FHEM-Perlfunktionen wurden ebenfalls im DOIF-Namensraum definiert, sie können, wie gewohnt ohne Doppelpunkt genutzt werden:

fhem, Log, Log3, InternVal, InternalNum, OldReadingsVal, OldReadingsNum, OldReadingsTimestamp, ReadingsVal, ReadingsNum, ReadingsTimestamp, ReadingsAge, Value, OldValue, OldTimestamp, AttrVal, AttrNum

Hier war es auch schon im Beitrag #84 erwähnt.

Über ::OldReadingsAge kann man es sicher im Namensraum main ausführen - muss ich noch probieren.

 ;)  Gibt es einen speziellen Grund, dass es nicht im DOIF-Namensraum definiert wurde?

GRuß Ralf
Titel: Aw: neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 09 Juli 2023, 16:22:39
Zitat von: RalfRog am 09 Juli 2023, 15:59:44Gibt es einen speziellen Grund, dass es nicht im DOIF-Namensraum definiert wurde?

War vermutlich damals in der WIKI-Liste der FHEM-Funktionen, wo ich nachgeschaut habe, nicht drin. Die Funktion kann ich aber beim nächsten Update aufnehmen.
Titel: Aw: neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: RalfRog am 09 Juli 2023, 16:26:47
Zitat von: Damian am 09 Juli 2023, 16:22:39War vermutlich damals in der WIKI-Liste der FHEM-Funktionen, wo ich nachgeschaut habe, nicht drin. Die Funktion kann ich aber beim nächsten Update aufnehmen.

::OldReadingsAge  funktioniert  :D
Eilt nicht spiele ein wenig rum. War mit nur aufgefallen und es wäre konsistent. Irgendwo las ich auch was von Performance.


Aber danke für die Ergänzung beim nächsten Update.

Schönen Restsonntag Ralf
Titel: Aw: neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: Damian am 10 Juli 2023, 11:43:52
Neue Version mit OldReadingsAge im DOIF-Package wurde eingecheckt.
Titel: Aw: neue Features: ereignisgesteuertes Perl - DOIF-Perl
Beitrag von: RalfRog am 11 Juli 2023, 12:11:03
Klappt und keine spontanen Nebenwirkungen.
Danke und Gruß Ralf