[gelöst] Frage zu Wiederholungen für Projekt "Adventsuhr"

Begonnen von dora71, 26 November 2020, 17:52:57

Vorheriges Thema - Nächstes Thema

dora71

Hallo zusammen,

nachdem ich durch weder durch Ausprobieren noch durch die Forensuche fündig geworden bin, stelle ich hier mal meine Fragen:

1. Kann ich das Attribut repeatsame "berechenbar" bzw. variabel machen ? Mein Ansatz war folgender:
attr leuchten repeatsame {$ hour}
Das hat aber leider nicht funktioniert. Stattdessen wird der Perl-Ausdruck so wie er ist in's Attribut geschrieben.

2. Ist es möglich, vor und nach einem Wiederholungsblock einzelne bzw. mehrere Kommandos innerhalb des gleichen Blocks abzusetzen, die nur einmalig ausgeführt werden?

Wofür ich das brauche? Ich möchte mir für die Adventszeit eine Lichtsteuerung bauen, die zu jeder vollen Stunde 4 Farben durchläuft, und zwar so oft wie die aktuelle Zeitstunde gerade ist. Quasi so ähnlich wie eine Kirchturmuhr  :D

Dazwischen soll minütlich das Licht zwischen 2 Farben wechseln.

Eventuell kann man das ja noch anders realisieren. Die Wiederholungen an sich funktionieren ja, nur ich bekomme sie nicht variabel.

Oder geht das gar nicht? Das kann ich ja fast nicht glauben.

Danke für Eure Ideen.

Gruß Rainer

Ellert

#1
zu 1. Ja, aber die richtige Syntax verwenden, dann klappt es. Die Syntax (set magic) ist hier beschrieben https://commandref.fhem.de/commandref_DE.html#set Das Attribut muss zur Berechnung aktualisiert werden. Möglicherweise funktionert auch die Berechnung über die übliche DOIF-Syntax, wie bei wait.

zu 2. Im Prinzip ja, ist aber etwas umständlich: Man setzt beim nach dem ersten Durchlauf ein Reading als Merker und führt die entsprechenden Befehle nur aus  wenn der Merker 0 ist. Beim letzten Durchlauf setzt man den Merker wieder zurück.

Damian

Man kann beim bei repeatsame genauso wie bei wait beliebige Berechnungen durchführen:

Auszug aus der Commandref

ZitatBeispiel:

attr my_doif wait 1:[mydummy:state]*3:rand(600)+100,Attr("mydevice","myattr","")

Ich glaube aber nicht, dass repeatsame alleine dafür ausreicht, denn du wirst deine Kommandos sicherlich jeweils mit einer Verzögerung nacheinander ausführen wollen, siehe Attribut repeatcmd

Zudem dürfte $hour beim Attribut repeatsame nicht bekannt sein.

Ich würde es mit der zuletzt aufgebohrten set_Exec-Funktion lösen:

z. B.

Beispiel:

defmod di_adventuhr DOIF {[:00];$_hour=$hour;set_Exec("timer",1,'fhem_set("dingdong on")','$count < $_hour')}

siehe:

https://fhem.de/commandref_DE.html#DOIF_set_Exec
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

dora71

Hallo und danke Euch für die schnellen Antworten.

Musste mir zuerst mal die neue DOIF-Version ziehen, um Damians Vorschlag auszuprobieren  :D

Bleibt mir noch eine Frage: Ich möchte mehrere Befehle zeitverzögert ausführen (und das in jeweils unterschiedlicher Anzahl), aber sleep blockiert ja das System, richtig? Zumindest wird das per perfmon mitgeteilt. Wie bekomme ich das Ganze non-blocking? Muss ich dann zwei set_Exec schachteln?

Im Moment sieht mein Code so aus:

{ [22:27];$_hour=($hour-12);set_Exec("timer",2,'fhem_set "myBroker publish licht/christmas/rgb/color #330000"; sleep 2; fhem_set "myBroker publish licht/christmas/rgb/color #003300"; sleep 2; fhem_set "myBroker publish licht/christmas/rgb/color #000033"; sleep 2; fhem_set "myBroker publish licht/christmas/rgb/color #333333"; sleep 2','$count < $_hour')}

Und letzte Frage: Wenn ich die Ausführung gerne zu jeder Stunde hätte, im Zeitraum zwischen 17:00 Uhr und 22:00 Uhr, dann wäre diese Zeitangabe richtig?
[17:00-22:00,+[1]:00]

Gruß Rainer

Damian

Verschiedene Befehle kannst du eleganter lösen.

Auch hier gehen wir vom Beispiel aus der Commandref aus:

Zitatdefmod di_dimm DOIF {["button:on"];;@{$_pct}=(10,35,65,80,90,100);;set_Exec("timer",1,'fhem_set"lamp pct ".$_pct[$count]','$count < 6')}

