FHEM Forum

FHEM => Anfängerfragen => Thema gestartet von: Marcus am 28 April 2013, 12:02:29

Titel: Programmieren mit Uhrzeit
Beitrag von: Marcus am 28 April 2013, 12:02:29
Wohl nicht so ganz Anfängerfrage, aber ich habs mal hier rein gestellt.

Ich möchte gern fhem etwas erweitern, kann auch gut programmieren, nur kein Perl. Ich möchte gern ein paar Dinge mit der Uhrzeit berechnen wie z.B.

if(uhrzeit1 < uhrzeit2)
oder
uhrzeit1 + 3 std.

usw. Allerdings weiß ich nicht so recht, in welchen Datentypen die Uhrzeit in fhem genutzt wird. In einigen Snippets die ich gesehen habe (z.B. http://www.fhemwiki.de/wiki/Uhrzeit:_Offset_berechnen (//www.fhemwiki.de/wiki/Uhrzeit:_Offset_berechnen)), wird das Uhrzeitobjekt zerlegt, dann mühsam mit den "Einzelteilen" davon gerechnet und dann als String wieder zurück gegeben. Geht das auch einfacher / besser? Oder ist das der Weg unter Perl/fhem?

Oder gibt es wenigstens eine integrierte Methode, mit der ich das Datum in einen Unix-Timestamp (damit lässt sich dann ja einfach rechnen / vergleichen) konvertieren (und wieder zurück) kann?
Titel: Aw: Programmieren mit Uhrzeit
Beitrag von: stromer-12 am 28 April 2013, 12:45:29
In der FHEM Console eingegeben ergibt das bei mir aktuelle Zeit + 3Stunden.

{strftime "%H:%M", localtime  time+3600*3;}
15:44
{time+3600*3;}
1367156676
Titel: Aw: Programmieren mit Uhrzeit
Beitrag von: Marcus am 28 April 2013, 16:50:37
Danke, das hilft mir schonmal. Wie ich sehe, gibt z.B. sunset die Uhrzeit allerdings "human readable" aus (21:30:21)?

D.h. fhem arbeitet mit diesen lesbaren Uhrzeitformaten? Wenn ich also eine Berechnung auf Basis von sunset machen will, muss ich das erst per mktime in einen Timestamp umwandeln, dann rechnen und dann per strftime wieder in die Form für fhem bringen?
Titel: Aw: Programmieren mit Uhrzeit
Beitrag von: Dietmar63 am 28 April 2013, 17:51:40
Sunset kann direkt ein offset in Sekunden einrechnen.

Perl hat ähnlich wie c++ nur ein oo - Aufsatz, der aber in vielen Fällen nicht genutzt wird. Such mal nach 'perl bless' im Netz. In fhem wird oo nicht genutzt. Es gibt aber viele Bibliotheken, die man in der Regel über cpan nachladen kann.

Fhem läuft aber auf vielen schwachbrustiger Hardware(FB, nas,... ) auf der das nun wieder auch nicht funktioniert.

Bevor du loslegst, such dir in den Sourcen von fhem Beispiele.

time() liefert epoch
Localtime, gmtime bereiten epoch als array auf - damit kann man nicht gut rechnen(alles zu Fuß) .

Trotzdem ist Perl ein Hammer!



Titel: Aw: Programmieren mit Uhrzeit
Beitrag von: Marcus am 29 April 2013, 07:09:17
Nur ein Offset bei sunset reicht mir nicht. Ich möchte noch das Wochenende mit einbauen und vor allem einen Min-/Max Wert (derzeit ist Sonnenaufgang um 5.24 Uhr, da sollen aber die Rolläden noch nicht hoch fahren, ein starres Offset funktioniert aber nicht, weil dann im Winter die Rolläden erst um 11 Uhr hoch fahren würden).

Trotzdem danke für den Hinweis.

Also wenn ich die Uhrzeit von sunset bekomme, muss ich per String-Zerlegung und mktime eine Unix-Zeit drauß machen?

Z.B. so, Stunde & Minute aus dem String und den rest aus der aktuellen Uhrzeit?

my $TimeP = mktime(0,substr($PtimeOrg,3,2),substr($PtimeOrg,0,2),$mday,$month,$year,$wday,$yday,$isdst);

Glaub gerne, dass Perl ein Hammer ist, wenn man es kann. ;) Also Java Programmierer sieht vieles erstmal recht gruselig aus. ;)
Titel: Aw: Programmieren mit Uhrzeit
Beitrag von: Dietmar63 am 29 April 2013, 19:50:05
im Prinzip richtig - aber localtime bzw. timelocal_nocheck nutzen. So(s.u.) hat es bei mir funktioniert als ich mal das Datum der Sommerzeitumstellung ermitteln wollte. Mit localtime() bzw. timelocal_nocheck wird der Zeitversatz zur utc eingerechnet(mktime habe ich nicht probiert):


