InternalTimer mit absoluter Zeit

Begonnen von Schuggi, 29 Juli 2013, 10:19:40

Vorheriges Thema - Nächstes Thema

Schuggi

Wie kann ich InternalTimer am einfachsten mit einer absoluten Zeit also zum Beispiel auf heute um 23:00 setzen?
Bei allen Beispielen die ich gefunden habe, wird der Timer immer auf eine relative Zeit gesetzt.

Gruß
  Schuggi
Fhem auf EEE-PC Windows7 (XAMPP),
CUL,
(RasPi, QNAP TS109II)
Angebunden an Fhem:
2xVelux-Rolladen, 3x S0 Stromzähler, Wetterstation WH1080, 2x S300TH

bugster_de

Hi,

setzt den Timer einmalig heute um 23:00:00 Uhr:
define myTimer at 23:00:00 set irgendwas

setzt den Timer jeden Tag um 23:00:00 Uhr:
define myTimer at *23:00:00 set irgendwas

setzt den Timer in einer Stunde:
define myTimer at +01:00:00 set irgendwas

setzt den Timer jede Stunde:
define myTimer at +*01:00:00 set irgendwas

Schuggi

Danke für die Antwort, da ich das aber in ein Modul einbauen will,
möchte ich den "InternalTimer" verwenden.

Gruß
  Schuggi
Fhem auf EEE-PC Windows7 (XAMPP),
CUL,
(RasPi, QNAP TS109II)
Angebunden an Fhem:
2xVelux-Rolladen, 3x S0 Stromzähler, Wetterstation WH1080, 2x S300TH

betateilchen

timestamp für den gewünschten Zeitpunkt errechnen und diesen als ersten Funktionswert an Internaltimer übergeben. Wenn Du dann innerhalb der ersten Ausführung mit gettimeofday+86400 triggerst, wird der Zeitpunkt am nächsten Tag wieder aktiviert.

InternalTimer($timestamp, "tueIrgendwas", $hash, 0);



Converting DMYHMS to Epoch Seconds
#-----------------------------
use Time::Local;
$TIME = timelocal($sec, $min, $hours, $mday, $mon, $year);
$TIME = timegm($sec, $min, $hours, $mday, $mon, $year);
#-----------------------------
# $hours, $minutes, and $seconds represent a time today,
# in the current time zone
use Time::Local;
$time = timelocal($seconds, $minutes, $hours, (localtime)[3,4,5]);
#-----------------------------
# $day is day in month (1-31)
# $month is month in year (1-12)
# $year is four-digit year e.g., 1967
# $hours, $minutes and $seconds represent UTC time
use Time::Local;
$time = timegm($seconds, $minutes, $hours, $day, $month-1, $year-1900);
#-----------------------------
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Schuggi

Hallo betateilchen,
prinzipiell funktioniert es:
InternalTimer(timelocal(0, 23, 12, (localtime)[3,4,5]),"Solarlog_Tagesergebnis",$hash, 0);

Ich dachte allerdings das ich auf die Zeit einfach einen Wert in Sekunden aufaddieren kann.
 my $next = timelocal(0, 23, 12, (localtime)[3,4,5])+120;
  InternalTimer($next ,"Solarlog_Tagesergebnis",$hash, 0);


Ich hätte gedacht das der Timer dann um 12:25 zuschlägt, das macht er aber nicht.
Wo liegt mein Denkfehler?

Das oben ist nur ein Test später wollte ich den Timer wie folgt setzen damit er morgen um 23:00 zuschlägt
 my $next = timelocal(0, 0, 23, (localtime)[3,4,5])+86400;
  InternalTimer($next ,"Solarlog_Tagesergebnis",$hash, 0);


Gruß
  Schuggi
Fhem auf EEE-PC Windows7 (XAMPP),
CUL,
(RasPi, QNAP TS109II)
Angebunden an Fhem:
2xVelux-Rolladen, 3x S0 Stromzähler, Wetterstation WH1080, 2x S300TH

