[gelöst] - ReadingsAge in HH:mm / Zeitspannen berechnen

Begonnen von 87insane, 12 April 2018, 16:00:12

Vorheriges Thema - Nächstes Thema

87insane

Hi zusammen,

bin den halben Tag dabei die Sekundenausgabe von ReadingsAge in etwas lesbares umzuwandeln ohne dabei x Variablen nutzen zu müssen.
Es geht mir vom Prinzip her darum:
Trockner läuft an und initiiert ein paar Dinge...(msg ich fange an usw.)
Trockner ist fertig und initiiert wieder ein paar Dinge...(msg ich bin fertig usw.)

Nun soll er mir am ende aber auch sagen wie lange er brauchte. Dafür wollte ich ReadingsAge nutzen.

Die Situation:
TP-Link HS110 Funkstecker
Dieser weiß aufgrund der Spannung wann er anläuft und wann er aufhört.

define n_s_trockner_start notify s_trockner:power:.* {\
     if (ReadingsNum("s_trockner", "power", 0) > 0 && ReadingsVal("s_trockner", "running", "off") eq "off") {\
          fhem("setreading s_trockner running on");;\
          fhem("set p.nachrichten message | ".strftime("%H:%M", localtime)." Uhr: Der Trockner startet");;\
     }\
     if (ReadingsNum("s_trockner", "power", 0) < 230 && ReadingsVal("s_trockner", "running", "off") eq "on") {\
          fhem("setreading s_trockner running off");;\
          fhem("set p.nachrichten message Verbrauch: ".ReadingsVal("s_trockner","trocknungsgang","")." Watt. Zeit: | ".strftime("%H:%M", localtime)." Uhr: Der Trockner ist fertig");;\
     }\
}


# Stromverbrauch berechenn
attr s_trockner userReadings total_temp:running.*on.* {ReadingsVal("s_trockner","total",0)},
attr s_trockner userReadings trocknungsgang:running.*off.* {ReadingsVal("s_trockner","total",0)-ReadingsVal("s_trockner","total_temp",0)}

# Zeit berechnen
???



Bessere Ideen und aber auch Anregungen, nehme ich gerne an! Ich komme mit ReadingsAge leider so nicht weiter. Kann man das ggf. irgendwie verschachteln?
Ich weiß, dass folgende macht keinen Sinn aber damit man besser versteht in wie fern ich das meine:
{strftime("%H:%M", localtime(ReadingsAge('s_trockner','total_temp',0)))}

DANKE!


EDIT 13.04.2018 - 22:03:

LÖSUNGEN
Um es allen Lesern einfacher zu machen, anbei die Ergebnisse...

Alle Lösungen bieten die Möglichkeit einfach und unkompliziert eine Zeitspanne zu bestimmen. Dies bezieht sich auf ein Reading welches gestartet wurde und beendet wurde.
Somit  ist es in meinem Fall, einfach möglich, heraus zu finden wann mein Trockner startete und wann er fertig war. Dies wird mir per Push auf mein Handy gesendet und
somit weiß ich wie lang er brauchte. Ob man es braucht? Es ist schön es zu haben.


{(split(' ', gmtime(ReadingsAge('s_trockner','running',0))))[3]} - Von @betateilchen (Einschränkung nicht mehr als 24 Stunden. @betateilchen hat noch weitere Möglichkeiten hier aufgezählt. Diese könnt ihr auf Seite zwei nachlesen.)

{strftime("%H:%M", gmtime(ReadingsAge('s_trockner','running',0)))} - Von @betateilchen, angepasst auf strftime Gleiches gillt auch für die Lösung. Hier wird die Zeit nicht durch split angepasst. Somit (soweit mir bekannt) kann das Zeitformat angepasst werden. Split teilt mit dem Trenner der in den ' ' angegeben wird.

sub sec2time($) {
    my ($sec) = @_;

    # return human readable format
    my $hours = ( abs($sec) < 3600 ? 0 : int( abs($sec) / 3600 ) );
    $sec -= ( $hours == 0 ? 0 : ( $hours * 3600 ) );
    my $minutes = ( abs($sec) < 60 ? 0 : int( abs($sec) / 60 ) );
    my $seconds = abs($sec) % 60;

    $hours   = "0" . $hours   if ( $hours < 10 );
    $minutes = "0" . $minutes if ( $minutes < 10 );
    $seconds = "0" . $seconds if ( $seconds < 10 );

    return "$hours:$minutes:$seconds";
}