use Time::Local 'timelocal_nocheck';

...

   my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($now);

   # compute epoch of last day of March, Oktober
   my $letzterTagImMaerzZweiUhr = timelocal_nocheck(0,0,2,31,2,$year);



Perl:

richtig gut sind hashs - vergleichbar mit hashmaps in Java.
werden ganz einfach wie Arrays mit Werten gefüllt - gibt noch mehr Möglichkeiten(goolge hilft immer).

my %hash = ();

$hash{eins} = "one";
$hash{zwei} = "two";

...

# hash of hash of hash of hash ...
$hash{ID1}{ID2}{ID3}{ID4} = "wasauchimmer";


oder:
mit dieser Zeile:
my @ret = &{$fn}($hash);

wird in der folgenden Schleife für alle Definitionen von Heating_Control in fhem die Funktion "Heating_Control_Update" aufgerufen. Der dynamische Aufruf von Funktionen wird in fhem vielfach genutzt und macht mit so wenig Code soviel möglich.


  foreach my $hc ( sort keys %{$modules{Heating_Control}{defptr}} ) {  # Schleife über alle defs von HC
     my $hash = $modules{Heating_Control}{defptr}{$hc};                # so etwas wie eine Instanz von Heating_Control

     my $val;
     my $cond = $hash->{helper}{CONDITION};                   # Bedingung(Perlcode)
     $val = eval $cond;                                       # Bedingung ausführen
     next if (!$val);

     $fn  = "Heating_Control_Update";

     no strict "refs";
     my @ret = &{$fn}($hash);                                 # Heating_Control_Update mit $hash als Parameter
  }


der Code:

$val = eval $cond;


führt den Code in $cond (z.Bsp: (heizungAnAus("An", 0)) ) dynamisch aus(wird über fhem.cfg oder die Oberfläche gesetzt, muss perl-syntaktisch richtig sein).
Der Aufruf von "Heating_Control_Update" wird nur dann ausgeführt, wenn $val true wird.
Titel: Aw: Programmieren mit Uhrzeit
Beitrag von: Marcus am 30 April 2013, 16:14:45
Danke, ich habs jetzt (erstmal) über diese beiden Methoden gelöst:
sub
fromFhemDate($)
{
  my $in = shift;
  my $h = substr($in, 0,2);
  my $m = substr($in, 3,2);
  my $s = substr($in, 6,2);

  my ($csec, $cmin, $chour, $cmonth, $cyear, $cwday, $cyday, $cisdst) = localtime;

  my $needADay = 0;
  while($h > 24) {
    $h = $h - 24;
    $needADay++;
  }

  my $t = mktime($s, $m, $h, $cmonth, $cyear, $cwday, $cyday, $cisdst);

  # Tage wieder drauf addieren
  #$t = $t + $needADay * 60 * 60 * 24;
  return $t;
}

sub
toFhemDate($)
{
  my $in = shift;
  my ($Psec,$Pmin,$Phour,$Pmday,$Pmonth,$Pyear,$Pwday,$Pyday,$Pisdst) = localtime($in);
  return sprintf("%02d:%02d:%02d", $Phour, $Pmin, $Psec);
}


Sicher nicht ganz schön und nicht ganz safe (erwartet die Zeit in der Form hh:mm:ss), aber für meine Zwecke reicht es derzeit. Brauche das ja hauptsächlich, um mit dem sunset/sunrise Datum weiter zu rechnen. Und das liefert mir genau dieses Format.

Perl:
Dass es in einigen Fällen ganz toll ist, glaube ich. Ist ja ähnlich PHP. Aber es fehlt halt auch einiges an "Compiler-Sicherheit". Und so konstrukte wie
return $u if(int(@a) < 3);
sind zwar gewissermaßen "menschenlesbar" (tue etwas, wenn...), aber wenn man aber Programmierer und die "Computersprache" gewöhnt ist, ist das erstmal total verwirrend. ;-)
Titel: Aw: Programmieren mit Uhrzeit
Beitrag von: fritz am 01 Mai 2013, 02:48:59
Zitat von: Marcus schrieb am Di, 30 April 2013 16:14Dass es in einigen Fällen ganz toll ist, glaube ich. Ist ja ähnlich PHP. Aber es fehlt halt auch einiges an "Compiler-Sicherheit". Und so konstrukte wie
return $u if(int(@a) < 3);
sind zwar gewissermaßen "menschenlesbar" (tue etwas, wenn...), aber wenn man aber Programmierer und die "Computersprache" gewöhnt ist, ist das erstmal total verwirrend. ;-)

In gewisser Weise trifft's das Wesen, aber auch wieder nicht. Ich war seinerzeit (2000) beim 2. Deutschen Perl-Workshop dabei - inzwischen gab es den 15. - wir bekamen damals u.a. auch ein T-Shirt mit einem Zitat von Larry Wall, Tom Christiansen Und Randal L. Schwartz (Vorwort zu "Programming Perl"):
ZitatPerl is a language to getting your job done.
Of course, if your job is programming, you can get your job done with any 'complete' computer language, theoretically speaking. But we know from experience that computer languages differ not so much in what they make possible, but in what they make easy. At one extreme, the so-called "fourth generation" languages" make it easy to do some things, but nearly impossible to do other things. At the other extreme, certail well-known, "industrial-strength" languages make it equally difficult to do almost everything.
Perl is different. In a nutshell, Perl is designed to make the easy jobs easy, without making the hard jobs impossible.

Und das ist meine Erfahrung aus vielen Jahren Entwicklung: Du kannst Perl "mal schnell" eben nutzen, ein Problemchen zu lösen (Logfile-Analyse, Auswertung von Web-Seiten, Code-Generierung etc.), wo es nicht darauf ankommt, wie Du Dein Programm entwirfst oder dokumentierst: perl -pe 's/(\d\d\d\d)\.(\d\d)\.(\d\d)/$3.$2.$1/' fhem-2013-04.log | less formatiert Dir z.B. mal schnell Dein Datum um, falls Du so etwas brauchst.
Das ist m.M.n. der Vorteil von Perl: Du kannst mal eben ganz schnell...
Und am anderen Ende findest Du solche Sachen wie FHEM oder bbbike.de in Perl programmiert...

"Aber wenn man aber Programmierer und die "Computersprache" gewöhnt ist, ist das erstmal total verwirrend." Was verwirrt dich? Dass du auf einmal so programmieren kannst, wie du auch denkst? Dass sich Dein Programm wie ein Text liest? Ist doch schön. Aber wenn du nicht (Ampel{rot, gelb, grün}=(\&halt, \&attention, \&go);
# hier würde ich gleich die Subroutinen definieren, aber es soll erst mal nicht zu "kompliziert" wirken
nebst Ampel{$farbe}->($arg1, $arg2) schreiben magst, sondern das etwas länger übersichtlicher empfindest, kannst du das in Perl natürlich auch. TIMTOWTDI(*). Lass das Computer-Stottern sein, unterhalte dich (auch) in Perl! :-)

