FHEM Forum

FHEM => Automatisierung => Thema gestartet von: betateilchen am 06 November 2015, 08:30:48

Titel: [Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: betateilchen am 06 November 2015, 08:30:48
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.
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: betateilchen am 07 November 2015, 15:13:29
ok, ich bin grade dabei, einen vernünftigen patch vorzubereiten :)
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: betateilchen am 07 November 2015, 15:55:48
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>
-      &lt;timedet&gt; 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.
+      &lt;timedet&gt; 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 :)
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: Markus Bloch am 07 November 2015, 15:59:45
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
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: betateilchen am 07 November 2015, 16:23:54
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.
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: justme1968 am 07 November 2015, 16:26:07
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.
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: justme1968 am 07 November 2015, 16:27:10
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.
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: betateilchen am 07 November 2015, 16:30:45
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.

Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: betateilchen am 07 November 2015, 16:32:25
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 :)
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: rudolfkoenig am 07 November 2015, 20:07:55
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.
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: betateilchen am 07 November 2015, 20:17:59
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.
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: betateilchen am 07 November 2015, 20:18:52
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)
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: rudolfkoenig am 07 November 2015, 20:46:30
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.
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: betateilchen am 07 November 2015, 20:50:00
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:

Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: betateilchen am 07 November 2015, 21:32:57
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));
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: rudolfkoenig am 07 November 2015, 21:40:21
Und was passiert mit *1448751600 oder gar +*1448751600 ?
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: betateilchen am 08 November 2015, 11:11:56
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.
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: betateilchen am 11 November 2015, 21:00:35
Hallo Rudi,

ich bitte Dich, Dich zwischen folgenden Varianten zu entscheiden.


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.
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: rudolfkoenig am 12 November 2015, 19:13:11
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.
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: betateilchen am 12 November 2015, 23:00:54
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)
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: betateilchen am 13 November 2015, 12:22:14
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.
Titel: Antw:[Wunsch] 90.at.pm - timespec Definition als timestamp ermöglichen
Beitrag von: rudolfkoenig am 15 November 2015, 20:02:14
alignTime ist doch kein Problem: es prueft selber auf periodic, und das ist bei der absoluten Zeitangabe nicht erlaubt.