betateilchen

Hallo :)

Eigentlich müsste es mit diesem Ablaufschema funktionieren:

1. Der InternalTimer wird bei der ersten Initialisierung auf einen von Dir gesetzten Wert eingestellt.
2. Zum eingestellten Zeitpunkt ruft er die Funktion "Solarlog_Tagesergebnis" auf.
3. Innerhalb dieser Funktion (!) musst Du den InternalTimer dann mit (gettimeofday()+interval) neu setzen.

Ich würde übrigens auch den ersten Zeitpunkt mit (gettimeofday()+offset) definieren und dabei das offset ausgehend von der aktuellen Uhrzeit einmalig berechnen.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Schuggi

Prinzipiell will ich ganau das machen.
Die Funktion soll jeden Tag um 23:00 aufgerufen werden um den Tagesertrag der Solaranlage umzukopieren.
Ich bin noch nicht so fitt in Perl daher wollte ich mir die Sache möglichst einfach machen.
Leider sind vile Funktionen nicht wirklich gut dokumentiert oder ich tu mich da einfach noch etwas schwer.

Aber warum funktioniert das Aufaddieren und den Zeitstempel nicht?

sub
Solarlog_Tagesergebnis($)
{
  my ($hash) = @_;
  $hash->{READINGS}{ErtragTag}{TIME} = TimeNow();
  $hash->{READINGS}{ErtragTag}{VAL} = $hash->{READINGS}{Ertrag}{VAL};
  my $next = timelocal(0, 23, 12, (localtime)[3,4,5])+120;
  InternalTimer($next ,"Solarlog_Tagesergebnis",$hash, 0);
  return undef;
}


Ich hab nicht nur eine zeitliche Verschiebung sondern der Timer wird immer wieder ständig aufgerufen.

Gruß
  Schuggi
Fhem auf EEE-PC Windows7 (XAMPP),
CUL,
(RasPi, QNAP TS109II)
Angebunden an Fhem:
2xVelux-Rolladen, 3x S0 Stromzähler, Wetterstation WH1080, 2x S300TH

betateilchen

Das macht man so nicht:

  my ($hash) = @_;
  $hash->{READINGS}{ErtragTag}{TIME} = TimeNow();
  $hash->{READINGS}{ErtragTag}{VAL} = $hash->{READINGS}{Ertrag}{VAL};


sondern so:

my ($hash) = @_;
my $name = $hash->{NAME};
readingsSingleUpdate($hash, "ErtragTag", ReadingsVal($name,"Ertrag",0), 1);


ZitatLeider sind viele Funktionen nicht wirklich gut dokumentiert

am besten versteht man sie, wenn man sie sich in der fhem.pl anschaut.

Zitatoder ich tu mich da einfach noch etwas schwer.

das ist nicht schlimm, dafür gibts ja das Forum.

ZitatAber warum funktioniert das Aufaddieren und den Zeitstempel nicht?

Weil Du das Prinzip des InternalTimers noch nicht ganz verstanden hast.

Nochmal - so nicht:


sub
Solarlog_Tagesergebnis($)
{
... was auch immer da gemacht wird;

InternalTimer($next ,"Solarlog_Tagesergebnis",$hash, 0);
}


sondern:


sub
Solarlog_Tagesergebnis($)
{
... was auch immer da gemacht wird;

RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+86400,"Solarlog_Tagesergebnis",$hash, 0);
}


Und NUR in der *_Define() Deines Moduls musst Du den InternalTimer EINMALIG auf den Timestamp für das nächste 23:00:00 einstellen.
Eigentlich müsste man das RemoveInternalTimer sogar weglassen können - aber es schadet auch nicht.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Dietmar63

bereite das Feld $next vor dem Setzen des InternalTimers mit
Log 3, "next: " . strftime('%d.%m.%Y %H:%M:%S',localtime($next));
auf. Dann wirst du das Problem schnell lokalisieren.
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