Von @CoolTux Mir sind keine Einschränkungen bekannt. (Bin aber auch noch neu und ggf. kann das jemand genau benennen.)

{strftime("%H:%M", localtime(ReadingsAge('s_trockner','running',0)-3600))}

# Mit oder ohne Klammern -> Egal

{strftime("%H:%M", localtime ReadingsAge('s_trockner','running',0)-3600)}

Von @Beta-User und (behaupte ich mal) 87insane

Ansonsten gibt es noch einen lesenswerten Artikel hier: https://wiki.fhem.de/wiki/Zeitangaben,_rechnen_mit den @nils_ nochmal verlinkt hat.


Dake an alle!

Beta-User

Kannst du mit dem hier was anfangen?

https://forum.fhem.de/index.php/topic,57519.msg489463.html#msg489463

Mußt du halt ggf. umbauen, soweit ich das verstehe, braucht das sprintf als $s eine Sekundenangabe...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

betateilchen

Schau mal in die Moduldatei 98_uptime.pm dort habe ich genau so eine Umrechnung einer Sekundendifferenz eingebaut.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

87insane

Danke euch beiden schon mal!

Was ich nach wie vor nicht verstehe, warum muss ich das errechnen und nicht nur anzeigen lassen in einem anderen Format?

So wie ich das verstehe ist das ein Unix/Industrie Standard Zeit Format. Dieses wird in Sekunden ausgegeben. Gibt es tatsächlich kein Modul oder eine andere Vorgehensweise für mein Problem?
Oben sagte ich ja das ich am besten keine variable verwenden mag. Gab es früher nicht mal so was wie mktime (unix) oder so?

An sich geht es mir ja nur darum, dass der Trockner mir bei fertigstellung sagt:
Ich bin fertig und habe xx:xx gebraucht.

Gesendet von meinem LG-H850 mit Tapatalk


betateilchen

Es gibt natürlich perl Module für sowas, aber wenn man das in wenigen Zeilen perl auch selbst errechnen kann, muss man nicht erst noch Installationsarbeiten auf Betriebssystemebene vornehmen.

Ausserdem


  • in den Moduldateien wird auch nix anderes gemacht, als die Sekunden durch größere Einheiten zu dividieren
  • die 99_myUtils.pm ist auch nur eine perl Moduldatei

Hier die fertige Lösung für die 99_myUtils.pm


sub secs2human($){
  my ($diff) = @_;
  my ($d,$h,$m,$ret);
  ($d,$diff) = _s2h_Div($diff,86400);
  ($h,$diff) = _s2h_Div($diff,3600);
  ($m,$diff) = _s2h_Div($diff,60);

  $ret  = "";
  $ret .= "$d days, " if($d >  1);
  $ret .= "1 day, "   if($d == 1);
  $ret .= sprintf("%02s:%02s:%02s", $h, $m, $diff);

  return $ret;
}

sub _s2h_Div($$) {
  my ($p1,$p2) = @_;
  return (int($p1/$p2), $p1 % $p2);
}



Beide Funktionen in die 99_myUtils.pm packen und dann das Ergebnis mit

secs2human(123456)

abrufen: 1 day, 10:17:36

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

CoolTux

Ungetestet


($Stunden, $Minuten, $Sekunden)=(int($Sekunden/3600), int(($Sekunden % 3600) / 60), $Sekunden % 60);
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

betateilchen

Das ist funktional die gleiche Kettendivision wie in meinem Beispiel, nur dass mein Beispiel auch noch Tag(e) zurückliefert.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

CoolTux

Sofern die Waschmaschine denn Tage benötigt   ;D
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

betateilchen

Ja, und man sollte bedenken, dass bei dieser Berechnung eventuell auftretende Schaltsekunden auch nicht berücksichtigt werden.




Aber hier noch eine Lösung mit perl Bordmitteln:


use strict;
use warnings;

use Time::Piece;
use Time::Seconds qw/ ONE_DAY /;

my $start = localtime;
my $end = $start + int(355/113 * ONE_DAY);

my $duration = ($end - $start)->pretty;
print "Total Execution time: $duration\n";


liefert:Total Execution time: 3 days, 3 hours, 23 minutes, 53 seconds

Die meisten Variablen darin dienen nur zur Erzeugung der Beispieldaten.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

87insane

Hey und danke!
Werde es morgen mal testen.

