FHEM Forum

FHEM => Automatisierung => DOIF => Thema gestartet von: FHEMAN am 14 Dezember 2020, 21:08:47

Titel: Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: FHEMAN am 14 Dezember 2020, 21:08:47
Hallo,

keine Frage, DOIF ist mega. Und irgendwie denke ich jedes Mal, ich kann alles damit lösen, und meist fehlen am Ende ein paar Prozent zu meinem Glück...
was sicherlich an mein Unvermögen liegt ::)
Daher ohne viel Umschweife mal gefragt, wie kann ich das folgende Konstrukt elegant lösen
([TFK.Schuppeneingang.Sw.Dummy] eq "closed" and ([Alarmanlage] eq "on" or ([TFK.Eingang.Sw.04.Verschluss] eq "closed" and [TFK.Nebeneingang.Sw.04.Verschluss] eq "closed") or [TFK.Schuppeneingang.Sw.Dummy:state:sec]>3600 or ([isTwilight] eq "on" and [TFK.Schuppeneingang.Sw.Dummy:state:sec]>600))) (
{
fhem("set Keymatic.Schuppentuer:FILTER=r:lock!=locked lock")
}
)

Ich habe gelernt, anstelle von :sec muss ich wait nutzen, da :sec nicht selbst triggert. Allerdings habe ich dann 3-4 CMDs mit ein und demselben Ergebnis. In diesem Fall ist die Pflege der einen Zeile im Ausführungsteil kein Problem. Bei anderen, komplexeren DOIFs jedoch schon.
Geht es daher irgendwie besser / eleganter?
Kann ich z.B. eine Art globale Funktion über allen CMDs definieren, die ich innerhalb der CMDs aufrufe und bei der ich alle DOIF Vorteile nutzen kann?

Danke für ein wenig Input...
Ronny
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: Damian am 14 Dezember 2020, 22:45:48
Im DOIF FHEM-Modus kannst du eigene Perl-Routinen aufrufen, es gibt aber keine globalen DOIF-Attribute

Im DOIF-Perlmodus kannst du dagegen mit Templates arbeiten, damit kann man gleiche Abläufe mehrfach verwenden:

https://wiki.fhem.de/wiki/DOIF/Templates

das kann man bis zu Szenarien mit WEB-GUI ausbauen:

https://wiki.fhem.de/wiki/DOIF/Automatisierung
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: FHEMAN am 15 Dezember 2020, 12:56:45
Danke für den Hint, das sieht schon vielversprechend aus. Und direkt kommen mir Fragen bei der Umsetzung:
Kann ich bei Template Bedingungen auch verschiedene "wait" Zeiträume hinterlegen?
Die Syntax aus dem Beispiel Zimmertemperaturen: {$1;;   ## Zeitangabe\ erschließt sich mir nicht - warum muss hier eine geschweifte Klammer vorangestellt sein und nicht eine einfache?
So recht kriege ich mein Konstrukt oben nicht in ein Template überführt. Mal vereinfacht, wie setze ich hier folgende Bedingung:
([Tuer] eq "closed" and [Alarmanlage] eq "on" and [Tuer:state:sec]>3600)
Hier bringt ja ein pauschales wait nichts, da nach Aktivieren der Alarmanlage nicht 1h gewartet werden soll.

PS: Bietest du auch doif-Intensivkurse an? ;)
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: Damian am 15 Dezember 2020, 14:14:36
Die Vorgehensweise ist folgende:

1) Zuerst ein FHEM-DOIF in gleichwertiges Perl-DOIF übersetzen
2) Im zweiten Schritt variable Stellen durch Platzhalter ($1, $2 usw) ersetzen und ein Template definieren.
3) Template für verschiedene Devices (Szenarien) aufrufen

Als variable Stelle könnte z. B. hier das Device gelten:

([$1] eq "closed" and [Alarmanlage] eq "on" and [$1:state:sec]>3600)




Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: FHEMAN am 15 Dezember 2020, 16:13:39
Ich dachte, ich wäre schon bei Punkt 2. Deswegen verstehe ich noch nicht, wie aus DOIF ([05:00|8])() auf einmal DOIF DEF TPL ({[05:00|8]}) wird. Der Perlmodus erwartet doch {} in Kombination von "if" bei den Bedingungstriggern, oder nicht? (Und den Platzhalter sehe ich einfach als String-Ersetzungstext) Na ich durchwühle wohl nochmal die umfangreiche Doku..
//Edit: In der Doku habe ich nun entdeckt, dass ich bestimmte Trigger ohne "if" mit ";" getrennt angeben kann.

ZitatAls variable Stelle könnte z. B. hier das Device gelten:

([$1] eq "closed" and [Alarmanlage] eq "on" and [$1:state:sec]>3600)

Aber dann triggert das CMD doch niemals nach der definierten Zeit?
Und unterschiedliche waits kann ich nicht nutzen bei den verschiedenen Platzhalten?

Ich will das gerne als DOIF umsetzen, brauche aber noch einige Schubse bitte..
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: Damian am 15 Dezember 2020, 17:34:59
Zitat von: FHEMAN am 15 Dezember 2020, 16:13:39
Ich dachte, ich wäre schon bei Punkt 2. Deswegen verstehe ich noch nicht, wie aus DOIF ([05:00|8])() auf einmal DOIF DEF TPL ({[05:00|8]}) wird. Der Perlmodus erwartet doch {} in Kombination von "if" bei den Bedingungstriggern, oder nicht? (Und den Platzhalter sehe ich einfach als String-Ersetzungstext) Na ich durchwühle wohl nochmal die umfangreiche Doku..
//Edit: In der Doku habe ich nun entdeckt, dass ich bestimmte Trigger ohne "if" mit ";" getrennt angeben kann.

Aber dann triggert das CMD doch niemals nach der definierten Zeit?
Und unterschiedliche waits kann ich nicht nutzen bei den verschiedenen Platzhalten?

Ich will das gerne als DOIF umsetzen, brauche aber noch einige Schubse bitte..

Es triggert auch sonst nicht nach einer bestimmten Zeit. Mit sec wird nur das Alter des Readings abgefragt.

DOIF im Perlmodus arbeitet weitgehend ohne Attribute, wait wird dort mit sec_Exec realisiert: https://fhem.de/commandref_DE.html#DOIF_set_Exec

Dort kann man ebenso mit Platzhaltern arbeiten, die verschiedene Verzögerungen darstellen.
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: FHEMAN am 16 Dezember 2020, 13:10:53
Danke für den Hinweis zu set_Exec. Immer, wenn ich mit DOIF aufgeben möchte, kommt eine Lösung zum Vorschein. Ich habe den Aufruf oben jetzt folgendermaßen gelöst:

([TFK.Schuppeneingang.Sw.Dummy] eq "closed" and ([Alarmanlage] eq "on" or ["isTwilight"] or ([TFK.Eingang.Sw.04.Verschluss] eq "closed" and [TFK.Nebeneingang.Sw.04.Verschluss] eq "closed"))) (
{
my $timer = 0;
if ("[Alarmanlage]" ne "on") {
$timer = ("[isTwilight]" eq "on") ? "600" : "3600";
}
set_Exec("timer",$timer,'fhem("set Keymatic.Schuppentuer:FILTER=r:lock!=locked lock")','ReadingsVal("TFK.Schuppeneingang.Sw.Dummy","state","open") eq "closed"')

}

Sollte eine der Bedingungen im unwahr werden, wird der Timer gecancelt, richtig?
isTwilight nutze ich als Eventtrigger. Ich bin gespannt, ob es klappt heute Abend.
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: Damian am 16 Dezember 2020, 15:01:18
("[Alarmanlage]" ne "on") wird nicht funktionieren

dann schon eher:

([Alarmanlage] ne "on")

Alarmanlage wirkt dann aber triggernd

daher eher:

([?Alarmanlage] ne "on")


Am besten, wenn es nicht triggern soll, gleich mit

(ReadingsVal("Alarmanlage","state","") ne "on")

abfragen.

Das Gleiche gilt für "isTwilight"
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: FHEMAN am 16 Dezember 2020, 19:38:09
Zitat von: Damian am 16 Dezember 2020, 15:01:18
("[Alarmanlage]" ne "on") wird nicht funktionieren
Ich habe das bisher verwendet, um ungültige Stringvergleiche zu vermeiden. Manchmal war die Variable laut Log leer (nicht ""). Aber er betrachtet alles in "" wohl als Regex.

del_Exec kann und muss ich nicht in DOELSE() aufrufen?
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: Damian am 16 Dezember 2020, 21:03:08
Zitat von: FHEMAN am 16 Dezember 2020, 19:38:09
Ich habe das bisher verwendet, um ungültige Stringvergleiche zu vermeiden. Manchmal war die Variable laut Log leer (nicht ""). Aber er betrachtet alles in "" wohl als Regex.

del_Exec kann und muss ich nicht in DOELSE() aufrufen?

del_Exec kannst du nicht in DOELSE () aufrufen, weil im Perlmodus kein DOELSE existiert ;)
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: FHEMAN am 21 Dezember 2020, 16:49:53
Zitat von: FHEMAN am 16 Dezember 2020, 13:10:53

([TFK.Schuppeneingang.Sw.Dummy] eq "closed" and ([Alarmanlage] eq "on" or ["isTwilight"] or ([TFK.Eingang.Sw.04.Verschluss] eq "closed" and [TFK.Nebeneingang.Sw.04.Verschluss] eq "closed"))) (
{
my $timer = 0;
if ("[Alarmanlage]" ne "on") {
$timer = ("[isTwilight]" eq "on") ? "600" : "3600";
}
set_Exec("timer",$timer,'fhem("set Keymatic.Schuppentuer:FILTER=r:lock!=locked lock")','ReadingsVal("TFK.Schuppeneingang.Sw.Dummy","state","open") eq "closed"')

}
)


Mit dieser Konstruktion gibt es den Perl Fehler, dass set_Exec unbekannt ist.
Ich vermute, es liegt daran, dass der Bedingungsteil noch in DOIF Notation ist? Was ich gerne so beibehalten würde. Aber wie muss ich die () dann richtig setzen?
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: Damian am 21 Dezember 2020, 16:57:06
Zitat von: FHEMAN am 21 Dezember 2020, 16:49:53
Mit dieser Konstruktion gibt es den Perl Fehler, dass set_Exec unbekannt ist.
Ich vermute, es liegt daran, dass der Bedingungsteil noch in DOIF Notation ist? Was ich gerne so beibehalten würde. Aber wie muss ich die () dann richtig setzen?

klar, das ist ein DOIF im FHEM-Modus und nicht im Perl-Modus, nur dort funktioniert set_Exec. Siehe https://fhem.de/commandref_DE.html#DOIF_Perl_Modus

Der Perl-Modus fängt nicht mit ( an.
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: FHEMAN am 21 Dezember 2020, 17:34:51
Boah, habe es nun umgebaut.. fühlt sich nun alles ganz anders an.. keine checkall etc. Funktionen mehr. DOELSE() ist dann sicherlich auch überflüssig geworden, oder gibt es ein else {{}}?
Wenigstens ist jetzt das eigentlich verwirrende Wort DOELSE weg ;)
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: Damian am 21 Dezember 2020, 17:37:34
Zitat von: FHEMAN am 21 Dezember 2020, 17:34:51
Boah, habe es nun umgebaut.. fühlt sich nun alles ganz anders an.. keine checkall etc. Funktionen mehr. DOELSE() ist dann sicherlich auch überflüssig geworden, oder gibt es ein else {{}}?
Wenigstens ist jetzt das eigentlich verwirrende Wort DOELSE weg ;)

