Da Weihnachten vor der Tür steht, schreibe ich mal Folgendes auf den Wunschzettel :)
define advent at 1448751600 set Weihnachtsbaum on
Damit könnte man auf einfach Art ein at zu einem bestimmten Datum vorprogrammieren, ohne die timespec erst umständlich in +hh:mm umrechnen zu müssen.
ok, ich bin grade dabei, einen vernünftigen patch vorzubereiten :)
Patch 1 - in fhem.pl wird die Funktion GetTimeSpec() angepaßt
Index: fhem.pl
===================================================================
--- fhem.pl (Revision 9804)
+++ fhem.pl (Arbeitskopie)
@@ -2919,6 +2919,8 @@
($hr, $min, $sec) = ($1, $2, $3);
} elsif($tspec =~ m/^([0-9]+):([0-5][0-9])$/) {
($hr, $min, $sec) = ($1, $2, 0);
+ } elsif($tspec =~ y/0-9// == length($tspec)) {
+ ($hr, $min, $sec) = (0, 0, $tspec);
} elsif($tspec =~ m/^{(.*)}$/) {
$fn = $1;
$tspec = AnalyzeCommand(undef, "{$fn}");
@@ -2926,6 +2928,8 @@
($hr, $min, $sec) = ($1, $2, $3);
} elsif(!$@ && $tspec =~ m/^([0-9]+):([0-5][0-9])$/) {
($hr, $min, $sec) = ($1, $2, 0);
+ } elsif(!$@ && ($tspec =~ y/0-9// == length($tspec))) {
+ ($hr, $min, $sec) = (0, 0, $tspec);
} else {
$tspec = "<empty string>" if(!$tspec);
return ("the at function \"$fn\" must return a timespec and not $tspec.",
Patch 2 - in der 90_at.pm
Index: 90_at.pm
===================================================================
--- 90_at.pm (Revision 9804)
+++ 90_at.pm (Arbeitskopie)
@@ -65,6 +65,21 @@
my ($err, $hr, $min, $sec, $fn) = GetTimeSpec($tspec);
return $err if($err);
+ if($sec > 60) {
+ # $tspec ist rein numerisch -> timestamp
+ return "Wrong timespec, timestamp must describe a future time"
+ if time() >= $sec;
+ my $val = FmtDateTime($sec);
+ $hash->{TRIGGERTIME} = $sec;
+ $hash->{TRIGGERTIME_FMT} = $val;
+ $hash->{COMMAND} = $command;
+ RemoveInternalTimer($hash);
+ InternalTimer($sec, "at_Exec", $hash, 0);
+ readingsSingleUpdate($hash, "state", $val,
+ !$hash->{READINGS}{state} || $hash->{READINGS}{state}{VAL} ne $val);
+ return undef;
+ }
+
$rel = "" if(!defined($rel));
$rep = "" if(!defined($rep));
$cnt = "" if(!defined($cnt));
@@ -386,9 +401,9 @@
executed <i>repeatedly</i>.<br>
The optional <code>{N}</code> after the * indicates,that the command
should be repeated <i>N-times</i> only.<br>
- <timedet> is either HH:MM, HH:MM:SS or {perlfunc()}, where perlfunc
- must return a HH:MM or HH:MM:SS date. Note: {perlfunc()} may not contain
- any spaces or tabs.
+ <timedet> is either HH:MM, HH:MM:SS, timestamp or {perlfunc()}, <br/>
+ where perlfunc must return a HH:MM or HH:MM:SS date or a future timestamp.<br/>
+ Note: {perlfunc()} may not contain any spaces or tabs.
</ul>
<br>
@@ -399,6 +414,7 @@
define a2 at 17:00:00 { Log 1, "Teatime" } # Perl command
define a3 at 17:00:00 "/bin/echo "Teatime" > /dev/console" # shell command
define a4 at *17:00:00 set lamp on # every day
+ define a5 at 1448751600 set lamp on # timestamp must describe a future time
# relative ones
define a5 at +00:00:10 set lamp on # switch on in 10 seconds
Damit wird es möglich, einen timestamp im DEF zu verwenden. Die Angabe kann sowohl als absoluter Wert als auch per perlfunc errechnet erfolgen.
Es wird geprüft, ob der timestamp in der Zukunft liegt, falls nicht, wird eine entsprechende Fehlermeldung ausgegeben.
Ich hoffe, nix wichtiges vergessen/übersehen zu haben :)
Ich versteh nicht, warum es umbedingt ein Timestamp sein muss? Ist jetzt nicht so, dass man den sich mal eben aus dem Finger saugen kann, es sei denn man ist Mathe-Autist.
Wäre eine optionale Angabemöglichkeit von Datum nicht interessanter? Dann kannst du folgendes machen (beispielhaft)
define advent at 2015-12-24/18:00 set Weihnachtsbaum on
oder so ähnlich. Ich hab mir da jetzt keine weiteren Gedanken zur Syntax gemacht.
Nur so als Idee ;)
Viele Grüße
Markus
Ich arbeite leichter mit timestamps als mit irgendwelchen Datums-/Zeitformaten, von denen Du dann entweder wieder unzählige prüfen oder ein bestimmtes vorgeben müsstest.
Ausserdem arbeitet at intern ohnehin mit timestamps, um Ausführungszeitpunkte abzuspeichern.
Nachtrag: fhem bringt ja von Haus aus einige Funktionen mit, um Strings in timestamps zu konvertieren. Insofern ist das, was Du vorschlägst, mit meinen Patches ebenfalls durchführbar.
ich denke auch ein lesbares datum wäre besser als ein timestamp.
was spricht denn gegen das gute alte iso 8601 format:define advent at 2015-12-24T18:00 set Weihnachtsbaum on
wenn man sich den standard anschaut findet man vermutlich noch ein paar andere nützliche dinge wie Zeitspannen, relative angaben oder kalender wochen. die könnte man nach und nach auch einbauen.
z.b. wäre es relativ leicht möglich dinge wie 'jedes jahr am 24.12.' oder 'eine woche vor weihnachten bis eine woche nach neujahr' abzubilden.
ZitatIch arbeite leichter mit timestamps als mit irgendwelchen Datums-/Zeitformaten
ich wette auch du kannst ohne nachsehen nicht den timestamp für weihnachten nächstes jahr sagen.
fhem bringt ja von Haus aus einige Funktionen mit, um Strings in timestamps zu konvertieren. Insofern ist das, was von Euch vorgeschlagen wird, mit meinen Patches ebenfalls durchführbar.
Zitat von: justme1968 am 07 November 2015, 16:26:07
wenn man sich den standard anschaut findet man vermutlich noch ein paar andere nützliche dinge wie Zeitspannen, relative angaben oder kalender wochen. die könnte man nach und nach auch einbauen.
z.b. wäre es relativ leicht möglich dinge wie 'jedes jahr am 24.12.' oder 'eine woche vor weihnachten bis eine woche nach neujahr' abzubilden.
Das kann ja gerne irgendjemand irgendwann auch noch einbauen.
Aber die reinen timestamps bräuchte ich trotzdem :)
Eigentlich gehoeren Wuensche in die Wunschliste, das lese ich naemlich nicht. :)
Der Patch gefaellt mir nicht: es aendert das Interface. GetTimeSpec wird z.Zt in 11 Dateien verwendet und ich will nicht anfangen alle Module zu testen und Patches vorzuschlagen. Ich habe eine Alternative ohne Interface-Aenderung in fhem.pl eingebaut, allerdings ohne Hintertuer fuer Datumspezifikation. Eine kompatible Erweiterung der GetTimeSpec Interface mit Datum (Stichwort 8601) ist zwar nicht sehr aufwendig, eine konsequente Anpassung von at ist mir aber jetzt zu aufwendig. Und ob die anderen Module das beachten ist auch fragwuerdig.
Weiterhin ruft jetzt die {} Variante GetTimeSpec rekursiv auf, damit kein Code wiederholt wird.
Hallo Rudi,
die Änderung in der jetzigen Form ist aber nicht wirklich hilfreich.
define advent at 1448751600 set Weihnachtsbaum on
liefert als Ergebnis:
(http://up.picr.de/23639781ga.png)
was schlichtweg falsch ist.
Und was Du mit 8601 meinst, weiss ich genausowenig wie ich Deine Aussage "Interface von GetTimeSpec ändert sich" nicht verstehe. Bei meinem vorgeschlagenen Patch hatte ich extra darauf geachtet, den Funktionsaufruf NICHT zu verändern.
Zitat von: rudolfkoenig am 07 November 2015, 20:07:55
Eigentlich gehoeren Wuensche in die Wunschliste, das lese ich naemlich nicht. :)
Was denkst Du, warum ich den Wunsch hier reingeschrieben hatte 8)
Zitatdie Änderung in der jetzigen Form ist aber nicht wirklich hilfreich.
Wenn deine Absicht war, via at etwas zu definieren, was nicht innerhalb der naechsten 24 Stunden ausloest, dann sorry, das geht nicht, und bleibt erstmal auch so.
ZitatBei meinem vorgeschlagenen Patch hatte ich extra darauf geachtet, den Funktionsaufruf NICHT zu verändern.
Mag sein, aber das, was zureuckgeliefert wird, ist nicht das was die anderen 10 Anwender von GetTimeSpec erwarten.
Zitat von: rudolfkoenig am 07 November 2015, 20:46:30
Wenn deine Absicht war, via at etwas zu definieren, was nicht innerhalb der naechsten 24 Stunden ausloest,
Genau DAS steht als Hintergrund meines Wunsches in meinem ersten Beitrag hier im Thread:
Zitat von: betateilchen am 06 November 2015, 08:30:48
Damit könnte man auf einfach Art ein at zu einem bestimmten Datum vorprogrammieren,
Zitat von: rudolfkoenig am 07 November 2015, 20:46:30
aber das, was zureuckgeliefert wird, ist nicht das was die anderen 10 Anwender von GetTimeSpec erwarten.
Ok, dann bleiben immer noch zwei Möglichkeiten:
- den timestamp als "neuen" Rückgabewert zu liefern (kompatibel zu bestehenden Anwendungen, da zusätzliche Rückgabewerte kein Problem darstellen)
- die Behandlung von timestamps ausschließlich in 90_at.pm abzubilden und GetTimeSpec dazu nicht zu verwenden.
Hier noch ein neuer Vorschlag, der auch Deine Bedenken bezüglich anderer Verwendungsstellen von GetTimeSpec berücksichtigt und trotzdem Zeitpunkte > 24 Stunden zulässt.
Index: fhem.pl
===================================================================
--- fhem.pl (Revision 9810)
+++ fhem.pl (Arbeitskopie)
@@ -2913,7 +2913,7 @@
GetTimeSpec($)
{
my ($tspec) = @_;
- my ($hr, $min, $sec, $fn);
+ my ($hr, $min, $sec, $fn, $timestamp) = (0,0,0,'',0);
if($tspec =~ m/^([0-9]+):([0-5][0-9]):([0-5][0-9])$/) { # HH:MM:SS
($hr, $min, $sec) = ($1, $2, $3);
@@ -2923,7 +2923,7 @@
} elsif($tspec =~ m/^([0-9]{10})$/) { # seconds-since-1970
my @a = localtime($1);
- ($hr, $min, $sec) = ($a[2],$a[1],$a[0]);
+ ($hr, $min, $sec, $timestamp) = ($a[2],$a[1],$a[0],$tspec);
} elsif($tspec =~ m/^{(.*)}$/) { # {function}
$fn = $1;
@@ -2930,15 +2930,15 @@
$tspec = AnalyzeCommand(undef, "{$fn}");
$tspec = "<empty string>" if(!$tspec);
my ($err, $fn2);
- ($err, $hr, $min, $sec, $fn2) = GetTimeSpec($tspec);
+ ($err, $hr, $min, $sec, $fn2, $timestamp) = GetTimeSpec($tspec);
return ("the function \"$fn\" must return a timespec and not $tspec.",
- undef, undef, undef, undef) if($err);
+ undef, undef, undef, undef, undef) if($err);
} else {
return ("Wrong timespec $tspec: either HH:MM:SS or {perlcode}",
- undef, undef, undef, undef);
+ undef, undef, undef, undef, undef);
}
- return (undef, $hr, $min, $sec, $fn);
+ return (undef, $hr, $min, $sec, $fn, $timestamp);
}
Index: FHEM/90_at.pm
===================================================================
--- FHEM/90_at.pm (Revision 9810)
+++ FHEM/90_at.pm (Arbeitskopie)
@@ -62,9 +62,23 @@
return "Wrong timespec, use \"[+][*[{count}]]<time or func>\""
if($tm !~ m/^(\+)?(\*({\d+})?)?(.*)$/);
my ($rel, $rep, $cnt, $tspec) = ($1, $2, $3, $4);
- my ($err, $hr, $min, $sec, $fn) = GetTimeSpec($tspec);
+ my ($err, $hr, $min, $sec, $fn, $timestamp) = GetTimeSpec($tspec);
return $err if($err);
+ if ($timestamp) {
+ return "Wrong timespec, timestamp must describe a future time"
+ if time() >= $timestamp;
+ my $val = FmtDateTime($timestamp);
+ $hash->{TRIGGERTIME} = $timestamp;
+ $hash->{TRIGGERTIME_FMT} = $val;
+ $hash->{COMMAND} = $command;
+ RemoveInternalTimer($hash);
+ InternalTimer($timestamp, "at_Exec", $hash, 0);
+ readingsSingleUpdate($hash, "state", $val,
+ !$hash->{READINGS}{state} || $hash->{READINGS}{state}{VAL} ne $val);
+ return undef;
+ }
+
$rel = "" if(!defined($rel));
$rep = "" if(!defined($rep));
$cnt = "" if(!defined($cnt));
Und was passiert mit *1448751600 oder gar +*1448751600 ?
Nichts unerwartetes:
(http://up.picr.de/23644993wg.png)
(http://up.picr.de/23644994jb.png)
(http://up.picr.de/23644995ya.png)
+ und * machen bei einem absoluten timestamp ja nicht viel Sinn.
Hallo Rudi,
ich bitte Dich, Dich zwischen folgenden Varianten zu entscheiden.
- Entweder timestamps als timespec so zu verarbeiten, dass der korrekte Zeitpunkt gesetzt wird, der durch den timestamp eindeutig definiert ist.
- Oder die in GetTimeSpec() eingeführte Änderung für timestamps wieder auszubauen und keine timestamps zuzulassen (was ich sehr schade fände).
Aktuell generiert das at-Modul kommentarlos völlig sinnlose (falsche) at-Devices, wenn der Timestamp mehr als 24 Stunden in der Zukunft liegt. Das ergibt keinen Sinn und ist absolut verwirrend.
Ich habe die Sekunden aus GetTimeSpec entfernt, und zur at Definition die Moeglichkeit einer Datumsangabe im Form von Sekunden seit 1970 oder ISO8601 hinzugefuegt. Ein + oder * mit Datumsangabe wird nicht erlaubt, weiterhin ist die Datumsangabe dokumentiert.
Was weiterhin nicht geht, und vermutlich noch Arbeit fuer mich verursachen wird:
- falls at per Datum definiert ist, macht ein gesetztes aligntime Attribut alles kaputt
- der Wizard in der FHEMWEB Detail-Ansicht beherrscht die Datumsangabe nicht.
Hallo Rudi,
danke, dass Du das Thema nochmal aufgegriffen hast, ich werde das die Tage mal testen, bin allerdings aktuell noch ausser Haus unterwegs.
Zum Thema "alignTime" fällt mir spontan ein: Das alignTime macht doch ohnehin nur dann Sinn, wenn es sich um ein wiederholendes at handelt. Das aber ist nach Deiner Beschreibung bei Datumsangaben ausgeschlossen. Insofern müsste man das Problem doch in der AttrFn einfach abfangen können, wenn man prüft, ob das at überhaupt eine Wiederholung besitzt und dann gar nichts tut (ausser vielleicht einen Fehler loggen)?
Zum Wizard kann ich nicht viel beitragen, der ist mir ohenhin schon immer suspekt, vor allem wenn man darin per Mausklick versucht, ein wiederholendes at in ein relatives umzuwandeln - da passieren die merkwürdigsten Dinge 8)
ich traue es mich ja fast nicht zu sagen... aber mit deiner jetzigen Implementierung ist die Möglichkeit weggefallen, die "Sekunden seit 1970" als Rechenergebnis in {EvalPerl} zu übergeben.
Das alignTime Problem sollte sich nach einem ersten Blick in den Code in der AttrFn lösen lassen, wenn man dort auf $hash->{PERIODIC} prüft und einfach nichts tut, wenn es kein periodisches at ist.
alignTime ist doch kein Problem: es prueft selber auf periodic, und das ist bei der absoluten Zeitangabe nicht erlaubt.