An sich kann ich wohl einfach nicht nachvollziehen das nur wenige Leute solche Fälle haben. Oder aber sie nehmen einen anderen weg. Sonst würden ja mehr auch die Umrechnung haben wollen. Und das ist meist das schöne in fhem-> es gibt ein Modul.

Die Ausgabe von readingsage sollte variabler sein. Vom Prinzip her ist ja alles da. Ich höre mal auf zu meckern, immerhin bin ich neu hier.

Aber mal am Rande: die sehr schnellen antworten und die gute Hilfe hier, ist echt gigantisch. Nicht mal bei XDA zb ist das derart gut. Top an alle!!

Gesendet von meinem LG-H850 mit Tapatalk


87insane

Hey zusammen,

ich versuche es nochmal anders rum....

Wenn ich nun ein Reading nehme. Dieses wird geschrieben zu Event beginn. Sieht man auch oben im Quelltext. Nun gehe ich hin und lese nicht das alter in Sekunden aus sondern den Timestamp.
Dies sollte ausgelöst werden durch den ENDE Event. Nun nehme ich die lokale Zeit und ziehe dies von der Zeit die zum Ursprung des Events drin war ab. Ich habe zwar einen Timestamp der auch im englischen Format ist (FHEM üblich) aber das sollte sich ja umwandeln lassen...

   
total_temp: 2018-04-12 13:02:37
localtime:    Thu Apr 12 22:11:19 2018

bestimmt gibt es bessere time Variablen aber die kann ich ja ggf noch googlen. Es gibt mit Sicherheit auch eine FHEM Variable die mir die Zeit wie in den LOGs anzeigt. Diese müsste man ja nur abziehen voneinander und am ende hätte ich das gewünschte Ergebnis ohne um zu rechnen, oder?

87insane

Guten Morgen zusammen,

scheint wohl auch nicht so recht zu klappen...

An sich würde ich wie folgt vorgehen wollen:
localtime: {strftime("%H:%M:%S",localtime)}
Timestamp: {(split(' ',ReadingsTimestamp("s_trockner","running",0)))[1]}

So hätte ich als Ausgabe einen identischen Wert. Zumindest was das Format angeht (HH:MM:SS).
Nun habe ich gedacht (ich dummerchen), ich könne wie in Excel einfach die Zeiten voneinander abziehen.
Hat da jemand ein Modul im Kops oder so, was dies ermöglicht? Auch hier wieder, am besten eine Zeile am Ende und keine Variablen und hin und her Wandlung....
Spannend ist was daraus wird ;)

Danke und bis später :)

nils_

also ich habe den Thread jetzt 5 mal gelesen, und ich verstehe dein Problem überhaupt nicht....

was ist an ReadingsAge "falsch" ??
hast du die Lösungen von betateilchen / CoolTux gesehen, gelesen, verstanden, ausprobiert??
viele Wege in FHEM es gibt!

87insane

Hey,

verstanden, ja - getestet, ja....

Was mich stört ist das man etwas programmieren muss. Für die Umwandlung von Zeit/Datum in ein UNIX Format gibt es einfache Befehle ohne es umrechnen zu müssen.
Das gleiche würde ich einfach nur gern umgekehrt machen wollen. Ich bin nun den zweiten Tag am googlen und finde nicht das richtige.
ReadingAge bringt nur Sekunden. Das ist unschön. Die Umrechnungen von den beiden Kollegen sind funktional aber nicht das gewünschte Resultat.
Zwei Wege hatte ich mir ausgedacht.

Weg 1: Über ReadingsAge (Siehe oben) - Ergebnis: Mit Sekunden kann man nicht ohne zusätzlich Berechnung auf Std:Min kommen.
Weg 2: Über den Timestamp (Siehe oben) - Ergebnis: Die beiden Timestaps kann ich aktuell nicht korrekt subtrahieren.

Weitere Wege würde ich gerne in Erfahrung bringen. Hinzu geht es mit den angedachten Wegen ja doch..

nils_

Zitat von: 87insane am 13 April 2018, 10:30:33
Was mich stört ist das man etwas programmieren muss.
willkommen bei fhem :D


Zitat von: 87insane am 13 April 2018, 10:30:33
ReadingAge bringt nur Sekunden. Das ist unschön. Die Umrechnungen von den beiden Kollegen sind funktional aber nicht das gewünschte Resultat.
was ist denn an dem Resultat falsch??
die Ausgabe des Textes?? den kannste dir ja auf deine Bedürfnisse anpassen.


viele Wege in FHEM es gibt!