Schuggi

 my ($hash) = @_;
  $hash->{READINGS}{ErtragTag}{TIME} = TimeNow();
  $hash->{READINGS}{ErtragTag}{VAL} = $hash->{READINGS}{Ertrag}{VAL};


Das war so in dem Modul drinnen, das ich gerade anpasse.
Das werde ich dann mal umstellen.

InternalTimer(gettimeofday()+86400,"Solarlog_Tagesergebnis",$hash, 0);
Bei dieser Lösung hatte ich bedenken, das sich der Zeitpunkt langsam verschiebt und dann langsam wegläuft.
Daher wollte ich den Zeitpunkt anhand einer absoluten Zeitangabe setzen.

RemoveInternalTimer($hash);
Bisher hab ich das auch so verstanden, dass man den Remove nicht braucht, da der Timer nicht automatisch wiederholt wird.

Gruß
  Schuggi
Fhem auf EEE-PC Windows7 (XAMPP),
CUL,
(RasPi, QNAP TS109II)
Angebunden an Fhem:
2xVelux-Rolladen, 3x S0 Stromzähler, Wetterstation WH1080, 2x S300TH

betateilchen

Zitat von: Schuggi schrieb am Mo, 29 Juli 2013 14:38Bei dieser Lösung hatte ich bedenken, das sich der Zeitpunkt langsam verschiebt und dann langsam wegläuft.

Wenn Du in Deinem Modul mit Time::Hires arbeitest, bewegst Du Dich da maximal im Millisekundenbereich. Und nicht vergessen: mit jedem Neustart (z.B. nach einem Update) wird das Ganze ja wieder neu getriggert. Ich denke, das Weglaufen kannst Du vernachlässigen. Probier diesen Ansatz doch einfach erstmal aus.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Dietmar63

wenn man

InternalTimer(gettimeofday()+86400,"Solarlog_Tagesergebnis",$hash, 0);

programmiert, landet man nicht immer exakt bei 23:00 Uhr. Man muss immer die Sekunden bis 23:00 ausrechen und auf time() addieren.

Ich glaube
my $next = timelocal(0, 0, 23, (localtime)[3,4,5])+86400;

ist schon richtig gedacht. Wie schon geschrieben mit strftime   die berechnete Zeit ausgeben. Dann ist der Fehler schnell gefunden.

Ich meine, dass wenn man einen InternalTimer in die Vergangenheit setzt, dann kann man sich leicht eine Endlosschleife basteln, weil die alten Timer alle immer wieder abgearbeitet werden - In der Testphase vielleicht mit $next > time() sicherstellen.
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

betateilchen

Zitat von: Dietmar63 schrieb am Mo, 29 Juli 2013 14:44wenn man
...
programmiert, landet man nicht immer exakt bei 23:00 Uhr.

Ich arbeite NUR so, und bisher bewege ich mich immer noch im gleichen stabilen Raum-Zeit-Kontinuum ohne jegliche Verschiebung.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Schuggi

Habs mal probiert.
hier der Code:

 my $next = timelocal(0, 0, 23, (localtime)[3,4,5]);
  Log 1, "next1: " . strftime('%d.%m.%Y %H:%M:%S',localtime($next));
  $next = $next+86400;
  Log 1, "next2: " . strftime('%d.%m.%Y %H:%M:%S',localtime($next));

 und hier die Ausgabe:

2013.07.29 14:53:00.027 1: next1: 29.07.2013 23:00:00
2013.07.29 14:53:00.028 1: next2: 30.07.2013 23:00:00


Sieht ja alles richtig aus. Ich hab jetzt auch den RemoveTimer drinnen. Eventuell lags daran.

Gruß und Dank
  Schuggi
Fhem auf EEE-PC Windows7 (XAMPP),
CUL,
(RasPi, QNAP TS109II)
Angebunden an Fhem:
2xVelux-Rolladen, 3x S0 Stromzähler, Wetterstation WH1080, 2x S300TH

betateilchen

-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!