Hallo zusammen,
ich möchte in einem notify mir ein at erzeugen lassen. Die Zeit des at's muss berechnet werden. Bisher sieht mein Versuch wie folgt aus:
fhem("define at_bad_duschheizung_aktivieren at {$zeit=+00:(($verbleibendeHeizzeitStundenInMinuten*60)-1):(60+$verbleibendeHeizzeitMinuten); return $zeit} set S7_DWrite_FBH10 on");
Nur leider klappt das nicht, weil nicht "zu ende" gerechnet wird, wie man an der Logausgabe erkennen kann:
2020.03.03 15:41:36.186 1: define at_bad_duschheizung_aktivieren at {=+00:{(300*60)-1}:(60+-11): Usage: define <name> at [timespec or datespec] <command>
2020.03.03 15:41:36.187 3: define at_bad_duschheizung_aktivieren at {=+00:{(300*60)-1}:(60+-11); return } set S7_DWrite_FBH10 on : Usage: define <name> at [timespec or datespec] <command>
Unknown command return, try help.
Was mache ich hier falsch? Wie bringe ich fhem dazu, an dieser Stelle die Berechnung zu machen, anstatt das Ganze als Textstring zu interpretieren?
Du musst komplett auf Perlebe bleiben. Also auch das erstellen des at über Perl machen.
Grüße
@Marko Das ist doch alles Perl?
Aber es fehlt doch ein ; ? Siehe auch (https://fhem.de/commandref_DE.html#command)
Oder liegt es daran?
Zitat<timespec> ist entweder HH:MM, HH:MM:SS oder {perlfunc()}. perlfunc muss ein String in timedet Format zurueckliefern. Achtung: {perlfunc()} darf keine Leerzeichen enthalten.
fhem("define at_bad_duschheizung_aktivieren at {$zeit=+00:(($verbleibendeHeizzeitStundenInMinuten*60)-1):(60+$verbleibendeHeizzeitMinuten);;return $zeit} set S7_DWrite_FBH10 on")
Denn Perlfunc wird ja vorm define ausgeführt?
Ob dann das geforderte Format rauskommt kann ich nicht prüfen :)
Gruß Otto
Mein Fehler ich hatte auf dem Handy das hintere } übersehen. Dachte es wäre weiter vorne.
Danke Ottot für die Richtigstellung.
Grüße
Vermutlich ist das auch eine unzulässige Vermischung von Code und (gedachter, aber nicht vercodeter) concatenation...
Du hast ja offensichtlich schon vor dieser einen Zeile Perl-Code, aus der auch $zeit zu kommen scheint (?), sonst müßte auch über das fehlende "my $zeit" irgendwas an Gemecker im log zu finden sein. Warum machst du die "Verstringung" zur richtigen Zeit nicht vorher und übergibst dann nur noch das Endergebnis? Könnte in etwa so aussehen:
$zeit="+00:".(($verbleibendeHeizzeitStundenInMinuten*60)-1).":".(60+$verbleibendeHeizzeitMinuten);
fhem("define at_bad_duschheizung_aktivieren at $zeit set S7_DWrite_FBH10 on");
Die concatenation kann man natürlich auch in den "fhem"-Aufruf reinnehmen, aber das ist m.E. unübersichtlicher:
fhem("define at_bad_duschheizung_aktivieren at {"+00:".(($verbleibendeHeizzeitStundenInMinuten*60)-1).":".(60+$verbleibendeHeizzeitMinuten)} set S7_DWrite_FBH10 on").
Ergibt dann folgende Timespec:
"+00:17999:49"
Da muss wohl auch noch ein wenig an der Formel gefeilt werden
Und wahrscheinlich kann man die ganze Fummelei mit den Strings einfach weglassen und mit epoch arbeiten?
Zitat<datespec> ist entweder ISO8601 (YYYY-MM-DDTHH:MM:SS) oder Anzahl der Sekunden seit 1970.
In der Art 8)
{my $at=int(time+3*24*3600);;fhem("define at_test at $at {}")}
Danke für die schnelle Hilfe!
In der Formel war in der Tat noch ein kleiner Fehler, so ist es jetzt richtig:
$zeit="+00:".(($verbleibendeHeizzeitStundenInMinuten/60)-1).":".(60+$verbleibendeHeizzeitMinuten);
fhem("define at_bad_duschheizung_aktivieren at $zeit set S7_DWrite_FBH10 on");
Wenn es einfacher geht, würde ich natürlich gerne ohne das ganze String-rumgemache arbeiten. Allerdings habe ich bisher nichts gefunden im Sinne von "Define für ein at das einmalig in xx Minuten (oder auch xx Sekunden) ausgeführt wird". Oder ich verstehe die Möglichkeiten der Zeitangabe beim at falsch...
Also mein Beispiel macht genau das: ab definition in drei Tagen
Oder Du siehst mein Beispiel von oben ausführlicher:
{my $Tage=0;; my $Stunden=0;; my $Minuten=15;; my $Sekunden=30;;my $at=int(time+$Tage*86400+$Stunden*3600+$Minuten*60+$Sekunden);;fhem("define at_test at $at {}")}
Wobei ich deine Formel gar nicht verstehe: rauskommen muss +HH:MM:SS
$zeit="+00:".(($verbleibendeHeizzeitStundenInMinuten/60)-1).":".(60+$verbleibendeHeizzeitMinuten);
HH ist bei Dir 00 - also die Stunden sind immer null
MM werden verbleibendeHeizzeitStundenInMinuten/60 - also der Wert enthält Stunden, die rechnest du um in Minuten?
SS wird 60 + verbleibendeHeizzeitMinuten - also HeizzeitMinuten ist negativ und es sind eigentlich Sekunden?
Was mir gerade noch einfällt: Viel einfacher :) ein FHEM sleep macht im Prinzip exakt das Gleiche.
my $at =$verbleibendeHeizzeitStundenInMinuten*3600+60-$verbleibendeHeizzeitMinuten; fhem("sleep $at;;set S7_DWrite_FBH10 on")
Zitat von: Otto123 am 03 März 2020, 17:36:05
Und wahrscheinlich kann man die ganze Fummelei mit den Strings einfach weglassen und mit epoch arbeiten?
In der Art 8)
{my $at=int(time+3*24*3600);;fhem("define at_test at $at {}")}
Ich habe tatsächlich eine Nacht schlaf gebraucht, bis ich diese Variante verstanden hatte. Hab mich immer an dem "time" aufgehangen und es nicht verstanden, aber jetzt verstehe ich die Lösung.
Genau DAS habe ich gesucht! Vielen Dank Otto, damit erspare ich mir das viele herumgerechne und einen Großteil der Konvertierung.
Hier auch noch das fertige notify. Ziel des ganzen ist eine Zeitverwahl für die Heizung in der Dusche. Da die Heizung eine gewisse Vorheizzeit benötigt, muss die Heizung X Minuten vor der gewünschten Duschzeit aktiviert werden. Genau das kann ich mit dem notify (und einem dummy zur Zeit/Tag-Auswahl) jetzt machen:
defmod notify_bad_zeitvorwahl_duschheizung_at_erzeugen notify dummy_bad_zeitvorwahl_duschheizung_aktivieren\
{\
my $aktuelleZeit = strftime('%H', localtime)*60*60 + strftime('%M', localtime)*60;;\
my $zielZeit = ReadingsVal("dummy_bad_zeitvorwahl_duschheizung","stunde",0)*60*60 + ReadingsVal("dummy_bad_zeitvorwahl_duschheizung","minute",0)*60;;\
my $benoetigteVorheizzeitInMinuten = ((ReadingsVal("readingsProxy_bad_heizung_dusche_vorheizzeit_bedien","state",0)/1000)/60);;\
my $zeit = time + ($zielZeit - $aktuelleZeit - $benoetigteVorheizzeitInMinuten*60);;\
\
if(ReadingsVal("dummy_bad_zeitvorwahl_duschheizung","tag",0) =~ /^morgen/){\
$zeit = $zeit + 60*60*24;;\
}\
if(ReadingsVal("dummy_bad_zeitvorwahl_duschheizung","tag",0) =~ /^übermorgen/){\
$zeit = $zeit + 60*60*24*2;;\
}\
\
\
if(ReadingsVal("dummy_bad_zeitvorwahl_duschheizung_aktivieren","state",0) eq "on")\
{\
Log3 'notify_bad_zeitvorwahl_duschheizung_at_erzeugen', 3, "benoetigteVorheizzeitInMinuten - $benoetigteVorheizzeitInMinuten ";;\
Log3 'notify_bad_zeitvorwahl_duschheizung_at_erzeugen', 3, "zeit - $zeit";;\
Log3 'notify_bad_zeitvorwahl_duschheizung_at_erzeugen', 3, "aktuelleZeit - $aktuelleZeit ";;\
Log3 'notify_bad_zeitvorwahl_duschheizung_at_erzeugen', 3, "zielZeit - $zielZeit ";;\
\
\
\
if(($zeit - time) gt $benoetigteVorheizzeitInMinuten*60)\
{\
Log3 'notify_bad_zeitvorwahl_duschheizung_at_erzeugen', 1, "Wir haben ausreichend Pufferzeit zum heizen";;\
fhem("define at_bad_duschheizung_aktivieren at $zeit set S7_DWrite_FBH10 on");;\
}\
else\
{\
Log3 'notify_bad_zeitvorwahl_duschheizung_at_erzeugen', 1, "Es ist zu wenig Zeit zum aufheizen";;\
\
}\
}\
}
Hinweis: time liefert auch Bruchteile von Sekunden, at will aber nur ganze Sekunden.
Dein define ... at dürfte in Deiner Variante Fehler werfen! Deswegen stand bei mir noch int()
int(time+3*24*3600)
Ich würde es deshalb so machen:
my $zeit = int(time + ($zielZeit - $aktuelleZeit - $benoetigteVorheizzeitInMinuten*60))
...wenn ihr schon mit Zeiten rechnet der Hinweis, dass es in FHEM auch einige Konstanten (https://wiki.fhem.de/wiki/Zeitangaben,_rechnen_mit#Konstanten_innerhalb_FHEM) gibt. MMn wird damit das ganze einfacher lesbar:
{my $at=int(time+3*DAYSECONDS);;fhem("define at_test at $at {}")}
Danke für die zusätzlichen Hinweise, das vereinfacht alles nochmal bzw. beugt hoffentlich Fehlern vor :-)