Es gibt alles, was es in Perl gibt, insb. else, elsif usw. und so gut wie keine Attribute ;) - man muss etwas umdenken, dafür kann man besser "programmieren"
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: FHEMAN am 28 Dezember 2020, 17:16:49
Ich kämpfe weiter.. Kannst Du mir das bitte näher erklären:
Zitat von: Damian am 16 Dezember 2020, 15:01:18
("[Alarmanlage]" ne "on") wird nicht funktionieren

dann schon eher:

([Alarmanlage] ne "on")

Ich erhalte bei Bedingungen in der Art

([Resident1:state] eq "off" or [Resident2:state] eq "off")

die Fehlermeldung

doif.Test: off eq "off" or off eq "off": Unknown command off, try help.

Für mich sieht das so aus, als würden da "" fehlen?
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: Damian am 28 Dezember 2020, 19:50:52
Immer ein komplettes list liefern, mit den Bruchstücken kann man nichts anfangen.
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: FHEMAN am 30 Dezember 2020, 17:47:37
Zitat von: Damian am 28 Dezember 2020, 19:50:52
Immer ein komplettes list liefern, mit den Bruchstücken kann man nichts anfangen.
Hi Damian, hier das list:
Internals:
   DEF        ([Residents.R:state] eq "on" or [Residents.M:state] eq "on" or [Residents.C:state] eq "on" or [Residents.E:state] eq "on" or [Residents.Unbekannt:state] eq "on")(
{
my @Residents =("Residents.R","Residents.M","Residents.Unbekannt");
my $PresenceCount = 0;
my $PresenceResidents = "";
foreach my $Resident (@Residents) {
my $ResidentState = (Value($Resident) eq "on") ? "1" : "0";
my $ResidentShort = alias($Resident);
if (($ResidentShort ne "Unbekannt") && ($ResidentState eq "1")) {
$PresenceResidents .= " $ResidentShort";
$PresenceCount++;
}
fhem("setreading Anwesenheit:FILTER=r:$ResidentShort!=$ResidentState $ResidentShort $ResidentState");
}
if ($PresenceResidents eq "") {
$PresenceResidents = "0";
}
fhem("setreading Anwesenheit PresenceResidents $PresenceResidents");
fhem("setreading Anwesenheit:FILTER=r:PresenceCount!=$PresenceCount PresenceCount $PresenceCount");
fhem("set Anwesenheit:FILTER=STATE!=on on");
my $ResidentTrigger = ReadingsVal("doif.Anwesenheit","cmd_event",-1);
}
) DOELSE ([Residents.R:state] eq "off" or [Residents.M:state] eq "off" or [Residents.C:state] eq "off" or [Residents.E:state] eq "off" or [Residents.Unbekannt:state] eq "off")(
{
fhem("setreading Anwesenheit:FILTER=r:Unbekannt!=0 Unbekannt 0");
fhem("setreading Anwesenheit:FILTER=r:PresenceCount!=0 PresenceCount 0");
fhem("setreading Anwesenheit:FILTER=r:PresenceResidents!=0 PresenceResidents 0");
fhem("set Anwesenheit:FILTER=STATE!=off off");
}
)
   FUUID      5f8c4fde-f33f-6078-ae31-c79ab2edfb5311e9
   MODEL      FHEM
   NAME       doif.Anwesenheit
   NOTIFYDEV  Residents.M,Residents.Unbekannt,Residents.R,Residents.E,Residents.C,global
   NR         1003
   NTFY_ORDER 50-doif.Anwesenheit
   STATE      cmd_1
   TYPE       DOIF
   VERSION    23235 2020-11-25 22:42:28
   READINGS:
     2020-12-30 14:11:15   Device          Residents.R
     2020-12-30 14:11:15   cmd             1
     2020-12-30 14:11:15   cmd_event       Residents.R
     2020-12-30 14:11:15   cmd_nr          1
     2020-12-30 14:10:15   e_Residents.M_state on
     2020-12-30 14:11:15   e_Residents.R_state on
     2020-12-30 14:10:40   e_Residents.Unbekannt_state on
     2020-12-28 17:02:10   mode            enabled
     2020-12-30 14:11:15   state           cmd_1
   Regex:
     accu:
     cond:
       Residents.C:
         0:
           state      ^Residents.C$:^state:
       Residents.E:
         0:
           state      ^Residents.E$:^state:
       Residents.M:
         0:
           state      ^Residents.M$:^state:
       Residents.R:
         0:
           state      ^Residents.R$:^state:
       Residents.Unbekannt:
         0:
           state      ^Residents.Unbekannt$:^state:
   attr:
     cmdState:
     wait:
     waitdel:
   condition:
     0          ::ReadingValDoIf($hash,'Residents.R','state') eq "on" or ::ReadingValDoIf($hash,'Residents.M','state') eq "on" or ::ReadingValDoIf($hash,'Residents.C','state') eq "on" or ::ReadingValDoIf($hash,'Residents.E','state') eq "on" or ::ReadingValDoIf($hash,'Residents.Unbekannt','state') eq "on"
   do:
     0:
       0            { my @Residents =("Residents.R","Residents.M","Residents.Unbekannt"); my $PresenceCount = 0; my $PresenceResidents = ""; foreach my $Resident (@Residents) { my $ResidentState = (Value($Resident) eq "on") ? "1" : "0"; my $ResidentShort = alias($Resident); if (($ResidentShort ne "Unbekannt") && ($ResidentState eq "1")) { $PresenceResidents .= " $ResidentShort"; $PresenceCount++; } fhem("setreading Anwesenheit:FILTER=r:$ResidentShort!=$ResidentState $ResidentShort $ResidentState"); } if ($PresenceResidents eq "") {  $PresenceResidents = "0"; } fhem("setreading Anwesenheit PresenceResidents $PresenceResidents"); fhem("setreading Anwesenheit:FILTER=r:PresenceCount!=$PresenceCount PresenceCount $PresenceCount"); fhem("set Anwesenheit:FILTER=STATE!=on on"); my $ResidentTrigger = ReadingsVal("doif.Anwesenheit","cmd_event",-1); }
     1:
       0          [Residents.R:state] eq "off" or [Residents.M:state] eq "off" or [Residents.C:state] eq "off" or [Residents.E:state] eq "off" or [Residents.Unbekannt:state] eq "off"
       1            { fhem("setreading Anwesenheit:FILTER=r:Unbekannt!=0 Unbekannt 0"); fhem("setreading Anwesenheit:FILTER=r:PresenceCount!=0 PresenceCount 0"); fhem("setreading Anwesenheit:FILTER=r:PresenceResidents!=0 PresenceResidents 0"); fhem("set Anwesenheit:FILTER=STATE!=off off"); }
   helper:
     DEVFILTER  ^global$|^Residents.M$|^Residents.Unbekannt$|^Residents.E$|^Residents.R$|^Residents.C$
     NOTIFYDEV  global|Residents.M|Residents.Unbekannt|Residents.E|Residents.R|Residents.C
     event      on
     globalinit 1
     last_timer 0
     sleeptimer -1
     timerdev   Residents.R
     timerevent on
     triggerDev Residents.R
     timerevents:
       on
     timereventsState:
       state: on
     triggerEvents:
       on
     triggerEventsState:
       state: on
   internals:
   readings:
     all         Residents.R:state Residents.M:state Residents.C:state Residents.E:state Residents.Unbekannt:state
   trigger:
   uiState:
   uiTable:
Attributes:
   do         always
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: Damian am 30 Dezember 2020, 18:35:24
DOELESE hat keine Bedingung, was du meinst ist wohl DOELSEIF
Titel: Antw:Verständnisfrage insb. zur Mehrfachnutzung eines Ausführungsteils
Beitrag von: FHEMAN am 01 Januar 2021, 12:17:46
Argh, ist mir komplett entgangen, da ich die zweite Bedingungen erst später formuliert habe. Die Fehlermeldung ist jetzt weg, danke!