passen es entsprechend an und bringen es in einer Routine (hier: lauflicht) unter. Diese Routine rufen wir dann über den anderen Timer auf:

defmod di_adventslicht DOIF
subs {
@{$_pct}=("#330000","#003300","#000033", "#333333");
sub lauflicht {set_Exec("timer2",2,'fhem_set"myBroker publish licht/christmas/rgb/color ".$_pct[$count]','$count < 4')}
}
{[17:00-22:00,+[1]:00];$_hour=$hour;set_Exec("timer1",10,'lauflicht()','$count < $_hour')}



Allerdings wirst du damit eine Licht-Orgie produzieren:

Um 22:00 Uhr: 22*4=88 mal.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

dora71

ZitatAllerdings wirst du damit eine Licht-Orgie produzieren:

Um 22:00 Uhr: 22*4=88 mal.

Dafür habe ich ja den "Stundenreduzierer" eingebaut:
$_hour=($hour-12);

Dann bleibt es bei maximal 10*4 = 40mal  8)
und wollen wir nicht eigentlich eine Licht-Orgie zur Adventszeit  ;)

Danke für den Code ... jetzt ist mir das klar, aber in der Commandref war mir das nicht so klar.
Und jetzt ist es auch non-blocking.

Damian

#6
ja, solche Lösungen dürften hier die meisten überfordern, dafür sind sie aus meiner Sicht recht elegant, weil sie in einem Modul stecken, mit wenig Code auskommen und effizient in Perl ablaufen.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

dora71

Eine Frage habe ich jetzt doch noch:

Ist es möglich, einen oder mehrere Befehle NACH Ablauf der ganzen Timer abzusetzen? Einfach hinter das set_Exec() zu schreiben funktioniert nicht, das habe ich ausprobiert (wahrscheinlich, weil non-blocking).

Spontan würde ich mit get_Exec("timer2") arbeiten wollen, aber bin mir nicht sicher, wo ich das reinbaue und ob ich das von "oberhalb" aufrufen kann, wenn "timer2" in der subs steht.

Damian

#8
Das ist das gleiche Problem, wie hier https://forum.fhem.de/index.php/topic,116199.msg1105105.html#msg1105105

Dann musst du timer1 anders realisieren:

defmod di_adventslicht DOIF
subs {
@{$_pct}=("#330000","#003300","#000033", "#333333");
sub lauflicht {set_Exec("timer2",2,'fhem_set"myBroker publish licht/christmas/rgb/color ".$_pct[$count]','$count < 4')}
sub check {
   if ($_count < $_hour) {
      $_count++;
      lauflicht();
      set_Exec("timer1",10,'check()');
   } else {
      fhem"alles was ich noch danach tun will";
   }
}   
}
{[17:00-22:00,+[1]:00];$_hour=$hour-12;$_count=0;set_Exec("timer1",10,'check()')}
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Damian

Hier eine andere Alternative:

defmod di_adventslicht DOIF
subs {
@{$_pct}=("#330000","#003300","#000033", "#333333");
sub lauflicht {set_Exec("timer2",2,'fhem_set"myBroker publish licht/christmas/rgb/color ".$_pct[$count]','$count < 4')}
}
{[17:00-22:00,+[1]:00];$_hour=$hour-12;set_Exec("timer1",10,'($count<$_hour ? lauflicht() : fhem"etwas danach")','$count <= $_hour')}
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

dora71

Hallo Damian, hallo Forum,

mit dem Ternär-Operator stehe ich leider (noch) auf Kriegsfuß  :'( habe es jetzt aber folgendermaßen gelöst. Funktioniert seit gestern einwandfrei:

defmod xmas2020_hour DOIF subs {\
@{$_pct}=("BB0000","00BB00","0000BB", "BBBBBB");;\
sub lauflicht \
  {set_Exec("timer2",2,'fhem_set "myBroker publish licht/christmas/rgb/color #".$_pct[$count];; \
   fhem_set "balkonleds RGB ".$_pct[$count]','$count < 4')}\
}\
{ [17:00-22:00,+[1]:00];;$_hour=($hour-12);;\
  set_Exec("timer1",10,'if ($count < $_hour) {lauflicht();;} else {\
    fhem_set "myBroker publish licht/christmas/rgb/color #003300";;\
fhem_set "balkonleds RGB 003300";;}','$count <= $_hour')}


Werde die Lösung noch in's Forum "Codeschnipsel" einfügen, vielleicht hat der Eine oder die Andere Spaß daran.

Vielen Dank für die schnelle und umfangreiche Hilfe.

Gruß und einen schönen (beleuchteten) 1. Advent.

Rainer