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.
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-)
= 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.
"Fehler bei der Wetterabfrage...$Zeitstring" wird ggf. an at weitergegeben.
$Zeitstring müsste doch schon das richtige Format habe.
Die Wandlung über localtime ist nicht notwendig.
Wenn doch, dann mit split oder substr.
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.
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.
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
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.
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.
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.
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);
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.
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.
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;
}
Hi, Dietmar!
Habe deine Routine eingefügt, welche leider zu folgenden Logeinträgen führt:
2013.03.08 01:10:45 3: midnight------------>08 00:00:00 Argument "sunrise" isn't numeric in int at /usr/local/FHEM/share/fhem/FHEM/99_myUtils.pm line 84. Use of uninitialized value $Array_wetter[1] in int at /usr/local/FHEM/share/fhem/FHEM/99_myUtils.pm line 84. Use of uninitialized value $Array_wetter[2] in int at /usr/local/FHEM/share/fhem/FHEM/99_myUtils.pm line 84.
2013.03.08 01:10:45 3: Zeit------------>08 00:00:00
2013.03.08 01:10:45 3: Summand----------->00:00
2013.03.08 01:10:45 3: newTime------------>08 00:00:00
2013.03.08 01:10:45 3: Zeitstring neu------------>08 00:00:00
2013.03.08 01:10:45 3: Offset-Routine_new liefert: sunrise ist 08 00:00:00
2013.03.08 01:10:45 1: define: the at function "Offset_new('sunrise','00:00:00','07:00:00','09:00:00')" must return a timespec and not 08 00:00:00. 2013.03.08 01:10:45 3: define Sonnenaufgang_new at {Offset_new('sunrise','00:00:00','07:00:00','09:00:00')} set Rollladen_EG 100 : the at function "Offset_new('sunrise','00:00:00','07:00:00','09:00:00')" must return a timespec and not 08 00:00:00. 2013.03.08 01:10:45 3: Rollladen_Yahoo_gesteuert_auf_new return value: the at function "Offset_new('sunrise','00:00:00','07:00:00','09:00:00')" must return a timespec and not 08 00:00:00. 2013.03.08 07:00:14 2: CUL_HM set Rollladen_EG 100 rxt:1 2013.03.08 07:00:14 1: 192.168.100.33:1000 disconnected, waiting to reappear 2013.03.08 07:02:59 1: 192.168.100.33:1000 reappeared (HMLAN)
MfG, MisterEltako.
Poste bitte den genauen Code, dann kann ich prüfen.
Habe exakt deinen o.g Code übernommen....
# my $Zeitstring = ReadingsVal("Local_Wetter","$Methode","nv");
my $Zeitstring = $Methode;
Entferne bitte mal das # vor dieser Zeile!
Dann sollte es schon besser aussehen
Dann kommt....
2013.03.08 18:14:00 3: midnight------------>08 00:00:00
2013.03.08 18:14:00 3: 06, 37, 00
2013.03.08 18:14:00 3: Zeit------------>08 06:37:00
2013.03.08 18:14:00 3: Summand----------->00:00
2013.03.08 18:14:00 3: newTime------------>08 06:37:00
2013.03.08 18:14:00 3: Zeitstring neu------------>08 06:37:00
2013.03.08 18:14:00 3: Offset-Routine_new liefert: sunrise ist 08 06:37:00
2013.03.08 18:14:00 1: define: the at function "Offset_new('sunrise','00:00:00','07:00:00','09:00:00')" must return a timespec and not 08 06:37:00. 2013.03.08 18:14:00 3: define Sonnenaufgang_new at {Offset_new('sunrise','00:00:00','07:00:00','09:00:00')} set Rollladen_EG 100 : the at function "Offset_new('sunrise','00:00:00','07:00:00','09:00:00')" must return a timespec and not 08 06:37:00. 2013.03.08 18:14:00 3: Rollladen_Yahoo_gesteuert_auf_new return value: the at function "Offset_new('sunrise','00:00:00','07:00:00','09:00:00')" must return a timespec and not 08 06:37:00
MfG, MisterEltako
mit der Ergänzung:
...
$Zeitstring = sprintf("%02d:%02d:%02d", $Stunden_wetter, $Minuten_wetter, $Sekunden_wetter);
$Zeitstring = substr($Zeitstring,4,11);
if ($Zeitstring lt $Zeit_min) {$Zeitstring = $Zeit_min}
if ($Zeitstring gt $Zeit_max) {$Zeitstring = $Zeit_max}
Log 3,"Offset-Routine_new liefert: $Methode ist $Zeitstring"; return $Zeitstring;
}
dann kommt:
2013.03.08 18:42:12 3: midnight------------>08 00:00:00
2013.03.08 18:42:12 3: 06, 37, 00
2013.03.08 18:42:12 3: Zeit------------>08 06:37:00
2013.03.08 18:42:12 3: Summand----------->00:00
2013.03.08 18:42:12 3: newTime------------>08 06:37:00
2013.03.08 18:42:12 3: Zeitstring neu------------>08 06:37:00
2013.03.08 18:42:12 3: Offset-Routine_new liefert: sunrise ist 09:00:00
MfG,MisterEltako.
Poste bitte den ganzen Code dann korrigiere ich alles, ein Fehler ist mir leider auch noch unterlaufen.
Ich hatte dir noch keinen voll funktionsfähigen Code sondern ein Beispiel mit dem Kern meiner Idee geschickt, was noch ein wenig Anpassung nötig hatte. Deine Erweiterung greift an der falschen Stelle!
so sollte es richtig sein:
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 $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, "$Methode------------>".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, "plus Summand------>".strftime("%H:%M:%S",localtime($newTime));
$Zeitstring = strftime("%H:%M:%S",localtime($newTime));
Log 3, "Zeitstring neu------------>$Zeitstring";
if ($Zeitstring lt $Zeit_min) {$Zeitstring = $Zeit_min}
if ($Zeitstring gt $Zeit_max) {$Zeitstring = $Zeit_max}
return $Zeitstring;
}
leider nur mit Schreibtischtest möglich weil ich "Local_Wetter" nicht definiert habe
Hi!
Vielen Dank! Das war schon fast richtig (s.u.). Jetzt möchte ich noch, das nur "sunset" oder "sunrise" Änderungen das Notify auslösen. Ist das so ok?
fhem.cfg:
define Local_Wetter Weather 12831828 3600 de
attr Local_Wetter localicons 1
attr Local_Wetter event-on-change-reading (sunrise|sunset)
define Rollladen_Yahoo_gesteuert_auf_new notify Local_Wetter:sunset.* {\
if (defined($defs{Sonnenaufgang_new})) {fhem('delete Sonnenaufgang_new')}\
fhem("define Sonnenaufgang_new at {Offset_new('sunrise','00:10:00','07:00:00','09:00:00')} set Rollladen_EG 100")}
99_myUtils.pm:
sub
Offset_new($$$$){
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 $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, "$Methode------------>".strftime("%d %H:%M:%S",localtime($Zeit));
my $newTime = $Zeit +
3600*(int($Summand[0])) +
60*(int($Summand[1])) +
1*(int($Summand[2]));
Log 3, "Summand----------->$Summand[0]:$Summand[1]:$Summand[2]";
Log 3, "plus Summand------>".strftime("%H:%M:%S",localtime($newTime));
$Zeitstring = strftime("%H:%M:%S",localtime($newTime));
Log 3, "Zeitstring neu------------>$Zeitstring, $Zeit_min,$Zeit_max";
if ($Zeitstring lt $Zeit_min) {$Zeitstring = $Zeit_min}
if ($Zeitstring gt $Zeit_max) {$Zeitstring = $Zeit_max}
Log 3, "$Zeit_min < $Zeitstring < $Zeit_max";
return $Zeitstring;
}
Nochmals Danke für deine Unterstützung!
MfG, MisterEltako.
Hast recht
Ich habe beim Aufbau meiner Testversion von offset übersehen, dass der Summand auch Sekunden hatte.
event-on-change-reading
The attribute takes a comma-separated list of readings. You may use regular expressions in that list. If set, only changes of the listed readings create events. In other words, if a reading listed here is updated with the new value identical to the old value, no event is created.1
scheint mir richtig zu sein. Ich würde es aber so formulieren:
attr xxx event-on-change-reading sunrise,sunset