(Das musste ich mal sagen, 'tschuldigung, dass es kein Problem löst)

<F>

P.S.: Perl war so universell, dass es seinerzeit als verbreitetste Skript-Sprache im Web eingesetzt wurde, nur kann man mit Perl natürlich viel mehr als nur dynamische Webseiten generieren. Da kam jemand daher, hat alles, was man im Web gemeinhin nicht braucht, aus der Sprache entfernt, dafür andere Sachen besser(?), gezielter(?) unterstützt und das ganze PHP genannt. Daher die "Ähnlichkeit".

(*) there is more than one way to do it. - Perl-Entwickler kennen keine "guten" und "schlechten" Lösungen.

Titel: Aw: Programmieren mit Uhrzeit
Beitrag von: jsb73 am 01 Mai 2013, 11:32:19
Hallo,

die Qualität eines Programms hängt nicht von der Programmierspache sondern von Disziplin und Fähigkeiten des Programmierers ab... Perl ist schon eine geniale Sprache, aber die Freiheiten können auch zu total unlesbaren Code führen.

Zurück zum Thema. Aktionen kannst Du z.B. per at mit variablen Zeiten definieren

# 15 min vor Sonnenuntergang - nicht vor 18:00, nach 20:00
define at_Abends_Rolladen_Zu at *{sunset(-600,"18:00","20:00")} { \



Wenn Du wirklich mit Zeiten rechnen willst, am besten alles auf epoch, d.h. forlaufende Sekunden umrechnen

# 2013-04-30 19:28:21
my $locked_tstamp = ReadingsTimestamp($name,"actor_locked",0);

my @locked        = split(" ",$locked_tstamp);
my @locked_day    = split("-",$locked[0]);
my @locked_time   = split(":",$locked[1]);
my $locked_time   = fhemTimeLocal($locked_time[2],$locked_time[1],$locked_time[0],$locked_day[2],$locked_day[1],$locked_day[0]);

my $now_tstamp    = TimeNow();
my @now           = split(" ",$now_tstamp);
my @now_day       = split("-",$now[0]);
my @now_time      = split(":",$now[1]);
my $now_time      = fhemTimeLocal($now_time[2],$now_time[1],$now_time[0],$now_day[2],$now_day[1],$now_day[0]);

my $del_minutes   = int(($now_time - $locked_time)/60);


In fhem.pl findest Du schon time-Funktionen, z.B. TimeNow(), FmtDateTime(), FmtTime(), SecondsTillTomorrow, ReadingsTimestamp(), fhemTzOffset(), fhemTimeGm(), fhemTimeLocal().

Gute Code-Beispiele für Perl findest Du bei Tante Gockle...

Jan
Titel: Antw:Aw: Programmieren mit Uhrzeit
Beitrag von: mi.ke am 24 August 2014, 19:24:09

Zitat von: jsb73 am 01 Mai 2013, 11:32:19
In fhem.pl findest Du schon time-Funktionen, z.B. TimeNow(), FmtDateTime(), FmtTime(), SecondsTillTomorrow, ReadingsTimestamp(), fhemTzOffset(), fhemTimeGm(), fhemTimeLocal().

wie geil ist das denn !
Der Thread ist 1,5 Jahre alt

Sowas hätt' ich schon des öfteren gebraucht.
Egal, klasse, endlich kann ich "frühr oder später" gescheit auswerten

PS.
Das steht in keiner commandref

Cheers
mi.ke
Titel: Antw:Programmieren mit Uhrzeit
Beitrag von: ronny332 am 05 Januar 2015, 13:52:03
Da ich auch gerade mal wieder das Rad neu erfunden habe (ohne hier zuerst zu gucken), werfe ich einfach mal mein Ergebnis hinterher, mit dem man prima mit Sonnenauf- und Sonnenuntergang rechnen kann:


  my ($seconds, $minutes, $hours, $day, $month, $year) = localtime(time);
  my ($sunrise_hours, $sunrise_minutes, $sunrise_seconds) = split(":", sunrise_abs());
  my ($sunset_hours, $sunset_minutes, $sunset_seconds) = split(":", sunset_abs());

  my $ts_sunrise = mktime($sunrise_seconds, $sunrise_minutes, $sunrise_hours, $day, $month, $year);
  my $ts_sunset = mktime($sunset_seconds, $sunset_minutes, $sunset_hours, $day, $month, $year);

  Log 1, $ts_sunrise;
  Log 1, $ts_sunset;


Das Ganze lässt sich natürlich beliebt hin und her bauen (unabhängig von sunset und sunrise), aber in meinem Fall brauchte ich den Timestamp vom Sonnenuntergang.
Titel: Antw:Programmieren mit Uhrzeit
Beitrag von: BenMarloe am 30 Juli 2015, 22:22:35
Danke! - das war wirklich eine Erkenntnis für mich.