at mit in Subroutine berechneter Zeit füllen

Begonnen von MisterEltako, 04 März 2013, 18:16:03

Vorheriges Thema - Nächstes Thema

MisterEltako

Hi!

Ich möchte aus fhem.cfg Parameter an eine Subroutine in myUtils.pm übergeben, eine Zeitdifferenz dortberechnen und wieder an Fhem zur Definition eines at-Kommandos übergeben (ähnlich sunset...).

Habe schon verschiedenes probiert, aber es kommt immer: Wrong timespec oder perlcode...

define Test at{Offset("sunset", "00:10:00, 17:00:00, 21:00:00)} set Rollladen on


myUtils.pm:
sub Offset($$$$){
my $Zeitstring = ReadingsVal("Local_Wetter",$Methode,"nv");
if ($Zeitstring eq "nv") {return "Fehler bei der Wetterabfrage...$Zeitstring"};
my @Summand = split(/:/, $Summand);
my @Array_wetter = split(/:/, $Zeitstring);
my $Sekunden_wetter = pop(@Array_wetter) + pop(@Summand);
my $Minuten_wetter = pop(@Array_wetter) + pop(@Summand);
my $Stunden_wetter = pop(@Array_wetter) + pop(@Summand);
Log 3, "$Stunden_wetter, $Minuten_wetter, $Sekunden_wetter";
$Zeitstring = sprintf("%02d:%02d:%02d", $Stunden_wetter, $Minuten_wetter, $Sekunden_wetter);
if ($Zeitstring lt $Zeit_min) {$Zeitstring = $Zeit_min}
if ($Zeitstring gt $Zeit_max) {$Zeitstring = $Zeit_max}
Log 3,"Offset-Routine liefert: $Zeitstring";
my ($Psec,$Pmin,$Phour,$Pmday,$Pmonth,$Pyear,$Pwday,$Pyday,$Pisdst) = localtime($Zeitstring); return sprintf("%02d:%02d:%02d", $Phour, $Pmin, $Psec);
}

Mache ich was falsch? Geht das überhaupt?

MfG, MisterEltako.
HMLAN-Konfigurations-Adapter, HM-Funkjalousieaktor/HM-Dimmaktor/HM-Schaltaktor f. Markenschalter, Jalousie-/Schaltaktor von Eltako, FT4 v. Eltako, TCM310

UliM

Zitat von: MisterEltako schrieb am Mo, 04 März 2013 18:16sub Offset($$$$){
my $Zeitstring = ReadingsVal("Local_Wetter",$Methode,"nv");

Hi,
fehlt da nicht die Übernahme der Parameter?  Also sowas wie
my ($Methose, $Summand, $x, $y) = @_;
=8-)
RPi4/Raspbian, CUL V3 (ca. 30 HomeMatic-devices), LAN (HarmonyHub, alexa etc.).  Fördermitglied des FHEM e.V.

Dietmar63

= localtime($Zeitstring); funktioniert nicht auf strings sondern auf sekunden seit dem 1.1.1970 ( time() ).

Logge mal bitte "sprintf("%02d:%02d:%02d", $Phour, $Pmin, $Psec);"
In diesem Wert muss etwas vernünftiges stehen - dann hast Du gewonnen.
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

Dietmar63

"Fehler bei der Wetterabfrage...$Zeitstring" wird ggf. an at weitergegeben.
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

Dietmar63

$Zeitstring müsste doch schon das richtige Format habe.

Die Wandlung über localtime ist nicht notwendig.

Wenn doch, dann mit split oder substr.
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

MisterEltako

Hi!

Danke für die Antworten. Ich habe das Auslesen der Parameter beim Kopieren versehentlich weggelassen ... ;o)
Also somit stimmt der erste Hinweis. Ich habe nun noch Mal geändert: Zum Testen der Sunroutine wurde at durch notify ersetzt.
Das hat folgendes ergeben:

Fhem.cfg:
define n_Taster4 notify Taster4 {\
           my $Ergebnis = {Offset('sunset','00:10:00','17:00:00','21:00:00')};;\
           Log 1, "$Ergebnis";;\
}


myUtils.pm:
sub
Offset($$$$){
my ($Methode,$Summand,$Zeit_min,$Zeit_max) = @_;
my $Zeitstring = ReadingsVal("Local_Wetter",$Methode,"nv");
if ($Zeitstring eq "nv") {Log 1, "Fehler bei der Wetterabfrage...$Zeitstring"};

Log 1, ("uebergebene Parameter sind Methode: $Methode, Summand: $Summand, Zeit_min: $Zeit_min, Zeit_max: $Zeit_max");

Log 1, "Von Yahoo ermittelter Wert: $Zeitstring";
my @Summand = split(/:/, $Summand);
my @Array_wetter = split(/:/, $Zeitstring);
my $Sekunden_wetter = pop(@Array_wetter) + pop(@Summand);
my $Minuten_wetter = pop(@Array_wetter) + pop(@Summand);
my $Stunden_wetter = pop(@Array_wetter) + pop(@Summand);

Log 3, "Stunden: $Stunden_wetter, Minuten: $Minuten_wetter, Sekunden: $Sekunden_wetter";
$Zeitstring = sprintf("%02d:%02d:%02d", $Stunden_wetter, $Minuten_wetter, $Sekunden_wetter);
Log 3, "daraus erstellter Zeitstring: $Zeitstring";
if ($Zeitstring lt $Zeit_min) {$Zeitstring = $Zeit_min}
if ($Zeitstring gt $Zeit_max) {$Zeitstring = $Zeit_max}
Log 3,"Offset-Routine liefert: $Zeitstring";

return "$Zeitstring";
}

FileLog:
2013.03.04 21:49:07 1: uebergebene Parameter sind Methode: sunset, Summand: 00:10:00, Zeit_min: 17:00:00, Zeit_max: 21:00:00
2013.03.04 21:49:07 1: Von Yahoo ermittelter Wert: 17:52:59
2013.03.04 21:49:07 3: Stunden: 17, Minuten: 62, Sekunden: 59
2013.03.04 21:49:07 3: daraus erstellter Zeitstring: 17:62:59
2013.03.04 21:49:07 3: Offset-Routine liefert: 17:62:59
Odd number of elements in anonymous hash at (eval 505) line 1.
2013.03.04 21:49:07 1: HASH(0x7a7858)

MfG, MisterEltako.
HMLAN-Konfigurations-Adapter, HM-Funkjalousieaktor/HM-Dimmaktor/HM-Schaltaktor f. Markenschalter, Jalousie-/Schaltaktor von Eltako, FT4 v. Eltako, TCM310

Dietmar63

17:62:59

Übertrage musst du bei der Addition der einzelnen Elemente selbst vornehmen.

"Odd number of elements" kann ich nicht so genau sagen wo das herkommt.


Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

UliM

Genau wegen des 17:62-Problems (und wg der Möglichkeit eines negativen offset) arbeitet die originale routine mit localtime - da wird das ganze Sekunden- und Minuten-weitergeschubse von perl übernommen.
LG, Uli
RPi4/Raspbian, CUL V3 (ca. 30 HomeMatic-devices), LAN (HarmonyHub, alexa etc.).  Fördermitglied des FHEM e.V.

Dietmar63

Du könntest ausgehend von time() modulo 24*3600 * 24*3600 + h*3600+m*60 das offset addieren und dann mit Sprint oder so returnieren.

Achtung : Zwischenergebnisse musst du mit int() in Ganzzahlen verwandeln.
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

MisterEltako

Hi!

Das muss ich heute Abend ausprobieren. ;o) Zunächst Danke!
Gestern war ich soweit, das "17:52:59" von der Subroutine zurückgegeben wurde (habe einfach den Summand zum Testen reduziert). Es wurde über Benutzung von Schalter4 die Variable $Ergebnis mit: 17:52:59 ausgegeben. Trotzdem funktioniert die at-Routine nicht mit:

define Test at{Offset("sunset", "00:10:00, 17:00:00, 21:00:00)} set Rollladen on


....Wrong Timespec oder ...perlcode...

habe mit "{ }" oder "{( )}" oder "(( ))" usw. probiert -> immer Fehlermeldung.
D.h. es muss schon der Aufruf falsch sein, oder???

MfG, MisterEltako.

HMLAN-Konfigurations-Adapter, HM-Funkjalousieaktor/HM-Dimmaktor/HM-Schaltaktor f. Markenschalter, Jalousie-/Schaltaktor von Eltako, FT4 v. Eltako, TCM310

rudolfkoenig

Zitat commandref.html:
 <timedet> is either HH:MM, HH:MM:SS or {perlfunc()}, where perlfunc must return a HH:MM or HH:MM:SS date.

{Offset(...)} kann man doch direkt in FHEM eingeben, und pruefen was es zurueckliefert.

Dietmar63

Du könntest zum Beispiel auch in  90_at.pm in Zeile 42, 46 in der Fehlermeldung den $tm bzw. $tspec ergänzen.
Dann kannst du oft schon sofort sehen was falsch läuft.

Reload nicht vergessen.


26 #####################################
27 sub
28 at_Define($$)
29 {
30  my ($hash, $def) = @_;
31  my ($name, undef, $tm, $command) = split("[ \t]+", $def, 4);
32
33  if(!$command) {
34    if($hash->{OLDDEF}) { # Called from modify, where command is optional
35      RemoveInternalTimer($hash);
36      (undef, $command) = split("[ \t]+", $hash->{OLDDEF}, 2);
37      $hash->{DEF} = "$tm $command";
38    } else {
39      return "Usage: define <name> at <timespec> <command>";
40    }
41  }
42  return "Wrong timespec, use \"[+][*[{count}]]<time or func>\""
43                                        if($tm !~ m/^(\+)?(\*({\d+})?)?(.*)$/);
44  my ($rel, $rep, $cnt, $tspec) = ($1, $2, $3, $4);
45  my ($err, $hr, $min, $sec, $fn) = GetTimeSpec($tspec);
46  return $err if($err);


Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

MisterEltako

define Test33 at {Offset('sunset','00:05:00','17:00:00','21:00:00')} {fhem('set Licht_all off')}

sub
Offset($$$$){
my ($Methode, $Summand, $Zeit_min,$Zeit_max) = @_;
my $Zeitstring = ReadingsVal("Local_Wetter","$Methode","nv");

if ($Zeitstring eq "nv") {return "Fehler bei der Wetterabfrage...$Zeitstring"};

my @Summand = split(/:/, $Summand);
my @Array_wetter = split(/:/, $Zeitstring);
my $Sekunden_wetter = pop(@Array_wetter) + pop(@Summand);
my $Minuten_wetter = pop(@Array_wetter) + pop(@Summand);
my $Stunden_wetter = pop(@Array_wetter) + pop(@Summand);

$Zeitstring = sprintf("%02d:%02d:%02d", $Stunden_wetter, $Minuten_wetter, $Sekunden_wetter);

if ($Zeitstring lt $Zeit_min) {$Zeitstring = $Zeit_min}
if ($Zeitstring gt $Zeit_max) {$Zeitstring = $Zeit_max}

return $Zeitstring;
}


So wird zunächst das at mit entsprechend ermitteltem Wert angelegt. Das Problem mit dem Zeitübertrag habe ich trotz des og. Hinweises von Dietmar leider noch nicht gelöst...

MfG, MisterEltako.
HMLAN-Konfigurations-Adapter, HM-Funkjalousieaktor/HM-Dimmaktor/HM-Schaltaktor f. Markenschalter, Jalousie-/Schaltaktor von Eltako, FT4 v. Eltako, TCM310

MisterEltako

So ich denke jetzt habe ich eine Möglichkeit:

if ($Minuten_wetter >= 60) {$Minuten_wetter = ($Minuten_wetter - 60);$Uebertrag = 1}
my $Stunden_wetter = pop(@Array_wetter) + pop(@Summand) + $Uebertrag;


MfG, MisterEltako.
HMLAN-Konfigurations-Adapter, HM-Funkjalousieaktor/HM-Dimmaktor/HM-Schaltaktor f. Markenschalter, Jalousie-/Schaltaktor von Eltako, FT4 v. Eltako, TCM310

Dietmar63

das funktioniert aber leider nicht wenn du einen Übertrag des Tages ... berücksichtigen musst.

folgender Code könnte auch das abbilden. Ich habe deine Routine ein wenig angepasst und die Logs gelassen:


# {Offset("17:52:59","52:59","15:00:00","23:59:59")}
# {Offset("23:52:59","52:59","00:00:00","23:59:59")}
sub
Offset($$$$){
my ($Methode, $Summand, $Zeit_min,$Zeit_max) = @_;
# my $Zeitstring = ReadingsVal("Local_Wetter","$Methode","nv");
  my $Zeitstring = $Methode;

if ($Zeitstring eq "nv") {return "Fehler bei der Wetterabfrage...$Zeitstring"};

my @Summand = split(/:/, $Summand);
my @Array_wetter = split(/:/, $Zeitstring);

  my $midnight = int (time()/24/3600) * 24*3600 - 3600;
  Log 3, "midnight------------>".strftime("%d %H:%M:%S",localtime($midnight));
  my $Zeit    = $midnight +
       3600*(int($Array_wetter[0])) +
         60*(int($Array_wetter[1])) +
          1*(int($Array_wetter[2]));

  Log 3, "Zeit------------>".strftime("%d %H:%M:%S",localtime($Zeit));
  my $newTime = $Zeit +
       60*(int($Summand[0])) +
        1*(int($Summand[1]));


  Log 3, "Summand----------->$Summand[0]:$Summand[1]";
  Log 3, "newTime------------>".strftime("%d %H:%M:%S",localtime($newTime));

  $Zeitstring = strftime("%d %H:%M:%S",localtime($newTime));
  Log 3, "Zeitstring neu------------>$Zeitstring";

#my $Sekunden_wetter = pop(@Array_wetter) + pop(@Summand);
#my $Minuten_wetter = pop(@Array_wetter) + pop(@Summand);
#my $Stunden_wetter = pop(@Array_wetter) + pop(@Summand);

# $Zeitstring = sprintf("%02d:%02d:%02d", $Stunden_wetter, $Minuten_wetter, $Sekunden_wetter);

if ($Zeitstring lt $Zeit_min) {$Zeitstring = $Zeit_min}
if ($Zeitstring gt $Zeit_max) {$Zeitstring = $Zeit_max}

return $Zeitstring;
}


Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm