Hallo!
Ich möchte mein DOIF (für eine Rolladensteuerung) jedes Mal triggern, wenn eine Readingänderung erfolgt. Die Readings sind
LastAction_Channel_01, LastAction_Channel_02, LastAction_Channel_03 ... LastAction_Channel_16
([SD_Rollo_16ch:"^LastAction_Channel_"])({
...
})
Dies triggert sobald sich ein Reading ändert.
Nun werden bei einer Gruppenstuerung mehrere Readings gleichzeitig gesetzt. Hier erfolgt nur eine Triggerung...obwohl mehrere Events generiert werden.
Events:
2019-03-03 17:34:42 SD_Keeloq SD_Rollo_16ch LastAction_Channel_01: stop
2019-03-03 17:34:42 SD_Keeloq SD_Rollo_16ch LastAction_Channel_02: stop
2019-03-03 17:34:42 SD_Keeloq SD_Rollo_16ch LastAction_Channel_03: stop
Doif
Device: SD_Rollo_16ch
Event:LastAction_Channel_01: stop
Do Always ist gesetzt....welchen Denkfehler mache ich?
Danke!
Gruß
Bismosa
Wie stellst Du fest, dass er nur einmal triggert?
Hallo,
indem ich am Anfang des DOIFs in die Log-Datei schreibe:
Log3 "di_Rollo", 3, "di_Rollo: Device: $DEVICE Event:$EVENT";
Es wird nichts protokolliert...und auch nichts ausgeführt. Daher bin ich mir "eigentlich" sicher, dass es nur 1x ausgeführt wird. ?
Gruß
Bismosa
Kann man das vollständige "list" des DOIFs sehen?
Hallo!
Na klar:
defmod di_Rollo DOIF ([SD_Rollo_16ch:"^LastAction_Channel_"])({\
Log3 "di_Rollo", 3, "di_Rollo: Device: $DEVICE Event:$EVENT";;\
\
my @PARTS=split(/ /,"$EVENT");;\
\
my $RolloReading=$PARTS[0];;\
chop $RolloReading;; ## ":" entfernen\
\
my $JaroCmd=ReadingsVal("$DEVICE", "$RolloReading", "");;\
if ($JaroCmd eq ""){\
return;;\
}\
Log3 "di_Rollo", 3, "di_Rollo: JaroCmd: $JaroCmd";;\
\
\
my $cmd;;\
if ($JaroCmd eq "up"){\
$cmd="open";;\
} elsif ($JaroCmd eq "stop"){\
$cmd="stop";;\
} elsif ($JaroCmd eq "down"){\
$cmd="closed";;\
} elsif ($JaroCmd eq "shade"){\
##Nur Position festlegen\
$cmd="";;\
} else {\
##learn=kein Fahrbefehl\
##updown=kein Fahrbefehl\
return;;\
}\
\
Log3 "di_Rollo", 3, "di_Rollo: cmd: $cmd";;\
\
my $RolloDev;;\
my $ShadePos;;\
if ($RolloReading eq "LastAction_Channel_01") { $ShadePos="50";; $RolloDev="Rolladen_Kueche";; }\
elsif ($RolloReading eq "LastAction_Channel_02") { $ShadePos="50";; $RolloDev="Rolladen_Essbereich";; }\
elsif ($RolloReading eq "LastAction_Channel_03") { $ShadePos="50";; $RolloDev="Rolladen_Wohnzimmer";; }\
elsif ($RolloReading eq "LastAction_Channel_04") { $ShadePos="50";; $RolloDev="Rolladen_Terrasse_Rechts";; }\
elsif ($RolloReading eq "LastAction_Channel_05") { $ShadePos="50";; $RolloDev="Rolladen_Terrasse_Links";; }\
elsif ($RolloReading eq "LastAction_Channel_06") { $ShadePos="50";; $RolloDev="Rolladen_Schlafzimmer";; }\
elsif ($RolloReading eq "LastAction_Channel_07") { $ShadePos="50";; $RolloDev="Rolladen_Gaeste";; }\
elsif ($RolloReading eq "LastAction_Channel_08") { $ShadePos="50";; $RolloDev="Rolladen_WC";; }\
elsif ($RolloReading eq "LastAction_Channel_09") { $ShadePos="60";; $RolloDev="Rolladen_Buero";; }\
else{\
##Keine weiteren festgelegt...\
return;;\
}\
\
Log3 "di_Rollo", 3, "di_Rollo: RolloDev: $RolloDev";;\
Log3 "di_Rollo", 3, "di_Rollo: ShadePos: $ShadePos";;\
\
##my $ROLLOistCMD = ReadingsVal("$RolloDev", "command", "nix");;\
##Log3 "di_Rollo", 3, "di_Rollo: ROLLOistCMD: $ROLLOistCMD";;\
##if ($ROLLOistCMD eq $cmd){\
## Log3 "di_Rollo", 3, "di_Rollo: Gleicher Fahrbefehl. Nicht ausführen!";;\
## return;;\
##}\
\
my $ROLLOistSTATE = ReadingsVal("$RolloDev", "state", "nix");;\
Log3 "di_Rollo", 3, "di_Rollo: ROLLOistSTATE: $ROLLOistSTATE";;\
\
if ($ROLLOistSTATE eq "drive-".$JaroCmd){\
Log3 "di_Rollo", 3, "di_Rollo: Gleicher Fahrbefehl. Nicht ausführen!";;\
return;;\
}\
\
\
if ($JaroCmd eq "shade"){\
Log3 "di_Rollo", 3, "di_Rollo: setreading $RolloDev pct $ShadePos";;\
fhem("setreading $RolloDev pct $ShadePos");;\
} else {\
Log3 "di_Rollo", 3, "di_Rollo: set $RolloDev extern $cmd";;\
fhem("set $RolloDev extern $cmd");;\
}\
\
})\
attr di_Rollo do always
attr di_Rollo room Rolläden
Es werden noch mehrere Log-Einträge geschrieben...ist beim Debuggen hilfreich.
Gruß
Bismosa
Das ist kein "list".
list di_Rollo
im Kommandofeld von Fhem.
Und ich würde keine eigene Variable $cmd in einem DOIF nutzen. $cmd ist schon eine Variable auf DOIF Ebene => unvorhersehbares Ergebnis ohne jedes Mal den Kontext zu analysieren.
Zitat von: CommandRef$cmd
Perl-Variablen mit der Bedeutung [$SELF:cmd]
Zitat von: bismosa am 03 März 2019, 17:37:06
Nun werden bei einer Gruppenstuerung mehrere Readings gleichzeitig gesetzt. Hier erfolgt nur eine Triggerung...obwohl mehrere Events generiert werden.
Events:
2019-03-03 17:34:42 SD_Keeloq SD_Rollo_16ch LastAction_Channel_01: stop
2019-03-03 17:34:42 SD_Keeloq SD_Rollo_16ch LastAction_Channel_02: stop
2019-03-03 17:34:42 SD_Keeloq SD_Rollo_16ch LastAction_Channel_03: stop
Wenn Du das Attribut mseclog setzt, dann siehst Du, ob die Events gleichzeitig kommen. Auf ein Eventpaket triggert DOIF nur einmal. Beim notify ist das seit einiger Zeit anders, wenn ich mich recht erinnere. Siehe auch https://wiki.fhem.de/wiki/Event
Hallo,
ups...sorry. Klar kenne ich list ::)
Wusste aber bisher noch nicht, dass es beim DOIF so viele nützliche Informationen beinhaltet :)
Internals:
DEF ([SD_Rollo_16ch:"^LastAction_Channel_"])({
##"LastAction_Channel_01: shade"-> $EVENT
Log3 "di_Rollo", 3, "di_Rollo: Device: $DEVICE Event:$EVENT";
my @PARTS=split(/ /,"$EVENT");
my $RolloReading=$PARTS[0];
chop $RolloReading; ## ":" entfernen
my $JaroCmd=ReadingsVal("$DEVICE", "$RolloReading", "");
if ($JaroCmd eq ""){
return;
}
##Log3 "di_Rollo", 3, "di_Rollo: Device: $DEVICE Event:$EVENT";
Log3 "di_Rollo", 3, "di_Rollo: JaroCmd: $JaroCmd";
my $DIcmd;
if ($JaroCmd eq "up"){
$DIcmd="open";
} elsif ($JaroCmd eq "stop"){
$DIcmd="stop";
} elsif ($JaroCmd eq "down"){
$DIcmd="closed";
} elsif ($JaroCmd eq "shade"){
##Nur Position festlegen
$DIcmd="";
} else {
##learn=kein Fahrbefehl
##updown=kein Fahrbefehl
return;
}
Log3 "di_Rollo", 3, "di_Rollo: DIcmd: $DIcmd";
my $RolloDev;
my $ShadePos;
if ($RolloReading eq "LastAction_Channel_01") { $ShadePos="50"; $RolloDev="Rolladen_Kueche"; }
elsif ($RolloReading eq "LastAction_Channel_02") { $ShadePos="50"; $RolloDev="Rolladen_Essbereich"; }
elsif ($RolloReading eq "LastAction_Channel_03") { $ShadePos="50"; $RolloDev="Rolladen_Wohnzimmer"; }
elsif ($RolloReading eq "LastAction_Channel_04") { $ShadePos="50"; $RolloDev="Rolladen_Terrasse_Rechts"; }
elsif ($RolloReading eq "LastAction_Channel_05") { $ShadePos="50"; $RolloDev="Rolladen_Terrasse_Links"; }
elsif ($RolloReading eq "LastAction_Channel_06") { $ShadePos="50"; $RolloDev="Rolladen_Schlafzimmer"; }
elsif ($RolloReading eq "LastAction_Channel_07") { $ShadePos="50"; $RolloDev="Rolladen_Gaeste"; }
elsif ($RolloReading eq "LastAction_Channel_08") { $ShadePos="50"; $RolloDev="Rolladen_WC"; }
elsif ($RolloReading eq "LastAction_Channel_09") { $ShadePos="60"; $RolloDev="Rolladen_Buero"; }
else{
##Keine weiteren festgelegt...
return;
}
Log3 "di_Rollo", 3, "di_Rollo: RolloDev: $RolloDev";
Log3 "di_Rollo", 3, "di_Rollo: ShadePos: $ShadePos";
##my $ROLLOistCMD = ReadingsVal("$RolloDev", "command", "nix");
##Log3 "di_Rollo", 3, "di_Rollo: ROLLOistCMD: $ROLLOistCMD";
##if ($ROLLOistCMD eq $DIcmd){
## Log3 "di_Rollo", 3, "di_Rollo: Gleicher Fahrbefehl. Nicht ausführen!";
## return;
##}
my $ROLLOistSTATE = ReadingsVal("$RolloDev", "state", "nix");
Log3 "di_Rollo", 3, "di_Rollo: ROLLOistSTATE: $ROLLOistSTATE";
if ($ROLLOistSTATE eq "drive-".$JaroCmd){
Log3 "di_Rollo", 3, "di_Rollo: Gleicher Fahrbefehl. Nicht ausführen!";
return;
}
if ($JaroCmd eq "shade"){
Log3 "di_Rollo", 3, "di_Rollo: setreading $RolloDev pct $ShadePos";
fhem("setreading $RolloDev pct $ShadePos");
} else {
Log3 "di_Rollo", 3, "di_Rollo: set $RolloDev extern $DIcmd";
fhem("set $RolloDev extern $DIcmd");
}
})
FUUID 5c7ba6bf-f33f-58e6-b800-e1252db5ec48fed1
MODEL FHEM
NAME di_Rollo
NR 907
NTFY_ORDER 50-di_Rollo
STATE cmd_1
TYPE DOIF
VERSION 18706 2019-02-23 21:48:22
READINGS:
2019-03-03 20:02:56 Device SD_Rollo_16ch
2019-03-03 20:02:56 cmd 1
2019-03-03 20:02:56 cmd_event SD_Rollo_16ch
2019-03-03 20:02:56 cmd_nr 1
2019-03-03 20:02:56 e_SD_Rollo_16ch_events button: stop,channel: 1,counter_send: 240,send stop,LastAction_Channel_01: stop,LastAction_Channel_02: stop,LastAction_Channel_03: stop,channel_control: 1,2,3
2019-02-27 21:50:24 event LastAction_Channel_09: shade
2019-03-03 20:02:48 mode enabled
2019-03-03 20:02:56 state cmd_1
Regex:
accu:
attr:
cmdState:
wait:
waitdel:
condition:
0 ::EventDoIf('SD_Rollo_16ch',$hash,'^LastAction_Channel_',1)
devices:
0 SD_Rollo_16ch
all SD_Rollo_16ch
do:
0:
0 { Log3 "di_Rollo", 3, "di_Rollo: Device: $DEVICE Event:$EVENT"; my @PARTS=split(/ /,"$EVENT"); my $RolloReading=$PARTS[0]; chop $RolloReading; my $JaroCmd=ReadingsVal("$DEVICE", "$RolloReading", ""); if ($JaroCmd eq ""){ return; } Log3 "di_Rollo", 3, "di_Rollo: JaroCmd: $JaroCmd"; my $DIcmd; if ($JaroCmd eq "up"){ $DIcmd="open"; } elsif ($JaroCmd eq "stop"){ $DIcmd="stop"; } elsif ($JaroCmd eq "down"){ $DIcmd="closed"; } elsif ($JaroCmd eq "shade"){ $DIcmd=""; } else { return; } Log3 "di_Rollo", 3, "di_Rollo: DIcmd: $DIcmd"; my $RolloDev; my $ShadePos; if ($RolloReading eq "LastAction_Channel_01") { $ShadePos="50"; $RolloDev="Rolladen_Kueche"; } elsif ($RolloReading eq "LastAction_Channel_02") { $ShadePos="50"; $RolloDev="Rolladen_Essbereich"; } elsif ($RolloReading eq "LastAction_Channel_03") { $ShadePos="50"; $RolloDev="Rolladen_Wohnzimmer"; } elsif ($RolloReading eq "LastAction_Channel_04") { $ShadePos="50"; $RolloDev="Rolladen_Terrasse_Rechts"; } elsif ($RolloReading eq "LastAction_Channel_05") { $ShadePos="50"; $RolloDev="Rolladen_Terrasse_Links"; } elsif ($RolloReading eq "LastAction_Channel_06") { $ShadePos="50"; $RolloDev="Rolladen_Schlafzimmer"; } elsif ($RolloReading eq "LastAction_Channel_07") { $ShadePos="50"; $RolloDev="Rolladen_Gaeste"; } elsif ($RolloReading eq "LastAction_Channel_08") { $ShadePos="50"; $RolloDev="Rolladen_WC"; } elsif ($RolloReading eq "LastAction_Channel_09") { $ShadePos="60"; $RolloDev="Rolladen_Buero"; } else{ return; } Log3 "di_Rollo", 3, "di_Rollo: RolloDev: $RolloDev"; Log3 "di_Rollo", 3, "di_Rollo: ShadePos: $ShadePos"; my $ROLLOistSTATE = ReadingsVal("$RolloDev", "state", "nix"); Log3 "di_Rollo", 3, "di_Rollo: ROLLOistSTATE: $ROLLOistSTATE"; if ($ROLLOistSTATE eq "drive-".$JaroCmd){ Log3 "di_Rollo", 3, "di_Rollo: Gleicher Fahrbefehl. Nicht ausführen!"; return; } if ($JaroCmd eq "shade"){ Log3 "di_Rollo", 3, "di_Rollo: setreading $RolloDev pct $ShadePos"; fhem("setreading $RolloDev pct $ShadePos"); } else { Log3 "di_Rollo", 3, "di_Rollo: set $RolloDev extern $DIcmd"; fhem("set $RolloDev extern $DIcmd"); } }
1:
helper:
event LastAction_Channel_01: stop
globalinit 1
last_timer 0
sleeptimer -1
timerdev SD_Rollo_16ch
timerevent LastAction_Channel_01: stop
triggerDev SD_Rollo_16ch
DOIF_eventas:
cmd_nr: 1
cmd: 1
cmd_event: SD_Rollo_16ch
state: cmd_1
timerevents:
button: stop
channel: 1
counter_send: 240
send stop
LastAction_Channel_01: stop
LastAction_Channel_02: stop
LastAction_Channel_03: stop
channel_control: 1,2,3
timereventsState:
button: stop
channel: 1
counter_send: 240
state: send stop
LastAction_Channel_01: stop
LastAction_Channel_02: stop
LastAction_Channel_03: stop
channel_control: 1,2,3
triggerEvents:
button: stop
channel: 1
counter_send: 240
send stop
LastAction_Channel_01: stop
LastAction_Channel_02: stop
LastAction_Channel_03: stop
channel_control: 1,2,3
triggerEventsState:
button: stop
channel: 1
counter_send: 240
state: send stop
LastAction_Channel_01: stop
LastAction_Channel_02: stop
LastAction_Channel_03: stop
channel_control: 1,2,3
internals:
itimer:
readings:
trigger:
all SD_Rollo_16ch
uiState:
uiTable:
Attributes:
checkReadingEvent 0
do always
room Rolläden
$cmd habe ich direkt ersetzt. Danke für den Tipp. Das hatte ich nicht bedacht.
ZitatWenn Du das Attribut mseclog setzt, dann siehst Du, ob die Events gleichzeitig kommen. Auf ein Eventpaket triggert DOIF nur einmal
Es kommt definitiv als Eventpaket. Dann wird da die Ursache liegen. Da sich das verhalten wohl nicht ändern lässt...muss ich meine Logik da nochmal überdenken...
Gruß
Bismosa
Zitat von: Ellert am 03 März 2019, 20:03:45
Auf ein Eventpaket triggert DOIF nur einmal.
Oh, das wusste ich nicht :( Auch nirgendwo gelesen.
Kann man dann mit $EVENTS alle gleichzeitige Events haben?
Zitat von: amenomade am 03 März 2019, 20:21:14
Kann man dann mit $EVENTS alle gleichzeitige Events haben?
Sollte so sein, daher das S am Ende :)
Hallo!
Ich habe mein DOIF nun komplett umgebaut. Damit hat sich der Thread hier erledigt :)
Danke für die tolle Unterstützung!
Falls jemand mitliest hier meine Lösung:
([SD_Rollo_16ch:"channel_control"])({
##([SD_Rollo_16ch:"^LastAction_Channel_"])({
##"LastAction_Channel_01: shade"-> $EVENT
Log3 "di_Rollo", 3, "di_Rollo: Device: $DEVICE Event:$EVENT";
my $ChannelReading = ReadingsVal("$DEVICE", "channel_control", "99");
my @channels;
if ("$ChannelReading" eq "no"){
push @channels, ReadingsVal("$DEVICE", "channel", "99");
} else {
push @channels, split /,/, $ChannelReading;
}
Log3 "di_Rollo", 3, "di_Rollo: channels: ".join(", ", @channels);;
my $JaroCmd=ReadingsVal("$DEVICE", "button", "");
Log3 "di_Rollo", 3, "di_Rollo: JaroCmd: $JaroCmd";
my $DIcmd;
if ($JaroCmd eq "up"){
$DIcmd="open";
} elsif ($JaroCmd eq "stop"){
$DIcmd="stop";
} elsif ($JaroCmd eq "down"){
$DIcmd="closed";
} elsif ($JaroCmd eq "shade"){
##Nur Position festlegen
$DIcmd="";
} else {
##learn=kein Fahrbefehl
##updown=kein Fahrbefehl
return;
}
Log3 "di_Rollo", 3, "di_Rollo: DIcmd: $DIcmd";
##Für jeden ausführen:
foreach my $Kanal (@channels) {
my $RolloDev;
my $ShadePos;
if ($Kanal eq "1") { $ShadePos="50"; $RolloDev="Rolladen_Kueche"; }
elsif ($Kanal eq "2") { $ShadePos="50"; $RolloDev="Rolladen_Essbereich"; }
elsif ($Kanal eq "3") { $ShadePos="50"; $RolloDev="Rolladen_Wohnzimmer"; }
elsif ($Kanal eq "4") { $ShadePos="50"; $RolloDev="Rolladen_Terrasse_Rechts"; }
elsif ($Kanal eq "5") { $ShadePos="50"; $RolloDev="Rolladen_Terrasse_Links"; }
elsif ($Kanal eq "6") { $ShadePos="50"; $RolloDev="Rolladen_Schlafzimmer"; }
elsif ($Kanal eq "7") { $ShadePos="50"; $RolloDev="Rolladen_Gaeste"; }
elsif ($Kanal eq "8") { $ShadePos="50"; $RolloDev="Rolladen_WC"; }
elsif ($Kanal eq "9") { $ShadePos="60"; $RolloDev="Rolladen_Buero"; }
else{
##Keine weiteren festgelegt...
next;
}
Log3 "di_Rollo", 3, "di_Rollo: RolloDev: $RolloDev";
Log3 "di_Rollo", 3, "di_Rollo: ShadePos: $ShadePos";
my $ROLLOistSTATE = ReadingsVal("$RolloDev", "state", "nix");
Log3 "di_Rollo", 3, "di_Rollo: ROLLOistSTATE: $ROLLOistSTATE";
if ($ROLLOistSTATE eq "drive-".$JaroCmd){
Log3 "di_Rollo", 3, "di_Rollo: Gleicher Fahrbefehl. Nicht ausführen!";
return;
}
if ($JaroCmd eq "shade"){
Log3 "di_Rollo", 3, "di_Rollo: setreading $RolloDev pct $ShadePos";
fhem("setreading $RolloDev pct $ShadePos");
} else {
Log3 "di_Rollo", 3, "di_Rollo: set $RolloDev extern $DIcmd";
fhem("set $RolloDev extern $DIcmd");
}
}
})
Gruß
Bismosa
Bei soviel Perlcode hättest du gleich den etwas effizienteren Perlmodus nehmen können ;)
Hallo!
Den Tipp hast Du mir schon mehrfach gegeben...habe mich aber bisher immer noch nicht da rangetraut ;)
War jetzt aber eine gute Gelegenheit. War in diesem Fall ja wenigstens sehr einfach:
{if ([SD_Rollo_16ch:"channel_control"]) {
Ob ich mich daran gewöhnen möchte weiß ich aber noch nicht. DIe Performance ist schon ein gutes Argument :)
Gruß
Bismosa
Zitat von: bismosa am 05 März 2019, 20:45:24
Hallo!
Den Tipp hast Du mir schon mehrfach gegeben...habe mich aber bisher immer noch nicht da rangetraut ;)
War jetzt aber eine gute Gelegenheit. War in diesem Fall ja wenigstens sehr einfach:
{if ([SD_Rollo_16ch:"channel_control"]) {
Ob ich mich daran gewöhnen möchte weiß ich aber noch nicht. DIe Performance ist schon ein gutes Argument :)
Gruß
Bismosa
Die Performance ist eine Sache, aber stell dir mal vor du willst dir etwas merken und das beim nächsten Trigger auswerten. Im ganzen FHEM wirst du nur die Möglichkeit finden es über Readings zu tun oder mit irgendwelchen internen hash-Variablen zu hantieren - DOIF-Perlmodus bietet dir Instanzvariablen ;)
Hallo!
DOIF-Perlmodus bietet dir Instanzvariablen
Wow. Das ist ein Grund sich da richtig Einzuarbeiten! Das hätte ich schon mehrfach benötigen können. Dafür musste dann immer ein Dummy herhalten.
Ich muss wohl mal meine DOIFs (die sehen übrigens alle so aus wie oben...teilweise sogar mit noch mehr PERL-Code, wenn ich den nicht in die myUtils ausgelagert habe) überarbeiten :)
Das wird aber bestimmt länger dauern:
DOIF
FHEM 108
Perl 1 <---dieser :)
Gruß
Bismsoa
Zitat von: bismosa am 05 März 2019, 21:36:30
Hallo!
DOIF-Perlmodus bietet dir Instanzvariablen
Wow. Das ist ein Grund sich da richtig Einzuarbeiten! Das hätte ich schon mehrfach benötigen können. Dafür musste dann immer ein Dummy herhalten.
Ich muss wohl mal meine DOIFs (die sehen übrigens alle so aus wie oben...teilweise sogar mit noch mehr PERL-Code, wenn ich den nicht in die myUtils ausgelagert habe) überarbeiten :)
Das wird aber bestimmt länger dauern:
DOIF
FHEM 108
Perl 1 <---dieser :)
Gruß
Bismsoa
Und wenn ich dir sage, dass du kurze Funktionsnamen für eigene Funktionen benutzen kannst ohne Gefahr zu laufen, dass sie irgendwo in FHEM defniert wurden, weil sie im DOIF-Perlmodus gekapselt sind, so gibt es noch mehr Gründe myUtils aufzuräumen.
Huhu,
dann muss ich morgen wohl mal mit meinem Arbeitgeber sprechen, ob ich nicht meinen Resturlaub nehmen darf :)
Danke :)
Gruß
Bismsoa